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