olpc_battery.c revision 5519d00e6a5d99a163484722ef7cea8bff47bc58
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 270fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse/********************************************************************* 271fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * Battery properties 272fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse *********************************************************************/ 273fb972873a767220333ffb509de8d9131336e212cDavid Woodhousestatic int olpc_bat_get_property(struct power_supply *psy, 274fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse enum power_supply_property psp, 275fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse union power_supply_propval *val) 276fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse{ 277fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse int ret = 0; 2788e9c7716c138fa82d919bfe1115ec8c938e90918Harvey Harrison __be16 ec_word; 279fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse uint8_t ec_byte; 2808e9c7716c138fa82d919bfe1115ec8c938e90918Harvey Harrison __be64 ser_buf; 281fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 282fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1); 283fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 284fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 285fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 286fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse /* Theoretically there's a race here -- the battery could be 287fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse removed immediately after we check whether it's present, and 288fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse then we query for some other property of the now-absent battery. 289fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse It doesn't matter though -- the EC will return the last-known 290fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse information, and it's as if we just ran that _little_ bit faster 291fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse and managed to read it out before the battery went away. */ 2928f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon if (!(ec_byte & (BAT_STAT_PRESENT | BAT_STAT_TRICKLE)) && 2938f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon psp != POWER_SUPPLY_PROP_PRESENT) 294fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return -ENODEV; 295fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 296fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse switch (psp) { 297fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_STATUS: 298b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_bat_get_status(val, ec_byte); 299b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon if (ret) 300b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon return ret; 301b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon break; 302ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon case POWER_SUPPLY_PROP_CHARGE_TYPE: 303ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon if (ec_byte & BAT_STAT_TRICKLE) 304ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 305ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon else if (ec_byte & BAT_STAT_CHARGING) 306ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; 307ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon else 308ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 309ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon break; 310fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_PRESENT: 3118f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon val->intval = !!(ec_byte & (BAT_STAT_PRESENT | 3128f7e57985fa794ab6afdcd3642581d9e1fe6de31Andres Salomon BAT_STAT_TRICKLE)); 313fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 314fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 315fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_HEALTH: 316fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ec_byte & BAT_STAT_DESTROY) 317fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse val->intval = POWER_SUPPLY_HEALTH_DEAD; 318fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse else { 319b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_bat_get_health(val); 320fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 321fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 322fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse } 323fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 324fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 325fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_MANUFACTURER: 326b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_bat_get_mfr(val); 327fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 328fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 329fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 330fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_TECHNOLOGY: 331b2bd8a3bcdd18101eb5d85c267c1a1fb8ce9acc7Andres Salomon ret = olpc_bat_get_tech(val); 332fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 333fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 334fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 335fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_VOLTAGE_AVG: 33622fadd766b2a222b273df9f2264b72e4b3bbe921Sascha Silbe case POWER_SUPPLY_PROP_VOLTAGE_NOW: 337fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2); 338fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 339fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 340fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 3417cfbb29466633e6ecdc14f76a693c8478c2b22afRichard A. Smith val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32; 342fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 343fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_CURRENT_AVG: 34422fadd766b2a222b273df9f2264b72e4b3bbe921Sascha Silbe case POWER_SUPPLY_PROP_CURRENT_NOW: 345fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2); 346fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 347fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 348fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 3497cfbb29466633e6ecdc14f76a693c8478c2b22afRichard A. Smith val->intval = (s16)be16_to_cpu(ec_word) * 15625L / 120; 350fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 351fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_CAPACITY: 352fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1); 353fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 354fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 355fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse val->intval = ec_byte; 356fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 357b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 358b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon if (ec_byte & BAT_STAT_FULL) 359b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 360b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon else if (ec_byte & BAT_STAT_LOW) 361b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW; 362b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon else 363b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 364b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon break; 365b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 366b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe ret = olpc_bat_get_charge_full_design(val); 367b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe if (ret) 368b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe return ret; 369b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe break; 37020fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe case POWER_SUPPLY_PROP_CHARGE_NOW: 37120fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe ret = olpc_bat_get_charge_now(val); 37220fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe if (ret) 37320fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe return ret; 37420fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe break; 375fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_TEMP: 376fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2); 377fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 378fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 3798e9c7716c138fa82d919bfe1115ec8c938e90918Harvey Harrison 3807cfbb29466633e6ecdc14f76a693c8478c2b22afRichard A. Smith val->intval = (s16)be16_to_cpu(ec_word) * 100 / 256; 381fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 382fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse case POWER_SUPPLY_PROP_TEMP_AMBIENT: 383fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2); 384fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 385fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 386fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 3878e9c7716c138fa82d919bfe1115ec8c938e90918Harvey Harrison val->intval = (int)be16_to_cpu(ec_word) * 100 / 256; 388fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 3898e552c36d90c03d2cabf5373788998966751b609Andres Salomon case POWER_SUPPLY_PROP_CHARGE_COUNTER: 3908e552c36d90c03d2cabf5373788998966751b609Andres Salomon ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2); 3918e552c36d90c03d2cabf5373788998966751b609Andres Salomon if (ret) 3928e552c36d90c03d2cabf5373788998966751b609Andres Salomon return ret; 3938e552c36d90c03d2cabf5373788998966751b609Andres Salomon 3947cfbb29466633e6ecdc14f76a693c8478c2b22afRichard A. Smith val->intval = (s16)be16_to_cpu(ec_word) * 6250 / 15; 3958e552c36d90c03d2cabf5373788998966751b609Andres Salomon break; 3961ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse case POWER_SUPPLY_PROP_SERIAL_NUMBER: 3971ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8); 3981ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse if (ret) 3991ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse return ret; 4001ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse 4011ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse sprintf(bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf)); 4021ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse val->strval = bat_serial; 4031ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse break; 404fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse default: 405fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = -EINVAL; 406fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse break; 407fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse } 408fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 409fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 410fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse} 411fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 412c566d299f91bdb622046126dbcb040f9e52572baDaniel Drakestatic enum power_supply_property olpc_xo1_bat_props[] = { 413fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_STATUS, 414ee8076ed3e1cdd0cd1e61318386932669c90b92fAndres Salomon POWER_SUPPLY_PROP_CHARGE_TYPE, 415fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_PRESENT, 416fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_HEALTH, 417fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_TECHNOLOGY, 418fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_VOLTAGE_AVG, 41922fadd766b2a222b273df9f2264b72e4b3bbe921Sascha Silbe POWER_SUPPLY_PROP_VOLTAGE_NOW, 420fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_CURRENT_AVG, 42122fadd766b2a222b273df9f2264b72e4b3bbe921Sascha Silbe POWER_SUPPLY_PROP_CURRENT_NOW, 422fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_CAPACITY, 423b294a290d24d1196d68399cc3a9b8c50bfb55abdAndres Salomon POWER_SUPPLY_PROP_CAPACITY_LEVEL, 424b202a5e6c94d8c43ade5adb97e87734cc4f4f228Sascha Silbe POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 42520fd9830ccc685adce65ba89ffc3ca5426a2b064Sascha Silbe POWER_SUPPLY_PROP_CHARGE_NOW, 426fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_TEMP, 427fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_TEMP_AMBIENT, 428fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse POWER_SUPPLY_PROP_MANUFACTURER, 4291ca5b9d2183f11bb8b69e04b19a7faf7f600a840David Woodhouse POWER_SUPPLY_PROP_SERIAL_NUMBER, 4308e552c36d90c03d2cabf5373788998966751b609Andres Salomon POWER_SUPPLY_PROP_CHARGE_COUNTER, 431fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse}; 432fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 433c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake/* XO-1.5 does not have ambient temperature property */ 434c566d299f91bdb622046126dbcb040f9e52572baDaniel Drakestatic enum power_supply_property olpc_xo15_bat_props[] = { 435c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_STATUS, 436c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CHARGE_TYPE, 437c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_PRESENT, 438c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_HEALTH, 439c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_TECHNOLOGY, 440c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_VOLTAGE_AVG, 441bf542a4e7b634c2adcba4241a29082f69b0f45dcSascha Silbe POWER_SUPPLY_PROP_VOLTAGE_NOW, 442c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CURRENT_AVG, 443bf542a4e7b634c2adcba4241a29082f69b0f45dcSascha Silbe POWER_SUPPLY_PROP_CURRENT_NOW, 444c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CAPACITY, 445c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CAPACITY_LEVEL, 446bf542a4e7b634c2adcba4241a29082f69b0f45dcSascha Silbe POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 447bf542a4e7b634c2adcba4241a29082f69b0f45dcSascha Silbe POWER_SUPPLY_PROP_CHARGE_NOW, 448c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_TEMP, 449c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_MANUFACTURER, 450c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_SERIAL_NUMBER, 451c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake POWER_SUPPLY_PROP_CHARGE_COUNTER, 452c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake}; 453c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake 454d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon/* EEPROM reading goes completely around the power_supply API, sadly */ 455d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 456d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon#define EEPROM_START 0x20 457d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon#define EEPROM_END 0x80 458d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon#define EEPROM_SIZE (EEPROM_END - EEPROM_START) 459d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 4602c3c8bea608866d8bd9dcf92657d57fdcac011c5Chris Wrightstatic ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj, 461d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon struct bin_attribute *attr, char *buf, loff_t off, size_t count) 462d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon{ 463d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon uint8_t ec_byte; 46404a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon int ret; 46504a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon int i; 466d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 467d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon if (off >= EEPROM_SIZE) 468d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon return 0; 469d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon if (off + count > EEPROM_SIZE) 470d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon count = EEPROM_SIZE - off; 471d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 47204a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon for (i = 0; i < count; i++) { 47304a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon ec_byte = EEPROM_START + off + i; 47404a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &buf[i], 1); 475d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon if (ret) { 47604a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon pr_err("olpc-battery: " 47704a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon "EC_BAT_EEPROM cmd @ 0x%x failed - %d!\n", 47804a820ead0838c76e9c1242feb5e71048bf3e9dcAndres Salomon ec_byte, ret); 479d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon return -EIO; 480d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon } 481d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon } 482d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 483d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon return count; 484d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon} 485d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 486d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomonstatic struct bin_attribute olpc_bat_eeprom = { 487d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .attr = { 488d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .name = "eeprom", 489d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .mode = S_IRUGO, 490d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon }, 491d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .size = 0, 492d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon .read = olpc_bat_eeprom_read, 493d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon}; 494d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 495144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon/* Allow userspace to see the specific error value pulled from the EC */ 496144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 497144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomonstatic ssize_t olpc_bat_error_read(struct device *dev, 498144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon struct device_attribute *attr, char *buf) 499144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon{ 500144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon uint8_t ec_byte; 501144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon ssize_t ret; 502144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 503144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1); 504144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon if (ret < 0) 505144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon return ret; 506144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 507144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon return sprintf(buf, "%d\n", ec_byte); 508144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon} 509144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 510144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomonstatic struct device_attribute olpc_bat_error = { 511144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon .attr = { 512144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon .name = "error", 513144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon .mode = S_IRUGO, 514144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon }, 515144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon .show = olpc_bat_error_read, 516144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon}; 517144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 518fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse/********************************************************************* 519fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse * Initialisation 520fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse *********************************************************************/ 521fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 522fb972873a767220333ffb509de8d9131336e212cDavid Woodhousestatic struct power_supply olpc_bat = { 523c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .name = "olpc-battery", 524fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse .get_property = olpc_bat_get_property, 525fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse .use_for_apm = 1, 526fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse}; 527fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 528fb972873a767220333ffb509de8d9131336e212cDavid Woodhousevoid olpc_battery_trigger_uevent(unsigned long cause) 529fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse{ 530fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (cause & EC_SCI_SRC_ACPWR) 531fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE); 532fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY)) 533fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE); 534fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse} 535fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 536cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drakestatic int olpc_battery_suspend(struct platform_device *pdev, 537cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake pm_message_t state) 538cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake{ 539cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake if (device_may_wakeup(olpc_ac.dev)) 540cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake olpc_ec_wakeup_set(EC_SCI_SRC_ACPWR); 541cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake else 542cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake olpc_ec_wakeup_clear(EC_SCI_SRC_ACPWR); 543cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake 544cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake if (device_may_wakeup(olpc_bat.dev)) 545cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake olpc_ec_wakeup_set(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC 546cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake | EC_SCI_SRC_BATERR); 547cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake else 548cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake olpc_ec_wakeup_clear(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC 549cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake | EC_SCI_SRC_BATERR); 550cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake 551cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake return 0; 552cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake} 553cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake 554c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drakestatic int __devinit olpc_battery_probe(struct platform_device *pdev) 555fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse{ 556c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake int ret; 557fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse uint8_t status; 558fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 559484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon /* 560484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon * We've seen a number of EC protocol changes; this driver requires 561484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon * the latest EC protocol, supported by 0x44 and above. 562484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon */ 563484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon if (olpc_platform_info.ecver < 0x44) { 564484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon printk(KERN_NOTICE "OLPC EC version 0x%02x too old for " 565484d6d50cca3941db6e063113d124333aed0abc0Andres Salomon "battery driver.\n", olpc_platform_info.ecver); 566fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return -ENXIO; 567fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse } 568fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 569fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1); 570fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 571fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 572fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 573fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse /* Ignore the status. It doesn't actually matter */ 574fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 575c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake ret = power_supply_register(&pdev->dev, &olpc_ac); 576fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 577c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake return ret; 578fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 579c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */ 580c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake olpc_bat.properties = olpc_xo15_bat_props; 581c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props); 582c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake } else { /* XO-1 */ 583c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake olpc_bat.properties = olpc_xo1_bat_props; 584c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props); 585c566d299f91bdb622046126dbcb040f9e52572baDaniel Drake } 586fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 587c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake ret = power_supply_register(&pdev->dev, &olpc_bat); 588fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse if (ret) 589fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse goto battery_failed; 590fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 591d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon ret = device_create_bin_file(olpc_bat.dev, &olpc_bat_eeprom); 592d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon if (ret) 593d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon goto eeprom_failed; 594d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon 595144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon ret = device_create_file(olpc_bat.dev, &olpc_bat_error); 596144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon if (ret) 597144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon goto error_failed; 598144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon 599cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake if (olpc_ec_wakeup_available()) { 600cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake device_set_wakeup_capable(olpc_ac.dev, true); 601cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake device_set_wakeup_capable(olpc_bat.dev, true); 602cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake } 603cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake 604c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake return 0; 605fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 606144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomonerror_failed: 607144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); 608d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomoneeprom_failed: 609d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon power_supply_unregister(&olpc_bat); 610fb972873a767220333ffb509de8d9131336e212cDavid Woodhousebattery_failed: 611fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse power_supply_unregister(&olpc_ac); 612fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse return ret; 613fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse} 614fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 615c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drakestatic int __devexit olpc_battery_remove(struct platform_device *pdev) 616fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse{ 617144bbeaedc53290eab21da82ce1cb5faefd14374Andres Salomon device_remove_file(olpc_bat.dev, &olpc_bat_error); 618d7eb9e36c42504e87c7d92dd5c05cb6f2cf74d28Andres Salomon device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); 619fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse power_supply_unregister(&olpc_bat); 620fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse power_supply_unregister(&olpc_ac); 621c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake return 0; 622fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse} 623fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 624c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drakestatic const struct of_device_id olpc_battery_ids[] __devinitconst = { 625c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake { .compatible = "olpc,xo1-battery" }, 626c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake {} 627c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake}; 628c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel DrakeMODULE_DEVICE_TABLE(of, olpc_battery_ids); 629c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake 6305519d00e6a5d99a163484722ef7cea8bff47bc58Anton Vorontsovstatic struct platform_driver olpc_battery_driver = { 631c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .driver = { 632c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .name = "olpc-battery", 633c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .owner = THIS_MODULE, 634c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .of_match_table = olpc_battery_ids, 635c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake }, 636c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .probe = olpc_battery_probe, 637c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake .remove = __devexit_p(olpc_battery_remove), 638cae659af87288a4b1723cdf94d713ef7fb4c56d9Daniel Drake .suspend = olpc_battery_suspend, 639c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake}; 640c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake 641c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drakestatic int __init olpc_bat_init(void) 642c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake{ 6435519d00e6a5d99a163484722ef7cea8bff47bc58Anton Vorontsov return platform_driver_register(&olpc_battery_driver); 644c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake} 645fb972873a767220333ffb509de8d9131336e212cDavid Woodhousemodule_init(olpc_bat_init); 646c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake 647c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drakestatic void __exit olpc_bat_exit(void) 648c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake{ 6495519d00e6a5d99a163484722ef7cea8bff47bc58Anton Vorontsov platform_driver_unregister(&olpc_battery_driver); 650c3503fd02558245ebbb0b48f3ae1d62416e3fd2aDaniel Drake} 651fb972873a767220333ffb509de8d9131336e212cDavid Woodhousemodule_exit(olpc_bat_exit); 652fb972873a767220333ffb509de8d9131336e212cDavid Woodhouse 653fb972873a767220333ffb509de8d9131336e212cDavid WoodhouseMODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 654fb972873a767220333ffb509de8d9131336e212cDavid WoodhouseMODULE_LICENSE("GPL"); 655fb972873a767220333ffb509de8d9131336e212cDavid WoodhouseMODULE_DESCRIPTION("Battery driver for One Laptop Per Child 'XO' machine"); 656