linux/drivers/staging/greybus/power_supply.c
<<
>>
Prefs
   1/*
   2 * Power Supply driver for a Greybus module.
   3 *
   4 * Copyright 2014-2015 Google Inc.
   5 * Copyright 2014-2015 Linaro Ltd.
   6 *
   7 * Released under the GPLv2 only.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/power_supply.h>
  13#include <linux/slab.h>
  14
  15#include "greybus.h"
  16
  17#define PROP_MAX 32
  18
  19struct gb_power_supply_prop {
  20        enum power_supply_property      prop;
  21        u8                              gb_prop;
  22        int                             val;
  23        int                             previous_val;
  24        bool                            is_writeable;
  25};
  26
  27struct gb_power_supply {
  28        u8                              id;
  29        bool                            registered;
  30        struct power_supply             *psy;
  31        struct power_supply_desc        desc;
  32        char                            name[64];
  33        struct gb_power_supplies        *supplies;
  34        struct delayed_work             work;
  35        char                            *manufacturer;
  36        char                            *model_name;
  37        char                            *serial_number;
  38        u8                              type;
  39        u8                              properties_count;
  40        u8                              properties_count_str;
  41        unsigned long                   last_update;
  42        u8                              cache_invalid;
  43        unsigned int                    update_interval;
  44        bool                            changed;
  45        struct gb_power_supply_prop     *props;
  46        enum power_supply_property      *props_raw;
  47        bool                            pm_acquired;
  48        struct mutex                    supply_lock;
  49};
  50
  51struct gb_power_supplies {
  52        struct gb_connection    *connection;
  53        u8                      supplies_count;
  54        struct gb_power_supply  *supply;
  55        struct mutex            supplies_lock;
  56};
  57
  58#define to_gb_power_supply(x) power_supply_get_drvdata(x)
  59
  60/*
  61 * General power supply properties that could be absent from various reasons,
  62 * like kernel versions or vendor specific versions
  63 */
  64#ifndef POWER_SUPPLY_PROP_VOLTAGE_BOOT
  65        #define POWER_SUPPLY_PROP_VOLTAGE_BOOT  -1
  66#endif
  67#ifndef POWER_SUPPLY_PROP_CURRENT_BOOT
  68        #define POWER_SUPPLY_PROP_CURRENT_BOOT  -1
  69#endif
  70#ifndef POWER_SUPPLY_PROP_CALIBRATE
  71        #define POWER_SUPPLY_PROP_CALIBRATE     -1
  72#endif
  73
  74/* cache time in milliseconds, if cache_time is set to 0 cache is disable */
  75static unsigned int cache_time = 1000;
  76/*
  77 * update interval initial and maximum value, between the two will
  78 * back-off exponential
  79 */
  80static unsigned int update_interval_init = 1 * HZ;
  81static unsigned int update_interval_max = 30 * HZ;
  82
  83struct gb_power_supply_changes {
  84        enum power_supply_property      prop;
  85        u32                             tolerance_change;
  86        void (*prop_changed)(struct gb_power_supply *gbpsy,
  87                             struct gb_power_supply_prop *prop);
  88};
  89
  90static void gb_power_supply_state_change(struct gb_power_supply *gbpsy,
  91                                         struct gb_power_supply_prop *prop);
  92
  93static const struct gb_power_supply_changes psy_props_changes[] = {
  94        {       .prop                   = GB_POWER_SUPPLY_PROP_STATUS,
  95                .tolerance_change       = 0,
  96                .prop_changed           = gb_power_supply_state_change,
  97        },
  98        {       .prop                   = GB_POWER_SUPPLY_PROP_TEMP,
  99                .tolerance_change       = 500,
 100                .prop_changed           = NULL,
 101        },
 102        {       .prop                   = GB_POWER_SUPPLY_PROP_ONLINE,
 103                .tolerance_change       = 0,
 104                .prop_changed           = NULL,
 105        },
 106};
 107
 108static int get_psp_from_gb_prop(int gb_prop, enum power_supply_property *psp)
 109{
 110        int prop;
 111
 112        switch (gb_prop) {
 113        case GB_POWER_SUPPLY_PROP_STATUS:
 114                prop = POWER_SUPPLY_PROP_STATUS;
 115                break;
 116        case GB_POWER_SUPPLY_PROP_CHARGE_TYPE:
 117                prop = POWER_SUPPLY_PROP_CHARGE_TYPE;
 118                break;
 119        case GB_POWER_SUPPLY_PROP_HEALTH:
 120                prop = POWER_SUPPLY_PROP_HEALTH;
 121                break;
 122        case GB_POWER_SUPPLY_PROP_PRESENT:
 123                prop = POWER_SUPPLY_PROP_PRESENT;
 124                break;
 125        case GB_POWER_SUPPLY_PROP_ONLINE:
 126                prop = POWER_SUPPLY_PROP_ONLINE;
 127                break;
 128        case GB_POWER_SUPPLY_PROP_AUTHENTIC:
 129                prop = POWER_SUPPLY_PROP_AUTHENTIC;
 130                break;
 131        case GB_POWER_SUPPLY_PROP_TECHNOLOGY:
 132                prop = POWER_SUPPLY_PROP_TECHNOLOGY;
 133                break;
 134        case GB_POWER_SUPPLY_PROP_CYCLE_COUNT:
 135                prop = POWER_SUPPLY_PROP_CYCLE_COUNT;
 136                break;
 137        case GB_POWER_SUPPLY_PROP_VOLTAGE_MAX:
 138                prop = POWER_SUPPLY_PROP_VOLTAGE_MAX;
 139                break;
 140        case GB_POWER_SUPPLY_PROP_VOLTAGE_MIN:
 141                prop = POWER_SUPPLY_PROP_VOLTAGE_MIN;
 142                break;
 143        case GB_POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
 144                prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN;
 145                break;
 146        case GB_POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
 147                prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN;
 148                break;
 149        case GB_POWER_SUPPLY_PROP_VOLTAGE_NOW:
 150                prop = POWER_SUPPLY_PROP_VOLTAGE_NOW;
 151                break;
 152        case GB_POWER_SUPPLY_PROP_VOLTAGE_AVG:
 153                prop = POWER_SUPPLY_PROP_VOLTAGE_AVG;
 154                break;
 155        case GB_POWER_SUPPLY_PROP_VOLTAGE_OCV:
 156                prop = POWER_SUPPLY_PROP_VOLTAGE_OCV;
 157                break;
 158        case GB_POWER_SUPPLY_PROP_VOLTAGE_BOOT:
 159                prop = POWER_SUPPLY_PROP_VOLTAGE_BOOT;
 160                break;
 161        case GB_POWER_SUPPLY_PROP_CURRENT_MAX:
 162                prop = POWER_SUPPLY_PROP_CURRENT_MAX;
 163                break;
 164        case GB_POWER_SUPPLY_PROP_CURRENT_NOW:
 165                prop = POWER_SUPPLY_PROP_CURRENT_NOW;
 166                break;
 167        case GB_POWER_SUPPLY_PROP_CURRENT_AVG:
 168                prop = POWER_SUPPLY_PROP_CURRENT_AVG;
 169                break;
 170        case GB_POWER_SUPPLY_PROP_CURRENT_BOOT:
 171                prop = POWER_SUPPLY_PROP_CURRENT_BOOT;
 172                break;
 173        case GB_POWER_SUPPLY_PROP_POWER_NOW:
 174                prop = POWER_SUPPLY_PROP_POWER_NOW;
 175                break;
 176        case GB_POWER_SUPPLY_PROP_POWER_AVG:
 177                prop = POWER_SUPPLY_PROP_POWER_AVG;
 178                break;
 179        case GB_POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 180                prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
 181                break;
 182        case GB_POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
 183                prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
 184                break;
 185        case GB_POWER_SUPPLY_PROP_CHARGE_FULL:
 186                prop = POWER_SUPPLY_PROP_CHARGE_FULL;
 187                break;
 188        case GB_POWER_SUPPLY_PROP_CHARGE_EMPTY:
 189                prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
 190                break;
 191        case GB_POWER_SUPPLY_PROP_CHARGE_NOW:
 192                prop = POWER_SUPPLY_PROP_CHARGE_NOW;
 193                break;
 194        case GB_POWER_SUPPLY_PROP_CHARGE_AVG:
 195                prop = POWER_SUPPLY_PROP_CHARGE_AVG;
 196                break;
 197        case GB_POWER_SUPPLY_PROP_CHARGE_COUNTER:
 198                prop = POWER_SUPPLY_PROP_CHARGE_COUNTER;
 199                break;
 200        case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 201                prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT;
 202                break;
 203        case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 204                prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
 205                break;
 206        case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 207                prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE;
 208                break;
 209        case GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
 210                prop = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX;
 211                break;
 212        case GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
 213                prop = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT;
 214                break;
 215        case GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
 216                prop = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX;
 217                break;
 218        case GB_POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 219                prop = POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
 220                break;
 221        case GB_POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
 222                prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
 223                break;
 224        case GB_POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN:
 225                prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
 226                break;
 227        case GB_POWER_SUPPLY_PROP_ENERGY_FULL:
 228                prop = POWER_SUPPLY_PROP_ENERGY_FULL;
 229                break;
 230        case GB_POWER_SUPPLY_PROP_ENERGY_EMPTY:
 231                prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
 232                break;
 233        case GB_POWER_SUPPLY_PROP_ENERGY_NOW:
 234                prop = POWER_SUPPLY_PROP_ENERGY_NOW;
 235                break;
 236        case GB_POWER_SUPPLY_PROP_ENERGY_AVG:
 237                prop = POWER_SUPPLY_PROP_ENERGY_AVG;
 238                break;
 239        case GB_POWER_SUPPLY_PROP_CAPACITY:
 240                prop = POWER_SUPPLY_PROP_CAPACITY;
 241                break;
 242        case GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
 243                prop = POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN;
 244                break;
 245        case GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX:
 246                prop = POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX;
 247                break;
 248        case GB_POWER_SUPPLY_PROP_CAPACITY_LEVEL:
 249                prop = POWER_SUPPLY_PROP_CAPACITY_LEVEL;
 250                break;
 251        case GB_POWER_SUPPLY_PROP_TEMP:
 252                prop = POWER_SUPPLY_PROP_TEMP;
 253                break;
 254        case GB_POWER_SUPPLY_PROP_TEMP_MAX:
 255                prop = POWER_SUPPLY_PROP_TEMP_MAX;
 256                break;
 257        case GB_POWER_SUPPLY_PROP_TEMP_MIN:
 258                prop = POWER_SUPPLY_PROP_TEMP_MIN;
 259                break;
 260        case GB_POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
 261                prop = POWER_SUPPLY_PROP_TEMP_ALERT_MIN;
 262                break;
 263        case GB_POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
 264                prop = POWER_SUPPLY_PROP_TEMP_ALERT_MAX;
 265                break;
 266        case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT:
 267                prop = POWER_SUPPLY_PROP_TEMP_AMBIENT;
 268                break;
 269        case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN:
 270                prop = POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN;
 271                break;
 272        case GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX:
 273                prop = POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX;
 274                break;
 275        case GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
 276                prop = POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW;
 277                break;
 278        case GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
 279                prop = POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG;
 280                break;
 281        case GB_POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
 282                prop = POWER_SUPPLY_PROP_TIME_TO_FULL_NOW;
 283                break;
 284        case GB_POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
 285                prop = POWER_SUPPLY_PROP_TIME_TO_FULL_AVG;
 286                break;
 287        case GB_POWER_SUPPLY_PROP_TYPE:
 288                prop = POWER_SUPPLY_PROP_TYPE;
 289                break;
 290        case GB_POWER_SUPPLY_PROP_SCOPE:
 291                prop = POWER_SUPPLY_PROP_SCOPE;
 292                break;
 293        case GB_POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
 294                prop = POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT;
 295                break;
 296        case GB_POWER_SUPPLY_PROP_CALIBRATE:
 297                prop = POWER_SUPPLY_PROP_CALIBRATE;
 298                break;
 299        default:
 300                prop = -1;
 301                break;
 302        }
 303
 304        if (prop < 0)
 305                return prop;
 306
 307        *psp = (enum power_supply_property)prop;
 308
 309        return 0;
 310}
 311
 312static struct gb_connection *get_conn_from_psy(struct gb_power_supply *gbpsy)
 313{
 314        return gbpsy->supplies->connection;
 315}
 316
 317static struct gb_power_supply_prop *get_psy_prop(struct gb_power_supply *gbpsy,
 318                                                 enum power_supply_property psp)
 319{
 320        int i;
 321
 322        for (i = 0; i < gbpsy->properties_count; i++)
 323                if (gbpsy->props[i].prop == psp)
 324                        return &gbpsy->props[i];
 325        return NULL;
 326}
 327
 328static int is_psy_prop_writeable(struct gb_power_supply *gbpsy,
 329                                     enum power_supply_property psp)
 330{
 331        struct gb_power_supply_prop *prop;
 332
 333        prop = get_psy_prop(gbpsy, psp);
 334        if (!prop)
 335                return -ENOENT;
 336        return prop->is_writeable ? 1 : 0;
 337}
 338
 339static int is_prop_valint(enum power_supply_property psp)
 340{
 341        return ((psp < POWER_SUPPLY_PROP_MODEL_NAME) ? 1 : 0);
 342}
 343
 344static void next_interval(struct gb_power_supply *gbpsy)
 345{
 346        if (gbpsy->update_interval == update_interval_max)
 347                return;
 348
 349        /* do some exponential back-off in the update interval */
 350        gbpsy->update_interval *= 2;
 351        if (gbpsy->update_interval > update_interval_max)
 352                gbpsy->update_interval = update_interval_max;
 353}
 354
 355static void __gb_power_supply_changed(struct gb_power_supply *gbpsy)
 356{
 357        power_supply_changed(gbpsy->psy);
 358}
 359
 360static void gb_power_supply_state_change(struct gb_power_supply *gbpsy,
 361                                         struct gb_power_supply_prop *prop)
 362{
 363        struct gb_connection *connection = get_conn_from_psy(gbpsy);
 364        int ret;
 365
 366        /*
 367         * Check gbpsy->pm_acquired to make sure only one pair of 'get_sync'
 368         * and 'put_autosuspend' runtime pm call for state property change.
 369         */
 370        mutex_lock(&gbpsy->supply_lock);
 371
 372        if ((prop->val == GB_POWER_SUPPLY_STATUS_CHARGING) &&
 373            !gbpsy->pm_acquired) {
 374                ret = gb_pm_runtime_get_sync(connection->bundle);
 375                if (ret)
 376                        dev_err(&connection->bundle->dev,
 377                                "Fail to set wake lock for charging state\n");
 378                else
 379                        gbpsy->pm_acquired = true;
 380        } else {
 381                if (gbpsy->pm_acquired) {
 382                        ret = gb_pm_runtime_put_autosuspend(connection->bundle);
 383                        if (ret)
 384                                dev_err(&connection->bundle->dev,
 385                                        "Fail to set wake unlock for none charging\n");
 386                        else
 387                                gbpsy->pm_acquired = false;
 388                }
 389        }
 390
 391        mutex_unlock(&gbpsy->supply_lock);
 392}
 393
 394static void check_changed(struct gb_power_supply *gbpsy,
 395                          struct gb_power_supply_prop *prop)
 396{
 397        const struct gb_power_supply_changes *psyc;
 398        int val = prop->val;
 399        int prev_val = prop->previous_val;
 400        bool changed = false;
 401        int i;
 402
 403        for (i = 0; i < ARRAY_SIZE(psy_props_changes); i++) {
 404                psyc = &psy_props_changes[i];
 405                if (prop->prop == psyc->prop) {
 406                        if (!psyc->tolerance_change)
 407                                changed = true;
 408                        else if (val < prev_val &&
 409                                 prev_val - val > psyc->tolerance_change)
 410                                changed = true;
 411                        else if (val > prev_val &&
 412                                 val - prev_val > psyc->tolerance_change)
 413                                changed = true;
 414
 415                        if (changed && psyc->prop_changed)
 416                                psyc->prop_changed(gbpsy, prop);
 417
 418                        if (changed)
 419                                gbpsy->changed = true;
 420                        break;
 421                }
 422        }
 423}
 424
 425static int total_props(struct gb_power_supply *gbpsy)
 426{
 427        /* this return the intval plus the strval properties */
 428        return (gbpsy->properties_count + gbpsy->properties_count_str);
 429}
 430
 431static void prop_append(struct gb_power_supply *gbpsy,
 432                        enum power_supply_property prop)
 433{
 434        enum power_supply_property *new_props_raw;
 435
 436        gbpsy->properties_count_str++;
 437        new_props_raw = krealloc(gbpsy->props_raw, total_props(gbpsy) *
 438                                 sizeof(enum power_supply_property),
 439                                 GFP_KERNEL);
 440        if (!new_props_raw)
 441                return;
 442        gbpsy->props_raw = new_props_raw;
 443        gbpsy->props_raw[total_props(gbpsy) - 1] = prop;
 444}
 445
 446static int __gb_power_supply_set_name(char *init_name, char *name, size_t len)
 447{
 448        unsigned int i = 0;
 449        int ret = 0;
 450        struct power_supply *psy;
 451
 452        if (!strlen(init_name))
 453                init_name = "gb_power_supply";
 454        strlcpy(name, init_name, len);
 455
 456        while ((ret < len) && (psy = power_supply_get_by_name(name))) {
 457                power_supply_put(psy);
 458
 459                ret = snprintf(name, len, "%s_%u", init_name, ++i);
 460        }
 461        if (ret >= len)
 462                return -ENOMEM;
 463        return i;
 464}
 465
 466static void _gb_power_supply_append_props(struct gb_power_supply *gbpsy)
 467{
 468        if (strlen(gbpsy->manufacturer))
 469                prop_append(gbpsy, POWER_SUPPLY_PROP_MANUFACTURER);
 470        if (strlen(gbpsy->model_name))
 471                prop_append(gbpsy, POWER_SUPPLY_PROP_MODEL_NAME);
 472        if (strlen(gbpsy->serial_number))
 473                prop_append(gbpsy, POWER_SUPPLY_PROP_SERIAL_NUMBER);
 474}
 475
 476static int gb_power_supply_description_get(struct gb_power_supply *gbpsy)
 477{
 478        struct gb_connection *connection = get_conn_from_psy(gbpsy);
 479        struct gb_power_supply_get_description_request req;
 480        struct gb_power_supply_get_description_response resp;
 481        int ret;
 482
 483        req.psy_id = gbpsy->id;
 484
 485        ret = gb_operation_sync(connection,
 486                                GB_POWER_SUPPLY_TYPE_GET_DESCRIPTION,
 487                                &req, sizeof(req), &resp, sizeof(resp));
 488        if (ret < 0)
 489                return ret;
 490
 491        gbpsy->manufacturer = kstrndup(resp.manufacturer, PROP_MAX, GFP_KERNEL);
 492        if (!gbpsy->manufacturer)
 493                return -ENOMEM;
 494        gbpsy->model_name = kstrndup(resp.model, PROP_MAX, GFP_KERNEL);
 495        if (!gbpsy->model_name)
 496                return -ENOMEM;
 497        gbpsy->serial_number = kstrndup(resp.serial_number, PROP_MAX,
 498                                       GFP_KERNEL);
 499        if (!gbpsy->serial_number)
 500                return -ENOMEM;
 501
 502        gbpsy->type = le16_to_cpu(resp.type);
 503        gbpsy->properties_count = resp.properties_count;
 504
 505        return 0;
 506}
 507
 508static int gb_power_supply_prop_descriptors_get(struct gb_power_supply *gbpsy)
 509{
 510        struct gb_connection *connection = get_conn_from_psy(gbpsy);
 511        struct gb_power_supply_get_property_descriptors_request *req;
 512        struct gb_power_supply_get_property_descriptors_response *resp;
 513        struct gb_operation *op;
 514        u8 props_count = gbpsy->properties_count;
 515        enum power_supply_property psp;
 516        int ret;
 517        int i, r = 0;
 518
 519        if (props_count == 0)
 520                return 0;
 521
 522        op = gb_operation_create(connection,
 523                                 GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS,
 524                                 sizeof(req), sizeof(*resp) + props_count *
 525                                 sizeof(struct gb_power_supply_props_desc),
 526                                 GFP_KERNEL);
 527        if (!op)
 528                return -ENOMEM;
 529
 530        req = op->request->payload;
 531        req->psy_id = gbpsy->id;
 532
 533        ret = gb_operation_request_send_sync(op);
 534        if (ret < 0)
 535                goto out_put_operation;
 536
 537        resp = op->response->payload;
 538
 539        /* validate received properties */
 540        for (i = 0; i < props_count; i++) {
 541                ret = get_psp_from_gb_prop(resp->props[i].property, &psp);
 542                if (ret < 0) {
 543                        dev_warn(&connection->bundle->dev,
 544                                 "greybus property %u it is not supported by this kernel, dropped\n",
 545                                 resp->props[i].property);
 546                        gbpsy->properties_count--;
 547                }
 548        }
 549
 550        gbpsy->props = kcalloc(gbpsy->properties_count, sizeof(*gbpsy->props),
 551                              GFP_KERNEL);
 552        if (!gbpsy->props) {
 553                ret = -ENOMEM;
 554                goto out_put_operation;
 555        }
 556
 557        gbpsy->props_raw = kcalloc(gbpsy->properties_count,
 558                                   sizeof(*gbpsy->props_raw), GFP_KERNEL);
 559        if (!gbpsy->props_raw) {
 560                ret = -ENOMEM;
 561                goto out_put_operation;
 562        }
 563
 564        /* Store available properties, skip the ones we do not support */
 565        for (i = 0; i < props_count; i++) {
 566                ret = get_psp_from_gb_prop(resp->props[i].property, &psp);
 567                if (ret < 0) {
 568                        r++;
 569                        continue;
 570                }
 571                gbpsy->props[i - r].prop = psp;
 572                gbpsy->props[i - r].gb_prop = resp->props[i].property;
 573                gbpsy->props_raw[i - r] = psp;
 574                if (resp->props[i].is_writeable)
 575                        gbpsy->props[i - r].is_writeable = true;
 576        }
 577
 578        /*
 579         * now append the properties that we already got information in the
 580         * get_description operation. (char * ones)
 581         */
 582        _gb_power_supply_append_props(gbpsy);
 583
 584        ret = 0;
 585out_put_operation:
 586        gb_operation_put(op);
 587
 588        return ret;
 589}
 590
 591static int __gb_power_supply_property_update(struct gb_power_supply *gbpsy,
 592                                             enum power_supply_property psp)
 593{
 594        struct gb_connection *connection = get_conn_from_psy(gbpsy);
 595        struct gb_power_supply_prop *prop;
 596        struct gb_power_supply_get_property_request req;
 597        struct gb_power_supply_get_property_response resp;
 598        int val;
 599        int ret;
 600
 601        prop = get_psy_prop(gbpsy, psp);
 602        if (!prop)
 603                return -EINVAL;
 604        req.psy_id = gbpsy->id;
 605        req.property = prop->gb_prop;
 606
 607        ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_GET_PROPERTY,
 608                                &req, sizeof(req), &resp, sizeof(resp));
 609        if (ret < 0)
 610                return ret;
 611
 612        val = le32_to_cpu(resp.prop_val);
 613        if (val == prop->val)
 614                return 0;
 615
 616        prop->previous_val = prop->val;
 617        prop->val = val;
 618
 619        check_changed(gbpsy, prop);
 620
 621        return 0;
 622}
 623
 624static int __gb_power_supply_property_get(struct gb_power_supply *gbpsy,
 625                                          enum power_supply_property psp,
 626                                          union power_supply_propval *val)
 627{
 628        struct gb_power_supply_prop *prop;
 629
 630        prop = get_psy_prop(gbpsy, psp);
 631        if (!prop)
 632                return -EINVAL;
 633
 634        val->intval = prop->val;
 635        return 0;
 636}
 637
 638static int __gb_power_supply_property_strval_get(struct gb_power_supply *gbpsy,
 639                                                enum power_supply_property psp,
 640                                                union power_supply_propval *val)
 641{
 642        switch (psp) {
 643        case POWER_SUPPLY_PROP_MODEL_NAME:
 644                val->strval = gbpsy->model_name;
 645                break;
 646        case POWER_SUPPLY_PROP_MANUFACTURER:
 647                val->strval = gbpsy->manufacturer;
 648                break;
 649        case POWER_SUPPLY_PROP_SERIAL_NUMBER:
 650                val->strval = gbpsy->serial_number;
 651                break;
 652        default:
 653                break;
 654        }
 655
 656        return 0;
 657}
 658
 659static int _gb_power_supply_property_get(struct gb_power_supply *gbpsy,
 660                                         enum power_supply_property psp,
 661                                         union power_supply_propval *val)
 662{
 663        struct gb_connection *connection = get_conn_from_psy(gbpsy);
 664        int ret;
 665
 666        /*
 667         * Properties of type const char *, were already fetched on
 668         * get_description operation and should be cached in gb
 669         */
 670        if (is_prop_valint(psp))
 671                ret = __gb_power_supply_property_get(gbpsy, psp, val);
 672        else
 673                ret = __gb_power_supply_property_strval_get(gbpsy, psp, val);
 674
 675        if (ret < 0)
 676                dev_err(&connection->bundle->dev, "get property %u\n", psp);
 677
 678        return 0;
 679}
 680
 681static int is_cache_valid(struct gb_power_supply *gbpsy)
 682{
 683        /* check if cache is good enough or it has expired */
 684        if (gbpsy->cache_invalid) {
 685                gbpsy->cache_invalid = 0;
 686                return 0;
 687        }
 688
 689        if (gbpsy->last_update &&
 690            time_is_after_jiffies(gbpsy->last_update +
 691                                  msecs_to_jiffies(cache_time)))
 692                return 1;
 693
 694        return 0;
 695}
 696
 697static int gb_power_supply_status_get(struct gb_power_supply *gbpsy)
 698{
 699        struct gb_connection *connection = get_conn_from_psy(gbpsy);
 700        int ret = 0;
 701        int i;
 702
 703        if (is_cache_valid(gbpsy))
 704                return 0;
 705
 706        ret = gb_pm_runtime_get_sync(connection->bundle);
 707        if (ret)
 708                return ret;
 709
 710        for (i = 0; i < gbpsy->properties_count; i++) {
 711                ret = __gb_power_supply_property_update(gbpsy,
 712                                                        gbpsy->props[i].prop);
 713                if (ret < 0)
 714                        break;
 715        }
 716
 717        if (ret == 0)
 718                gbpsy->last_update = jiffies;
 719
 720        gb_pm_runtime_put_autosuspend(connection->bundle);
 721        return ret;
 722}
 723
 724static void gb_power_supply_status_update(struct gb_power_supply *gbpsy)
 725{
 726        /* check if there a change that need to be reported */
 727        gb_power_supply_status_get(gbpsy);
 728
 729        if (!gbpsy->changed)
 730                return;
 731
 732        gbpsy->update_interval = update_interval_init;
 733        __gb_power_supply_changed(gbpsy);
 734        gbpsy->changed = false;
 735}
 736
 737static void gb_power_supply_work(struct work_struct *work)
 738{
 739        struct gb_power_supply *gbpsy = container_of(work,
 740                                                     struct gb_power_supply,
 741                                                     work.work);
 742
 743        /*
 744         * if the poll interval is not set, disable polling, this is helpful
 745         * specially at unregister time.
 746         */
 747        if (!gbpsy->update_interval)
 748                return;
 749
 750        gb_power_supply_status_update(gbpsy);
 751        next_interval(gbpsy);
 752        schedule_delayed_work(&gbpsy->work, gbpsy->update_interval);
 753}
 754
 755static int get_property(struct power_supply *b,
 756                        enum power_supply_property psp,
 757                        union power_supply_propval *val)
 758{
 759        struct gb_power_supply *gbpsy = to_gb_power_supply(b);
 760
 761        gb_power_supply_status_get(gbpsy);
 762
 763        return _gb_power_supply_property_get(gbpsy, psp, val);
 764}
 765
 766static int gb_power_supply_property_set(struct gb_power_supply *gbpsy,
 767                                        enum power_supply_property psp,
 768                                        int val)
 769{
 770        struct gb_connection *connection = get_conn_from_psy(gbpsy);
 771        struct gb_power_supply_prop *prop;
 772        struct gb_power_supply_set_property_request req;
 773        int ret;
 774
 775        ret = gb_pm_runtime_get_sync(connection->bundle);
 776        if (ret)
 777                return ret;
 778
 779        prop = get_psy_prop(gbpsy, psp);
 780        if (!prop) {
 781                ret = -EINVAL;
 782                goto out;
 783        }
 784
 785        req.psy_id = gbpsy->id;
 786        req.property = prop->gb_prop;
 787        req.prop_val = cpu_to_le32((s32)val);
 788
 789        ret = gb_operation_sync(connection, GB_POWER_SUPPLY_TYPE_SET_PROPERTY,
 790                                &req, sizeof(req), NULL, 0);
 791        if (ret < 0)
 792                goto out;
 793
 794        /* cache immediately the new value */
 795        prop->val = val;
 796
 797out:
 798        gb_pm_runtime_put_autosuspend(connection->bundle);
 799        return ret;
 800}
 801
 802static int set_property(struct power_supply *b,
 803                        enum power_supply_property psp,
 804                        const union power_supply_propval *val)
 805{
 806        struct gb_power_supply *gbpsy = to_gb_power_supply(b);
 807
 808        return gb_power_supply_property_set(gbpsy, psp, val->intval);
 809}
 810
 811static int property_is_writeable(struct power_supply *b,
 812                                 enum power_supply_property psp)
 813{
 814        struct gb_power_supply *gbpsy = to_gb_power_supply(b);
 815
 816        return is_psy_prop_writeable(gbpsy, psp);
 817}
 818
 819static int gb_power_supply_register(struct gb_power_supply *gbpsy)
 820{
 821        struct gb_connection *connection = get_conn_from_psy(gbpsy);
 822        struct power_supply_config cfg = {};
 823
 824        cfg.drv_data = gbpsy;
 825
 826        gbpsy->desc.name                = gbpsy->name;
 827        gbpsy->desc.type                = gbpsy->type;
 828        gbpsy->desc.properties          = gbpsy->props_raw;
 829        gbpsy->desc.num_properties      = total_props(gbpsy);
 830        gbpsy->desc.get_property        = get_property;
 831        gbpsy->desc.set_property        = set_property;
 832        gbpsy->desc.property_is_writeable = property_is_writeable;
 833
 834        gbpsy->psy = power_supply_register(&connection->bundle->dev,
 835                                           &gbpsy->desc, &cfg);
 836        return PTR_ERR_OR_ZERO(gbpsy->psy);
 837}
 838
 839static void _gb_power_supply_free(struct gb_power_supply *gbpsy)
 840{
 841        kfree(gbpsy->serial_number);
 842        kfree(gbpsy->model_name);
 843        kfree(gbpsy->manufacturer);
 844        kfree(gbpsy->props_raw);
 845        kfree(gbpsy->props);
 846}
 847
 848static void _gb_power_supply_release(struct gb_power_supply *gbpsy)
 849{
 850        gbpsy->update_interval = 0;
 851
 852        cancel_delayed_work_sync(&gbpsy->work);
 853
 854        if (gbpsy->registered)
 855                power_supply_unregister(gbpsy->psy);
 856
 857        _gb_power_supply_free(gbpsy);
 858}
 859
 860static void _gb_power_supplies_release(struct gb_power_supplies *supplies)
 861{
 862        int i;
 863
 864        if (!supplies->supply)
 865                return;
 866
 867        mutex_lock(&supplies->supplies_lock);
 868        for (i = 0; i < supplies->supplies_count; i++)
 869                _gb_power_supply_release(&supplies->supply[i]);
 870        kfree(supplies->supply);
 871        mutex_unlock(&supplies->supplies_lock);
 872        kfree(supplies);
 873}
 874
 875static int gb_power_supplies_get_count(struct gb_power_supplies *supplies)
 876{
 877        struct gb_power_supply_get_supplies_response resp;
 878        int ret;
 879
 880        ret = gb_operation_sync(supplies->connection,
 881                                GB_POWER_SUPPLY_TYPE_GET_SUPPLIES,
 882                                NULL, 0, &resp, sizeof(resp));
 883        if (ret < 0)
 884                return ret;
 885
 886        if  (!resp.supplies_count)
 887                return -EINVAL;
 888
 889        supplies->supplies_count = resp.supplies_count;
 890
 891        return ret;
 892}
 893
 894static int gb_power_supply_config(struct gb_power_supplies *supplies, int id)
 895{
 896        struct gb_power_supply *gbpsy = &supplies->supply[id];
 897        int ret;
 898
 899        gbpsy->supplies = supplies;
 900        gbpsy->id = id;
 901
 902        ret = gb_power_supply_description_get(gbpsy);
 903        if (ret < 0)
 904                return ret;
 905
 906        return gb_power_supply_prop_descriptors_get(gbpsy);
 907}
 908
 909static int gb_power_supply_enable(struct gb_power_supply *gbpsy)
 910{
 911        int ret;
 912
 913        /* guarantee that we have an unique name, before register */
 914        ret =  __gb_power_supply_set_name(gbpsy->model_name, gbpsy->name,
 915                                          sizeof(gbpsy->name));
 916        if (ret < 0)
 917                return ret;
 918
 919        mutex_init(&gbpsy->supply_lock);
 920
 921        ret = gb_power_supply_register(gbpsy);
 922        if (ret < 0)
 923                return ret;
 924
 925        gbpsy->update_interval = update_interval_init;
 926        INIT_DELAYED_WORK(&gbpsy->work, gb_power_supply_work);
 927        schedule_delayed_work(&gbpsy->work, 0);
 928
 929        /* everything went fine, mark it for release code to know */
 930        gbpsy->registered = true;
 931
 932        return 0;
 933}
 934
 935static int gb_power_supplies_setup(struct gb_power_supplies *supplies)
 936{
 937        struct gb_connection *connection = supplies->connection;
 938        int ret;
 939        int i;
 940
 941        mutex_lock(&supplies->supplies_lock);
 942
 943        ret = gb_power_supplies_get_count(supplies);
 944        if (ret < 0)
 945                goto out;
 946
 947        supplies->supply = kcalloc(supplies->supplies_count,
 948                                     sizeof(struct gb_power_supply),
 949                                     GFP_KERNEL);
 950
 951        if (!supplies->supply) {
 952                ret = -ENOMEM;
 953                goto out;
 954        }
 955
 956        for (i = 0; i < supplies->supplies_count; i++) {
 957                ret = gb_power_supply_config(supplies, i);
 958                if (ret < 0) {
 959                        dev_err(&connection->bundle->dev,
 960                                "Fail to configure supplies devices\n");
 961                        goto out;
 962                }
 963        }
 964out:
 965        mutex_unlock(&supplies->supplies_lock);
 966        return ret;
 967}
 968
 969static int gb_power_supplies_register(struct gb_power_supplies *supplies)
 970{
 971        struct gb_connection *connection = supplies->connection;
 972        int ret = 0;
 973        int i;
 974
 975        mutex_lock(&supplies->supplies_lock);
 976
 977        for (i = 0; i < supplies->supplies_count; i++) {
 978                ret = gb_power_supply_enable(&supplies->supply[i]);
 979                if (ret < 0) {
 980                        dev_err(&connection->bundle->dev,
 981                                "Fail to enable supplies devices\n");
 982                        break;
 983                }
 984        }
 985
 986        mutex_unlock(&supplies->supplies_lock);
 987        return ret;
 988}
 989
 990static int gb_supplies_request_handler(struct gb_operation *op)
 991{
 992        struct gb_connection *connection = op->connection;
 993        struct gb_power_supplies *supplies = gb_connection_get_data(connection);
 994        struct gb_power_supply *gbpsy;
 995        struct gb_message *request;
 996        struct gb_power_supply_event_request *payload;
 997        u8 psy_id;
 998        u8 event;
 999        int ret = 0;
1000
1001        if (op->type != GB_POWER_SUPPLY_TYPE_EVENT) {
1002                dev_err(&connection->bundle->dev,
1003                        "Unsupported unsolicited event: %u\n", op->type);
1004                return -EINVAL;
1005        }
1006
1007        request = op->request;
1008
1009        if (request->payload_size < sizeof(*payload)) {
1010                dev_err(&connection->bundle->dev,
1011                        "Wrong event size received (%zu < %zu)\n",
1012                        request->payload_size, sizeof(*payload));
1013                return -EINVAL;
1014        }
1015
1016        payload = request->payload;
1017        psy_id = payload->psy_id;
1018        mutex_lock(&supplies->supplies_lock);
1019        if (psy_id >= supplies->supplies_count ||
1020            !supplies->supply[psy_id].registered) {
1021                dev_err(&connection->bundle->dev,
1022                        "Event received for unconfigured power_supply id: %d\n",
1023                        psy_id);
1024                ret = -EINVAL;
1025                goto out_unlock;
1026        }
1027
1028        event = payload->event;
1029        /*
1030         * we will only handle events after setup is done and before release is
1031         * running. For that just check update_interval.
1032         */
1033        gbpsy = &supplies->supply[psy_id];
1034        if (!gbpsy->update_interval) {
1035                ret = -ESHUTDOWN;
1036                goto out_unlock;
1037        }
1038
1039        if (event & GB_POWER_SUPPLY_UPDATE) {
1040                /*
1041                 * we need to make sure we invalidate cache, if not no new
1042                 * values for the properties will be fetch and the all propose
1043                 * of this event is missed
1044                 */
1045                gbpsy->cache_invalid = 1;
1046                gb_power_supply_status_update(gbpsy);
1047        }
1048
1049out_unlock:
1050        mutex_unlock(&supplies->supplies_lock);
1051        return ret;
1052}
1053
1054static int gb_power_supply_probe(struct gb_bundle *bundle,
1055                                 const struct greybus_bundle_id *id)
1056{
1057        struct greybus_descriptor_cport *cport_desc;
1058        struct gb_connection *connection;
1059        struct gb_power_supplies *supplies;
1060        int ret;
1061
1062        if (bundle->num_cports != 1)
1063                return -ENODEV;
1064
1065        cport_desc = &bundle->cport_desc[0];
1066        if (cport_desc->protocol_id != GREYBUS_PROTOCOL_POWER_SUPPLY)
1067                return -ENODEV;
1068
1069        supplies = kzalloc(sizeof(*supplies), GFP_KERNEL);
1070        if (!supplies)
1071                return -ENOMEM;
1072
1073        connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
1074                                          gb_supplies_request_handler);
1075        if (IS_ERR(connection)) {
1076                ret = PTR_ERR(connection);
1077                goto out;
1078        }
1079
1080        supplies->connection = connection;
1081        gb_connection_set_data(connection, supplies);
1082
1083        mutex_init(&supplies->supplies_lock);
1084
1085        greybus_set_drvdata(bundle, supplies);
1086
1087        /* We aren't ready to receive an incoming request yet */
1088        ret = gb_connection_enable_tx(connection);
1089        if (ret)
1090                goto error_connection_destroy;
1091
1092        ret = gb_power_supplies_setup(supplies);
1093        if (ret < 0)
1094                goto error_connection_disable;
1095
1096        /* We are ready to receive an incoming request now, enable RX as well */
1097        ret = gb_connection_enable(connection);
1098        if (ret)
1099                goto error_connection_disable;
1100
1101        ret = gb_power_supplies_register(supplies);
1102        if (ret < 0)
1103                goto error_connection_disable;
1104
1105        gb_pm_runtime_put_autosuspend(bundle);
1106        return 0;
1107
1108error_connection_disable:
1109        gb_connection_disable(connection);
1110error_connection_destroy:
1111        gb_connection_destroy(connection);
1112out:
1113        _gb_power_supplies_release(supplies);
1114        return ret;
1115}
1116
1117static void gb_power_supply_disconnect(struct gb_bundle *bundle)
1118{
1119        struct gb_power_supplies *supplies = greybus_get_drvdata(bundle);
1120
1121        gb_connection_disable(supplies->connection);
1122        gb_connection_destroy(supplies->connection);
1123
1124        _gb_power_supplies_release(supplies);
1125}
1126
1127static const struct greybus_bundle_id gb_power_supply_id_table[] = {
1128        { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) },
1129        { }
1130};
1131MODULE_DEVICE_TABLE(greybus, gb_power_supply_id_table);
1132
1133static struct greybus_driver gb_power_supply_driver = {
1134        .name           = "power_supply",
1135        .probe          = gb_power_supply_probe,
1136        .disconnect     = gb_power_supply_disconnect,
1137        .id_table       = gb_power_supply_id_table,
1138};
1139module_greybus_driver(gb_power_supply_driver);
1140
1141MODULE_LICENSE("GPL v2");
1142