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