greybus: power_supply: convert greybus properties to power supply properties
authorRui Miguel Silva <rui.silva@linaro.org>
Wed, 13 Jul 2016 13:11:20 +0000 (14:11 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Fri, 15 Jul 2016 22:55:41 +0000 (07:55 +0900)
We need to translate greybus properties to power supply core properties,
for that when parsing the properties that were fetch during
configuration we check if there is a match to the running kernel version
and store it in a new field (gb_prop) in the gb_power_supply_prop
struct.

If the corresponding property does not exist in the running
kernel (because of version or vendor specific property) we drop that
property.

A collection of properties that, at this time, may diverge are defined
in the kernel_ver.h to avoid breakage at build time and run time if this
properties are not supported by the kernel.

Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
Reviewed-by: Sandeep Patil <sspatil@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/kernel_ver.h
drivers/staging/greybus/power_supply.c

index 24d5bcd..5d13e36 100644 (file)
@@ -305,6 +305,20 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev)
 #define PSY_HAVE_PUT
 #endif
 
+/*
+ * General power supply properties that could be absent from various reasons,
+ * like kernel versions or vendor specific versions
+ */
+#ifndef POWER_SUPPLY_PROP_VOLTAGE_BOOT
+       #define POWER_SUPPLY_PROP_VOLTAGE_BOOT  -1
+#endif
+#ifndef POWER_SUPPLY_PROP_CURRENT_BOOT
+       #define POWER_SUPPLY_PROP_CURRENT_BOOT  -1
+#endif
+#ifndef POWER_SUPPLY_PROP_CALIBRATE
+       #define POWER_SUPPLY_PROP_CALIBRATE     -1
+#endif
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
 #define SPI_DEV_MODALIAS "spidev"
 #define SPI_NOR_MODALIAS "spi-nor"
index f905c3c..058fd3c 100644 (file)
@@ -18,6 +18,7 @@
 
 struct gb_power_supply_prop {
        enum power_supply_property      prop;
+       u8                              gb_prop;
        int                             val;
        int                             previous_val;
        bool                            is_writeable;
@@ -83,6 +84,210 @@ static const struct gb_power_supply_changes psy_props_changes[] = {
        },
 };
 
