mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-27 23:35:03 +07:00
greybus: Merge branch 'gregkh_work' into master
This pulls in the battery driver work I did there.
This commit is contained in:
commit
cc662399dc
@ -25,45 +25,245 @@ struct gb_battery {
|
||||
};
|
||||
#define to_gb_battery(x) container_of(x, struct gb_battery, bat)
|
||||
|
||||
/* Version of the Greybus battery protocol we support */
|
||||
#define GB_BATTERY_VERSION_MAJOR 0x00
|
||||
#define GB_BATTERY_VERSION_MINOR 0x01
|
||||
|
||||
/* Greybus battery request types */
|
||||
#define GB_BATTERY_TYPE_INVALID 0x00
|
||||
#define GB_BATTERY_TYPE_PROTOCOL_VERSION 0x01
|
||||
#define GB_BATTERY_TYPE_TECHNOLOGY 0x02
|
||||
#define GB_BATTERY_TYPE_STATUS 0x03
|
||||
#define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04
|
||||
#define GB_BATTERY_TYPE_CAPACITY 0x05
|
||||
#define GB_BATTERY_TYPE_TEMPERATURE 0x06
|
||||
#define GB_BATTERY_TYPE_VOLTAGE 0x07
|
||||
|
||||
struct gb_battery_proto_version_response {
|
||||
__u8 status;
|
||||
__u8 major;
|
||||
__u8 minor;
|
||||
};
|
||||
|
||||
/* Should match up with battery types in linux/power_supply.h */
|
||||
#define GB_BATTERY_TECH_UNKNOWN 0x0000
|
||||
#define GB_BATTERY_TECH_NiMH 0x0001
|
||||
#define GB_BATTERY_TECH_LION 0x0002
|
||||
#define GB_BATTERY_TECH_LIPO 0x0003
|
||||
#define GB_BATTERY_TECH_LiFe 0x0004
|
||||
#define GB_BATTERY_TECH_NiCd 0x0005
|
||||
#define GB_BATTERY_TECH_LiMn 0x0006
|
||||
|
||||
struct gb_battery_technology_request {
|
||||
__u8 status;
|
||||
__le32 technology;
|
||||
};
|
||||
|
||||
/* Should match up with battery status in linux/power_supply.h */
|
||||
#define GB_BATTERY_STATUS_UNKNOWN 0x0000
|
||||
#define GB_BATTERY_STATUS_CHARGING 0x0001
|
||||
#define GB_BATTERY_STATUS_DISCHARGING 0x0002
|
||||
#define GB_BATTERY_STATUS_NOT_CHARGING 0x0003
|
||||
#define GB_BATTERY_STATUS_FULL 0x0004
|
||||
|
||||
struct gb_battery_status_request {
|
||||
__u8 status;
|
||||
__le16 battery_status;
|
||||
};
|
||||
|
||||
struct gb_battery_max_voltage_request {
|
||||
__u8 status;
|
||||
__le32 max_voltage;
|
||||
};
|
||||
|
||||
struct gb_battery_capacity_request {
|
||||
__u8 status;
|
||||
__le32 capacity;
|
||||
};
|
||||
|
||||
struct gb_battery_temperature_request {
|
||||
__u8 status;
|
||||
__le32 temperature;
|
||||
};
|
||||
|
||||
struct gb_battery_voltage_request {
|
||||
__u8 status;
|
||||
__le32 voltage;
|
||||
};
|
||||
|
||||
|
||||
static const struct greybus_module_id id_table[] = {
|
||||
{ GREYBUS_DEVICE(0x42, 0x42) }, /* make shit up */
|
||||
{ }, /* terminating NULL entry */
|
||||
};
|
||||
|
||||
static int battery_operation(struct gb_battery *gb, int type,
|
||||
void *response, int response_size)
|
||||
{
|
||||
struct gb_connection *connection = gb->connection;
|
||||
struct gb_operation *operation;
|
||||
struct gb_battery_technology_request *fake_request;
|
||||
u8 *local_response;
|
||||
int ret;
|
||||
|
||||
local_response = kmalloc(response_size, GFP_KERNEL);
|
||||
if (!local_response)
|
||||
return -ENOMEM;
|
||||
|
||||
operation = gb_operation_create(connection, type, 0, response_size);
|
||||
if (!operation) {
|
||||
kfree(local_response);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Synchronous operation--no callback */
|
||||
ret = gb_operation_request_send(operation, NULL);
|
||||
if (ret) {
|
||||
pr_err("version operation failed (%d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We only want to look at the status, and all requests have the same
|
||||
* layout for where the status is, so cast this to a random request so
|
||||
* we can see the status easier.
|
||||
*/
|
||||
fake_request = (struct gb_battery_technology_request *)local_response;
|
||||
if (fake_request->status) {
|
||||
gb_connection_err(connection, "version response %hhu",
|
||||
fake_request->status);
|
||||
ret = -EIO;
|
||||
} else {
|
||||
/* Good request, so copy to the caller's buffer */
|
||||
memcpy(response, local_response, response_size);
|
||||
}
|
||||
out:
|
||||
gb_operation_destroy(operation);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This request only uses the connection field, and if successful,
|
||||
* fills in the major and minor protocol version of the target.
|
||||
*/
|
||||
static int get_version(struct gb_battery *gb)
|
||||
{
|
||||
struct gb_battery_proto_version_response version_request;
|
||||
int retval;
|
||||
|
||||
retval = battery_operation(gb, GB_BATTERY_TYPE_PROTOCOL_VERSION,
|
||||
&version_request, sizeof(version_request));
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (version_request.major > GB_BATTERY_VERSION_MAJOR) {
|
||||
pr_err("unsupported major version (%hhu > %hhu)\n",
|
||||
version_request.major, GB_BATTERY_VERSION_MAJOR);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
gb->version_major = version_request.major;
|
||||
gb->version_minor = version_request.minor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_tech(struct gb_battery *gb)
|
||||
{
|
||||
// FIXME - guess!
|
||||
return POWER_SUPPLY_TECHNOLOGY_NiMH;
|
||||
struct gb_battery_technology_request tech_request;
|
||||
u32 technology;
|
||||
int retval;
|
||||
|
||||
retval = battery_operation(gb, GB_BATTERY_TYPE_TECHNOLOGY,
|
||||
&tech_request, sizeof(tech_request));
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* We have a one-to-one mapping of tech types to power_supply
|
||||
* status, so just return that value.
|
||||
*/
|
||||
technology = le32_to_cpu(tech_request.technology);
|
||||
return technology;
|
||||
}
|
||||
|
||||
static int get_status(struct gb_battery *gb)
|
||||
{
|
||||
// FIXME!!!
|
||||
return 0;
|
||||
struct gb_battery_status_request status_request;
|
||||
u16 battery_status;
|
||||
int retval;
|
||||
|
||||
retval = battery_operation(gb, GB_BATTERY_TYPE_STATUS,
|
||||
&status_request, sizeof(status_request));
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* We have a one-to-one mapping of battery status to power_supply
|
||||
* status, so just return that value.
|
||||
*/
|
||||
battery_status = le16_to_cpu(status_request.battery_status);
|
||||
return battery_status;
|
||||
}
|
||||
|
||||
static int get_max_voltage(struct gb_battery *gb)
|
||||
{
|
||||
// FIXME!!!
|
||||
return 4700000;
|
||||
struct gb_battery_max_voltage_request volt_request;
|
||||
u32 max_voltage;
|
||||
int retval;
|
||||
|
||||
retval = battery_operation(gb, GB_BATTERY_TYPE_MAX_VOLTAGE,
|
||||
&volt_request, sizeof(volt_request));
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
max_voltage = le32_to_cpu(volt_request.max_voltage);
|
||||
return max_voltage;
|
||||
}
|
||||
|
||||
static int get_capacity(struct gb_battery *gb)
|
||||
{
|
||||
// FIXME!!!
|
||||
return 0;
|
||||
struct gb_battery_capacity_request capacity_request;
|
||||
u32 capacity;
|
||||
int retval;
|
||||
|
||||
retval = battery_operation(gb, GB_BATTERY_TYPE_CAPACITY,
|
||||
&capacity_request, sizeof(capacity_request));
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
capacity = le32_to_cpu(capacity_request.capacity);
|
||||
return capacity;
|
||||
}
|
||||
|
||||
static int get_temp(struct gb_battery *gb)
|
||||
{
|
||||
// FIXME!!!
|
||||
return 0;
|
||||
struct gb_battery_temperature_request temp_request;
|
||||
u32 temperature;
|
||||
int retval;
|
||||
|
||||
retval = battery_operation(gb, GB_BATTERY_TYPE_TEMPERATURE,
|
||||
&temp_request, sizeof(temp_request));
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
temperature = le32_to_cpu(temp_request.temperature);
|
||||
return temperature;
|
||||
}
|
||||
|
||||
static int get_voltage(struct gb_battery *gb)
|
||||
{
|
||||
// FIXME!!!
|
||||
return 0;
|
||||
struct gb_battery_voltage_request voltage_request;
|
||||
u32 voltage;
|
||||
int retval;
|
||||
|
||||
retval = battery_operation(gb, GB_BATTERY_TYPE_VOLTAGE,
|
||||
&voltage_request, sizeof(voltage_request));
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
voltage = le32_to_cpu(voltage_request.voltage);
|
||||
return voltage;
|
||||
}
|
||||
|
||||
static int get_property(struct power_supply *b,
|
||||
@ -127,6 +327,13 @@ int gb_battery_device_init(struct gb_connection *connection)
|
||||
gb->connection = connection; // FIXME refcount!
|
||||
connection->private = gb;
|
||||
|
||||
/* Check the version */
|
||||
retval = get_version(gb);
|
||||
if (retval) {
|
||||
kfree(gb);
|
||||
return retval;
|
||||
}
|
||||
|
||||
b = &gb->bat;
|
||||
// FIXME - get a better (i.e. unique) name
|
||||
// FIXME - anything else needs to be set?
|
||||
|
Loading…
Reference in New Issue
Block a user