linux/drivers/macintosh/apm_emu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * APM emulation for PMU-based machines
   4 *
   5 * Copyright 2001 Benjamin Herrenschmidt (benh@kernel.crashing.org)
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/module.h>
  10#include <linux/apm-emulation.h>
  11#include <linux/adb.h>
  12#include <linux/pmu.h>
  13
  14#define APM_CRITICAL            10
  15#define APM_LOW                 30
  16
  17static void pmu_apm_get_power_status(struct apm_power_info *info)
  18{
  19        int percentage = -1;
  20        int batteries = 0;
  21        int time_units = -1;
  22        int real_count = 0;
  23        int i;
  24        char charging = 0;
  25        long charge = -1;
  26        long amperage = 0;
  27        unsigned long btype = 0;
  28
  29        info->battery_status = APM_BATTERY_STATUS_UNKNOWN;
  30        info->battery_flag = APM_BATTERY_FLAG_UNKNOWN;
  31        info->units = APM_UNITS_MINS;
  32
  33        if (pmu_power_flags & PMU_PWR_AC_PRESENT)
  34                info->ac_line_status = APM_AC_ONLINE;
  35        else
  36                info->ac_line_status = APM_AC_OFFLINE;
  37
  38        for (i=0; i<pmu_battery_count; i++) {
  39                if (pmu_batteries[i].flags & PMU_BATT_PRESENT) {
  40                        batteries++;
  41                        if (percentage < 0)
  42                                percentage = 0;
  43                        if (charge < 0)
  44                                charge = 0;
  45                        percentage += (pmu_batteries[i].charge * 100) /
  46                                pmu_batteries[i].max_charge;
  47                        charge += pmu_batteries[i].charge;
  48                        amperage += pmu_batteries[i].amperage;
  49                        if (btype == 0)
  50                                btype = (pmu_batteries[i].flags & PMU_BATT_TYPE_MASK);
  51                        real_count++;
  52                        if ((pmu_batteries[i].flags & PMU_BATT_CHARGING))
  53                                charging++;
  54                }
  55        }
  56        if (batteries == 0)
  57                info->ac_line_status = APM_AC_ONLINE;
  58
  59        if (real_count) {
  60                if (amperage < 0) {
  61                        if (btype == PMU_BATT_TYPE_SMART)
  62                                time_units = (charge * 59) / (amperage * -1);
  63                        else
  64                                time_units = (charge * 16440) / (amperage * -60);
  65                }
  66                percentage /= real_count;
  67                if (charging > 0) {
  68                        info->battery_status = APM_BATTERY_STATUS_CHARGING;
  69                        info->battery_flag = APM_BATTERY_FLAG_CHARGING;
  70                } else if (percentage <= APM_CRITICAL) {
  71                        info->battery_status = APM_BATTERY_STATUS_CRITICAL;
  72                        info->battery_flag = APM_BATTERY_FLAG_CRITICAL;
  73                } else if (percentage <= APM_LOW) {
  74                        info->battery_status = APM_BATTERY_STATUS_LOW;
  75                        info->battery_flag = APM_BATTERY_FLAG_LOW;
  76                } else {
  77                        info->battery_status = APM_BATTERY_STATUS_HIGH;
  78                        info->battery_flag = APM_BATTERY_FLAG_HIGH;
  79                }
  80        }
  81
  82        info->battery_life = percentage;
  83        info->time = time_units;
  84}
  85
  86static int __init apm_emu_init(void)
  87{
  88        apm_get_power_status = pmu_apm_get_power_status;
  89
  90        printk(KERN_INFO "apm_emu: PMU APM Emulation initialized.\n");
  91
  92        return 0;
  93}
  94
  95static void __exit apm_emu_exit(void)
  96{
  97        if (apm_get_power_status == pmu_apm_get_power_status)
  98                apm_get_power_status = NULL;
  99
 100        printk(KERN_INFO "apm_emu: PMU APM Emulation removed.\n");
 101}
 102
 103module_init(apm_emu_init);
 104module_exit(apm_emu_exit);
 105
 106MODULE_AUTHOR("Benjamin Herrenschmidt");
 107MODULE_DESCRIPTION("APM emulation for PowerMac");
 108MODULE_LICENSE("GPL");
 109