Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * APM emulation for PMU-based machines
0004  *
0005  * Copyright 2001 Benjamin Herrenschmidt (benh@kernel.crashing.org)
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/apm-emulation.h>
0011 #include <linux/adb.h>
0012 #include <linux/pmu.h>
0013 
0014 #define APM_CRITICAL        10
0015 #define APM_LOW         30
0016 
0017 static void pmu_apm_get_power_status(struct apm_power_info *info)
0018 {
0019     int percentage = -1;
0020     int batteries = 0;
0021     int time_units = -1;
0022     int real_count = 0;
0023     int i;
0024     char charging = 0;
0025     long charge = -1;
0026     long amperage = 0;
0027     unsigned long btype = 0;
0028 
0029     info->battery_status = APM_BATTERY_STATUS_UNKNOWN;
0030     info->battery_flag = APM_BATTERY_FLAG_UNKNOWN;
0031     info->units = APM_UNITS_MINS;
0032 
0033     if (pmu_power_flags & PMU_PWR_AC_PRESENT)
0034         info->ac_line_status = APM_AC_ONLINE;
0035     else
0036         info->ac_line_status = APM_AC_OFFLINE;
0037 
0038     for (i=0; i<pmu_battery_count; i++) {
0039         if (pmu_batteries[i].flags & PMU_BATT_PRESENT) {
0040             batteries++;
0041             if (percentage < 0)
0042                 percentage = 0;
0043             if (charge < 0)
0044                 charge = 0;
0045             percentage += (pmu_batteries[i].charge * 100) /
0046                 pmu_batteries[i].max_charge;
0047             charge += pmu_batteries[i].charge;
0048             amperage += pmu_batteries[i].amperage;
0049             if (btype == 0)
0050                 btype = (pmu_batteries[i].flags & PMU_BATT_TYPE_MASK);
0051             real_count++;
0052             if ((pmu_batteries[i].flags & PMU_BATT_CHARGING))
0053                 charging++;
0054         }
0055     }
0056     if (batteries == 0)
0057         info->ac_line_status = APM_AC_ONLINE;
0058 
0059     if (real_count) {
0060         if (amperage < 0) {
0061             if (btype == PMU_BATT_TYPE_SMART)
0062                 time_units = (charge * 59) / (amperage * -1);
0063             else
0064                 time_units = (charge * 16440) / (amperage * -60);
0065         }
0066         percentage /= real_count;
0067         if (charging > 0) {
0068             info->battery_status = APM_BATTERY_STATUS_CHARGING;
0069             info->battery_flag = APM_BATTERY_FLAG_CHARGING;
0070         } else if (percentage <= APM_CRITICAL) {
0071             info->battery_status = APM_BATTERY_STATUS_CRITICAL;
0072             info->battery_flag = APM_BATTERY_FLAG_CRITICAL;
0073         } else if (percentage <= APM_LOW) {
0074             info->battery_status = APM_BATTERY_STATUS_LOW;
0075             info->battery_flag = APM_BATTERY_FLAG_LOW;
0076         } else {
0077             info->battery_status = APM_BATTERY_STATUS_HIGH;
0078             info->battery_flag = APM_BATTERY_FLAG_HIGH;
0079         }
0080     }
0081 
0082     info->battery_life = percentage;
0083     info->time = time_units;
0084 }
0085 
0086 static int __init apm_emu_init(void)
0087 {
0088     apm_get_power_status = pmu_apm_get_power_status;
0089 
0090     printk(KERN_INFO "apm_emu: PMU APM Emulation initialized.\n");
0091 
0092     return 0;
0093 }
0094 
0095 static void __exit apm_emu_exit(void)
0096 {
0097     if (apm_get_power_status == pmu_apm_get_power_status)
0098         apm_get_power_status = NULL;
0099 
0100     printk(KERN_INFO "apm_emu: PMU APM Emulation removed.\n");
0101 }
0102 
0103 module_init(apm_emu_init);
0104 module_exit(apm_emu_exit);
0105 
0106 MODULE_AUTHOR("Benjamin Herrenschmidt");
0107 MODULE_DESCRIPTION("APM emulation for PowerMac");
0108 MODULE_LICENSE("GPL");