-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds some simple PM stubs and the basic APM interfaces, primarily for use by hp6xx, where the existing userland expects it. Signed-off-by: Andriy Skulysh <askulysh@gmail.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
- Loading branch information
Andriy Skulysh
authored and
Paul Mundt
committed
Sep 27, 2006
1 parent
ef48e8e
commit 3aa770e
Showing
21 changed files
with
1,124 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/* | ||
* bios-less APM driver for hp680 | ||
* | ||
* Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com> | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License. | ||
*/ | ||
#include <linux/config.h> | ||
#include <linux/module.h> | ||
#include <linux/apm_bios.h> | ||
#include <linux/kernel.h> | ||
#include <linux/init.h> | ||
#include <linux/interrupt.h> | ||
#include <asm/io.h> | ||
#include <asm/apm.h> | ||
#include <asm/adc.h> | ||
#include <asm/hp6xx/hp6xx.h> | ||
|
||
#define SH7709_PGDR 0xa400012c | ||
|
||
#define APM_CRITICAL 10 | ||
#define APM_LOW 30 | ||
|
||
#define HP680_BATTERY_MAX 875 | ||
#define HP680_BATTERY_MIN 600 | ||
#define HP680_BATTERY_AC_ON 900 | ||
|
||
#define MODNAME "hp6x0_apm" | ||
|
||
static int hp6x0_apm_get_info(char *buf, char **start, off_t fpos, int length) | ||
{ | ||
u8 pgdr; | ||
char *p; | ||
int battery_status; | ||
int battery_flag; | ||
int ac_line_status; | ||
int time_units = APM_BATTERY_LIFE_UNKNOWN; | ||
|
||
int battery = adc_single(ADC_CHANNEL_BATTERY); | ||
int backup = adc_single(ADC_CHANNEL_BACKUP); | ||
int charging = adc_single(ADC_CHANNEL_CHARGE); | ||
int percentage; | ||
|
||
percentage = 100 * (battery - HP680_BATTERY_MIN) / | ||
(HP680_BATTERY_MAX - HP680_BATTERY_MIN); | ||
|
||
ac_line_status = (battery > HP680_BATTERY_AC_ON) ? | ||
APM_AC_ONLINE : APM_AC_OFFLINE; | ||
|
||
p = buf; | ||
|
||
pgdr = ctrl_inb(SH7709_PGDR); | ||
if (pgdr & PGDR_MAIN_BATTERY_OUT) { | ||
battery_status = APM_BATTERY_STATUS_NOT_PRESENT; | ||
battery_flag = 0x80; | ||
percentage = -1; | ||
} else if (charging < 8 ) { | ||
battery_status = APM_BATTERY_STATUS_CHARGING; | ||
battery_flag = 0x08; | ||
ac_line_status = 0xff; | ||
} else if (percentage <= APM_CRITICAL) { | ||
battery_status = APM_BATTERY_STATUS_CRITICAL; | ||
battery_flag = 0x04; | ||
} else if (percentage <= APM_LOW) { | ||
battery_status = APM_BATTERY_STATUS_LOW; | ||
battery_flag = 0x02; | ||
} else { | ||
battery_status = APM_BATTERY_STATUS_HIGH; | ||
battery_flag = 0x01; | ||
} | ||
|
||
p += sprintf(p, "1.0 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", | ||
APM_32_BIT_SUPPORT, | ||
ac_line_status, | ||
battery_status, | ||
battery_flag, | ||
percentage, | ||
time_units, | ||
"min"); | ||
p += sprintf(p, "bat=%d backup=%d charge=%d\n", | ||
battery, backup, charging); | ||
|
||
return p - buf; | ||
} | ||
|
||
static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev, struct pt_regs *regs) | ||
{ | ||
if (!apm_suspended) | ||
apm_queue_event(APM_USER_SUSPEND); | ||
|
||
return IRQ_HANDLED; | ||
} | ||
|
||
static int __init hp6x0_apm_init(void) | ||
{ | ||
int ret; | ||
|
||
ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt, | ||
SA_INTERRUPT, MODNAME, 0); | ||
if (unlikely(ret < 0)) { | ||
printk(KERN_ERR MODNAME ": IRQ %d request failed\n", | ||
HP680_BTN_IRQ); | ||
return ret; | ||
} | ||
|
||
apm_get_info = hp6x0_apm_get_info; | ||
|
||
return ret; | ||
} | ||
|
||
static void __exit hp6x0_apm_exit(void) | ||
{ | ||
free_irq(HP680_BTN_IRQ, 0); | ||
apm_get_info = 0; | ||
} | ||
|
||
module_init(hp6x0_apm_init); | ||
module_exit(hp6x0_apm_exit); | ||
|
||
MODULE_AUTHOR("Adriy Skulysh"); | ||
MODULE_DESCRIPTION("hp6xx Advanced Power Management"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* hp6x0 Power Management Routines | ||
* | ||
* Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com> | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License. | ||
*/ | ||
#include <linux/config.h> | ||
#include <linux/init.h> | ||
#include <linux/suspend.h> | ||
#include <linux/errno.h> | ||
#include <linux/time.h> | ||
#include <asm/io.h> | ||
#include <asm/hd64461.h> | ||
#include <asm/hp6xx/hp6xx.h> | ||
#include <asm/cpu/dac.h> | ||
#include <asm/pm.h> | ||
|
||
#define STBCR 0xffffff82 | ||
#define STBCR2 0xffffff88 | ||
|
||
static int hp6x0_pm_enter(suspend_state_t state) | ||
{ | ||
u8 stbcr, stbcr2; | ||
#ifdef CONFIG_HD64461_ENABLER | ||
u8 scr; | ||
u16 hd64461_stbcr; | ||
#endif | ||
|
||
if (state != PM_SUSPEND_MEM) | ||
return -EINVAL; | ||
|
||
#ifdef CONFIG_HD64461_ENABLER | ||
outb(0, HD64461_PCC1CSCIER); | ||
|
||
scr = inb(HD64461_PCC1SCR); | ||
scr |= HD64461_PCCSCR_VCC1; | ||
outb(scr, HD64461_PCC1SCR); | ||
|
||
hd64461_stbcr = inw(HD64461_STBCR); | ||
hd64461_stbcr |= HD64461_STBCR_SPC1ST; | ||
outw(hd64461_stbcr, HD64461_STBCR); | ||
#endif | ||
|
||
ctrl_outb(0x1f, DACR); | ||
|
||
stbcr = ctrl_inb(STBCR); | ||
ctrl_outb(0x01, STBCR); | ||
|
||
stbcr2 = ctrl_inb(STBCR2); | ||
ctrl_outb(0x7f , STBCR2); | ||
|
||
outw(0xf07f, HD64461_SCPUCR); | ||
|
||
pm_enter(); | ||
|
||
outw(0, HD64461_SCPUCR); | ||
ctrl_outb(stbcr, STBCR); | ||
ctrl_outb(stbcr2, STBCR2); | ||
|
||
#ifdef CONFIG_HD64461_ENABLER | ||
hd64461_stbcr = inw(HD64461_STBCR); | ||
hd64461_stbcr &= ~HD64461_STBCR_SPC1ST; | ||
outw(hd64461_stbcr, HD64461_STBCR); | ||
|
||
outb(0x4c, HD64461_PCC1CSCIER); | ||
outb(0x00, HD64461_PCC1CSCR); | ||
#endif | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. | ||
*/ | ||
static struct pm_ops hp6x0_pm_ops = { | ||
.pm_disk_mode = PM_DISK_FIRMWARE, | ||
.enter = hp6x0_pm_enter, | ||
}; | ||
|
||
static int __init hp6x0_pm_init(void) | ||
{ | ||
pm_set_ops(&hp6x0_pm_ops); | ||
return 0; | ||
} | ||
|
||
late_initcall(hp6x0_pm_init); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com> | ||
* | ||
* This file is subject to the terms and conditions of the GNU General Public | ||
* License. See the file "COPYING" in the main directory of this archive | ||
* for more details. | ||
* | ||
*/ | ||
|
||
#include <linux/linkage.h> | ||
#include <asm/cpu/mmu_context.h> | ||
|
||
#define k0 r0 | ||
#define k1 r1 | ||
#define k2 r2 | ||
#define k3 r3 | ||
#define k4 r4 | ||
|
||
/* | ||
* Kernel mode register usage: | ||
* k0 scratch | ||
* k1 scratch | ||
* k2 scratch (Exception code) | ||
* k3 scratch (Return address) | ||
* k4 scratch | ||
* k5 reserved | ||
* k6 Global Interrupt Mask (0--15 << 4) | ||
* k7 CURRENT_THREAD_INFO (pointer to current thread info) | ||
*/ | ||
|
||
ENTRY(wakeup_start) | ||
! clear STBY bit | ||
mov #-126, k2 | ||
and #127, k0 | ||
mov.b k0, @k2 | ||
! enable refresh | ||
mov.l 5f, k1 | ||
mov.w 6f, k0 | ||
mov.w k0, @k1 | ||
! jump to handler | ||
mov.l 2f, k2 | ||
mov.l 3f, k3 | ||
mov.l @k2, k2 | ||
|
||
mov.l 4f, k1 | ||
jmp @k1 | ||
nop | ||
|
||
.align 2 | ||
1: .long EXPEVT | ||
2: .long INTEVT | ||
3: .long ret_from_irq | ||
4: .long handle_exception | ||
5: .long 0xffffff68 | ||
6: .word 0x0524 | ||
|
||
ENTRY(wakeup_end) | ||
nop |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.