aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/cchips
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sh/cchips
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/sh/cchips')
-rw-r--r--arch/sh/cchips/Kconfig96
-rw-r--r--arch/sh/cchips/hd6446x/hd64461/Makefile6
-rw-r--r--arch/sh/cchips/hd6446x/hd64461/io.c157
-rw-r--r--arch/sh/cchips/hd6446x/hd64461/setup.c171
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/Makefile6
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/gpio.c196
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/io.c216
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/setup.c202
-rw-r--r--arch/sh/cchips/voyagergx/Makefile8
-rw-r--r--arch/sh/cchips/voyagergx/consistent.c126
-rw-r--r--arch/sh/cchips/voyagergx/irq.c194
-rw-r--r--arch/sh/cchips/voyagergx/setup.c37
12 files changed, 1415 insertions, 0 deletions
diff --git a/arch/sh/cchips/Kconfig b/arch/sh/cchips/Kconfig
new file mode 100644
index 000000000000..155d139884c3
--- /dev/null
+++ b/arch/sh/cchips/Kconfig
@@ -0,0 +1,96 @@
1menu "Companion Chips"
2
3config VOYAGERGX
4 bool "VoyagerGX chip support"
5 depends on SH_RTS7751R2D
6 help
7 Selecting this option will support Silicon Motion, Inc. SM501.
8 Designed to complement needs for the embedded industry, it
9 provides video and 2D capability. To reduce system cost a
10 wide variety of include I/O is supported, including analog RGB
11 and digital LCD Panel interface, 8-bit parallel interface, USB,
12 UART, IrDA, Zoom Video, AC97 or I2S, SSP, PWM, and I2C. There
13 are additional GPIO bits that can be used to interface to
14 external as well.
15
16# A board must have defined HD6446X_SERIES in order to see these
17config HD6446X_SERIES
18 bool "HD6446x support"
19 default n
20
21choice
22 prompt "HD6446x options"
23 depends on HD6446X_SERIES
24 default HD64461
25
26config HD64461
27 bool "Hitachi HD64461 companion chip support"
28 depends on CPU_SUBTYPE_SH7709
29 ---help---
30 The Hitachi HD64461 provides an interface for
31 the SH7709 CPU, supporting a LCD controller,
32 CRT color controller, IrDA up to 4 Mbps, and a
33 PCMCIA controller supporting 2 slots.
34
35 More information is available at
36 <http://semiconductor.hitachi.com/windowsce/superh/sld013.htm>.
37
38 Say Y if you want support for the HD64461.
39 Otherwise, say N.
40
41config HD64465
42 bool "Hitachi HD64465 companion chip support"
43 depends on CPU_SUBTYPE_SH7750
44 ---help---
45 The Hitachi HD64465 provides an interface for
46 the SH7750 CPU, supporting a LCD controller,
47 CRT color controller, IrDA, USB, PCMCIA,
48 keyboard controller, and a printer interface.
49
50 More information is available at
51 <http://global.hitachi.com/New/cnews/E/1998/981019B.html>.
52
53 Say Y if you want support for the HD64465.
54 Otherwise, say N.
55
56endchoice
57
58# These will also be split into the Kconfig's below
59config HD64461_IRQ
60 int "HD64461 IRQ"
61 depends on HD64461
62 default "36"
63 help
64 The default setting of the HD64461 IRQ is 36.
65
66 Do not change this unless you know what you are doing.
67
68config HD64461_ENABLER
69 bool "HD64461 PCMCIA enabler"
70 depends on HD64461
71 help
72 Say Y here if you want to enable PCMCIA support
73 via the HD64461 companion chip.
74 Otherwise, say N.
75
76
77config HD64465_IOBASE
78 hex "HD64465 start address"
79 depends on HD64465
80 default "0xb0000000"
81 help
82 The default setting of the HD64465 IO base address is 0xb0000000.
83
84 Do not change this unless you know what you are doing.
85
86config HD64465_IRQ
87 int "HD64465 IRQ"
88 depends on HD64465
89 default "5"
90 help
91 The default setting of the HD64465 IRQ is 5.
92
93 Do not change this unless you know what you are doing.
94
95endmenu
96
diff --git a/arch/sh/cchips/hd6446x/hd64461/Makefile b/arch/sh/cchips/hd6446x/hd64461/Makefile
new file mode 100644
index 000000000000..bff4b92e388c
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64461/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the HD64461
3#
4
5obj-y := setup.o io.o
6
diff --git a/arch/sh/cchips/hd6446x/hd64461/io.c b/arch/sh/cchips/hd6446x/hd64461/io.c
new file mode 100644
index 000000000000..4c062d6b7a97
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64461/io.c
@@ -0,0 +1,157 @@
1/*
2 * $Id: io.c,v 1.6 2004/03/16 00:07:50 lethal Exp $
3 * Copyright (C) 2000 YAEGASHI Takeshi
4 * Typical I/O routines for HD64461 system.
5 */
6
7#include <linux/config.h>
8#include <asm/io.h>
9#include <asm/hd64461/hd64461.h>
10
11#define MEM_BASE (CONFIG_HD64461_IOBASE - HD64461_STBCR)
12
13static __inline__ unsigned long PORT2ADDR(unsigned long port)
14{
15 /* 16550A: HD64461 internal */
16 if (0x3f8<=port && port<=0x3ff)
17 return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1);
18 if (0x2f8<=port && port<=0x2ff)
19 return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1);
20
21#ifdef CONFIG_HD64461_ENABLER
22 /* NE2000: HD64461 PCMCIA channel 0 (I/O) */
23 if (0x300<=port && port<=0x31f)
24 return 0xba000000 + port;
25
26 /* ide0: HD64461 PCMCIA channel 1 (memory) */
27 /* On HP690, CF in slot 1 is configured as a memory card
28 device. See CF+ and CompactFlash Specification for the
29 detail of CF's memory mapped addressing. */
30 if (0x1f0<=port && port<=0x1f7) return 0xb5000000 + port;
31 if (port == 0x3f6) return 0xb50001fe;
32 if (port == 0x3f7) return 0xb50001ff;
33
34 /* ide1 */
35 if (0x170<=port && port<=0x177) return 0xba000000 + port;
36 if (port == 0x376) return 0xba000376;
37 if (port == 0x377) return 0xba000377;
38#endif
39
40 /* ??? */
41 if (port < 0xf000) return 0xa0000000 + port;
42 /* PCMCIA channel 0, I/O (0xba000000) */
43 if (port < 0x10000) return 0xba000000 + port - 0xf000;
44
45 /* HD64461 internal devices (0xb0000000) */
46 if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000;
47
48 /* PCMCIA channel 0, I/O (0xba000000) */
49 if (port < 0x30000) return 0xba000000 + port - 0x20000;
50
51 /* PCMCIA channel 1, memory (0xb5000000) */
52 if (port < 0x40000) return 0xb5000000 + port - 0x30000;
53
54 /* Whole physical address space (0xa0000000) */
55 return 0xa0000000 + (port & 0x1fffffff);
56}
57
58static inline void delay(void)
59{
60 ctrl_inw(0xa0000000);
61}
62
63unsigned char hd64461_inb(unsigned long port)
64{
65 return *(volatile unsigned char*)PORT2ADDR(port);
66}
67
68unsigned char hd64461_inb_p(unsigned long port)
69{
70 unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
71 delay();
72 return v;
73}
74
75unsigned short hd64461_inw(unsigned long port)
76{
77 return *(volatile unsigned short*)PORT2ADDR(port);
78}
79
80unsigned int hd64461_inl(unsigned long port)
81{
82 return *(volatile unsigned long*)PORT2ADDR(port);
83}
84
85void hd64461_outb(unsigned char b, unsigned long port)
86{
87 *(volatile unsigned char*)PORT2ADDR(port) = b;
88}
89
90void hd64461_outb_p(unsigned char b, unsigned long port)
91{
92 *(volatile unsigned char*)PORT2ADDR(port) = b;
93 delay();
94}
95
96void hd64461_outw(unsigned short b, unsigned long port)
97{
98 *(volatile unsigned short*)PORT2ADDR(port) = b;
99}
100
101void hd64461_outl(unsigned int b, unsigned long port)
102{
103 *(volatile unsigned long*)PORT2ADDR(port) = b;
104}
105
106void hd64461_insb(unsigned long port, void *buffer, unsigned long count)
107{
108 volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port);
109 unsigned char *buf=buffer;
110 while(count--) *buf++=*addr;
111}
112
113void hd64461_insw(unsigned long port, void *buffer, unsigned long count)
114{
115 volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port);
116 unsigned short *buf=buffer;
117 while(count--) *buf++=*addr;
118}
119
120void hd64461_insl(unsigned long port, void *buffer, unsigned long count)
121{
122 volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port);
123 unsigned long *buf=buffer;
124 while(count--) *buf++=*addr;
125}
126
127void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count)
128{
129 volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port);
130 const unsigned char *buf=buffer;
131 while(count--) *addr=*buf++;
132}
133
134void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count)
135{
136 volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port);
137 const unsigned short *buf=buffer;
138 while(count--) *addr=*buf++;
139}
140
141void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count)
142{
143 volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port);
144 const unsigned long *buf=buffer;
145 while(count--) *addr=*buf++;
146}
147
148unsigned short hd64461_readw(unsigned long addr)
149{
150 return *(volatile unsigned short*)(MEM_BASE+addr);
151}
152
153void hd64461_writew(unsigned short b, unsigned long addr)
154{
155 *(volatile unsigned short*)(MEM_BASE+addr) = b;
156}
157
diff --git a/arch/sh/cchips/hd6446x/hd64461/setup.c b/arch/sh/cchips/hd6446x/hd64461/setup.c
new file mode 100644
index 000000000000..f014b9bf6922
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64461/setup.c
@@ -0,0 +1,171 @@
1/*
2 * $Id: setup.c,v 1.5 2004/03/16 00:07:50 lethal Exp $
3 * Copyright (C) 2000 YAEGASHI Takeshi
4 * Hitachi HD64461 companion chip support
5 */
6
7#include <linux/config.h>
8#include <linux/sched.h>
9#include <linux/module.h>
10#include <linux/kernel.h>
11#include <linux/param.h>
12#include <linux/interrupt.h>
13#include <linux/init.h>
14#include <linux/irq.h>
15
16#include <asm/io.h>
17#include <asm/irq.h>
18
19#include <asm/hd64461/hd64461.h>
20
21static void disable_hd64461_irq(unsigned int irq)
22{
23 unsigned long flags;
24 unsigned short nimr;
25 unsigned short mask = 1 << (irq - HD64461_IRQBASE);
26
27 local_irq_save(flags);
28 nimr = inw(HD64461_NIMR);
29 nimr |= mask;
30 outw(nimr, HD64461_NIMR);
31 local_irq_restore(flags);
32}
33
34static void enable_hd64461_irq(unsigned int irq)
35{
36 unsigned long flags;
37 unsigned short nimr;
38 unsigned short mask = 1 << (irq - HD64461_IRQBASE);
39
40 local_irq_save(flags);
41 nimr = inw(HD64461_NIMR);
42 nimr &= ~mask;
43 outw(nimr, HD64461_NIMR);
44 local_irq_restore(flags);
45}
46
47static void mask_and_ack_hd64461(unsigned int irq)
48{
49 disable_hd64461_irq(irq);
50#ifdef CONFIG_HD64461_ENABLER
51 if (irq == HD64461_IRQBASE + 13)
52 outb(0x00, HD64461_PCC1CSCR);
53#endif
54}
55
56static void end_hd64461_irq(unsigned int irq)
57{
58 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
59 enable_hd64461_irq(irq);
60}
61
62static unsigned int startup_hd64461_irq(unsigned int irq)
63{
64 enable_hd64461_irq(irq);
65 return 0;
66}
67
68static void shutdown_hd64461_irq(unsigned int irq)
69{
70 disable_hd64461_irq(irq);
71}
72
73static struct hw_interrupt_type hd64461_irq_type = {
74 .typename = "HD64461-IRQ",
75 .startup = startup_hd64461_irq,
76 .shutdown = shutdown_hd64461_irq,
77 .enable = enable_hd64461_irq,
78 .disable = disable_hd64461_irq,
79 .ack = mask_and_ack_hd64461,
80 .end = end_hd64461_irq,
81};
82
83static irqreturn_t hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs)
84{
85 printk(KERN_INFO
86 "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n",
87 inw(HD64461_NIRR), inw(HD64461_NIMR));
88
89 return IRQ_NONE;
90}
91
92static struct {
93 int (*func) (int, void *);
94 void *dev;
95} hd64461_demux[HD64461_IRQ_NUM];
96
97void hd64461_register_irq_demux(int irq,
98 int (*demux) (int irq, void *dev), void *dev)
99{
100 hd64461_demux[irq - HD64461_IRQBASE].func = demux;
101 hd64461_demux[irq - HD64461_IRQBASE].dev = dev;
102}
103
104EXPORT_SYMBOL(hd64461_register_irq_demux);
105
106void hd64461_unregister_irq_demux(int irq)
107{
108 hd64461_demux[irq - HD64461_IRQBASE].func = 0;
109}
110
111EXPORT_SYMBOL(hd64461_unregister_irq_demux);
112
113int hd64461_irq_demux(int irq)
114{
115 if (irq == CONFIG_HD64461_IRQ) {
116 unsigned short bit;
117 unsigned short nirr = inw(HD64461_NIRR);
118 unsigned short nimr = inw(HD64461_NIMR);
119 int i;
120
121 nirr &= ~nimr;
122 for (bit = 1, i = 0; i < 16; bit <<= 1, i++)
123 if (nirr & bit)
124 break;
125 if (i == 16)
126 irq = CONFIG_HD64461_IRQ;
127 else {
128 irq = HD64461_IRQBASE + i;
129 if (hd64461_demux[i].func != 0) {
130 irq = hd64461_demux[i].func(irq, hd64461_demux[i].dev);
131 }
132 }
133 }
134 return __irq_demux(irq);
135}
136
137static struct irqaction irq0 = { hd64461_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "HD64461", NULL, NULL };
138
139int __init setup_hd64461(void)
140{
141 int i;
142
143 if (!MACH_HD64461)
144 return 0;
145
146 printk(KERN_INFO
147 "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n",
148 CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ, HD64461_IRQBASE,
149 HD64461_IRQBASE + 15);
150
151#if defined(CONFIG_CPU_SUBTYPE_SH7709) /* Should be at processor specific part.. */
152 outw(0x2240, INTC_ICR1);
153#endif
154 outw(0xffff, HD64461_NIMR);
155
156 for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) {
157 irq_desc[i].handler = &hd64461_irq_type;
158 }
159
160 setup_irq(CONFIG_HD64461_IRQ, &irq0);
161
162#ifdef CONFIG_HD64461_ENABLER
163 printk(KERN_INFO "HD64461: enabling PCMCIA devices\n");
164 outb(0x4c, HD64461_PCC1CSCIER);
165 outb(0x00, HD64461_PCC1CSCR);
166#endif
167
168 return 0;
169}
170
171module_init(setup_hd64461);
diff --git a/arch/sh/cchips/hd6446x/hd64465/Makefile b/arch/sh/cchips/hd6446x/hd64465/Makefile
new file mode 100644
index 000000000000..f66edcb52c5b
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64465/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the HD64465
3#
4
5obj-y := setup.o io.o gpio.o
6
diff --git a/arch/sh/cchips/hd6446x/hd64465/gpio.c b/arch/sh/cchips/hd6446x/hd64465/gpio.c
new file mode 100644
index 000000000000..9785fdef868e
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64465/gpio.c
@@ -0,0 +1,196 @@
1/*
2 * $Id: gpio.c,v 1.4 2003/05/19 22:24:18 lethal Exp $
3 * by Greg Banks <gbanks@pocketpenguins.com>
4 * (c) 2000 PocketPenguins Inc
5 *
6 * GPIO pin support for HD64465 companion chip.
7 */
8
9#include <linux/kernel.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/sched.h>
13#include <linux/ioport.h>
14#include <asm/io.h>
15#include <asm/hd64465/gpio.h>
16
17#define _PORTOF(portpin) (((portpin)>>3)&0x7)
18#define _PINOF(portpin) ((portpin)&0x7)
19
20/* Register addresses parametrised on port */
21#define GPIO_CR(port) (HD64465_REG_GPACR+((port)<<1))
22#define GPIO_DR(port) (HD64465_REG_GPADR+((port)<<1))
23#define GPIO_ICR(port) (HD64465_REG_GPAICR+((port)<<1))
24#define GPIO_ISR(port) (HD64465_REG_GPAISR+((port)<<1))
25
26#define GPIO_NPORTS 5
27
28#define MODNAME "hd64465_gpio"
29
30EXPORT_SYMBOL(hd64465_gpio_configure);
31EXPORT_SYMBOL(hd64465_gpio_get_pin);
32EXPORT_SYMBOL(hd64465_gpio_get_port);
33EXPORT_SYMBOL(hd64465_gpio_register_irq);
34EXPORT_SYMBOL(hd64465_gpio_set_pin);
35EXPORT_SYMBOL(hd64465_gpio_set_port);
36EXPORT_SYMBOL(hd64465_gpio_unregister_irq);
37
38/* TODO: each port should be protected with a spinlock */
39
40
41void hd64465_gpio_configure(int portpin, int direction)
42{
43 unsigned short cr;
44 unsigned int shift = (_PINOF(portpin)<<1);
45
46 cr = inw(GPIO_CR(_PORTOF(portpin)));
47 cr &= ~(3<<shift);
48 cr |= direction<<shift;
49 outw(cr, GPIO_CR(_PORTOF(portpin)));
50}
51
52void hd64465_gpio_set_pin(int portpin, unsigned int value)
53{
54 unsigned short d;
55 unsigned short mask = 1<<(_PINOF(portpin));
56
57 d = inw(GPIO_DR(_PORTOF(portpin)));
58 if (value)
59 d |= mask;
60 else
61 d &= ~mask;
62 outw(d, GPIO_DR(_PORTOF(portpin)));
63}
64
65unsigned int hd64465_gpio_get_pin(int portpin)
66{
67 return inw(GPIO_DR(_PORTOF(portpin))) & (1<<(_PINOF(portpin)));
68}
69
70/* TODO: for cleaner atomicity semantics, add a mask to this routine */
71
72void hd64465_gpio_set_port(int port, unsigned int value)
73{
74 outw(value, GPIO_DR(port));
75}
76
77unsigned int hd64465_gpio_get_port(int port)
78{
79 return inw(GPIO_DR(port));
80}
81
82
83static struct {
84 void (*func)(int portpin, void *dev);
85 void *dev;
86} handlers[GPIO_NPORTS * 8];
87
88static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs)
89{
90 unsigned short port, pin, isr, mask, portpin;
91
92 for (port=0 ; port<GPIO_NPORTS ; port++) {
93 isr = inw(GPIO_ISR(port));
94
95 for (pin=0 ; pin<8 ; pin++) {
96 mask = 1<<pin;
97 if (isr & mask) {
98 portpin = (port<<3)|pin;
99 if (handlers[portpin].func != 0)
100 handlers[portpin].func(portpin, handlers[portpin].dev);
101 else
102 printk(KERN_NOTICE "unexpected GPIO interrupt, pin %c%d\n",
103 port+'A', (int)pin);
104 }
105 }
106
107 /* Write 1s back to ISR to clear it? That's what the manual says.. */
108 outw(isr, GPIO_ISR(port));
109 }
110
111 return IRQ_HANDLED;
112}
113
114void hd64465_gpio_register_irq(int portpin, int mode,
115 void (*handler)(int portpin, void *dev), void *dev)
116{
117 unsigned long flags;
118 unsigned short icr, mask;
119
120 if (handler == 0)
121 return;
122
123 local_irq_save(flags);
124
125 handlers[portpin].func = handler;
126 handlers[portpin].dev = dev;
127
128 /*
129 * Configure Interrupt Control Register
130 */
131 icr = inw(GPIO_ICR(_PORTOF(portpin)));
132 mask = (1<<_PINOF(portpin));
133
134 /* unmask interrupt */
135 icr &= ~mask;
136
137 /* set TS bit */
138 mask <<= 8;
139 icr &= ~mask;
140 if (mode == HD64465_GPIO_RISING)
141 icr |= mask;
142
143 outw(icr, GPIO_ICR(_PORTOF(portpin)));
144
145 local_irq_restore(flags);
146}
147
148void hd64465_gpio_unregister_irq(int portpin)
149{
150 unsigned long flags;
151 unsigned short icr;
152
153 local_irq_save(flags);
154
155 /*
156 * Configure Interrupt Control Register
157 */
158 icr = inw(GPIO_ICR(_PORTOF(portpin)));
159 icr |= (1<<_PINOF(portpin)); /* mask interrupt */
160 outw(icr, GPIO_ICR(_PORTOF(portpin)));
161
162 handlers[portpin].func = 0;
163 handlers[portpin].dev = 0;
164
165 local_irq_restore(flags);
166}
167
168static int __init hd64465_gpio_init(void)
169{
170 if (!request_region(HD64465_REG_GPACR, 0x1000, MODNAME))
171 return -EBUSY;
172 if (request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt,
173 SA_INTERRUPT, MODNAME, 0))
174 goto out_irqfailed;
175
176 printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO);
177
178 return 0;
179
180out_irqfailed:
181 release_region(HD64465_REG_GPACR, 0x1000);
182
183 return -EINVAL;
184}
185
186static void __exit hd64465_gpio_exit(void)
187{
188 release_region(HD64465_REG_GPACR, 0x1000);
189 free_irq(HD64465_IRQ_GPIO, 0);
190}
191
192module_init(hd64465_gpio_init);
193module_exit(hd64465_gpio_exit);
194
195MODULE_LICENSE("GPL");
196
diff --git a/arch/sh/cchips/hd6446x/hd64465/io.c b/arch/sh/cchips/hd6446x/hd64465/io.c
new file mode 100644
index 000000000000..99ac709c550e
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64465/io.c
@@ -0,0 +1,216 @@
1/*
2 * $Id: io.c,v 1.4 2003/08/03 03:05:10 lethal Exp $
3 * by Greg Banks <gbanks@pocketpenguins.com>
4 * (c) 2000 PocketPenguins Inc
5 *
6 * Derived from io_hd64461.c, which bore the message:
7 * Copyright (C) 2000 YAEGASHI Takeshi
8 *
9 * Typical I/O routines for HD64465 system.
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <asm/io.h>
16#include <asm/hd64465/hd64465.h>
17
18
19#define HD64465_DEBUG 0
20
21#if HD64465_DEBUG
22#define DPRINTK(args...) printk(args)
23#define DIPRINTK(n, args...) if (hd64465_io_debug>(n)) printk(args)
24#else
25#define DPRINTK(args...)
26#define DIPRINTK(n, args...)
27#endif
28
29
30
31/* This is a hack suitable only for debugging IO port problems */
32int hd64465_io_debug;
33EXPORT_SYMBOL(hd64465_io_debug);
34
35/* Low iomap maps port 0-1K to addresses in 8byte chunks */
36#define HD64465_IOMAP_LO_THRESH 0x400
37#define HD64465_IOMAP_LO_SHIFT 3
38#define HD64465_IOMAP_LO_MASK ((1<<HD64465_IOMAP_LO_SHIFT)-1)
39#define HD64465_IOMAP_LO_NMAP (HD64465_IOMAP_LO_THRESH>>HD64465_IOMAP_LO_SHIFT)
40static unsigned long hd64465_iomap_lo[HD64465_IOMAP_LO_NMAP];
41static unsigned char hd64465_iomap_lo_shift[HD64465_IOMAP_LO_NMAP];
42
43/* High iomap maps port 1K-64K to addresses in 1K chunks */
44#define HD64465_IOMAP_HI_THRESH 0x10000
45#define HD64465_IOMAP_HI_SHIFT 10
46#define HD64465_IOMAP_HI_MASK ((1<<HD64465_IOMAP_HI_SHIFT)-1)
47#define HD64465_IOMAP_HI_NMAP (HD64465_IOMAP_HI_THRESH>>HD64465_IOMAP_HI_SHIFT)
48static unsigned long hd64465_iomap_hi[HD64465_IOMAP_HI_NMAP];
49static unsigned char hd64465_iomap_hi_shift[HD64465_IOMAP_HI_NMAP];
50
51#ifndef MAX
52#define MAX(a,b) ((a)>(b)?(a):(b))
53#endif
54
55#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
56
57void hd64465_port_map(unsigned short baseport, unsigned int nports,
58 unsigned long addr, unsigned char shift)
59{
60 unsigned int port, endport = baseport + nports;
61
62 DPRINTK("hd64465_port_map(base=0x%04hx, n=0x%04hx, addr=0x%08lx,endport=0x%04x)\n",
63 baseport, nports, addr,endport);
64
65 for (port = baseport ;
66 port < endport && port < HD64465_IOMAP_LO_THRESH ;
67 port += (1<<HD64465_IOMAP_LO_SHIFT)) {
68 DPRINTK(" maplo[0x%x] = 0x%08lx\n", port, addr);
69 hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = addr;
70 hd64465_iomap_lo_shift[port>>HD64465_IOMAP_LO_SHIFT] = shift;
71 addr += (1<<(HD64465_IOMAP_LO_SHIFT));
72 }
73
74 for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
75 port < endport && port < HD64465_IOMAP_HI_THRESH ;
76 port += (1<<HD64465_IOMAP_HI_SHIFT)) {
77 DPRINTK(" maphi[0x%x] = 0x%08lx\n", port, addr);
78 hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = addr;
79 hd64465_iomap_hi_shift[port>>HD64465_IOMAP_HI_SHIFT] = shift;
80 addr += (1<<(HD64465_IOMAP_HI_SHIFT));
81 }
82}
83EXPORT_SYMBOL(hd64465_port_map);
84
85void hd64465_port_unmap(unsigned short baseport, unsigned int nports)
86{
87 unsigned int port, endport = baseport + nports;
88
89 DPRINTK("hd64465_port_unmap(base=0x%04hx, n=0x%04hx)\n",
90 baseport, nports);
91
92 for (port = baseport ;
93 port < endport && port < HD64465_IOMAP_LO_THRESH ;
94 port += (1<<HD64465_IOMAP_LO_SHIFT)) {
95 hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = 0;
96 }
97
98 for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
99 port < endport && port < HD64465_IOMAP_HI_THRESH ;
100 port += (1<<HD64465_IOMAP_HI_SHIFT)) {
101 hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = 0;
102 }
103}
104EXPORT_SYMBOL(hd64465_port_unmap);
105
106unsigned long hd64465_isa_port2addr(unsigned long port)
107{
108 unsigned long addr = 0;
109 unsigned char shift;
110
111 /* handle remapping of low IO ports */
112 if (port < HD64465_IOMAP_LO_THRESH) {
113 addr = hd64465_iomap_lo[port >> HD64465_IOMAP_LO_SHIFT];
114 shift = hd64465_iomap_lo_shift[port >> HD64465_IOMAP_LO_SHIFT];
115 if (addr != 0)
116 addr += (port & HD64465_IOMAP_LO_MASK) << shift;
117 else
118 printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port);
119 } else if (port < HD64465_IOMAP_HI_THRESH) {
120 addr = hd64465_iomap_hi[port >> HD64465_IOMAP_HI_SHIFT];
121 shift = hd64465_iomap_hi_shift[port >> HD64465_IOMAP_HI_SHIFT];
122 if (addr != 0)
123 addr += (port & HD64465_IOMAP_HI_MASK) << shift;
124 else
125 printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port);
126 }
127
128 /* HD64465 internal devices (0xb0000000) */
129 else if (port < 0x20000)
130 addr = CONFIG_HD64465_IOBASE + port - 0x10000;
131
132 /* Whole physical address space (0xa0000000) */
133 else
134 addr = P2SEGADDR(port);
135
136 DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr);
137
138 return addr;
139}
140
141static inline void delay(void)
142{
143 ctrl_inw(0xa0000000);
144}
145
146unsigned char hd64465_inb(unsigned long port)
147{
148 unsigned long addr = PORT2ADDR(port);
149 unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
150
151 DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b);
152 return b;
153}
154
155unsigned char hd64465_inb_p(unsigned long port)
156{
157 unsigned long v;
158 unsigned long addr = PORT2ADDR(port);
159
160 v = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
161 delay();
162 DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v);
163 return v;
164}
165
166unsigned short hd64465_inw(unsigned long port)
167{
168 unsigned long addr = PORT2ADDR(port);
169 unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr);
170 DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b);
171 return b;
172}
173
174unsigned int hd64465_inl(unsigned long port)
175{
176 unsigned long addr = PORT2ADDR(port);
177 unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr);
178 DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b);
179 return b;
180}
181
182void hd64465_outb(unsigned char b, unsigned long port)
183{
184 unsigned long addr = PORT2ADDR(port);
185
186 DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr);
187 if (addr != 0)
188 *(volatile unsigned char*)addr = b;
189}
190
191void hd64465_outb_p(unsigned char b, unsigned long port)
192{
193 unsigned long addr = PORT2ADDR(port);
194
195 DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr);
196 if (addr != 0)
197 *(volatile unsigned char*)addr = b;
198 delay();
199}
200
201void hd64465_outw(unsigned short b, unsigned long port)
202{
203 unsigned long addr = PORT2ADDR(port);
204 DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr);
205 if (addr != 0)
206 *(volatile unsigned short*)addr = b;
207}
208
209void hd64465_outl(unsigned int b, unsigned long port)
210{
211 unsigned long addr = PORT2ADDR(port);
212 DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr);
213 if (addr != 0)
214 *(volatile unsigned long*)addr = b;
215}
216
diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c
new file mode 100644
index 000000000000..68e4c4e4283d
--- /dev/null
+++ b/arch/sh/cchips/hd6446x/hd64465/setup.c
@@ -0,0 +1,202 @@
1/*
2 * $Id: setup.c,v 1.4 2003/08/03 03:05:10 lethal Exp $
3 *
4 * Setup and IRQ handling code for the HD64465 companion chip.
5 * by Greg Banks <gbanks@pocketpenguins.com>
6 * Copyright (c) 2000 PocketPenguins Inc
7 *
8 * Derived from setup_hd64461.c which bore the message:
9 * Copyright (C) 2000 YAEGASHI Takeshi
10 */
11
12#include <linux/config.h>
13#include <linux/sched.h>
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/param.h>
17#include <linux/ioport.h>
18#include <linux/interrupt.h>
19#include <linux/init.h>
20#include <linux/irq.h>
21
22#include <asm/io.h>
23#include <asm/irq.h>
24
25#include <asm/hd64465/hd64465.h>
26
27static void disable_hd64465_irq(unsigned int irq)
28{
29 unsigned long flags;
30 unsigned short nimr;
31 unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
32
33 pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask);
34 local_irq_save(flags);
35 nimr = inw(HD64465_REG_NIMR);
36 nimr |= mask;
37 outw(nimr, HD64465_REG_NIMR);
38 local_irq_restore(flags);
39}
40
41
42static void enable_hd64465_irq(unsigned int irq)
43{
44 unsigned long flags;
45 unsigned short nimr;
46 unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
47
48 pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask);
49 local_irq_save(flags);
50 nimr = inw(HD64465_REG_NIMR);
51 nimr &= ~mask;
52 outw(nimr, HD64465_REG_NIMR);
53 local_irq_restore(flags);
54}
55
56
57static void mask_and_ack_hd64465(unsigned int irq)
58{
59 disable_hd64465_irq(irq);
60}
61
62
63static void end_hd64465_irq(unsigned int irq)
64{
65 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
66 enable_hd64465_irq(irq);
67}
68
69
70static unsigned int startup_hd64465_irq(unsigned int irq)
71{
72 enable_hd64465_irq(irq);
73 return 0;
74}
75
76
77static void shutdown_hd64465_irq(unsigned int irq)
78{
79 disable_hd64465_irq(irq);
80}
81
82
83static struct hw_interrupt_type hd64465_irq_type = {
84 .typename = "HD64465-IRQ",
85 .startup = startup_hd64465_irq,
86 .shutdown = shutdown_hd64465_irq,
87 .enable = enable_hd64465_irq,
88 .disable = disable_hd64465_irq,
89 .ack = mask_and_ack_hd64465,
90 .end = end_hd64465_irq,
91};
92
93
94static irqreturn_t hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs)
95{
96 printk(KERN_INFO
97 "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n",
98 inw(HD64465_REG_NIRR), inw(HD64465_REG_NIMR));
99
100 return IRQ_NONE;
101}
102
103
104/*====================================================*/
105
106/*
107 * Support for a secondary IRQ demux step. This is necessary
108 * because the HD64465 presents a very thin interface to the
109 * PCMCIA bus; a lot of features (such as remapping interrupts)
110 * normally done in hardware by other PCMCIA host bridges is
111 * instead done in software.
112 */
113static struct
114{
115 int (*func)(int, void *);
116 void *dev;
117} hd64465_demux[HD64465_IRQ_NUM];
118
119void hd64465_register_irq_demux(int irq,
120 int (*demux)(int irq, void *dev), void *dev)
121{
122 hd64465_demux[irq - HD64465_IRQ_BASE].func = demux;
123 hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev;
124}
125EXPORT_SYMBOL(hd64465_register_irq_demux);
126
127void hd64465_unregister_irq_demux(int irq)
128{
129 hd64465_demux[irq - HD64465_IRQ_BASE].func = 0;
130}
131EXPORT_SYMBOL(hd64465_unregister_irq_demux);
132
133
134
135int hd64465_irq_demux(int irq)
136{
137 if (irq == CONFIG_HD64465_IRQ) {
138 unsigned short i, bit;
139 unsigned short nirr = inw(HD64465_REG_NIRR);
140 unsigned short nimr = inw(HD64465_REG_NIMR);
141
142 pr_debug("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr);
143 nirr &= ~nimr;
144 for (bit = 1, i = 0 ; i < HD64465_IRQ_NUM ; bit <<= 1, i++)
145 if (nirr & bit)
146 break;
147
148 if (i < HD64465_IRQ_NUM) {
149 irq = HD64465_IRQ_BASE + i;
150 if (hd64465_demux[i].func != 0)
151 irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev);
152 }
153 }
154 return irq;
155}
156
157static struct irqaction irq0 = { hd64465_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "HD64465", NULL, NULL};
158
159
160static int __init setup_hd64465(void)
161{
162 int i;
163 unsigned short rev;
164 unsigned short smscr;
165
166 if (!MACH_HD64465)
167 return 0;
168
169 printk(KERN_INFO "HD64465 configured at 0x%x on irq %d(mapped into %d to %d)\n",
170 CONFIG_HD64465_IOBASE,
171 CONFIG_HD64465_IRQ,
172 HD64465_IRQ_BASE,
173 HD64465_IRQ_BASE+HD64465_IRQ_NUM-1);
174
175 if (inw(HD64465_REG_SDID) != HD64465_SDID) {
176 printk(KERN_ERR "HD64465 device ID not found, check base address\n");
177 }
178
179 rev = inw(HD64465_REG_SRR);
180 printk(KERN_INFO "HD64465 hardware revision %d.%d\n", (rev >> 8) & 0xff, rev & 0xff);
181
182 outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */
183
184 for (i = 0; i < HD64465_IRQ_NUM ; i++) {
185 irq_desc[HD64465_IRQ_BASE + i].handler = &hd64465_irq_type;
186 }
187
188 setup_irq(CONFIG_HD64465_IRQ, &irq0);
189
190#ifdef CONFIG_SERIAL
191 /* wake up the UART from STANDBY at this point */
192 smscr = inw(HD64465_REG_SMSCR);
193 outw(smscr & (~HD64465_SMSCR_UARTST), HD64465_REG_SMSCR);
194
195 /* remap IO ports for first ISA serial port to HD64465 UART */
196 hd64465_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1);
197#endif
198
199 return 0;
200}
201
202module_init(setup_hd64465);
diff --git a/arch/sh/cchips/voyagergx/Makefile b/arch/sh/cchips/voyagergx/Makefile
new file mode 100644
index 000000000000..085de72fd327
--- /dev/null
+++ b/arch/sh/cchips/voyagergx/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for VoyagerGX
3#
4
5obj-y := irq.o setup.o
6
7obj-$(CONFIG_USB_OHCI_HCD) += consistent.o
8
diff --git a/arch/sh/cchips/voyagergx/consistent.c b/arch/sh/cchips/voyagergx/consistent.c
new file mode 100644
index 000000000000..5b92585a38d2
--- /dev/null
+++ b/arch/sh/cchips/voyagergx/consistent.c
@@ -0,0 +1,126 @@
1/*
2 * arch/sh/cchips/voyagergx/consistent.c
3 *
4 * Copyright (C) 2004 Paul Mundt
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/mm.h>
11#include <linux/dma-mapping.h>
12#include <linux/slab.h>
13#include <linux/list.h>
14#include <linux/types.h>
15#include <linux/module.h>
16#include <linux/device.h>
17#include <asm/io.h>
18#include <asm/bus-sh.h>
19
20struct voya_alloc_entry {
21 struct list_head list;
22 unsigned long ofs;
23 unsigned long len;
24};
25
26static DEFINE_SPINLOCK(voya_list_lock);
27static LIST_HEAD(voya_alloc_list);
28
29#define OHCI_SRAM_START 0xb0000000
30#define OHCI_HCCA_SIZE 0x100
31#define OHCI_SRAM_SIZE 0x10000
32
33void *voyagergx_consistent_alloc(struct device *dev, size_t size,
34 dma_addr_t *handle, int flag)
35{
36 struct list_head *list = &voya_alloc_list;
37 struct voya_alloc_entry *entry;
38 struct sh_dev *shdev = to_sh_dev(dev);
39 unsigned long start, end;
40 unsigned long flags;
41
42 /*
43 * The SM501 contains an integrated 8051 with its own SRAM.
44 * Devices within the cchip can all hook into the 8051 SRAM.
45 * We presently use this for the OHCI.
46 *
47 * Everything else goes through consistent_alloc().
48 */
49 if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
50 (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
51 shdev->dev_id != SH_DEV_ID_USB_OHCI))
52 return NULL;
53
54 start = OHCI_SRAM_START + OHCI_HCCA_SIZE;
55
56 entry = kmalloc(sizeof(struct voya_alloc_entry), GFP_ATOMIC);
57 if (!entry)
58 return ERR_PTR(-ENOMEM);
59
60 entry->len = (size + 15) & ~15;
61
62 /*
63 * The basis for this allocator is dwmw2's malloc.. the
64 * Matrox allocator :-)
65 */
66 spin_lock_irqsave(&voya_list_lock, flags);
67 list_for_each(list, &voya_alloc_list) {
68 struct voya_alloc_entry *p;
69
70 p = list_entry(list, struct voya_alloc_entry, list);
71
72 if (p->ofs - start >= size)
73 goto out;
74
75 start = p->ofs + p->len;
76 }
77
78 end = start + (OHCI_SRAM_SIZE - OHCI_HCCA_SIZE);
79 list = &voya_alloc_list;
80
81 if (end - start >= size) {
82out:
83 entry->ofs = start;
84 list_add_tail(&entry->list, list);
85 spin_unlock_irqrestore(&voya_list_lock, flags);
86
87 *handle = start;
88 return (void *)start;
89 }
90
91 kfree(entry);
92 spin_unlock_irqrestore(&voya_list_lock, flags);
93
94 return ERR_PTR(-EINVAL);
95}
96
97int voyagergx_consistent_free(struct device *dev, size_t size,
98 void *vaddr, dma_addr_t handle)
99{
100 struct voya_alloc_entry *entry;
101 struct sh_dev *shdev = to_sh_dev(dev);
102 unsigned long flags;
103
104 if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
105 (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
106 shdev->dev_id != SH_DEV_ID_USB_OHCI))
107 return -EINVAL;
108
109 spin_lock_irqsave(&voya_list_lock, flags);
110 list_for_each_entry(entry, &voya_alloc_list, list) {
111 if (entry->ofs != handle)
112 continue;
113
114 list_del(&entry->list);
115 kfree(entry);
116
117 break;
118 }
119 spin_unlock_irqrestore(&voya_list_lock, flags);
120
121 return 0;
122}
123
124EXPORT_SYMBOL(voyagergx_consistent_alloc);
125EXPORT_SYMBOL(voyagergx_consistent_free);
126
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
new file mode 100644
index 000000000000..3079234cb65b
--- /dev/null
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -0,0 +1,194 @@
1/* -------------------------------------------------------------------- */
2/* setup_voyagergx.c: */
3/* -------------------------------------------------------------------- */
4/* This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 Copyright 2003 (c) Lineo uSolutions,Inc.
19*/
20/* -------------------------------------------------------------------- */
21
22#undef DEBUG
23
24#include <linux/config.h>
25#include <linux/sched.h>
26#include <linux/module.h>
27#include <linux/kernel.h>
28#include <linux/param.h>
29#include <linux/ioport.h>
30#include <linux/interrupt.h>
31#include <linux/init.h>
32#include <linux/irq.h>
33
34#include <asm/io.h>
35#include <asm/irq.h>
36#include <asm/rts7751r2d/rts7751r2d.h>
37#include <asm/rts7751r2d/voyagergx_reg.h>
38
39static void disable_voyagergx_irq(unsigned int irq)
40{
41 unsigned long flags, val;
42 unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
43
44 pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
45 local_irq_save(flags);
46 val = inl(VOYAGER_INT_MASK);
47 val &= ~mask;
48 outl(val, VOYAGER_INT_MASK);
49 local_irq_restore(flags);
50}
51
52
53static void enable_voyagergx_irq(unsigned int irq)
54{
55 unsigned long flags, val;
56 unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
57
58 pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
59 local_irq_save(flags);
60 val = inl(VOYAGER_INT_MASK);
61 val |= mask;
62 outl(val, VOYAGER_INT_MASK);
63 local_irq_restore(flags);
64}
65
66
67static void mask_and_ack_voyagergx(unsigned int irq)
68{
69 disable_voyagergx_irq(irq);
70}
71
72static void end_voyagergx_irq(unsigned int irq)
73{
74 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
75 enable_voyagergx_irq(irq);
76}
77
78static unsigned int startup_voyagergx_irq(unsigned int irq)
79{
80 enable_voyagergx_irq(irq);
81 return 0;
82}
83
84static void shutdown_voyagergx_irq(unsigned int irq)
85{
86 disable_voyagergx_irq(irq);
87}
88
89static struct hw_interrupt_type voyagergx_irq_type = {
90 "VOYAGERGX-IRQ",
91 startup_voyagergx_irq,
92 shutdown_voyagergx_irq,
93 enable_voyagergx_irq,
94 disable_voyagergx_irq,
95 mask_and_ack_voyagergx,
96 end_voyagergx_irq,
97};
98
99static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
100{
101 printk(KERN_INFO
102 "VoyagerGX: spurious interrupt, status: 0x%x\n",
103 inl(INT_STATUS));
104 return IRQ_HANDLED;
105}
106
107
108/*====================================================*/
109
110static struct {
111 int (*func)(int, void *);
112 void *dev;
113} voyagergx_demux[VOYAGER_IRQ_NUM];
114
115void voyagergx_register_irq_demux(int irq,
116 int (*demux)(int irq, void *dev), void *dev)
117{
118 voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux;
119 voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev;
120}
121
122void voyagergx_unregister_irq_demux(int irq)
123{
124 voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0;
125}
126
127int voyagergx_irq_demux(int irq)
128{
129
130 if (irq == IRQ_VOYAGER ) {
131 unsigned long i = 0, bit __attribute__ ((unused));
132 unsigned long val = inl(INT_STATUS);
133#if 1
134 if ( val & ( 1 << 1 )){
135 i = 1;
136 } else if ( val & ( 1 << 2 )){
137 i = 2;
138 } else if ( val & ( 1 << 6 )){
139 i = 6;
140 } else if( val & ( 1 << 10 )){
141 i = 10;
142 } else if( val & ( 1 << 11 )){
143 i = 11;
144 } else if( val & ( 1 << 12 )){
145 i = 12;
146 } else if( val & ( 1 << 17 )){
147 i = 17;
148 } else {
149 printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
150 }
151 pr_debug("voyagergx_irq_demux %d \n", i);
152#else
153 for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++)
154 if (val & bit)
155 break;
156#endif
157 if (i < VOYAGER_IRQ_NUM) {
158 irq = VOYAGER_IRQ_BASE + i;
159 if (voyagergx_demux[i].func != 0)
160 irq = voyagergx_demux[i].func(irq, voyagergx_demux[i].dev);
161 }
162 }
163 return irq;
164}
165
166static struct irqaction irq0 = { voyagergx_interrupt, SA_INTERRUPT, 0, "VOYAGERGX", NULL, NULL};
167
168void __init setup_voyagergx_irq(void)
169{
170 int i, flag;
171
172 printk(KERN_INFO "VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n",
173 VOYAGER_BASE,
174 IRQ_VOYAGER,
175 VOYAGER_IRQ_BASE,
176 VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1);
177
178 for (i=0; i<VOYAGER_IRQ_NUM; i++) {
179 flag = 0;
180 switch (VOYAGER_IRQ_BASE + i) {
181 case VOYAGER_USBH_IRQ:
182 case VOYAGER_8051_IRQ:
183 case VOYAGER_UART0_IRQ:
184 case VOYAGER_UART1_IRQ:
185 case VOYAGER_AC97_IRQ:
186 flag = 1;
187 }
188 if (flag == 1)
189 irq_desc[VOYAGER_IRQ_BASE + i].handler = &voyagergx_irq_type;
190 }
191
192 setup_irq(IRQ_VOYAGER, &irq0);
193}
194
diff --git a/arch/sh/cchips/voyagergx/setup.c b/arch/sh/cchips/voyagergx/setup.c
new file mode 100644
index 000000000000..139ca88ac9e6
--- /dev/null
+++ b/arch/sh/cchips/voyagergx/setup.c
@@ -0,0 +1,37 @@
1/*
2 * arch/sh/cchips/voyagergx/setup.c
3 *
4 * Setup routines for VoyagerGX cchip.
5 *
6 * Copyright (C) 2003 Lineo uSolutions, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13#include <linux/init.h>
14#include <linux/module.h>
15#include <asm/io.h>
16#include <asm/rts7751r2d/voyagergx_reg.h>
17
18static int __init setup_voyagergx(void)
19{
20 unsigned long val;
21
22 val = inl(DRAM_CTRL);
23 val |= (DRAM_CTRL_CPU_COLUMN_SIZE_256 |
24 DRAM_CTRL_CPU_ACTIVE_PRECHARGE |
25 DRAM_CTRL_CPU_RESET |
26 DRAM_CTRL_REFRESH_COMMAND |
27 DRAM_CTRL_BLOCK_WRITE_TIME |
28 DRAM_CTRL_BLOCK_WRITE_PRECHARGE |
29 DRAM_CTRL_ACTIVE_PRECHARGE |
30 DRAM_CTRL_RESET |
31 DRAM_CTRL_REMAIN_ACTIVE);
32 outl(val, DRAM_CTRL);
33
34 return 0;
35}
36
37module_init(setup_voyagergx);