1 // SPDX-License-Identifier: GPL-2.0
3 * bios-less APM driver for hp680
5 * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
6 * Copyright 2008 (c) Kristoffer Ericson <kristoffer.ericson@gmail.com>
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/interrupt.h>
12 #include <linux/apm-emulation.h>
15 #include <mach/hp6xx.h>
17 /* percentage values */
18 #define APM_CRITICAL 10
21 /* resonably sane values */
22 #define HP680_BATTERY_MAX 898
23 #define HP680_BATTERY_MIN 486
24 #define HP680_BATTERY_AC_ON 1023
26 #define MODNAME "hp6x0_apm"
28 #define PGDR 0xa400012c
30 static void hp6x0_apm_get_power_status(struct apm_power_info
*info
)
32 int battery
, backup
, charging
, percentage
;
35 battery
= adc_single(ADC_CHANNEL_BATTERY
);
36 backup
= adc_single(ADC_CHANNEL_BACKUP
);
37 charging
= adc_single(ADC_CHANNEL_CHARGE
);
39 percentage
= 100 * (battery
- HP680_BATTERY_MIN
) /
40 (HP680_BATTERY_MAX
- HP680_BATTERY_MIN
);
42 /* % of full battery */
43 info
->battery_life
= percentage
;
45 /* We want our estimates in minutes */
48 /* Extremely(!!) rough estimate, we will replace this with a datalist later on */
49 info
->time
= (2 * battery
);
51 info
->ac_line_status
= (battery
> HP680_BATTERY_AC_ON
) ?
52 APM_AC_ONLINE
: APM_AC_OFFLINE
;
54 pgdr
= __raw_readb(PGDR
);
55 if (pgdr
& PGDR_MAIN_BATTERY_OUT
) {
56 info
->battery_status
= APM_BATTERY_STATUS_NOT_PRESENT
;
57 info
->battery_flag
= 0x80;
58 } else if (charging
< 8) {
59 info
->battery_status
= APM_BATTERY_STATUS_CHARGING
;
60 info
->battery_flag
= 0x08;
61 info
->ac_line_status
= 0x01;
62 } else if (percentage
<= APM_CRITICAL
) {
63 info
->battery_status
= APM_BATTERY_STATUS_CRITICAL
;
64 info
->battery_flag
= 0x04;
65 } else if (percentage
<= APM_LOW
) {
66 info
->battery_status
= APM_BATTERY_STATUS_LOW
;
67 info
->battery_flag
= 0x02;
69 info
->battery_status
= APM_BATTERY_STATUS_HIGH
;
70 info
->battery_flag
= 0x01;
74 static irqreturn_t
hp6x0_apm_interrupt(int irq
, void *dev
)
77 apm_queue_event(APM_USER_SUSPEND
);
82 static int __init
hp6x0_apm_init(void)
86 ret
= request_irq(HP680_BTN_IRQ
, hp6x0_apm_interrupt
,
88 if (unlikely(ret
< 0)) {
89 printk(KERN_ERR MODNAME
": IRQ %d request failed\n",
94 apm_get_power_status
= hp6x0_apm_get_power_status
;
99 static void __exit
hp6x0_apm_exit(void)
101 free_irq(HP680_BTN_IRQ
, 0);
104 module_init(hp6x0_apm_init
);
105 module_exit(hp6x0_apm_exit
);
107 MODULE_AUTHOR("Adriy Skulysh");
108 MODULE_DESCRIPTION("hp6xx Advanced Power Management");
109 MODULE_LICENSE("GPL");