2019-05-23 12:14:55 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2007-03-19 21:18:02 +03:00
/*
* APM emulation for PMU - based machines
2005-04-17 02:20:36 +04:00
*
2007-03-19 21:18:02 +03:00
* Copyright 2001 Benjamin Herrenschmidt ( benh @ kernel . crashing . org )
2005-04-17 02:20:36 +04:00
*/
# include <linux/kernel.h>
2007-03-19 21:18:02 +03:00
# include <linux/module.h>
# include <linux/apm-emulation.h>
2005-04-17 02:20:36 +04:00
# include <linux/adb.h>
# include <linux/pmu.h>
# define APM_CRITICAL 10
# define APM_LOW 30
2007-03-19 21:18:02 +03:00
static void pmu_apm_get_power_status ( struct apm_power_info * info )
2005-04-17 02:20:36 +04:00
{
2007-03-19 21:18:02 +03:00
int percentage = - 1 ;
int batteries = 0 ;
int time_units = - 1 ;
int real_count = 0 ;
int i ;
char charging = 0 ;
long charge = - 1 ;
long amperage = 0 ;
unsigned long btype = 0 ;
info - > battery_status = APM_BATTERY_STATUS_UNKNOWN ;
info - > battery_flag = APM_BATTERY_FLAG_UNKNOWN ;
info - > units = APM_UNITS_MINS ;
if ( pmu_power_flags & PMU_PWR_AC_PRESENT )
info - > ac_line_status = APM_AC_ONLINE ;
else
info - > ac_line_status = APM_AC_OFFLINE ;
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < pmu_battery_count ; i + + ) {
if ( pmu_batteries [ i ] . flags & PMU_BATT_PRESENT ) {
2007-03-19 21:18:02 +03:00
batteries + + ;
2005-04-17 02:20:36 +04:00
if ( percentage < 0 )
percentage = 0 ;
if ( charge < 0 )
charge = 0 ;
percentage + = ( pmu_batteries [ i ] . charge * 100 ) /
pmu_batteries [ i ] . max_charge ;
charge + = pmu_batteries [ i ] . charge ;
amperage + = pmu_batteries [ i ] . amperage ;
if ( btype = = 0 )
btype = ( pmu_batteries [ i ] . flags & PMU_BATT_TYPE_MASK ) ;
real_count + + ;
if ( ( pmu_batteries [ i ] . flags & PMU_BATT_CHARGING ) )
charging + + ;
}
}
2007-03-19 21:18:02 +03:00
if ( batteries = = 0 )
info - > ac_line_status = APM_AC_ONLINE ;
2005-04-17 02:20:36 +04:00
if ( real_count ) {
if ( amperage < 0 ) {
if ( btype = = PMU_BATT_TYPE_SMART )
time_units = ( charge * 59 ) / ( amperage * - 1 ) ;
else
time_units = ( charge * 16440 ) / ( amperage * - 60 ) ;
}
percentage / = real_count ;
if ( charging > 0 ) {
2007-03-19 21:18:02 +03:00
info - > battery_status = APM_BATTERY_STATUS_CHARGING ;
info - > battery_flag = APM_BATTERY_FLAG_CHARGING ;
2005-04-17 02:20:36 +04:00
} else if ( percentage < = APM_CRITICAL ) {
2007-03-19 21:18:02 +03:00
info - > battery_status = APM_BATTERY_STATUS_CRITICAL ;
info - > battery_flag = APM_BATTERY_FLAG_CRITICAL ;
2005-04-17 02:20:36 +04:00
} else if ( percentage < = APM_LOW ) {
2007-03-19 21:18:02 +03:00
info - > battery_status = APM_BATTERY_STATUS_LOW ;
info - > battery_flag = APM_BATTERY_FLAG_LOW ;
2005-04-17 02:20:36 +04:00
} else {
2007-03-19 21:18:02 +03:00
info - > battery_status = APM_BATTERY_STATUS_HIGH ;
info - > battery_flag = APM_BATTERY_FLAG_HIGH ;
2005-04-17 02:20:36 +04:00
}
}
2007-03-19 21:18:02 +03:00
info - > battery_life = percentage ;
info - > time = time_units ;
2005-04-17 02:20:36 +04:00
}
static int __init apm_emu_init ( void )
{
2007-03-19 21:18:02 +03:00
apm_get_power_status = pmu_apm_get_power_status ;
2005-04-17 02:20:36 +04:00
2007-03-19 21:18:02 +03:00
printk ( KERN_INFO " apm_emu: PMU APM Emulation initialized. \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static void __exit apm_emu_exit ( void )
{
2007-03-19 21:18:02 +03:00
if ( apm_get_power_status = = pmu_apm_get_power_status )
apm_get_power_status = NULL ;
2005-04-17 02:20:36 +04:00
2007-03-19 21:18:02 +03:00
printk ( KERN_INFO " apm_emu: PMU APM Emulation removed. \n " ) ;
2005-04-17 02:20:36 +04:00
}
module_init ( apm_emu_init ) ;
module_exit ( apm_emu_exit ) ;
MODULE_AUTHOR ( " Benjamin Herrenschmidt " ) ;
2007-03-19 21:18:02 +03:00
MODULE_DESCRIPTION ( " APM emulation for PowerMac " ) ;
2005-04-17 02:20:36 +04:00
MODULE_LICENSE ( " GPL " ) ;