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