root/drivers/power/supply/wilco-charger.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. psp_val_to_charge_mode
  2. charge_mode_to_psp_val
  3. wilco_charge_get_property
  4. wilco_charge_set_property
  5. wilco_charge_property_is_writeable
  6. wilco_charge_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Charging control driver for the Wilco EC
   4  *
   5  * Copyright 2019 Google LLC
   6  *
   7  * See Documentation/ABI/testing/sysfs-class-power and
   8  * Documentation/ABI/testing/sysfs-class-power-wilco for userspace interface
   9  * and other info.
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/platform_data/wilco-ec.h>
  15 #include <linux/power_supply.h>
  16 
  17 #define DRV_NAME "wilco-charger"
  18 
  19 /* Property IDs and related EC constants */
  20 #define PID_CHARGE_MODE         0x0710
  21 #define PID_CHARGE_LOWER_LIMIT  0x0711
  22 #define PID_CHARGE_UPPER_LIMIT  0x0712
  23 
  24 enum charge_mode {
  25         CHARGE_MODE_STD = 1,    /* Used for Standard */
  26         CHARGE_MODE_EXP = 2,    /* Express Charge, used for Fast */
  27         CHARGE_MODE_AC = 3,     /* Mostly AC use, used for Trickle */
  28         CHARGE_MODE_AUTO = 4,   /* Used for Adaptive */
  29         CHARGE_MODE_CUSTOM = 5, /* Used for Custom */
  30 };
  31 
  32 #define CHARGE_LOWER_LIMIT_MIN  50
  33 #define CHARGE_LOWER_LIMIT_MAX  95
  34 #define CHARGE_UPPER_LIMIT_MIN  55
  35 #define CHARGE_UPPER_LIMIT_MAX  100
  36 
  37 /* Convert from POWER_SUPPLY_PROP_CHARGE_TYPE value to the EC's charge mode */
  38 static int psp_val_to_charge_mode(int psp_val)
  39 {
  40         switch (psp_val) {
  41         case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:
  42                 return CHARGE_MODE_AC;
  43         case POWER_SUPPLY_CHARGE_TYPE_FAST:
  44                 return CHARGE_MODE_EXP;
  45         case POWER_SUPPLY_CHARGE_TYPE_STANDARD:
  46                 return CHARGE_MODE_STD;
  47         case POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE:
  48                 return CHARGE_MODE_AUTO;
  49         case POWER_SUPPLY_CHARGE_TYPE_CUSTOM:
  50                 return CHARGE_MODE_CUSTOM;
  51         default:
  52                 return -EINVAL;
  53         }
  54 }
  55 
  56 /* Convert from EC's charge mode to POWER_SUPPLY_PROP_CHARGE_TYPE value */
  57 static int charge_mode_to_psp_val(enum charge_mode mode)
  58 {
  59         switch (mode) {
  60         case CHARGE_MODE_AC:
  61                 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
  62         case CHARGE_MODE_EXP:
  63                 return POWER_SUPPLY_CHARGE_TYPE_FAST;
  64         case CHARGE_MODE_STD:
  65                 return POWER_SUPPLY_CHARGE_TYPE_STANDARD;
  66         case CHARGE_MODE_AUTO:
  67                 return POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE;
  68         case CHARGE_MODE_CUSTOM:
  69                 return POWER_SUPPLY_CHARGE_TYPE_CUSTOM;
  70         default:
  71                 return -EINVAL;
  72         }
  73 }
  74 
  75 static enum power_supply_property wilco_charge_props[] = {
  76         POWER_SUPPLY_PROP_CHARGE_TYPE,
  77         POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD,
  78         POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD,
  79 };
  80 
  81 static int wilco_charge_get_property(struct power_supply *psy,
  82                                      enum power_supply_property psp,
  83                                      union power_supply_propval *val)
  84 {
  85         struct wilco_ec_device *ec = power_supply_get_drvdata(psy);
  86         u32 property_id;
  87         int ret;
  88         u8 raw;
  89 
  90         switch (psp) {
  91         case POWER_SUPPLY_PROP_CHARGE_TYPE:
  92                 property_id = PID_CHARGE_MODE;
  93                 break;
  94         case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
  95                 property_id = PID_CHARGE_LOWER_LIMIT;
  96                 break;
  97         case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
  98                 property_id = PID_CHARGE_UPPER_LIMIT;
  99                 break;
 100         default:
 101                 return -EINVAL;
 102         }
 103 
 104         ret = wilco_ec_get_byte_property(ec, property_id, &raw);
 105         if (ret < 0)
 106                 return ret;
 107         if (property_id == PID_CHARGE_MODE) {
 108                 ret = charge_mode_to_psp_val(raw);
 109                 if (ret < 0)
 110                         return -EBADMSG;
 111                 raw = ret;
 112         }
 113         val->intval = raw;
 114 
 115         return 0;
 116 }
 117 
 118 static int wilco_charge_set_property(struct power_supply *psy,
 119                                      enum power_supply_property psp,
 120                                      const union power_supply_propval *val)
 121 {
 122         struct wilco_ec_device *ec = power_supply_get_drvdata(psy);
 123         int mode;
 124 
 125         switch (psp) {
 126         case POWER_SUPPLY_PROP_CHARGE_TYPE:
 127                 mode = psp_val_to_charge_mode(val->intval);
 128                 if (mode < 0)
 129                         return -EINVAL;
 130                 return wilco_ec_set_byte_property(ec, PID_CHARGE_MODE, mode);
 131         case POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD:
 132                 if (val->intval < CHARGE_LOWER_LIMIT_MIN ||
 133                     val->intval > CHARGE_LOWER_LIMIT_MAX)
 134                         return -EINVAL;
 135                 return wilco_ec_set_byte_property(ec, PID_CHARGE_LOWER_LIMIT,
 136                                                   val->intval);
 137         case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
 138                 if (val->intval < CHARGE_UPPER_LIMIT_MIN ||
 139                     val->intval > CHARGE_UPPER_LIMIT_MAX)
 140                         return -EINVAL;
 141                 return wilco_ec_set_byte_property(ec, PID_CHARGE_UPPER_LIMIT,
 142                                                   val->intval);
 143         default:
 144                 return -EINVAL;
 145         }
 146 }
 147 
 148 static int wilco_charge_property_is_writeable(struct power_supply *psy,
 149                                               enum power_supply_property psp)
 150 {
 151         return 1;
 152 }
 153 
 154 static const struct power_supply_desc wilco_ps_desc = {
 155         .properties             = wilco_charge_props,
 156         .num_properties         = ARRAY_SIZE(wilco_charge_props),
 157         .get_property           = wilco_charge_get_property,
 158         .set_property           = wilco_charge_set_property,
 159         .property_is_writeable  = wilco_charge_property_is_writeable,
 160         .name                   = DRV_NAME,
 161         .type                   = POWER_SUPPLY_TYPE_MAINS,
 162 };
 163 
 164 static int wilco_charge_probe(struct platform_device *pdev)
 165 {
 166         struct wilco_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
 167         struct power_supply_config psy_cfg = {};
 168         struct power_supply *psy;
 169 
 170         psy_cfg.drv_data = ec;
 171         psy = devm_power_supply_register(&pdev->dev, &wilco_ps_desc, &psy_cfg);
 172 
 173         return PTR_ERR_OR_ZERO(psy);
 174 }
 175 
 176 static struct platform_driver wilco_charge_driver = {
 177         .probe  = wilco_charge_probe,
 178         .driver = {
 179                 .name = DRV_NAME,
 180         }
 181 };
 182 module_platform_driver(wilco_charge_driver);
 183 
 184 MODULE_ALIAS("platform:" DRV_NAME);
 185 MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>");
 186 MODULE_LICENSE("GPL v2");
 187 MODULE_DESCRIPTION("Wilco EC charge control driver");

/* [<][>][^][v][top][bottom][index][help] */