aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/boards/mach-hp6xx
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2008-07-29 08:01:19 -0400
committerPaul Mundt <lethal@linux-sh.org>2008-07-29 08:01:19 -0400
commitda2014a2b080e7f3024a4eb6917d47069ad9620b (patch)
treecfde12c6d4b5baa222966b14a676f107992cf786 /arch/sh/boards/mach-hp6xx
parent71b8064e7df5698520d73b4c1566a3dbc98eb9ef (diff)
sh: Shuffle the board directories in to mach groups.
This flattens out the board directories in to individual mach groups, we will use this for getting rid of unneeded directories, simplifying the build system, and becoming more coherent with the refactored arch/sh/include topology. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/boards/mach-hp6xx')
-rw-r--r--arch/sh/boards/mach-hp6xx/Makefile7
-rw-r--r--arch/sh/boards/mach-hp6xx/hp6xx_apm.c111
-rw-r--r--arch/sh/boards/mach-hp6xx/pm.c81
-rw-r--r--arch/sh/boards/mach-hp6xx/pm_wakeup.S58
-rw-r--r--arch/sh/boards/mach-hp6xx/setup.c121
5 files changed, 378 insertions, 0 deletions
diff --git a/arch/sh/boards/mach-hp6xx/Makefile b/arch/sh/boards/mach-hp6xx/Makefile
new file mode 100644
index 000000000000..b3124278247c
--- /dev/null
+++ b/arch/sh/boards/mach-hp6xx/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the HP6xx specific parts of the kernel
3#
4
5obj-y := setup.o
6obj-$(CONFIG_PM) += pm.o pm_wakeup.o
7obj-$(CONFIG_APM_EMULATION) += hp6xx_apm.o
diff --git a/arch/sh/boards/mach-hp6xx/hp6xx_apm.c b/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
new file mode 100644
index 000000000000..177f4f028e0d
--- /dev/null
+++ b/arch/sh/boards/mach-hp6xx/hp6xx_apm.c
@@ -0,0 +1,111 @@
1/*
2 * bios-less APM driver for hp680
3 *
4 * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
5 * Copyright 2008 (c) Kristoffer Ericson <kristoffer.ericson@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License.
9 */
10#include <linux/module.h>
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/apm-emulation.h>
15#include <linux/io.h>
16#include <asm/adc.h>
17#include <asm/hp6xx.h>
18
19/* percentage values */
20#define APM_CRITICAL 10
21#define APM_LOW 30
22
23/* resonably sane values */
24#define HP680_BATTERY_MAX 898
25#define HP680_BATTERY_MIN 486
26#define HP680_BATTERY_AC_ON 1023
27
28#define MODNAME "hp6x0_apm"
29
30#define PGDR 0xa400012c
31
32static void hp6x0_apm_get_power_status(struct apm_power_info *info)
33{
34 int battery, backup, charging, percentage;
35 u8 pgdr;
36
37 battery = adc_single(ADC_CHANNEL_BATTERY);
38 backup = adc_single(ADC_CHANNEL_BACKUP);
39 charging = adc_single(ADC_CHANNEL_CHARGE);
40
41 percentage = 100 * (battery - HP680_BATTERY_MIN) /
42 (HP680_BATTERY_MAX - HP680_BATTERY_MIN);
43
44 /* % of full battery */
45 info->battery_life = percentage;
46
47 /* We want our estimates in minutes */
48 info->units = 0;
49
50 /* Extremely(!!) rough estimate, we will replace this with a datalist later on */
51 info->time = (2 * battery);
52
53 info->ac_line_status = (battery > HP680_BATTERY_AC_ON) ?
54 APM_AC_ONLINE : APM_AC_OFFLINE;
55
56 pgdr = ctrl_inb(PGDR);
57 if (pgdr & PGDR_MAIN_BATTERY_OUT) {
58 info->battery_status = APM_BATTERY_STATUS_NOT_PRESENT;
59 info->battery_flag = 0x80;
60 } else if (charging < 8) {
61 info->battery_status = APM_BATTERY_STATUS_CHARGING;
62 info->battery_flag = 0x08;
63 info->ac_line_status = 0x01;
64 } else if (percentage <= APM_CRITICAL) {
65 info->battery_status = APM_BATTERY_STATUS_CRITICAL;
66 info->battery_flag = 0x04;
67 } else if (percentage <= APM_LOW) {
68 info->battery_status = APM_BATTERY_STATUS_LOW;
69 info->battery_flag = 0x02;
70 } else {
71 info->battery_status = APM_BATTERY_STATUS_HIGH;
72 info->battery_flag = 0x01;
73 }
74}
75
76static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev)
77{
78 if (!APM_DISABLED)
79 apm_queue_event(APM_USER_SUSPEND);
80
81 return IRQ_HANDLED;
82}
83
84static int __init hp6x0_apm_init(void)
85{
86 int ret;
87
88 ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
89 IRQF_DISABLED, MODNAME, NULL);
90 if (unlikely(ret < 0)) {
91 printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
92 HP680_BTN_IRQ);
93 return ret;
94 }
95
96 apm_get_power_status = hp6x0_apm_get_power_status;
97
98 return ret;
99}
100
101static void __exit hp6x0_apm_exit(void)
102{
103 free_irq(HP680_BTN_IRQ, 0);
104}
105
106module_init(hp6x0_apm_init);
107module_exit(hp6x0_apm_exit);
108
109MODULE_AUTHOR("Adriy Skulysh");
110MODULE_DESCRIPTION("hp6xx Advanced Power Management");
111MODULE_LICENSE("GPL");
diff --git a/arch/sh/boards/mach-hp6xx/pm.c b/arch/sh/boards/mach-hp6xx/pm.c
new file mode 100644
index 000000000000..e96684def788
--- /dev/null
+++ b/arch/sh/boards/mach-hp6xx/pm.c
@@ -0,0 +1,81 @@
1/*
2 * hp6x0 Power Management Routines
3 *
4 * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License.
8 */
9#include <linux/init.h>
10#include <linux/suspend.h>
11#include <linux/errno.h>
12#include <linux/time.h>
13#include <asm/io.h>
14#include <asm/hd64461.h>
15#include <asm/hp6xx.h>
16#include <cpu/dac.h>
17#include <asm/pm.h>
18
19#define STBCR 0xffffff82
20#define STBCR2 0xffffff88
21
22static int hp6x0_pm_enter(suspend_state_t state)
23{
24 u8 stbcr, stbcr2;
25#ifdef CONFIG_HD64461_ENABLER
26 u8 scr;
27 u16 hd64461_stbcr;
28#endif
29
30#ifdef CONFIG_HD64461_ENABLER
31 outb(0, HD64461_PCC1CSCIER);
32
33 scr = inb(HD64461_PCC1SCR);
34 scr |= HD64461_PCCSCR_VCC1;
35 outb(scr, HD64461_PCC1SCR);
36
37 hd64461_stbcr = inw(HD64461_STBCR);
38 hd64461_stbcr |= HD64461_STBCR_SPC1ST;
39 outw(hd64461_stbcr, HD64461_STBCR);
40#endif
41
42 ctrl_outb(0x1f, DACR);
43
44 stbcr = ctrl_inb(STBCR);
45 ctrl_outb(0x01, STBCR);
46
47 stbcr2 = ctrl_inb(STBCR2);
48 ctrl_outb(0x7f , STBCR2);
49
50 outw(0xf07f, HD64461_SCPUCR);
51
52 pm_enter();
53
54 outw(0, HD64461_SCPUCR);
55 ctrl_outb(stbcr, STBCR);
56 ctrl_outb(stbcr2, STBCR2);
57
58#ifdef CONFIG_HD64461_ENABLER
59 hd64461_stbcr = inw(HD64461_STBCR);
60 hd64461_stbcr &= ~HD64461_STBCR_SPC1ST;
61 outw(hd64461_stbcr, HD64461_STBCR);
62
63 outb(0x4c, HD64461_PCC1CSCIER);
64 outb(0x00, HD64461_PCC1CSCR);
65#endif
66
67 return 0;
68}
69
70static struct platform_suspend_ops hp6x0_pm_ops = {
71 .enter = hp6x0_pm_enter,
72 .valid = suspend_valid_only_mem,
73};
74
75static int __init hp6x0_pm_init(void)
76{
77 suspend_set_ops(&hp6x0_pm_ops);
78 return 0;
79}
80
81late_initcall(hp6x0_pm_init);
diff --git a/arch/sh/boards/mach-hp6xx/pm_wakeup.S b/arch/sh/boards/mach-hp6xx/pm_wakeup.S
new file mode 100644
index 000000000000..44b648cf6f23
--- /dev/null
+++ b/arch/sh/boards/mach-hp6xx/pm_wakeup.S
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 */
9
10#include <linux/linkage.h>
11#include <cpu/mmu_context.h>
12
13#define k0 r0
14#define k1 r1
15#define k2 r2
16#define k3 r3
17#define k4 r4
18
19/*
20 * Kernel mode register usage:
21 * k0 scratch
22 * k1 scratch
23 * k2 scratch (Exception code)
24 * k3 scratch (Return address)
25 * k4 scratch
26 * k5 reserved
27 * k6 Global Interrupt Mask (0--15 << 4)
28 * k7 CURRENT_THREAD_INFO (pointer to current thread info)
29 */
30
31ENTRY(wakeup_start)
32! clear STBY bit
33 mov #-126, k2
34 and #127, k0
35 mov.b k0, @k2
36! enable refresh
37 mov.l 5f, k1
38 mov.w 6f, k0
39 mov.w k0, @k1
40! jump to handler
41 mov.l 2f, k2
42 mov.l 3f, k3
43 mov.l @k2, k2
44
45 mov.l 4f, k1
46 jmp @k1
47 nop
48
49 .align 2
501: .long EXPEVT
512: .long INTEVT
523: .long ret_from_irq
534: .long handle_exception
545: .long 0xffffff68
556: .word 0x0524
56
57ENTRY(wakeup_end)
58 nop
diff --git a/arch/sh/boards/mach-hp6xx/setup.c b/arch/sh/boards/mach-hp6xx/setup.c
new file mode 100644
index 000000000000..475b46caec1f
--- /dev/null
+++ b/arch/sh/boards/mach-hp6xx/setup.c
@@ -0,0 +1,121 @@
1/*
2 * linux/arch/sh/boards/hp6xx/setup.c
3 *
4 * Copyright (C) 2002 Andriy Skulysh
5 * Copyright (C) 2007 Kristoffer Ericson <Kristoffer_e1@hotmail.com>
6 *
7 * May be copied or modified under the terms of the GNU General Public
8 * License. See linux/COPYING for more information.
9 *
10 * Setup code for HP620/HP660/HP680/HP690 (internal peripherials only)
11 */
12#include <linux/types.h>
13#include <linux/init.h>
14#include <linux/platform_device.h>
15#include <asm/hd64461.h>
16#include <asm/io.h>
17#include <asm/irq.h>
18#include <asm/hp6xx.h>
19#include <cpu/dac.h>
20
21#define SCPCR 0xa4000116
22#define SCPDR 0xa4000136
23
24/* CF Slot */
25static struct resource cf_ide_resources[] = {
26 [0] = {
27 .start = 0x15000000 + 0x1f0,
28 .end = 0x15000000 + 0x1f0 + 0x08 - 0x01,
29 .flags = IORESOURCE_MEM,
30 },
31 [1] = {
32 .start = 0x15000000 + 0x1fe,
33 .end = 0x15000000 + 0x1fe + 0x01,
34 .flags = IORESOURCE_MEM,
35 },
36 [2] = {
37 .start = 77,
38 .flags = IORESOURCE_IRQ,
39 },
40};
41
42static struct platform_device cf_ide_device = {
43 .name = "pata_platform",
44 .id = -1,
45 .num_resources = ARRAY_SIZE(cf_ide_resources),
46 .resource = cf_ide_resources,
47};
48
49static struct platform_device jornadakbd_device = {
50 .name = "jornada680_kbd",
51 .id = -1,
52};
53
54static struct platform_device *hp6xx_devices[] __initdata = {
55 &cf_ide_device,
56 &jornadakbd_device,
57};
58
59static void __init hp6xx_init_irq(void)
60{
61 /* Gets touchscreen and powerbutton IRQ working */
62 plat_irq_setup_pins(IRQ_MODE_IRQ);
63}
64
65static int __init hp6xx_devices_setup(void)
66{
67 return platform_add_devices(hp6xx_devices, ARRAY_SIZE(hp6xx_devices));
68}
69
70static void __init hp6xx_setup(char **cmdline_p)
71{
72 u8 v8;
73 u16 v;
74
75 v = inw(HD64461_STBCR);
76 v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
77 HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
78 HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
79 HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST|
80 HD64461_STBCR_SAFECKE_IST;
81#ifndef CONFIG_HD64461_ENABLER
82 v |= HD64461_STBCR_SPC1ST;
83#endif
84 outw(v, HD64461_STBCR);
85 v = inw(HD64461_GPADR);
86 v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
87 outw(v, HD64461_GPADR);
88
89 outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC0GCR);
90
91#ifndef CONFIG_HD64461_ENABLER
92 outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC1GCR);
93#endif
94
95 sh_dac_output(0, DAC_SPEAKER_VOLUME);
96 sh_dac_disable(DAC_SPEAKER_VOLUME);
97 v8 = ctrl_inb(DACR);
98 v8 &= ~DACR_DAE;
99 ctrl_outb(v8,DACR);
100
101 v8 = ctrl_inb(SCPDR);
102 v8 |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
103 v8 &= ~SCPDR_TS_SCAN_ENABLE;
104 ctrl_outb(v8, SCPDR);
105
106 v = ctrl_inw(SCPCR);
107 v &= ~SCPCR_TS_MASK;
108 v |= SCPCR_TS_ENABLE;
109 ctrl_outw(v, SCPCR);
110}
111device_initcall(hp6xx_devices_setup);
112
113static struct sh_machine_vector mv_hp6xx __initmv = {
114 .mv_name = "hp6xx",
115 .mv_setup = hp6xx_setup,
116 /* IRQ's : CPU(64) + CCHIP(16) + FREE_TO_USE(6) */
117 .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM + 6,
118 .mv_irq_demux = hd64461_irq_demux,
119 /* Enable IRQ0 -> IRQ3 in IRQ_MODE */
120 .mv_init_irq = hp6xx_init_irq,
121};