+static int get_psp_from_gb_prop(int gb_prop, enum power_supply_property *psp)
+{
+       int prop;
+
+       switch (gb_prop) {
+       case GB_POWER_SUPPLY_PROP_STATUS:
+               prop = POWER_SUPPLY_PROP_STATUS;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_TYPE:
+               prop = POWER_SUPPLY_PROP_CHARGE_TYPE;
+               break;
+       case GB_POWER_SUPPLY_PROP_HEALTH:
+               prop = POWER_SUPPLY_PROP_HEALTH;
+               break;
+       case GB_POWER_SUPPLY_PROP_PRESENT:
+               prop = POWER_SUPPLY_PROP_PRESENT;
+               break;
+       case GB_POWER_SUPPLY_PROP_ONLINE:
+               prop = POWER_SUPPLY_PROP_ONLINE;
+               break;
+       case GB_POWER_SUPPLY_PROP_AUTHENTIC:
+               prop = POWER_SUPPLY_PROP_AUTHENTIC;
+               break;
+       case GB_POWER_SUPPLY_PROP_TECHNOLOGY:
+               prop = POWER_SUPPLY_PROP_TECHNOLOGY;
+               break;
+       case GB_POWER_SUPPLY_PROP_CYCLE_COUNT:
+               prop = POWER_SUPPLY_PROP_CYCLE_COUNT;
+               break;
+       case GB_POWER_SUPPLY_PROP_VOLTAGE_MAX:
+               prop = POWER_SUPPLY_PROP_VOLTAGE_MAX;
+               break;
+       case GB_POWER_SUPPLY_PROP_VOLTAGE_MIN:
+               prop = POWER_SUPPLY_PROP_VOLTAGE_MIN;
+               break;
+       case GB_POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+               prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN;
+               break;
+       case GB_POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+               prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN;
+               break;
+       case GB_POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               prop = POWER_SUPPLY_PROP_VOLTAGE_NOW;
+               break;
+       case GB_POWER_SUPPLY_PROP_VOLTAGE_AVG:
+               prop = POWER_SUPPLY_PROP_VOLTAGE_AVG;
+               break;
+       case GB_POWER_SUPPLY_PROP_VOLTAGE_OCV:
+               prop = POWER_SUPPLY_PROP_VOLTAGE_OCV;
+               break;
+       case GB_POWER_SUPPLY_PROP_VOLTAGE_BOOT:
+               prop = POWER_SUPPLY_PROP_VOLTAGE_BOOT;
+               break;
+       case GB_POWER_SUPPLY_PROP_CURRENT_MAX:
+               prop = POWER_SUPPLY_PROP_CURRENT_MAX;
+               break;
+       case GB_POWER_SUPPLY_PROP_CURRENT_NOW:
+               prop = POWER_SUPPLY_PROP_CURRENT_NOW;
+               break;
+       case GB_POWER_SUPPLY_PROP_CURRENT_AVG:
+               prop = POWER_SUPPLY_PROP_CURRENT_AVG;
+               break;
+       case GB_POWER_SUPPLY_PROP_CURRENT_BOOT:
+               prop = POWER_SUPPLY_PROP_CURRENT_BOOT;
+               break;
+       case GB_POWER_SUPPLY_PROP_POWER_NOW:
+               prop = POWER_SUPPLY_PROP_POWER_NOW;
+               break;
+       case GB_POWER_SUPPLY_PROP_POWER_AVG:
+               prop = POWER_SUPPLY_PROP_POWER_AVG;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+               prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
+               prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_FULL:
+               prop = POWER_SUPPLY_PROP_CHARGE_FULL;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_EMPTY:
+               prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_NOW:
+               prop = POWER_SUPPLY_PROP_CHARGE_NOW;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_AVG:
+               prop = POWER_SUPPLY_PROP_CHARGE_AVG;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_COUNTER:
+               prop = POWER_SUPPLY_PROP_CHARGE_COUNTER;
+               break;
+       case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+               prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT;
+               break;
+       case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+               prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
+               break;
+       case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+               prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE;
+               break;
+       case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+               prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+               prop = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
+               prop = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX;
+               break;
+       case GB_POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+               prop = POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
+               break;
+       case GB_POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+               prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
+               break;
+       case GB_POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN:
+               prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
+               break;
+       case GB_POWER_SUPPLY_PROP_ENERGY_FULL:
+               prop = POWER_SUPPLY_PROP_ENERGY_FULL;
+               break;
+       case GB_POWER_SUPPLY_PROP_ENERGY_EMPTY:
+               prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
+               break;
+       case GB_POWER_SUPPLY_PROP_ENERGY_NOW:
+               prop = POWER_SUPPLY_PROP_ENERGY_NOW;
+               break;
+       case GB_POWER_SUPPLY_PROP_ENERGY_AVG:
+               prop = POWER_SUPPLY_PROP_ENERGY_AVG;
+               break;
+       case GB_POWER_SUPPLY_PROP_CAPACITY:
+               prop = POWER_SUPPLY_PROP_CAPACITY;
+               break;
+       case GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
+               prop = POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN;
+               break;
+       case GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX:
+               prop = POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX;
+               break;
+       case GB_POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+               prop = POWER_SUPPLY_PROP_CAPACITY_LEVEL;
+               break;
+       case GB_POWER_SUPPLY_PROP_TEMP:
+               prop = POWER_SUPPLY_PROP_TEMP;
+               break;
+       case GB_POWER_SUPPLY_PROP_TEMP_MAX:
+               prop = POWER_SUPPLY_PROP_TEMP_MAX;
+               break;
+       case GB_POWER_SUPPLY_PROP_TEMP_MIN:
+               prop = POWER_SUPPLY_PROP_TEMP_MIN;
+               break;
+       case GB_POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+               prop = POWER_SUPPLY_PROP_TEMP_ALERT_MIN;
+               break;
+       case GB_POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+               prop = POWER_SUPPLY_PROP_TEMP_ALERT_MAX;
+               break;
+       case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT:
+               prop = POWER_SUPPLY_PROP_TEMP_AMBIENT;
+               break;
+       case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN:
+               prop = POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN;
+               break;
+       case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX:
+               prop = POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX;
+               break;
+       case GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+               prop = POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW;
+               break;
+       case GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+               prop = POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG;
+               break;
+       case GB_POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
+               prop = POWER_SUPPLY_PROP_TIME_TO_FULL_NOW;
+               break;
+       case GB_POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
+               prop = POWER_SUPPLY_PROP_TIME_TO_FULL_AVG;
+               break;
+       case GB_POWER_SUPPLY_PROP_TYPE:
+               prop = POWER_SUPPLY_PROP_TYPE;
+               break;
+       case GB_POWER_SUPPLY_PROP_SCOPE:
+               prop = POWER_SUPPLY_PROP_SCOPE;
+               break;
+       case GB_POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+               prop = POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT;
+               break;
+       case GB_POWER_SUPPLY_PROP_CALIBRATE:
+               prop = POWER_SUPPLY_PROP_CALIBRATE;
+               break;
+       default:
+               prop = -1;
+               break;
+       }
+
+       if (prop < 0)
+               return prop;
+
+       *psp = (enum power_supply_property)prop;
+
+       return 0;
+}
+
 static struct gb_connection *get_conn_from_psy(struct gb_power_supply *gbpsy)
 {
        return gbpsy->supplies->connection;
@@ -253,8 +458,9 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy)
        struct gb_power_supply_get_property_descriptors_response *resp;
        struct gb_operation *op;
        u8 props_count = gbpsy->properties_count;
