root/drivers/power/supply/pmu_battery.c

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

DEFINITIONS

This source file includes following definitions.
  1. pmu_get_ac_prop
  2. pmu_bat_get_model_name
  3. pmu_bat_get_property
  4. pmu_bat_init
  5. pmu_bat_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Battery class driver for Apple PMU
   4  *
   5  *      Copyright © 2006  David Woodhouse <dwmw2@infradead.org>
   6  */
   7 
   8 #include <linux/module.h>
   9 #include <linux/platform_device.h>
  10 #include <linux/err.h>
  11 #include <linux/power_supply.h>
  12 #include <linux/adb.h>
  13 #include <linux/pmu.h>
  14 #include <linux/slab.h>
  15 
  16 static struct pmu_battery_dev {
  17         struct power_supply *bat;
  18         struct power_supply_desc bat_desc;
  19         struct pmu_battery_info *pbi;
  20         char name[16];
  21         int propval;
  22 } *pbats[PMU_MAX_BATTERIES];
  23 
  24 #define to_pmu_battery_dev(x) power_supply_get_drvdata(x)
  25 
  26 /*********************************************************************
  27  *              Power
  28  *********************************************************************/
  29 
  30 static int pmu_get_ac_prop(struct power_supply *psy,
  31                            enum power_supply_property psp,
  32                            union power_supply_propval *val)
  33 {
  34         switch (psp) {
  35         case POWER_SUPPLY_PROP_ONLINE:
  36                 val->intval = (!!(pmu_power_flags & PMU_PWR_AC_PRESENT)) ||
  37                               (pmu_battery_count == 0);
  38                 break;
  39         default:
  40                 return -EINVAL;
  41         }
  42 
  43         return 0;
  44 }
  45 
  46 static enum power_supply_property pmu_ac_props[] = {
  47         POWER_SUPPLY_PROP_ONLINE,
  48 };
  49 
  50 static const struct power_supply_desc pmu_ac_desc = {
  51         .name = "pmu-ac",
  52         .type = POWER_SUPPLY_TYPE_MAINS,
  53         .properties = pmu_ac_props,
  54         .num_properties = ARRAY_SIZE(pmu_ac_props),
  55         .get_property = pmu_get_ac_prop,
  56 };
  57 
  58 static struct power_supply *pmu_ac;
  59 
  60 /*********************************************************************
  61  *              Battery properties
  62  *********************************************************************/
  63 
  64 static char *pmu_batt_types[] = {
  65         "Smart", "Comet", "Hooper", "Unknown"
  66 };
  67 
  68 static char *pmu_bat_get_model_name(struct pmu_battery_info *pbi)
  69 {
  70         switch (pbi->flags & PMU_BATT_TYPE_MASK) {
  71         case PMU_BATT_TYPE_SMART:
  72                 return pmu_batt_types[0];
  73         case PMU_BATT_TYPE_COMET:
  74                 return pmu_batt_types[1];
  75         case PMU_BATT_TYPE_HOOPER:
  76                 return pmu_batt_types[2];
  77         default: break;
  78         }
  79         return pmu_batt_types[3];
  80 }
  81 
  82 static int pmu_bat_get_property(struct power_supply *psy,
  83                                 enum power_supply_property psp,
  84                                 union power_supply_propval *val)
  85 {
  86         struct pmu_battery_dev *pbat = to_pmu_battery_dev(psy);
  87         struct pmu_battery_info *pbi = pbat->pbi;
  88 
  89         switch (psp) {
  90         case POWER_SUPPLY_PROP_STATUS:
  91                 if (pbi->flags & PMU_BATT_CHARGING)
  92                         val->intval = POWER_SUPPLY_STATUS_CHARGING;
  93                 else if (pmu_power_flags & PMU_PWR_AC_PRESENT)
  94                         val->intval = POWER_SUPPLY_STATUS_FULL;
  95                 else
  96                         val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
  97                 break;
  98         case POWER_SUPPLY_PROP_PRESENT:
  99                 val->intval = !!(pbi->flags & PMU_BATT_PRESENT);
 100                 break;
 101         case POWER_SUPPLY_PROP_MODEL_NAME:
 102                 val->strval = pmu_bat_get_model_name(pbi);
 103                 break;
 104         case POWER_SUPPLY_PROP_ENERGY_AVG:
 105                 val->intval = pbi->charge     * 1000; /* mWh -> µWh */
 106                 break;
 107         case POWER_SUPPLY_PROP_ENERGY_FULL:
 108                 val->intval = pbi->max_charge * 1000; /* mWh -> µWh */
 109                 break;
 110         case POWER_SUPPLY_PROP_CURRENT_AVG:
 111                 val->intval = pbi->amperage   * 1000; /* mA -> µA */
 112                 break;
 113         case POWER_SUPPLY_PROP_VOLTAGE_AVG:
 114                 val->intval = pbi->voltage    * 1000; /* mV -> µV */
 115                 break;
 116         case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
 117                 val->intval = pbi->time_remaining;
 118                 break;
 119         default:
 120                 return -EINVAL;
 121         }
 122 
 123         return 0;
 124 }
 125 
 126 static enum power_supply_property pmu_bat_props[] = {
 127         POWER_SUPPLY_PROP_STATUS,
 128         POWER_SUPPLY_PROP_PRESENT,
 129         POWER_SUPPLY_PROP_MODEL_NAME,
 130         POWER_SUPPLY_PROP_ENERGY_AVG,
 131         POWER_SUPPLY_PROP_ENERGY_FULL,
 132         POWER_SUPPLY_PROP_CURRENT_AVG,
 133         POWER_SUPPLY_PROP_VOLTAGE_AVG,
 134         POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
 135 };
 136 
 137 /*********************************************************************
 138  *              Initialisation
 139  *********************************************************************/
 140 
 141 static struct platform_device *bat_pdev;
 142 
 143 static int __init pmu_bat_init(void)
 144 {
 145         int ret = 0;
 146         int i;
 147 
 148         bat_pdev = platform_device_register_simple("pmu-battery",
 149                                                    0, NULL, 0);
 150         if (IS_ERR(bat_pdev)) {
 151                 ret = PTR_ERR(bat_pdev);
 152                 goto pdev_register_failed;
 153         }
 154 
 155         pmu_ac = power_supply_register(&bat_pdev->dev, &pmu_ac_desc, NULL);
 156         if (IS_ERR(pmu_ac)) {
 157                 ret = PTR_ERR(pmu_ac);
 158                 goto ac_register_failed;
 159         }
 160 
 161         for (i = 0; i < pmu_battery_count; i++) {
 162                 struct power_supply_config psy_cfg = {};
 163                 struct pmu_battery_dev *pbat = kzalloc(sizeof(*pbat),
 164                                                        GFP_KERNEL);
 165                 if (!pbat)
 166                         break;
 167 
 168                 sprintf(pbat->name, "PMU_battery_%d", i);
 169                 pbat->bat_desc.name = pbat->name;
 170                 pbat->bat_desc.properties = pmu_bat_props;
 171                 pbat->bat_desc.num_properties = ARRAY_SIZE(pmu_bat_props);
 172                 pbat->bat_desc.get_property = pmu_bat_get_property;
 173                 pbat->pbi = &pmu_batteries[i];
 174                 psy_cfg.drv_data = pbat;
 175 
 176                 pbat->bat = power_supply_register(&bat_pdev->dev,
 177                                                   &pbat->bat_desc,
 178                                                   &psy_cfg);
 179                 if (IS_ERR(pbat->bat)) {
 180                         ret = PTR_ERR(pbat->bat);
 181                         kfree(pbat);
 182                         goto battery_register_failed;
 183                 }
 184                 pbats[i] = pbat;
 185         }
 186 
 187         goto success;
 188 
 189 battery_register_failed:
 190         while (i--) {
 191                 if (!pbats[i])
 192                         continue;
 193                 power_supply_unregister(pbats[i]->bat);
 194                 kfree(pbats[i]);
 195         }
 196         power_supply_unregister(pmu_ac);
 197 ac_register_failed:
 198         platform_device_unregister(bat_pdev);
 199 pdev_register_failed:
 200 success:
 201         return ret;
 202 }
 203 
 204 static void __exit pmu_bat_exit(void)
 205 {
 206         int i;
 207 
 208         for (i = 0; i < PMU_MAX_BATTERIES; i++) {
 209                 if (!pbats[i])
 210                         continue;
 211                 power_supply_unregister(pbats[i]->bat);
 212                 kfree(pbats[i]);
 213         }
 214         power_supply_unregister(pmu_ac);
 215         platform_device_unregister(bat_pdev);
 216 }
 217 
 218 module_init(pmu_bat_init);
 219 module_exit(pmu_bat_exit);
 220 
 221 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
 222 MODULE_LICENSE("GPL");
 223 MODULE_DESCRIPTION("PMU battery driver");

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