Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
cc662399
Commit
cc662399
authored
Oct 21, 2014
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
greybus: Merge branch 'gregkh_work' into master
This pulls in the battery driver work I did there.
parents
98f4ab2d
c0855bfd
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
219 additions
and
12 deletions
+219
-12
drivers/staging/greybus/battery-gb.c
drivers/staging/greybus/battery-gb.c
+219
-12
No files found.
drivers/staging/greybus/battery-gb.c
View file @
cc662399
...
...
@@ -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?
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment