Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Battery driver for a Greybus module. |
| 3 | * |
| 4 | * Copyright 2014 Google Inc. |
Alex Elder | a46e967 | 2014-12-12 12:08:42 -0600 | [diff] [blame] | 5 | * Copyright 2014 Linaro Ltd. |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 6 | * |
| 7 | * Released under the GPLv2 only. |
| 8 | */ |
| 9 | |
| 10 | #include <linux/kernel.h> |
| 11 | #include <linux/module.h> |
| 12 | #include <linux/slab.h> |
| 13 | #include <linux/power_supply.h> |
| 14 | #include "greybus.h" |
| 15 | |
| 16 | struct gb_battery { |
Greg Kroah-Hartman | a549be51 | 2015-05-01 20:41:00 +0200 | [diff] [blame] | 17 | /* |
| 18 | * The power supply api changed in 4.1, so handle both the old |
| 19 | * and new apis in the same driver for now, until this is merged |
| 20 | * upstream, when all of these version checks can be removed. |
| 21 | */ |
Alex Elder | 5c58640 | 2015-05-07 13:00:21 -0500 | [diff] [blame] | 22 | #ifdef DRIVER_OWNS_PSY_STRUCT |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 23 | struct power_supply bat; |
Greg Kroah-Hartman | a549be51 | 2015-05-01 20:41:00 +0200 | [diff] [blame] | 24 | #define to_gb_battery(x) container_of(x, struct gb_battery, bat) |
| 25 | #else |
| 26 | struct power_supply *bat; |
| 27 | struct power_supply_desc desc; |
| 28 | #define to_gb_battery(x) power_supply_get_drvdata(x) |
| 29 | #endif |
Greg Kroah-Hartman | d47aa76 | 2014-09-07 15:54:24 -0700 | [diff] [blame] | 30 | // FIXME |
| 31 | // we will want to keep the battery stats in here as we will be getting |
| 32 | // updates from the SVC "on the fly" so we don't have to always go ask |
| 33 | // the battery for some information. Hopefully... |
Greg Kroah-Hartman | 2bb7eae | 2014-10-20 15:24:57 +0800 | [diff] [blame] | 34 | struct gb_connection *connection; |
| 35 | u8 version_major; |
| 36 | u8 version_minor; |
| 37 | |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 38 | }; |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 39 | |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 40 | /* Version of the Greybus battery protocol we support */ |
| 41 | #define GB_BATTERY_VERSION_MAJOR 0x00 |
| 42 | #define GB_BATTERY_VERSION_MINOR 0x01 |
| 43 | |
| 44 | /* Greybus battery request types */ |
| 45 | #define GB_BATTERY_TYPE_INVALID 0x00 |
| 46 | #define GB_BATTERY_TYPE_PROTOCOL_VERSION 0x01 |
| 47 | #define GB_BATTERY_TYPE_TECHNOLOGY 0x02 |
| 48 | #define GB_BATTERY_TYPE_STATUS 0x03 |
| 49 | #define GB_BATTERY_TYPE_MAX_VOLTAGE 0x04 |
Greg Kroah-Hartman | 6b7dff8 | 2014-12-08 17:45:10 -0500 | [diff] [blame] | 50 | #define GB_BATTERY_TYPE_PERCENT_CAPACITY 0x05 |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 51 | #define GB_BATTERY_TYPE_TEMPERATURE 0x06 |
| 52 | #define GB_BATTERY_TYPE_VOLTAGE 0x07 |
Greg Kroah-Hartman | 6b7dff8 | 2014-12-08 17:45:10 -0500 | [diff] [blame] | 53 | #define GB_BATTERY_TYPE_CURRENT 0x08 |
| 54 | #define GB_BATTERY_TYPE_CAPACITY 0x09 // TODO - POWER_SUPPLY_PROP_CURRENT_MAX |
| 55 | #define GB_BATTERY_TYPE_SHUTDOWN_TEMP 0x0a // TODO - POWER_SUPPLY_PROP_TEMP_ALERT_MAX |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 56 | |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 57 | /* Should match up with battery types in linux/power_supply.h */ |
| 58 | #define GB_BATTERY_TECH_UNKNOWN 0x0000 |
| 59 | #define GB_BATTERY_TECH_NiMH 0x0001 |
| 60 | #define GB_BATTERY_TECH_LION 0x0002 |
| 61 | #define GB_BATTERY_TECH_LIPO 0x0003 |
| 62 | #define GB_BATTERY_TECH_LiFe 0x0004 |
| 63 | #define GB_BATTERY_TECH_NiCd 0x0005 |
| 64 | #define GB_BATTERY_TECH_LiMn 0x0006 |
| 65 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 66 | struct gb_battery_technology_response { |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 67 | __le32 technology; |
| 68 | }; |
| 69 | |
| 70 | /* Should match up with battery status in linux/power_supply.h */ |
| 71 | #define GB_BATTERY_STATUS_UNKNOWN 0x0000 |
| 72 | #define GB_BATTERY_STATUS_CHARGING 0x0001 |
| 73 | #define GB_BATTERY_STATUS_DISCHARGING 0x0002 |
| 74 | #define GB_BATTERY_STATUS_NOT_CHARGING 0x0003 |
| 75 | #define GB_BATTERY_STATUS_FULL 0x0004 |
| 76 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 77 | struct gb_battery_status_response { |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 78 | __le16 battery_status; |
| 79 | }; |
| 80 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 81 | struct gb_battery_max_voltage_response { |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 82 | __le32 max_voltage; |
| 83 | }; |
| 84 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 85 | struct gb_battery_capacity_response { |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 86 | __le32 capacity; |
| 87 | }; |
| 88 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 89 | struct gb_battery_temperature_response { |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 90 | __le32 temperature; |
| 91 | }; |
| 92 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 93 | struct gb_battery_voltage_response { |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 94 | __le32 voltage; |
| 95 | }; |
| 96 | |
Viresh Kumar | 36e79de | 2015-01-21 18:12:36 +0530 | [diff] [blame] | 97 | /* Define get_version() routine */ |
| 98 | define_get_version(gb_battery, BATTERY); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 99 | |
Greg Kroah-Hartman | 43789c3 | 2014-10-20 15:09:49 +0800 | [diff] [blame] | 100 | static int get_tech(struct gb_battery *gb) |
| 101 | { |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 102 | struct gb_battery_technology_response tech_response; |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 103 | u32 technology; |
| 104 | int retval; |
| 105 | |
Greg Kroah-Hartman | d5671a6 | 2014-11-23 17:45:19 -0800 | [diff] [blame] | 106 | retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TECHNOLOGY, |
| 107 | NULL, 0, |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 108 | &tech_response, sizeof(tech_response)); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 109 | if (retval) |
| 110 | return retval; |
| 111 | |
| 112 | /* |
Greg Kroah-Hartman | 0369a45 | 2014-10-21 16:25:13 +0800 | [diff] [blame] | 113 | * Map greybus values to power_supply values. Hopefully these are |
Viresh Kumar | 696e0cc | 2014-11-21 11:26:30 +0530 | [diff] [blame] | 114 | * "identical" which should allow gcc to optimize the code away to |
Greg Kroah-Hartman | 0369a45 | 2014-10-21 16:25:13 +0800 | [diff] [blame] | 115 | * nothing. |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 116 | */ |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 117 | technology = le32_to_cpu(tech_response.technology); |
Greg Kroah-Hartman | 0369a45 | 2014-10-21 16:25:13 +0800 | [diff] [blame] | 118 | switch (technology) { |
| 119 | case GB_BATTERY_TECH_NiMH: |
| 120 | technology = POWER_SUPPLY_TECHNOLOGY_NiMH; |
| 121 | break; |
| 122 | case GB_BATTERY_TECH_LION: |
| 123 | technology = POWER_SUPPLY_TECHNOLOGY_LION; |
| 124 | break; |
| 125 | case GB_BATTERY_TECH_LIPO: |
| 126 | technology = POWER_SUPPLY_TECHNOLOGY_LIPO; |
| 127 | break; |
| 128 | case GB_BATTERY_TECH_LiFe: |
| 129 | technology = POWER_SUPPLY_TECHNOLOGY_LiFe; |
| 130 | break; |
| 131 | case GB_BATTERY_TECH_NiCd: |
| 132 | technology = POWER_SUPPLY_TECHNOLOGY_NiCd; |
| 133 | break; |
| 134 | case GB_BATTERY_TECH_LiMn: |
| 135 | technology = POWER_SUPPLY_TECHNOLOGY_LiMn; |
| 136 | break; |
| 137 | case GB_BATTERY_TECH_UNKNOWN: |
| 138 | default: |
| 139 | technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; |
| 140 | break; |
| 141 | } |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 142 | return technology; |
Greg Kroah-Hartman | 43789c3 | 2014-10-20 15:09:49 +0800 | [diff] [blame] | 143 | } |
| 144 | |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 145 | static int get_status(struct gb_battery *gb) |
| 146 | { |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 147 | struct gb_battery_status_response status_response; |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 148 | u16 battery_status; |
| 149 | int retval; |
| 150 | |
Greg Kroah-Hartman | d5671a6 | 2014-11-23 17:45:19 -0800 | [diff] [blame] | 151 | retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_STATUS, |
| 152 | NULL, 0, |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 153 | &status_response, sizeof(status_response)); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 154 | if (retval) |
| 155 | return retval; |
| 156 | |
| 157 | /* |
Greg Kroah-Hartman | 0369a45 | 2014-10-21 16:25:13 +0800 | [diff] [blame] | 158 | * Map greybus values to power_supply values. Hopefully these are |
Viresh Kumar | 696e0cc | 2014-11-21 11:26:30 +0530 | [diff] [blame] | 159 | * "identical" which should allow gcc to optimize the code away to |
Greg Kroah-Hartman | 0369a45 | 2014-10-21 16:25:13 +0800 | [diff] [blame] | 160 | * nothing. |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 161 | */ |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 162 | battery_status = le16_to_cpu(status_response.battery_status); |
Greg Kroah-Hartman | 0369a45 | 2014-10-21 16:25:13 +0800 | [diff] [blame] | 163 | switch (battery_status) { |
| 164 | case GB_BATTERY_STATUS_CHARGING: |
| 165 | battery_status = POWER_SUPPLY_STATUS_CHARGING; |
| 166 | break; |
| 167 | case GB_BATTERY_STATUS_DISCHARGING: |
| 168 | battery_status = POWER_SUPPLY_STATUS_DISCHARGING; |
| 169 | break; |
| 170 | case GB_BATTERY_STATUS_NOT_CHARGING: |
| 171 | battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING; |
| 172 | break; |
| 173 | case GB_BATTERY_STATUS_FULL: |
| 174 | battery_status = POWER_SUPPLY_STATUS_FULL; |
| 175 | break; |
| 176 | case GB_BATTERY_STATUS_UNKNOWN: |
| 177 | default: |
| 178 | battery_status = POWER_SUPPLY_STATUS_UNKNOWN; |
| 179 | break; |
| 180 | } |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 181 | return battery_status; |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 182 | } |
| 183 | |
Greg Kroah-Hartman | 43789c3 | 2014-10-20 15:09:49 +0800 | [diff] [blame] | 184 | static int get_max_voltage(struct gb_battery *gb) |
| 185 | { |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 186 | struct gb_battery_max_voltage_response volt_response; |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 187 | u32 max_voltage; |
| 188 | int retval; |
| 189 | |
Greg Kroah-Hartman | d5671a6 | 2014-11-23 17:45:19 -0800 | [diff] [blame] | 190 | retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_MAX_VOLTAGE, |
| 191 | NULL, 0, |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 192 | &volt_response, sizeof(volt_response)); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 193 | if (retval) |
| 194 | return retval; |
| 195 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 196 | max_voltage = le32_to_cpu(volt_response.max_voltage); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 197 | return max_voltage; |
Greg Kroah-Hartman | 43789c3 | 2014-10-20 15:09:49 +0800 | [diff] [blame] | 198 | } |
| 199 | |
Greg Kroah-Hartman | 6b7dff8 | 2014-12-08 17:45:10 -0500 | [diff] [blame] | 200 | static int get_percent_capacity(struct gb_battery *gb) |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 201 | { |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 202 | struct gb_battery_capacity_response capacity_response; |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 203 | u32 capacity; |
| 204 | int retval; |
| 205 | |
Greg Kroah-Hartman | 6b7dff8 | 2014-12-08 17:45:10 -0500 | [diff] [blame] | 206 | retval = gb_operation_sync(gb->connection, |
| 207 | GB_BATTERY_TYPE_PERCENT_CAPACITY, |
Greg Kroah-Hartman | d5671a6 | 2014-11-23 17:45:19 -0800 | [diff] [blame] | 208 | NULL, 0, &capacity_response, |
| 209 | sizeof(capacity_response)); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 210 | if (retval) |
| 211 | return retval; |
| 212 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 213 | capacity = le32_to_cpu(capacity_response.capacity); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 214 | return capacity; |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | static int get_temp(struct gb_battery *gb) |
| 218 | { |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 219 | struct gb_battery_temperature_response temp_response; |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 220 | u32 temperature; |
| 221 | int retval; |
| 222 | |
Greg Kroah-Hartman | d5671a6 | 2014-11-23 17:45:19 -0800 | [diff] [blame] | 223 | retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_TEMPERATURE, |
| 224 | NULL, 0, |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 225 | &temp_response, sizeof(temp_response)); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 226 | if (retval) |
| 227 | return retval; |
| 228 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 229 | temperature = le32_to_cpu(temp_response.temperature); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 230 | return temperature; |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | static int get_voltage(struct gb_battery *gb) |
| 234 | { |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 235 | struct gb_battery_voltage_response voltage_response; |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 236 | u32 voltage; |
| 237 | int retval; |
| 238 | |
Greg Kroah-Hartman | d5671a6 | 2014-11-23 17:45:19 -0800 | [diff] [blame] | 239 | retval = gb_operation_sync(gb->connection, GB_BATTERY_TYPE_VOLTAGE, |
| 240 | NULL, 0, |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 241 | &voltage_response, sizeof(voltage_response)); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 242 | if (retval) |
| 243 | return retval; |
| 244 | |
Alex Elder | 0bbfe04 | 2014-11-19 16:29:14 -0600 | [diff] [blame] | 245 | voltage = le32_to_cpu(voltage_response.voltage); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 246 | return voltage; |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 247 | } |
| 248 | |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 249 | static int get_property(struct power_supply *b, |
| 250 | enum power_supply_property psp, |
| 251 | union power_supply_propval *val) |
| 252 | { |
| 253 | struct gb_battery *gb = to_gb_battery(b); |
| 254 | |
| 255 | switch (psp) { |
| 256 | case POWER_SUPPLY_PROP_TECHNOLOGY: |
Greg Kroah-Hartman | 43789c3 | 2014-10-20 15:09:49 +0800 | [diff] [blame] | 257 | val->intval = get_tech(gb); |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 258 | break; |
| 259 | |
| 260 | case POWER_SUPPLY_PROP_STATUS: |
| 261 | val->intval = get_status(gb); |
| 262 | break; |
| 263 | |
| 264 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: |
Greg Kroah-Hartman | 43789c3 | 2014-10-20 15:09:49 +0800 | [diff] [blame] | 265 | val->intval = get_max_voltage(gb); |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 266 | break; |
| 267 | |
| 268 | case POWER_SUPPLY_PROP_CAPACITY: |
Greg Kroah-Hartman | 6b7dff8 | 2014-12-08 17:45:10 -0500 | [diff] [blame] | 269 | val->intval = get_percent_capacity(gb); |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 270 | break; |
| 271 | |
| 272 | case POWER_SUPPLY_PROP_TEMP: |
| 273 | val->intval = get_temp(gb); |
| 274 | break; |
| 275 | |
| 276 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
| 277 | val->intval = get_voltage(gb); |
| 278 | break; |
| 279 | |
| 280 | default: |
| 281 | return -EINVAL; |
| 282 | } |
| 283 | |
| 284 | return 0; |
| 285 | } |
| 286 | |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 287 | // FIXME - verify this list, odds are some can be removed and others added. |
| 288 | static enum power_supply_property battery_props[] = { |
| 289 | POWER_SUPPLY_PROP_TECHNOLOGY, |
| 290 | POWER_SUPPLY_PROP_STATUS, |
| 291 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, |
| 292 | POWER_SUPPLY_PROP_CAPACITY, |
| 293 | POWER_SUPPLY_PROP_TEMP, |
| 294 | POWER_SUPPLY_PROP_VOLTAGE_NOW, |
| 295 | }; |
| 296 | |
Alex Elder | 5c58640 | 2015-05-07 13:00:21 -0500 | [diff] [blame] | 297 | #ifdef DRIVER_OWNS_PSY_STRUCT |
Greg Kroah-Hartman | a549be51 | 2015-05-01 20:41:00 +0200 | [diff] [blame] | 298 | static int init_and_register(struct gb_connection *connection, |
| 299 | struct gb_battery *gb) |
| 300 | { |
Greg Kroah-Hartman | a549be51 | 2015-05-01 20:41:00 +0200 | [diff] [blame] | 301 | // FIXME - get a better (i.e. unique) name |
| 302 | // FIXME - anything else needs to be set? |
| 303 | gb->bat.name = "gb_battery"; |
| 304 | gb->bat.type = POWER_SUPPLY_TYPE_BATTERY; |
| 305 | gb->bat.properties = battery_props; |
| 306 | gb->bat.num_properties = ARRAY_SIZE(battery_props); |
| 307 | gb->bat.get_property = get_property; |
| 308 | |
Alex Elder | 9ade6d3 | 2015-05-07 13:00:20 -0500 | [diff] [blame] | 309 | return power_supply_register(&connection->bundle->intf->dev, &gb->bat); |
Greg Kroah-Hartman | a549be51 | 2015-05-01 20:41:00 +0200 | [diff] [blame] | 310 | } |
| 311 | #else |
| 312 | static int init_and_register(struct gb_connection *connection, |
| 313 | struct gb_battery *gb) |
| 314 | { |
| 315 | struct power_supply_config cfg = {}; |
Greg Kroah-Hartman | a549be51 | 2015-05-01 20:41:00 +0200 | [diff] [blame] | 316 | |
| 317 | cfg.drv_data = gb; |
| 318 | |
| 319 | // FIXME - get a better (i.e. unique) name |
| 320 | // FIXME - anything else needs to be set? |
| 321 | gb->desc.name = "gb_battery"; |
| 322 | gb->desc.type = POWER_SUPPLY_TYPE_BATTERY; |
| 323 | gb->desc.properties = battery_props; |
| 324 | gb->desc.num_properties = ARRAY_SIZE(battery_props); |
| 325 | gb->desc.get_property = get_property; |
| 326 | |
| 327 | gb->bat = power_supply_register(&connection->bundle->intf->dev, |
| 328 | &gb->desc, &cfg); |
Alex Elder | 9ade6d3 | 2015-05-07 13:00:20 -0500 | [diff] [blame] | 329 | if (IS_ERR(gb->bat)) |
| 330 | return PTR_ERR(gb->bat); |
| 331 | |
| 332 | return 0; |
Greg Kroah-Hartman | a549be51 | 2015-05-01 20:41:00 +0200 | [diff] [blame] | 333 | } |
| 334 | #endif |
| 335 | |
Alex Elder | 3689f97 | 2014-10-27 06:04:30 -0500 | [diff] [blame] | 336 | static int gb_battery_connection_init(struct gb_connection *connection) |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 337 | { |
| 338 | struct gb_battery *gb; |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 339 | int retval; |
| 340 | |
| 341 | gb = kzalloc(sizeof(*gb), GFP_KERNEL); |
| 342 | if (!gb) |
| 343 | return -ENOMEM; |
| 344 | |
Greg Kroah-Hartman | 6507cce | 2014-10-27 17:58:54 +0800 | [diff] [blame] | 345 | gb->connection = connection; |
Alex Elder | fb305c3 | 2014-10-20 23:01:03 -0500 | [diff] [blame] | 346 | connection->private = gb; |
Greg Kroah-Hartman | 2bb7eae | 2014-10-20 15:24:57 +0800 | [diff] [blame] | 347 | |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 348 | /* Check the version */ |
| 349 | retval = get_version(gb); |
Alex Elder | 9ade6d3 | 2015-05-07 13:00:20 -0500 | [diff] [blame] | 350 | if (retval) |
| 351 | goto out; |
| 352 | retval = init_and_register(connection, gb); |
| 353 | out: |
| 354 | if (retval) |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 355 | kfree(gb); |
Greg Kroah-Hartman | c0855bf | 2014-10-21 14:31:24 +0800 | [diff] [blame] | 356 | |
Alex Elder | 9ade6d3 | 2015-05-07 13:00:20 -0500 | [diff] [blame] | 357 | return retval; |
Greg Kroah-Hartman | 33ea3a3 | 2014-09-07 15:39:34 -0700 | [diff] [blame] | 358 | } |
| 359 | |
Alex Elder | 3689f97 | 2014-10-27 06:04:30 -0500 | [diff] [blame] | 360 | static void gb_battery_connection_exit(struct gb_connection *connection) |
Alex Elder | 697e55d | 2014-10-20 23:01:04 -0500 | [diff] [blame] | 361 | { |
| 362 | struct gb_battery *gb = connection->private; |
| 363 | |
Alex Elder | 5c58640 | 2015-05-07 13:00:21 -0500 | [diff] [blame] | 364 | #ifdef DRIVER_OWNS_PSY_STRUCT |
Alex Elder | 697e55d | 2014-10-20 23:01:04 -0500 | [diff] [blame] | 365 | power_supply_unregister(&gb->bat); |
Greg Kroah-Hartman | a549be51 | 2015-05-01 20:41:00 +0200 | [diff] [blame] | 366 | #else |
| 367 | power_supply_unregister(gb->bat); |
| 368 | #endif |
Alex Elder | 697e55d | 2014-10-20 23:01:04 -0500 | [diff] [blame] | 369 | kfree(gb); |
| 370 | } |
| 371 | |
Alex Elder | 19d03de | 2014-11-05 16:12:53 -0600 | [diff] [blame] | 372 | static struct gb_protocol battery_protocol = { |
Greg Kroah-Hartman | 7422a1e | 2014-12-24 13:01:45 -0800 | [diff] [blame] | 373 | .name = "battery", |
Alex Elder | 19d03de | 2014-11-05 16:12:53 -0600 | [diff] [blame] | 374 | .id = GREYBUS_PROTOCOL_BATTERY, |
| 375 | .major = 0, |
| 376 | .minor = 1, |
Alex Elder | 5d9fd7e | 2014-11-05 16:12:54 -0600 | [diff] [blame] | 377 | .connection_init = gb_battery_connection_init, |
| 378 | .connection_exit = gb_battery_connection_exit, |
Alex Elder | f8fb05e | 2014-11-05 16:12:55 -0600 | [diff] [blame] | 379 | .request_recv = NULL, /* no incoming requests */ |
Alex Elder | 19d03de | 2014-11-05 16:12:53 -0600 | [diff] [blame] | 380 | }; |
| 381 | |
Greg Kroah-Hartman | 7dd2626 | 2014-12-24 13:01:42 -0800 | [diff] [blame] | 382 | gb_protocol_driver(&battery_protocol); |
Alex Elder | 19d03de | 2014-11-05 16:12:53 -0600 | [diff] [blame] | 383 | |
Greg Kroah-Hartman | 7dd2626 | 2014-12-24 13:01:42 -0800 | [diff] [blame] | 384 | MODULE_LICENSE("GPL v2"); |