+       enum power_supply_property psp;
        int ret;
-       int i;
+       int i, r = 0;
 
        if (props_count == 0)
                return 0;
@@ -276,6 +482,17 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy)
 
        resp = op->response->payload;
 
+       /* validate received properties */
+       for (i = 0; i < props_count; i++) {
+               ret = get_psp_from_gb_prop(resp->props[i].property, &psp);
+               if (ret < 0) {
+                       dev_warn(&connection->bundle->dev,
+                                "greybus property %u it is not supported by this kernel, dropped\n",
+                                resp->props[i].property);
+                       gbpsy->properties_count--;
+               }
+       }
+
        gbpsy->props = kcalloc(gbpsy->properties_count, sizeof(*gbpsy->props),
                              GFP_KERNEL);
        if (!gbpsy->props) {
@@ -290,12 +507,18 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy)
                goto out_put_operation;
        }
 
-       /* Store available properties */
-       for (i = 0; i < gbpsy->properties_count; i++) {
-               gbpsy->props[i].prop = resp->props[i].property;
-               gbpsy->props_raw[i] = resp->props[i].property;
+       /* Store available properties, skip the ones we do not support */
+       for (i = 0; i < props_count; i++) {
+               ret = get_psp_from_gb_prop(resp->props[i].property, &psp);
+               if (ret < 0) {
+                       r++;
+                       continue;
+               }
+               gbpsy->props[i - r].prop = psp;
+               gbpsy->props[i - r].gb_prop = resp->props[i].property;
+               gbpsy->props_raw[i - r] = psp;
                if (resp->props[i].is_writeable)
-                       gbpsy->props[i].is_writeable = true;
+                       gbpsy->props[i - r].is_writeable = true;
        }
 
        /*
@@ -304,6 +527,7 @@ static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy)
         */
        _gb_power_supply_append_props(gbpsy);
 
+       ret = 0;
 out_put_operation:
        gb_operation_put(op);
 
@@ -324,7 +548,7 @@ static int __gb_power_supply_property_update(struct gb_power_supply *gbpsy,
        if (!prop)
                return -EINVAL;
        req.psy_id = gbpsy->id;
-       req.property = (u8)psp;
+       req.property = prop->gb_prop;
 
        ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_GET_PROPERTY,
                                &req, sizeof(req), &resp, sizeof(resp));
@@ -479,8 +703,7 @@ static int gb_power_supply_property_set(struct gb_power_supply *gbpsy,
        if (!prop)
                return -EINVAL;
        req.psy_id = gbpsy->id;
-       req.property = (u8)psp;
-       req.prop_val = cpu_to_le32(val);
+       req.property = prop->gb_prop;
        req.prop_val = cpu_to_le32((s32)val);
 
        ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_SET_PROPERTY,