Commit 6d15702c authored by Vladimir Lebedev's avatar Vladimir Lebedev Committed by Len Brown

ACPI: sbs: use EC rather than I2C

SBS is based on EC function(ec_read/ec_write).
Not needed using of I2C structures/functions ... is removed.
SBS does not depend on I2C now.
Signed-off-by: default avatarVladimir Lebedev <vladimir.p.lebedev@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 8559840c
...@@ -30,30 +30,9 @@ ...@@ -30,30 +30,9 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/i2c.h> #include <linux/timer.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "i2c_ec.h"
#define DEF_CAPACITY_UNIT 3
#define MAH_CAPACITY_UNIT 1
#define MWH_CAPACITY_UNIT 2
#define CAPACITY_UNIT DEF_CAPACITY_UNIT
#define REQUEST_UPDATE_MODE 1
#define QUEUE_UPDATE_MODE 2
#define DATA_TYPE_COMMON 0
#define DATA_TYPE_INFO 1
#define DATA_TYPE_STATE 2
#define DATA_TYPE_ALARM 3
#define DATA_TYPE_AC_STATE 4
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
#define ACPI_SBS_COMPONENT 0x00080000 #define ACPI_SBS_COMPONENT 0x00080000
#define ACPI_SBS_CLASS "sbs" #define ACPI_SBS_CLASS "sbs"
#define ACPI_AC_CLASS "ac_adapter" #define ACPI_AC_CLASS "ac_adapter"
...@@ -74,15 +53,62 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); ...@@ -74,15 +53,62 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
#define _COMPONENT ACPI_SBS_COMPONENT #define _COMPONENT ACPI_SBS_COMPONENT
#define MAX_SBS_BAT 4
#define MAX_SMBUS_ERR 1
ACPI_MODULE_NAME("sbs"); ACPI_MODULE_NAME("sbs");
MODULE_AUTHOR("Rich Townsend"); MODULE_AUTHOR("Rich Townsend");
MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define xmsleep(t) msleep(t)
#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */
#define ACPI_EC_SMB_STS 0x01 /* status */
#define ACPI_EC_SMB_ADDR 0x02 /* address */
#define ACPI_EC_SMB_CMD 0x03 /* command */
#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */
#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */
#define ACPI_EC_SMB_STS_DONE 0x80
#define ACPI_EC_SMB_STS_STATUS 0x1f
#define ACPI_EC_SMB_PRTCL_WRITE 0x00
#define ACPI_EC_SMB_PRTCL_READ 0x01
#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08
#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a
#define ACPI_EC_SMB_TRANSACTION_SLEEP 1
#define ACPI_EC_SMB_ACCESS_SLEEP1 1
#define ACPI_EC_SMB_ACCESS_SLEEP2 10
#define DEF_CAPACITY_UNIT 3
#define MAH_CAPACITY_UNIT 1
#define MWH_CAPACITY_UNIT 2
#define CAPACITY_UNIT DEF_CAPACITY_UNIT
#define REQUEST_UPDATE_MODE 1
#define QUEUE_UPDATE_MODE 2
#define DATA_TYPE_COMMON 0
#define DATA_TYPE_INFO 1
#define DATA_TYPE_STATE 2
#define DATA_TYPE_ALARM 3
#define DATA_TYPE_AC_STATE 4
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
#define MAX_SBS_BAT 4
#define ACPI_SBS_BLOCK_MAX 32
#define ACPI_SBS_SMBUS_READ 1
#define ACPI_SBS_SMBUS_WRITE 2
#define ACPI_SBS_WORD_DATA 1
#define ACPI_SBS_BLOCK_DATA 2
static struct semaphore sbs_sem; static struct semaphore sbs_sem;
#define UPDATE_MODE QUEUE_UPDATE_MODE #define UPDATE_MODE QUEUE_UPDATE_MODE
...@@ -105,7 +131,6 @@ module_param(update_time2, int, 0); ...@@ -105,7 +131,6 @@ module_param(update_time2, int, 0);
static int acpi_sbs_add(struct acpi_device *device); static int acpi_sbs_add(struct acpi_device *device);
static int acpi_sbs_remove(struct acpi_device *device, int type); static int acpi_sbs_remove(struct acpi_device *device, int type);
static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus);
static void acpi_sbs_update_queue(void *data); static void acpi_sbs_update_queue(void *data);
static struct acpi_driver acpi_sbs_driver = { static struct acpi_driver acpi_sbs_driver = {
...@@ -126,9 +151,9 @@ struct acpi_battery_info { ...@@ -126,9 +151,9 @@ struct acpi_battery_info {
int vscale; int vscale;
int ipscale; int ipscale;
s16 serial_number; s16 serial_number;
char manufacturer_name[I2C_SMBUS_BLOCK_MAX + 3]; char manufacturer_name[ACPI_SBS_BLOCK_MAX + 3];
char device_name[I2C_SMBUS_BLOCK_MAX + 3]; char device_name[ACPI_SBS_BLOCK_MAX + 3];
char device_chemistry[I2C_SMBUS_BLOCK_MAX + 3]; char device_chemistry[ACPI_SBS_BLOCK_MAX + 3];
}; };
struct acpi_battery_state { struct acpi_battery_state {
...@@ -158,8 +183,8 @@ struct acpi_battery { ...@@ -158,8 +183,8 @@ struct acpi_battery {
struct acpi_sbs { struct acpi_sbs {
acpi_handle handle; acpi_handle handle;
int base;
struct acpi_device *device; struct acpi_device *device;
struct acpi_ec_smbus *smbus;
int sbsm_present; int sbsm_present;
int sbsm_batteries_supported; int sbsm_batteries_supported;
int ac_present; int ac_present;
...@@ -172,6 +197,14 @@ struct acpi_sbs { ...@@ -172,6 +197,14 @@ struct acpi_sbs {
struct timer_list update_timer; struct timer_list update_timer;
}; };
union sbs_rw_data {
u16 word;
u8 block[ACPI_SBS_BLOCK_MAX + 2];
};
static int acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
char read_write, u8 command, int size,
union sbs_rw_data *data);
static void acpi_update_delay(struct acpi_sbs *sbs); static void acpi_update_delay(struct acpi_sbs *sbs);
static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type); static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type);
...@@ -179,155 +212,172 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type); ...@@ -179,155 +212,172 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type);
SMBus Communication SMBus Communication
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus) static int acpi_ec_sbs_read(struct acpi_sbs *sbs, u8 address, u8 * data)
{ {
union i2c_smbus_data data; u8 val;
int result = 0; int err;
char *err_str;
int err_number;
data.word = 0; err = ec_read(sbs->base + address, &val);
if (!err) {
*data = val;
}
xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
return (err);
}
result = smbus->adapter.algo-> static int acpi_ec_sbs_write(struct acpi_sbs *sbs, u8 address, u8 data)
smbus_xfer(&smbus->adapter, {
ACPI_SB_SMBUS_ADDR, int err;
0, I2C_SMBUS_READ, 0x16, I2C_SMBUS_BLOCK_DATA, &data);
err_number = (data.word & 0x000f); err = ec_write(sbs->base + address, data);
return (err);
}
switch (data.word & 0x000f) { static int
case 0x0000: acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr,
err_str = "unexpected bus error"; char read_write, u8 command, int size,
break; union sbs_rw_data *data)
case 0x0001: {
err_str = "busy"; unsigned char protocol, len = 0, temp[2] = { 0, 0 };
break; int i;
case 0x0002:
err_str = "reserved command"; if (read_write == ACPI_SBS_SMBUS_READ) {
break; protocol = ACPI_EC_SMB_PRTCL_READ;
case 0x0003: } else {
err_str = "unsupported command"; protocol = ACPI_EC_SMB_PRTCL_WRITE;
break; }
case 0x0004:
err_str = "access denied"; switch (size) {
case ACPI_SBS_WORD_DATA:
acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
if (read_write == ACPI_SBS_SMBUS_WRITE) {
acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA, data->word);
acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + 1,
data->word >> 8);
}
protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA;
break; break;
case 0x0005: case ACPI_SBS_BLOCK_DATA:
err_str = "overflow/underflow"; acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command);
if (read_write == ACPI_SBS_SMBUS_WRITE) {
len = min_t(u8, data->block[0], 32);
acpi_ec_sbs_write(sbs, ACPI_EC_SMB_BCNT, len);
for (i = 0; i < len; i++)
acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + i,
data->block[i + 1]);
}
protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA;
break; break;
case 0x0006: default:
err_str = "bad size"; ACPI_EXCEPTION((AE_INFO, AE_ERROR,
"unsupported transaction %d\n", size));
return (-1);
}
acpi_ec_sbs_write(sbs, ACPI_EC_SMB_ADDR, addr << 1);
acpi_ec_sbs_write(sbs, ACPI_EC_SMB_PRTCL, protocol);
acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
xmsleep(ACPI_EC_SMB_ACCESS_SLEEP1);
acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
}
if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp);
}
if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
|| (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
ACPI_EXCEPTION((AE_INFO, AE_ERROR,
"transaction %d error\n", size));
return (-1);
}
if (read_write == ACPI_SBS_SMBUS_WRITE) {
return (0);
}
switch (size) {
case ACPI_SBS_WORD_DATA:
acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA, temp);
acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + 1, temp + 1);
data->word = (temp[1] << 8) | temp[0];
break; break;
case 0x0007:
err_str = "unknown error"; case ACPI_SBS_BLOCK_DATA:
len = 0;
acpi_ec_sbs_read(sbs, ACPI_EC_SMB_BCNT, &len);
len = min_t(u8, len, 32);
for (i = 0; i < len; i++)
acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + i,
data->block + i + 1);
data->block[0] = len;
break; break;
default: default:
err_str = "unrecognized error"; ACPI_EXCEPTION((AE_INFO, AE_ERROR,
"unsupported transaction %d\n", size));
return (-1);
} }
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"%s: ret %i, err %i\n", err_str, result, err_number)); return (0);
} }
static int static int
acpi_sbs_smbus_read_word(struct acpi_ec_smbus *smbus, int addr, int func, acpi_sbs_read_word(struct acpi_sbs *sbs, int addr, int func, u16 * word)
u16 * word,
void (*err_handler) (struct acpi_ec_smbus * smbus))
{ {
union i2c_smbus_data data; union sbs_rw_data data;
int result = 0; int result = 0;
int i;
if (err_handler == NULL) { result = acpi_ec_sbs_access(sbs, addr,
err_handler = acpi_battery_smbus_err_handler; ACPI_SBS_SMBUS_READ, func,
} ACPI_SBS_WORD_DATA, &data);
if (result) {
for (i = 0; i < MAX_SMBUS_ERR; i++) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
result = "acpi_ec_sbs_access() failed\n"));
smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, } else {
I2C_SMBUS_READ, func, *word = data.word;
I2C_SMBUS_WORD_DATA, &data);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"try %i: smbus->adapter.algo->smbus_xfer() failed\n",
i));
if (err_handler) {
err_handler(smbus);
}
} else {
*word = data.word;
break;
}
} }
return result; return result;
} }
static int static int
acpi_sbs_smbus_read_str(struct acpi_ec_smbus *smbus, int addr, int func, acpi_sbs_read_str(struct acpi_sbs *sbs, int addr, int func, char *str)
char *str,
void (*err_handler) (struct acpi_ec_smbus * smbus))
{ {
union i2c_smbus_data data; union sbs_rw_data data;
int result = 0; int result = 0;
int i;
if (err_handler == NULL) {
err_handler = acpi_battery_smbus_err_handler;
}
for (i = 0; i < MAX_SMBUS_ERR; i++) { result = acpi_ec_sbs_access(sbs, addr,
result = ACPI_SBS_SMBUS_READ, func,
smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, ACPI_SBS_BLOCK_DATA, &data);
I2C_SMBUS_READ, func, if (result) {
I2C_SMBUS_BLOCK_DATA, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
&data); "acpi_ec_sbs_access() failed\n"));
if (result) { } else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, strncpy(str, (const char *)data.block + 1, data.block[0]);
"try %i: smbus->adapter.algo->smbus_xfer() failed\n", str[data.block[0]] = 0;
i));
if (err_handler) {
err_handler(smbus);
}
} else {
strncpy(str, (const char *)data.block + 1,
data.block[0]);
str[data.block[0]] = 0;
break;
}
} }
return result; return result;
} }
static int static int
acpi_sbs_smbus_write_word(struct acpi_ec_smbus *smbus, int addr, int func, acpi_sbs_write_word(struct acpi_sbs *sbs, int addr, int func, int word)
int word,
void (*err_handler) (struct acpi_ec_smbus * smbus))
{ {
union i2c_smbus_data data; union sbs_rw_data data;
int result = 0; int result = 0;
int i;
if (err_handler == NULL) {
err_handler = acpi_battery_smbus_err_handler;
}
data.word = word; data.word = word;
for (i = 0; i < MAX_SMBUS_ERR; i++) { result = acpi_ec_sbs_access(sbs, addr,
result = ACPI_SBS_SMBUS_WRITE, func,
smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, ACPI_SBS_WORD_DATA, &data);
I2C_SMBUS_WRITE, func, if (result) {
I2C_SMBUS_WORD_DATA, &data); ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
if (result) { "acpi_ec_sbs_access() failed\n"));
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"try %i: smbus->adapter.algo"
"->smbus_xfer() failed\n", i));
if (err_handler) {
err_handler(smbus);
}
} else {
break;
}
} }
return result; return result;
...@@ -366,12 +416,11 @@ static int acpi_battery_get_present(struct acpi_battery *battery) ...@@ -366,12 +416,11 @@ static int acpi_battery_get_present(struct acpi_battery *battery)
int result = 0; int result = 0;
int is_present = 0; int is_present = 0;
result = acpi_sbs_smbus_read_word(battery->sbs->smbus, result = acpi_sbs_read_word(battery->sbs,
ACPI_SBSM_SMBUS_ADDR, 0x01, ACPI_SBSM_SMBUS_ADDR, 0x01, &state);
&state, NULL);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed")); "acpi_sbs_read_word() failed"));
} }
if (!result) { if (!result) {
is_present = (state & 0x000f) & (1 << battery->id); is_present = (state & 0x000f) & (1 << battery->id);
...@@ -393,7 +442,7 @@ static int acpi_ac_is_present(struct acpi_sbs *sbs) ...@@ -393,7 +442,7 @@ static int acpi_ac_is_present(struct acpi_sbs *sbs)
static int acpi_battery_select(struct acpi_battery *battery) static int acpi_battery_select(struct acpi_battery *battery)
{ {
struct acpi_ec_smbus *smbus = battery->sbs->smbus; struct acpi_sbs *sbs = battery->sbs;
int result = 0; int result = 0;
s16 state; s16 state;
int foo; int foo;
...@@ -405,21 +454,19 @@ static int acpi_battery_select(struct acpi_battery *battery) ...@@ -405,21 +454,19 @@ static int acpi_battery_select(struct acpi_battery *battery)
* it causes charging to halt on SBSELs */ * it causes charging to halt on SBSELs */
result = result =
acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01, acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, &state);
&state, NULL);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
foo = (state & 0x0fff) | (1 << (battery->id + 12)); foo = (state & 0x0fff) | (1 << (battery->id + 12));
result = result =
acpi_sbs_smbus_write_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01, acpi_sbs_write_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, foo);
foo, NULL);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_write_word() failed\n")); "acpi_sbs_write_word() failed\n"));
goto end; goto end;
} }
} }
...@@ -430,15 +477,14 @@ static int acpi_battery_select(struct acpi_battery *battery) ...@@ -430,15 +477,14 @@ static int acpi_battery_select(struct acpi_battery *battery)
static int acpi_sbsm_get_info(struct acpi_sbs *sbs) static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
{ {
struct acpi_ec_smbus *smbus = sbs->smbus;
int result = 0; int result = 0;
s16 battery_system_info; s16 battery_system_info;
result = acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x04, result = acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x04,
&battery_system_info, NULL); &battery_system_info);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
...@@ -451,53 +497,48 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs) ...@@ -451,53 +497,48 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
static int acpi_battery_get_info(struct acpi_battery *battery) static int acpi_battery_get_info(struct acpi_battery *battery)
{ {
struct acpi_ec_smbus *smbus = battery->sbs->smbus; struct acpi_sbs *sbs = battery->sbs;
int result = 0; int result = 0;
s16 battery_mode; s16 battery_mode;
s16 specification_info; s16 specification_info;
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03,
&battery_mode, &battery_mode);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
battery->info.capacity_mode = (battery_mode & 0x8000) >> 15; battery->info.capacity_mode = (battery_mode & 0x8000) >> 15;
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x10, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x10,
&battery->info.full_charge_capacity, &battery->info.full_charge_capacity);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x18, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x18,
&battery->info.design_capacity, &battery->info.design_capacity);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
goto end; goto end;
} }
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x19, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x19,
&battery->info.design_voltage, &battery->info.design_voltage);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1a, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1a,
&specification_info, &specification_info);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
...@@ -529,37 +570,33 @@ static int acpi_battery_get_info(struct acpi_battery *battery) ...@@ -529,37 +570,33 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
battery->info.ipscale = 1; battery->info.ipscale = 1;
} }
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1c, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1c,
&battery->info.serial_number, &battery->info.serial_number);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
goto end; goto end;
} }
result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x20, result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x20,
battery->info.manufacturer_name, battery->info.manufacturer_name);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_str() failed\n")); "acpi_sbs_read_str() failed\n"));
goto end; goto end;
} }
result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x21, result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x21,
battery->info.device_name, battery->info.device_name);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_str() failed\n")); "acpi_sbs_read_str() failed\n"));
goto end; goto end;
} }
result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x22, result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x22,
battery->info.device_chemistry, battery->info.device_chemistry);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_str() failed\n")); "acpi_sbs_read_str() failed\n"));
goto end; goto end;
} }
...@@ -579,66 +616,60 @@ static void acpi_update_delay(struct acpi_sbs *sbs) ...@@ -579,66 +616,60 @@ static void acpi_update_delay(struct acpi_sbs *sbs)
static int acpi_battery_get_state(struct acpi_battery *battery) static int acpi_battery_get_state(struct acpi_battery *battery)
{ {
struct acpi_ec_smbus *smbus = battery->sbs->smbus; struct acpi_sbs *sbs = battery->sbs;
int result = 0; int result = 0;
acpi_update_delay(battery->sbs); acpi_update_delay(battery->sbs);
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x09, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x09,
&battery->state.voltage, &battery->state.voltage);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
acpi_update_delay(battery->sbs); acpi_update_delay(battery->sbs);
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0a, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0a,
&battery->state.amperage, &battery->state.amperage);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
acpi_update_delay(battery->sbs); acpi_update_delay(battery->sbs);
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0f, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0f,
&battery->state.remaining_capacity, &battery->state.remaining_capacity);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
acpi_update_delay(battery->sbs); acpi_update_delay(battery->sbs);
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x12, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x12,
&battery->state.average_time_to_empty, &battery->state.average_time_to_empty);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
acpi_update_delay(battery->sbs); acpi_update_delay(battery->sbs);
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x13, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x13,
&battery->state.average_time_to_full, &battery->state.average_time_to_full);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
acpi_update_delay(battery->sbs); acpi_update_delay(battery->sbs);
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x16, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x16,
&battery->state.battery_status, &battery->state.battery_status);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
...@@ -650,15 +681,14 @@ static int acpi_battery_get_state(struct acpi_battery *battery) ...@@ -650,15 +681,14 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
static int acpi_battery_get_alarm(struct acpi_battery *battery) static int acpi_battery_get_alarm(struct acpi_battery *battery)
{ {
struct acpi_ec_smbus *smbus = battery->sbs->smbus; struct acpi_sbs *sbs = battery->sbs;
int result = 0; int result = 0;
result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01,
&battery->alarm.remaining_capacity, &battery->alarm.remaining_capacity);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
...@@ -672,7 +702,7 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery) ...@@ -672,7 +702,7 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery)
static int acpi_battery_set_alarm(struct acpi_battery *battery, static int acpi_battery_set_alarm(struct acpi_battery *battery,
unsigned long alarm) unsigned long alarm)
{ {
struct acpi_ec_smbus *smbus = battery->sbs->smbus; struct acpi_sbs *sbs = battery->sbs;
int result = 0; int result = 0;
s16 battery_mode; s16 battery_mode;
int foo; int foo;
...@@ -688,33 +718,29 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery, ...@@ -688,33 +718,29 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
if (alarm > 0) { if (alarm > 0) {
result = result =
acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03, acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03,
&battery_mode, &battery_mode);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
result = result =
acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01,
battery_mode & 0xbfff, battery_mode & 0xbfff);
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_write_word() failed\n")); "acpi_sbs_write_word() failed\n"));
goto end; goto end;
} }
} }
foo = alarm / (battery->info.capacity_mode ? 10 : 1); foo = alarm / (battery->info.capacity_mode ? 10 : 1);
result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, result = acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, foo);
foo,
&acpi_battery_smbus_err_handler);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_write_word() failed\n")); "acpi_sbs_write_word() failed\n"));
goto end; goto end;
} }
...@@ -732,12 +758,11 @@ static int acpi_battery_set_mode(struct acpi_battery *battery) ...@@ -732,12 +758,11 @@ static int acpi_battery_set_mode(struct acpi_battery *battery)
goto end; goto end;
} }
result = acpi_sbs_smbus_read_word(battery->sbs->smbus, result = acpi_sbs_read_word(battery->sbs,
ACPI_SB_SMBUS_ADDR, 0x03, ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
&battery_mode, NULL);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
...@@ -746,21 +771,19 @@ static int acpi_battery_set_mode(struct acpi_battery *battery) ...@@ -746,21 +771,19 @@ static int acpi_battery_set_mode(struct acpi_battery *battery)
} else { } else {
battery_mode |= 0x8000; battery_mode |= 0x8000;
} }
result = acpi_sbs_smbus_write_word(battery->sbs->smbus, result = acpi_sbs_write_word(battery->sbs,
ACPI_SB_SMBUS_ADDR, 0x03, ACPI_SB_SMBUS_ADDR, 0x03, battery_mode);
battery_mode, NULL);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_write_word() failed\n")); "acpi_sbs_write_word() failed\n"));
goto end; goto end;
} }
result = acpi_sbs_smbus_read_word(battery->sbs->smbus, result = acpi_sbs_read_word(battery->sbs,
ACPI_SB_SMBUS_ADDR, 0x03, ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode);
&battery_mode, NULL);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
...@@ -813,16 +836,15 @@ static int acpi_battery_init(struct acpi_battery *battery) ...@@ -813,16 +836,15 @@ static int acpi_battery_init(struct acpi_battery *battery)
static int acpi_ac_get_present(struct acpi_sbs *sbs) static int acpi_ac_get_present(struct acpi_sbs *sbs)
{ {
struct acpi_ec_smbus *smbus = sbs->smbus;
int result = 0; int result = 0;
s16 charger_status; s16 charger_status;
result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x13, result = acpi_sbs_read_word(sbs, ACPI_SBC_SMBUS_ADDR, 0x13,
&charger_status, NULL); &charger_status);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_smbus_read_word() failed\n")); "acpi_sbs_read_word() failed\n"));
goto end; goto end;
} }
...@@ -1567,38 +1589,27 @@ static void acpi_sbs_update_queue(void *data) ...@@ -1567,38 +1589,27 @@ static void acpi_sbs_update_queue(void *data)
static int acpi_sbs_add(struct acpi_device *device) static int acpi_sbs_add(struct acpi_device *device)
{ {
struct acpi_sbs *sbs = NULL; struct acpi_sbs *sbs = NULL;
struct acpi_ec_hc *ec_hc = NULL; int result;
int result, remove_result = 0;
unsigned long sbs_obj; unsigned long sbs_obj;
int id, cnt; int id;
acpi_status status = AE_OK; acpi_status status = AE_OK;
unsigned long val;
status =
acpi_evaluate_integer(device->parent->handle, "_EC", NULL, &val);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n"));
return -EIO;
}
sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
if (!sbs) { if (!sbs) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "kmalloc() failed\n")); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "kmalloc() failed\n"));
return -ENOMEM; return -ENOMEM;
} }
sbs->base = (val & 0xff00ull) >> 8;
cnt = 0;
while (cnt < 10) {
cnt++;
ec_hc = acpi_get_ec_hc(device);
if (ec_hc) {
break;
}
msleep(1000);
}
if (!ec_hc) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_get_ec_hc() failed: "
"NO driver found for EC HC SMBus\n"));
result = -ENODEV;
goto end;
}
sbs->device = device; sbs->device = device;
sbs->smbus = ec_hc->smbus;
strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_SBS_CLASS); strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
...@@ -1669,11 +1680,7 @@ static int acpi_sbs_add(struct acpi_device *device) ...@@ -1669,11 +1680,7 @@ static int acpi_sbs_add(struct acpi_device *device)
end: end:
if (result) { if (result) {
remove_result = acpi_sbs_remove(device, 0); acpi_sbs_remove(device, 0);
if (remove_result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"acpi_sbs_remove() failed\n"));
}
} }
return result; return result;
...@@ -1707,6 +1714,8 @@ int acpi_sbs_remove(struct acpi_device *device, int type) ...@@ -1707,6 +1714,8 @@ int acpi_sbs_remove(struct acpi_device *device, int type)
acpi_ac_remove(sbs); acpi_ac_remove(sbs);
acpi_driver_data(device) = NULL;
kfree(sbs); kfree(sbs);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment