Commit 6d20819f8050092d40e9c99c55d82c8e26d42599
Committed by
Linus Torvalds
1 parent
5fb55ae955
Exists in
master
and in
7 other branches
[PATCH] irq-flags: SH: Use the new IRQF_ constants
Use the new IRQF_ constants and remove the SA_INTERRUPT define Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Cc: "David S. Miller" <davem@davemloft.net> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mundt <lethal@linux-sh.org> Cc: Kazumoto Kojima <kkojima@rr.iij4u.or.jp> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 13 changed files with 16 additions and 19 deletions Inline Diff
- arch/sh/boards/snapgear/setup.c
- arch/sh/cchips/hd6446x/hd64461/setup.c
- arch/sh/cchips/hd6446x/hd64465/gpio.c
- arch/sh/cchips/hd6446x/hd64465/setup.c
- arch/sh/cchips/voyagergx/irq.c
- arch/sh/drivers/dma/dma-g2.c
- arch/sh/drivers/dma/dma-pvr2.c
- arch/sh/drivers/dma/dma-sh.c
- arch/sh/drivers/pci/pci-st40.c
- arch/sh/kernel/timers/timer-tmu.c
- include/asm-sh/floppy.h
- include/asm-sh/mpc1211/keyboard.h
- include/asm-sh/signal.h
arch/sh/boards/snapgear/setup.c
1 | /****************************************************************************/ | 1 | /****************************************************************************/ |
2 | /* | 2 | /* |
3 | * linux/arch/sh/boards/snapgear/setup.c | 3 | * linux/arch/sh/boards/snapgear/setup.c |
4 | * | 4 | * |
5 | * Copyright (C) 2002 David McCullough <davidm@snapgear.com> | 5 | * Copyright (C) 2002 David McCullough <davidm@snapgear.com> |
6 | * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org> | 6 | * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org> |
7 | * | 7 | * |
8 | * Based on files with the following comments: | 8 | * Based on files with the following comments: |
9 | * | 9 | * |
10 | * Copyright (C) 2000 Kazumoto Kojima | 10 | * Copyright (C) 2000 Kazumoto Kojima |
11 | * | 11 | * |
12 | * Modified for 7751 Solution Engine by | 12 | * Modified for 7751 Solution Engine by |
13 | * Ian da Silva and Jeremy Siegel, 2001. | 13 | * Ian da Silva and Jeremy Siegel, 2001. |
14 | */ | 14 | */ |
15 | /****************************************************************************/ | 15 | /****************************************************************************/ |
16 | 16 | ||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/timer.h> | 20 | #include <linux/timer.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | 24 | ||
25 | #include <asm/machvec.h> | 25 | #include <asm/machvec.h> |
26 | #include <asm/mach/io.h> | 26 | #include <asm/mach/io.h> |
27 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
28 | #include <asm/io.h> | 28 | #include <asm/io.h> |
29 | #include <asm/cpu/timer.h> | 29 | #include <asm/cpu/timer.h> |
30 | 30 | ||
31 | extern void (*board_time_init)(void); | 31 | extern void (*board_time_init)(void); |
32 | extern void secureedge5410_rtc_init(void); | 32 | extern void secureedge5410_rtc_init(void); |
33 | extern void pcibios_init(void); | 33 | extern void pcibios_init(void); |
34 | 34 | ||
35 | /****************************************************************************/ | 35 | /****************************************************************************/ |
36 | /* | 36 | /* |
37 | * EraseConfig handling functions | 37 | * EraseConfig handling functions |
38 | */ | 38 | */ |
39 | 39 | ||
40 | static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 40 | static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
41 | { | 41 | { |
42 | volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000; | 42 | volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000; |
43 | 43 | ||
44 | printk("SnapGear: erase switch interrupt!\n"); | 44 | printk("SnapGear: erase switch interrupt!\n"); |
45 | 45 | ||
46 | return IRQ_HANDLED; | 46 | return IRQ_HANDLED; |
47 | } | 47 | } |
48 | 48 | ||
49 | static int __init eraseconfig_init(void) | 49 | static int __init eraseconfig_init(void) |
50 | { | 50 | { |
51 | printk("SnapGear: EraseConfig init\n"); | 51 | printk("SnapGear: EraseConfig init\n"); |
52 | /* Setup "EraseConfig" switch on external IRQ 0 */ | 52 | /* Setup "EraseConfig" switch on external IRQ 0 */ |
53 | if (request_irq(IRL0_IRQ, eraseconfig_interrupt, SA_INTERRUPT, | 53 | if (request_irq(IRL0_IRQ, eraseconfig_interrupt, IRQF_DISABLED, |
54 | "Erase Config", NULL)) | 54 | "Erase Config", NULL)) |
55 | printk("SnapGear: failed to register IRQ%d for Reset witch\n", | 55 | printk("SnapGear: failed to register IRQ%d for Reset witch\n", |
56 | IRL0_IRQ); | 56 | IRL0_IRQ); |
57 | else | 57 | else |
58 | printk("SnapGear: registered EraseConfig switch on IRQ%d\n", | 58 | printk("SnapGear: registered EraseConfig switch on IRQ%d\n", |
59 | IRL0_IRQ); | 59 | IRL0_IRQ); |
60 | return(0); | 60 | return(0); |
61 | } | 61 | } |
62 | 62 | ||
63 | module_init(eraseconfig_init); | 63 | module_init(eraseconfig_init); |
64 | 64 | ||
65 | /****************************************************************************/ | 65 | /****************************************************************************/ |
66 | /* | 66 | /* |
67 | * Initialize IRQ setting | 67 | * Initialize IRQ setting |
68 | * | 68 | * |
69 | * IRL0 = erase switch | 69 | * IRL0 = erase switch |
70 | * IRL1 = eth0 | 70 | * IRL1 = eth0 |
71 | * IRL2 = eth1 | 71 | * IRL2 = eth1 |
72 | * IRL3 = crypto | 72 | * IRL3 = crypto |
73 | */ | 73 | */ |
74 | 74 | ||
75 | static void __init init_snapgear_IRQ(void) | 75 | static void __init init_snapgear_IRQ(void) |
76 | { | 76 | { |
77 | /* enable individual interrupt mode for externals */ | 77 | /* enable individual interrupt mode for externals */ |
78 | ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); | 78 | ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); |
79 | 79 | ||
80 | printk("Setup SnapGear IRQ/IPR ...\n"); | 80 | printk("Setup SnapGear IRQ/IPR ...\n"); |
81 | 81 | ||
82 | make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); | 82 | make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); |
83 | make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); | 83 | make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); |
84 | make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); | 84 | make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); |
85 | make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); | 85 | make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); |
86 | } | 86 | } |
87 | 87 | ||
88 | /****************************************************************************/ | 88 | /****************************************************************************/ |
89 | /* | 89 | /* |
90 | * Fast poll interrupt simulator. | 90 | * Fast poll interrupt simulator. |
91 | */ | 91 | */ |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * Leave all of the fast timer/fast poll stuff commented out for now, since | 94 | * Leave all of the fast timer/fast poll stuff commented out for now, since |
95 | * it's not clear whether it actually works or not. Since it wasn't being used | 95 | * it's not clear whether it actually works or not. Since it wasn't being used |
96 | * at all in 2.4, we'll assume it's not sane for 2.6 either.. -- PFM | 96 | * at all in 2.4, we'll assume it's not sane for 2.6 either.. -- PFM |
97 | */ | 97 | */ |
98 | #if 0 | 98 | #if 0 |
99 | #define FAST_POLL 1000 | 99 | #define FAST_POLL 1000 |
100 | //#define FAST_POLL_INTR | 100 | //#define FAST_POLL_INTR |
101 | 101 | ||
102 | #define FASTTIMER_IRQ 17 | 102 | #define FASTTIMER_IRQ 17 |
103 | #define FASTTIMER_IPR_ADDR INTC_IPRA | 103 | #define FASTTIMER_IPR_ADDR INTC_IPRA |
104 | #define FASTTIMER_IPR_POS 2 | 104 | #define FASTTIMER_IPR_POS 2 |
105 | #define FASTTIMER_PRIORITY 3 | 105 | #define FASTTIMER_PRIORITY 3 |
106 | 106 | ||
107 | #ifdef FAST_POLL_INTR | 107 | #ifdef FAST_POLL_INTR |
108 | #define TMU1_TCR_INIT 0x0020 | 108 | #define TMU1_TCR_INIT 0x0020 |
109 | #else | 109 | #else |
110 | #define TMU1_TCR_INIT 0 | 110 | #define TMU1_TCR_INIT 0 |
111 | #endif | 111 | #endif |
112 | #define TMU_TSTR_INIT 1 | 112 | #define TMU_TSTR_INIT 1 |
113 | #define TMU1_TCR_CALIB 0x0000 | 113 | #define TMU1_TCR_CALIB 0x0000 |
114 | 114 | ||
115 | 115 | ||
116 | #ifdef FAST_POLL_INTR | 116 | #ifdef FAST_POLL_INTR |
117 | static void fast_timer_irq(int irq, void *dev_instance, struct pt_regs *regs) | 117 | static void fast_timer_irq(int irq, void *dev_instance, struct pt_regs *regs) |
118 | { | 118 | { |
119 | unsigned long timer_status; | 119 | unsigned long timer_status; |
120 | timer_status = ctrl_inw(TMU1_TCR); | 120 | timer_status = ctrl_inw(TMU1_TCR); |
121 | timer_status &= ~0x100; | 121 | timer_status &= ~0x100; |
122 | ctrl_outw(timer_status, TMU1_TCR); | 122 | ctrl_outw(timer_status, TMU1_TCR); |
123 | } | 123 | } |
124 | #endif | 124 | #endif |
125 | 125 | ||
126 | /* | 126 | /* |
127 | * return the current ticks on the fast timer | 127 | * return the current ticks on the fast timer |
128 | */ | 128 | */ |
129 | 129 | ||
130 | unsigned long fast_timer_count(void) | 130 | unsigned long fast_timer_count(void) |
131 | { | 131 | { |
132 | return(ctrl_inl(TMU1_TCNT)); | 132 | return(ctrl_inl(TMU1_TCNT)); |
133 | } | 133 | } |
134 | 134 | ||
135 | /* | 135 | /* |
136 | * setup a fast timer for profiling etc etc | 136 | * setup a fast timer for profiling etc etc |
137 | */ | 137 | */ |
138 | 138 | ||
139 | static void setup_fast_timer() | 139 | static void setup_fast_timer() |
140 | { | 140 | { |
141 | unsigned long interval; | 141 | unsigned long interval; |
142 | 142 | ||
143 | #ifdef FAST_POLL_INTR | 143 | #ifdef FAST_POLL_INTR |
144 | interval = (current_cpu_data.module_clock/4 + FAST_POLL/2) / FAST_POLL; | 144 | interval = (current_cpu_data.module_clock/4 + FAST_POLL/2) / FAST_POLL; |
145 | 145 | ||
146 | make_ipr_irq(FASTTIMER_IRQ, FASTTIMER_IPR_ADDR, FASTTIMER_IPR_POS, | 146 | make_ipr_irq(FASTTIMER_IRQ, FASTTIMER_IPR_ADDR, FASTTIMER_IPR_POS, |
147 | FASTTIMER_PRIORITY); | 147 | FASTTIMER_PRIORITY); |
148 | 148 | ||
149 | printk("SnapGear: %dHz fast timer on IRQ %d\n",FAST_POLL,FASTTIMER_IRQ); | 149 | printk("SnapGear: %dHz fast timer on IRQ %d\n",FAST_POLL,FASTTIMER_IRQ); |
150 | 150 | ||
151 | if (request_irq(FASTTIMER_IRQ, fast_timer_irq, 0, "SnapGear fast timer", | 151 | if (request_irq(FASTTIMER_IRQ, fast_timer_irq, 0, "SnapGear fast timer", |
152 | NULL) != 0) | 152 | NULL) != 0) |
153 | printk("%s(%d): request_irq() failed?\n", __FILE__, __LINE__); | 153 | printk("%s(%d): request_irq() failed?\n", __FILE__, __LINE__); |
154 | #else | 154 | #else |
155 | printk("SnapGear: fast timer running\n",FAST_POLL,FASTTIMER_IRQ); | 155 | printk("SnapGear: fast timer running\n",FAST_POLL,FASTTIMER_IRQ); |
156 | interval = 0xffffffff; | 156 | interval = 0xffffffff; |
157 | #endif | 157 | #endif |
158 | 158 | ||
159 | ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x2, TMU_TSTR); /* disable timer 1 */ | 159 | ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x2, TMU_TSTR); /* disable timer 1 */ |
160 | ctrl_outw(TMU1_TCR_INIT, TMU1_TCR); | 160 | ctrl_outw(TMU1_TCR_INIT, TMU1_TCR); |
161 | ctrl_outl(interval, TMU1_TCOR); | 161 | ctrl_outl(interval, TMU1_TCOR); |
162 | ctrl_outl(interval, TMU1_TCNT); | 162 | ctrl_outl(interval, TMU1_TCNT); |
163 | ctrl_outb(ctrl_inb(TMU_TSTR) | 0x2, TMU_TSTR); /* enable timer 1 */ | 163 | ctrl_outb(ctrl_inb(TMU_TSTR) | 0x2, TMU_TSTR); /* enable timer 1 */ |
164 | 164 | ||
165 | printk("Timer count 1 = 0x%x\n", fast_timer_count()); | 165 | printk("Timer count 1 = 0x%x\n", fast_timer_count()); |
166 | udelay(1000); | 166 | udelay(1000); |
167 | printk("Timer count 2 = 0x%x\n", fast_timer_count()); | 167 | printk("Timer count 2 = 0x%x\n", fast_timer_count()); |
168 | } | 168 | } |
169 | #endif | 169 | #endif |
170 | 170 | ||
171 | /****************************************************************************/ | 171 | /****************************************************************************/ |
172 | 172 | ||
173 | const char *get_system_type(void) | 173 | const char *get_system_type(void) |
174 | { | 174 | { |
175 | return "SnapGear SecureEdge5410"; | 175 | return "SnapGear SecureEdge5410"; |
176 | } | 176 | } |
177 | 177 | ||
178 | /* | 178 | /* |
179 | * The Machine Vector | 179 | * The Machine Vector |
180 | */ | 180 | */ |
181 | 181 | ||
182 | struct sh_machine_vector mv_snapgear __initmv = { | 182 | struct sh_machine_vector mv_snapgear __initmv = { |
183 | .mv_nr_irqs = 72, | 183 | .mv_nr_irqs = 72, |
184 | 184 | ||
185 | .mv_inb = snapgear_inb, | 185 | .mv_inb = snapgear_inb, |
186 | .mv_inw = snapgear_inw, | 186 | .mv_inw = snapgear_inw, |
187 | .mv_inl = snapgear_inl, | 187 | .mv_inl = snapgear_inl, |
188 | .mv_outb = snapgear_outb, | 188 | .mv_outb = snapgear_outb, |
189 | .mv_outw = snapgear_outw, | 189 | .mv_outw = snapgear_outw, |
190 | .mv_outl = snapgear_outl, | 190 | .mv_outl = snapgear_outl, |
191 | 191 | ||
192 | .mv_inb_p = snapgear_inb_p, | 192 | .mv_inb_p = snapgear_inb_p, |
193 | .mv_inw_p = snapgear_inw, | 193 | .mv_inw_p = snapgear_inw, |
194 | .mv_inl_p = snapgear_inl, | 194 | .mv_inl_p = snapgear_inl, |
195 | .mv_outb_p = snapgear_outb_p, | 195 | .mv_outb_p = snapgear_outb_p, |
196 | .mv_outw_p = snapgear_outw, | 196 | .mv_outw_p = snapgear_outw, |
197 | .mv_outl_p = snapgear_outl, | 197 | .mv_outl_p = snapgear_outl, |
198 | 198 | ||
199 | .mv_isa_port2addr = snapgear_isa_port2addr, | 199 | .mv_isa_port2addr = snapgear_isa_port2addr, |
200 | 200 | ||
201 | .mv_init_irq = init_snapgear_IRQ, | 201 | .mv_init_irq = init_snapgear_IRQ, |
202 | }; | 202 | }; |
203 | ALIAS_MV(snapgear) | 203 | ALIAS_MV(snapgear) |
204 | 204 | ||
205 | /* | 205 | /* |
206 | * Initialize the board | 206 | * Initialize the board |
207 | */ | 207 | */ |
208 | 208 | ||
209 | int __init platform_setup(void) | 209 | int __init platform_setup(void) |
210 | { | 210 | { |
211 | board_time_init = secureedge5410_rtc_init; | 211 | board_time_init = secureedge5410_rtc_init; |
212 | 212 | ||
213 | return 0; | 213 | return 0; |
214 | } | 214 | } |
215 | 215 | ||
216 | 216 |
arch/sh/cchips/hd6446x/hd64461/setup.c
1 | /* | 1 | /* |
2 | * $Id: setup.c,v 1.5 2004/03/16 00:07:50 lethal Exp $ | 2 | * $Id: setup.c,v 1.5 2004/03/16 00:07:50 lethal Exp $ |
3 | * Copyright (C) 2000 YAEGASHI Takeshi | 3 | * Copyright (C) 2000 YAEGASHI Takeshi |
4 | * Hitachi HD64461 companion chip support | 4 | * Hitachi HD64461 companion chip support |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/param.h> | 10 | #include <linux/param.h> |
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | 14 | ||
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | #include <asm/irq.h> | 16 | #include <asm/irq.h> |
17 | 17 | ||
18 | #include <asm/hd64461/hd64461.h> | 18 | #include <asm/hd64461/hd64461.h> |
19 | 19 | ||
20 | static void disable_hd64461_irq(unsigned int irq) | 20 | static void disable_hd64461_irq(unsigned int irq) |
21 | { | 21 | { |
22 | unsigned long flags; | 22 | unsigned long flags; |
23 | unsigned short nimr; | 23 | unsigned short nimr; |
24 | unsigned short mask = 1 << (irq - HD64461_IRQBASE); | 24 | unsigned short mask = 1 << (irq - HD64461_IRQBASE); |
25 | 25 | ||
26 | local_irq_save(flags); | 26 | local_irq_save(flags); |
27 | nimr = inw(HD64461_NIMR); | 27 | nimr = inw(HD64461_NIMR); |
28 | nimr |= mask; | 28 | nimr |= mask; |
29 | outw(nimr, HD64461_NIMR); | 29 | outw(nimr, HD64461_NIMR); |
30 | local_irq_restore(flags); | 30 | local_irq_restore(flags); |
31 | } | 31 | } |
32 | 32 | ||
33 | static void enable_hd64461_irq(unsigned int irq) | 33 | static void enable_hd64461_irq(unsigned int irq) |
34 | { | 34 | { |
35 | unsigned long flags; | 35 | unsigned long flags; |
36 | unsigned short nimr; | 36 | unsigned short nimr; |
37 | unsigned short mask = 1 << (irq - HD64461_IRQBASE); | 37 | unsigned short mask = 1 << (irq - HD64461_IRQBASE); |
38 | 38 | ||
39 | local_irq_save(flags); | 39 | local_irq_save(flags); |
40 | nimr = inw(HD64461_NIMR); | 40 | nimr = inw(HD64461_NIMR); |
41 | nimr &= ~mask; | 41 | nimr &= ~mask; |
42 | outw(nimr, HD64461_NIMR); | 42 | outw(nimr, HD64461_NIMR); |
43 | local_irq_restore(flags); | 43 | local_irq_restore(flags); |
44 | } | 44 | } |
45 | 45 | ||
46 | static void mask_and_ack_hd64461(unsigned int irq) | 46 | static void mask_and_ack_hd64461(unsigned int irq) |
47 | { | 47 | { |
48 | disable_hd64461_irq(irq); | 48 | disable_hd64461_irq(irq); |
49 | #ifdef CONFIG_HD64461_ENABLER | 49 | #ifdef CONFIG_HD64461_ENABLER |
50 | if (irq == HD64461_IRQBASE + 13) | 50 | if (irq == HD64461_IRQBASE + 13) |
51 | outb(0x00, HD64461_PCC1CSCR); | 51 | outb(0x00, HD64461_PCC1CSCR); |
52 | #endif | 52 | #endif |
53 | } | 53 | } |
54 | 54 | ||
55 | static void end_hd64461_irq(unsigned int irq) | 55 | static void end_hd64461_irq(unsigned int irq) |
56 | { | 56 | { |
57 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 57 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
58 | enable_hd64461_irq(irq); | 58 | enable_hd64461_irq(irq); |
59 | } | 59 | } |
60 | 60 | ||
61 | static unsigned int startup_hd64461_irq(unsigned int irq) | 61 | static unsigned int startup_hd64461_irq(unsigned int irq) |
62 | { | 62 | { |
63 | enable_hd64461_irq(irq); | 63 | enable_hd64461_irq(irq); |
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | 66 | ||
67 | static void shutdown_hd64461_irq(unsigned int irq) | 67 | static void shutdown_hd64461_irq(unsigned int irq) |
68 | { | 68 | { |
69 | disable_hd64461_irq(irq); | 69 | disable_hd64461_irq(irq); |
70 | } | 70 | } |
71 | 71 | ||
72 | static struct hw_interrupt_type hd64461_irq_type = { | 72 | static struct hw_interrupt_type hd64461_irq_type = { |
73 | .typename = "HD64461-IRQ", | 73 | .typename = "HD64461-IRQ", |
74 | .startup = startup_hd64461_irq, | 74 | .startup = startup_hd64461_irq, |
75 | .shutdown = shutdown_hd64461_irq, | 75 | .shutdown = shutdown_hd64461_irq, |
76 | .enable = enable_hd64461_irq, | 76 | .enable = enable_hd64461_irq, |
77 | .disable = disable_hd64461_irq, | 77 | .disable = disable_hd64461_irq, |
78 | .ack = mask_and_ack_hd64461, | 78 | .ack = mask_and_ack_hd64461, |
79 | .end = end_hd64461_irq, | 79 | .end = end_hd64461_irq, |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static irqreturn_t hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 82 | static irqreturn_t hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
83 | { | 83 | { |
84 | printk(KERN_INFO | 84 | printk(KERN_INFO |
85 | "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", | 85 | "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", |
86 | inw(HD64461_NIRR), inw(HD64461_NIMR)); | 86 | inw(HD64461_NIRR), inw(HD64461_NIMR)); |
87 | 87 | ||
88 | return IRQ_NONE; | 88 | return IRQ_NONE; |
89 | } | 89 | } |
90 | 90 | ||
91 | static struct { | 91 | static struct { |
92 | int (*func) (int, void *); | 92 | int (*func) (int, void *); |
93 | void *dev; | 93 | void *dev; |
94 | } hd64461_demux[HD64461_IRQ_NUM]; | 94 | } hd64461_demux[HD64461_IRQ_NUM]; |
95 | 95 | ||
96 | void hd64461_register_irq_demux(int irq, | 96 | void hd64461_register_irq_demux(int irq, |
97 | int (*demux) (int irq, void *dev), void *dev) | 97 | int (*demux) (int irq, void *dev), void *dev) |
98 | { | 98 | { |
99 | hd64461_demux[irq - HD64461_IRQBASE].func = demux; | 99 | hd64461_demux[irq - HD64461_IRQBASE].func = demux; |
100 | hd64461_demux[irq - HD64461_IRQBASE].dev = dev; | 100 | hd64461_demux[irq - HD64461_IRQBASE].dev = dev; |
101 | } | 101 | } |
102 | 102 | ||
103 | EXPORT_SYMBOL(hd64461_register_irq_demux); | 103 | EXPORT_SYMBOL(hd64461_register_irq_demux); |
104 | 104 | ||
105 | void hd64461_unregister_irq_demux(int irq) | 105 | void hd64461_unregister_irq_demux(int irq) |
106 | { | 106 | { |
107 | hd64461_demux[irq - HD64461_IRQBASE].func = 0; | 107 | hd64461_demux[irq - HD64461_IRQBASE].func = 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | EXPORT_SYMBOL(hd64461_unregister_irq_demux); | 110 | EXPORT_SYMBOL(hd64461_unregister_irq_demux); |
111 | 111 | ||
112 | int hd64461_irq_demux(int irq) | 112 | int hd64461_irq_demux(int irq) |
113 | { | 113 | { |
114 | if (irq == CONFIG_HD64461_IRQ) { | 114 | if (irq == CONFIG_HD64461_IRQ) { |
115 | unsigned short bit; | 115 | unsigned short bit; |
116 | unsigned short nirr = inw(HD64461_NIRR); | 116 | unsigned short nirr = inw(HD64461_NIRR); |
117 | unsigned short nimr = inw(HD64461_NIMR); | 117 | unsigned short nimr = inw(HD64461_NIMR); |
118 | int i; | 118 | int i; |
119 | 119 | ||
120 | nirr &= ~nimr; | 120 | nirr &= ~nimr; |
121 | for (bit = 1, i = 0; i < 16; bit <<= 1, i++) | 121 | for (bit = 1, i = 0; i < 16; bit <<= 1, i++) |
122 | if (nirr & bit) | 122 | if (nirr & bit) |
123 | break; | 123 | break; |
124 | if (i == 16) | 124 | if (i == 16) |
125 | irq = CONFIG_HD64461_IRQ; | 125 | irq = CONFIG_HD64461_IRQ; |
126 | else { | 126 | else { |
127 | irq = HD64461_IRQBASE + i; | 127 | irq = HD64461_IRQBASE + i; |
128 | if (hd64461_demux[i].func != 0) { | 128 | if (hd64461_demux[i].func != 0) { |
129 | irq = hd64461_demux[i].func(irq, hd64461_demux[i].dev); | 129 | irq = hd64461_demux[i].func(irq, hd64461_demux[i].dev); |
130 | } | 130 | } |
131 | } | 131 | } |
132 | } | 132 | } |
133 | return __irq_demux(irq); | 133 | return __irq_demux(irq); |
134 | } | 134 | } |
135 | 135 | ||
136 | static struct irqaction irq0 = { hd64461_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "HD64461", NULL, NULL }; | 136 | static struct irqaction irq0 = { hd64461_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "HD64461", NULL, NULL }; |
137 | 137 | ||
138 | int __init setup_hd64461(void) | 138 | int __init setup_hd64461(void) |
139 | { | 139 | { |
140 | int i; | 140 | int i; |
141 | 141 | ||
142 | if (!MACH_HD64461) | 142 | if (!MACH_HD64461) |
143 | return 0; | 143 | return 0; |
144 | 144 | ||
145 | printk(KERN_INFO | 145 | printk(KERN_INFO |
146 | "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n", | 146 | "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n", |
147 | CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ, HD64461_IRQBASE, | 147 | CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ, HD64461_IRQBASE, |
148 | HD64461_IRQBASE + 15); | 148 | HD64461_IRQBASE + 15); |
149 | 149 | ||
150 | #if defined(CONFIG_CPU_SUBTYPE_SH7709) /* Should be at processor specific part.. */ | 150 | #if defined(CONFIG_CPU_SUBTYPE_SH7709) /* Should be at processor specific part.. */ |
151 | outw(0x2240, INTC_ICR1); | 151 | outw(0x2240, INTC_ICR1); |
152 | #endif | 152 | #endif |
153 | outw(0xffff, HD64461_NIMR); | 153 | outw(0xffff, HD64461_NIMR); |
154 | 154 | ||
155 | for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) { | 155 | for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) { |
156 | irq_desc[i].chip = &hd64461_irq_type; | 156 | irq_desc[i].chip = &hd64461_irq_type; |
157 | } | 157 | } |
158 | 158 | ||
159 | setup_irq(CONFIG_HD64461_IRQ, &irq0); | 159 | setup_irq(CONFIG_HD64461_IRQ, &irq0); |
160 | 160 | ||
161 | #ifdef CONFIG_HD64461_ENABLER | 161 | #ifdef CONFIG_HD64461_ENABLER |
162 | printk(KERN_INFO "HD64461: enabling PCMCIA devices\n"); | 162 | printk(KERN_INFO "HD64461: enabling PCMCIA devices\n"); |
163 | outb(0x4c, HD64461_PCC1CSCIER); | 163 | outb(0x4c, HD64461_PCC1CSCIER); |
164 | outb(0x00, HD64461_PCC1CSCR); | 164 | outb(0x00, HD64461_PCC1CSCR); |
165 | #endif | 165 | #endif |
166 | 166 | ||
167 | return 0; | 167 | return 0; |
168 | } | 168 | } |
169 | 169 | ||
170 | module_init(setup_hd64461); | 170 | module_init(setup_hd64461); |
171 | 171 |
arch/sh/cchips/hd6446x/hd64465/gpio.c
1 | /* | 1 | /* |
2 | * $Id: gpio.c,v 1.4 2003/05/19 22:24:18 lethal Exp $ | 2 | * $Id: gpio.c,v 1.4 2003/05/19 22:24:18 lethal Exp $ |
3 | * by Greg Banks <gbanks@pocketpenguins.com> | 3 | * by Greg Banks <gbanks@pocketpenguins.com> |
4 | * (c) 2000 PocketPenguins Inc | 4 | * (c) 2000 PocketPenguins Inc |
5 | * | 5 | * |
6 | * GPIO pin support for HD64465 companion chip. | 6 | * GPIO pin support for HD64465 companion chip. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | #include <linux/ioport.h> | 13 | #include <linux/ioport.h> |
14 | #include <asm/io.h> | 14 | #include <asm/io.h> |
15 | #include <asm/hd64465/gpio.h> | 15 | #include <asm/hd64465/gpio.h> |
16 | 16 | ||
17 | #define _PORTOF(portpin) (((portpin)>>3)&0x7) | 17 | #define _PORTOF(portpin) (((portpin)>>3)&0x7) |
18 | #define _PINOF(portpin) ((portpin)&0x7) | 18 | #define _PINOF(portpin) ((portpin)&0x7) |
19 | 19 | ||
20 | /* Register addresses parametrised on port */ | 20 | /* Register addresses parametrised on port */ |
21 | #define GPIO_CR(port) (HD64465_REG_GPACR+((port)<<1)) | 21 | #define GPIO_CR(port) (HD64465_REG_GPACR+((port)<<1)) |
22 | #define GPIO_DR(port) (HD64465_REG_GPADR+((port)<<1)) | 22 | #define GPIO_DR(port) (HD64465_REG_GPADR+((port)<<1)) |
23 | #define GPIO_ICR(port) (HD64465_REG_GPAICR+((port)<<1)) | 23 | #define GPIO_ICR(port) (HD64465_REG_GPAICR+((port)<<1)) |
24 | #define GPIO_ISR(port) (HD64465_REG_GPAISR+((port)<<1)) | 24 | #define GPIO_ISR(port) (HD64465_REG_GPAISR+((port)<<1)) |
25 | 25 | ||
26 | #define GPIO_NPORTS 5 | 26 | #define GPIO_NPORTS 5 |
27 | 27 | ||
28 | #define MODNAME "hd64465_gpio" | 28 | #define MODNAME "hd64465_gpio" |
29 | 29 | ||
30 | EXPORT_SYMBOL(hd64465_gpio_configure); | 30 | EXPORT_SYMBOL(hd64465_gpio_configure); |
31 | EXPORT_SYMBOL(hd64465_gpio_get_pin); | 31 | EXPORT_SYMBOL(hd64465_gpio_get_pin); |
32 | EXPORT_SYMBOL(hd64465_gpio_get_port); | 32 | EXPORT_SYMBOL(hd64465_gpio_get_port); |
33 | EXPORT_SYMBOL(hd64465_gpio_register_irq); | 33 | EXPORT_SYMBOL(hd64465_gpio_register_irq); |
34 | EXPORT_SYMBOL(hd64465_gpio_set_pin); | 34 | EXPORT_SYMBOL(hd64465_gpio_set_pin); |
35 | EXPORT_SYMBOL(hd64465_gpio_set_port); | 35 | EXPORT_SYMBOL(hd64465_gpio_set_port); |
36 | EXPORT_SYMBOL(hd64465_gpio_unregister_irq); | 36 | EXPORT_SYMBOL(hd64465_gpio_unregister_irq); |
37 | 37 | ||
38 | /* TODO: each port should be protected with a spinlock */ | 38 | /* TODO: each port should be protected with a spinlock */ |
39 | 39 | ||
40 | 40 | ||
41 | void hd64465_gpio_configure(int portpin, int direction) | 41 | void hd64465_gpio_configure(int portpin, int direction) |
42 | { | 42 | { |
43 | unsigned short cr; | 43 | unsigned short cr; |
44 | unsigned int shift = (_PINOF(portpin)<<1); | 44 | unsigned int shift = (_PINOF(portpin)<<1); |
45 | 45 | ||
46 | cr = inw(GPIO_CR(_PORTOF(portpin))); | 46 | cr = inw(GPIO_CR(_PORTOF(portpin))); |
47 | cr &= ~(3<<shift); | 47 | cr &= ~(3<<shift); |
48 | cr |= direction<<shift; | 48 | cr |= direction<<shift; |
49 | outw(cr, GPIO_CR(_PORTOF(portpin))); | 49 | outw(cr, GPIO_CR(_PORTOF(portpin))); |
50 | } | 50 | } |
51 | 51 | ||
52 | void hd64465_gpio_set_pin(int portpin, unsigned int value) | 52 | void hd64465_gpio_set_pin(int portpin, unsigned int value) |
53 | { | 53 | { |
54 | unsigned short d; | 54 | unsigned short d; |
55 | unsigned short mask = 1<<(_PINOF(portpin)); | 55 | unsigned short mask = 1<<(_PINOF(portpin)); |
56 | 56 | ||
57 | d = inw(GPIO_DR(_PORTOF(portpin))); | 57 | d = inw(GPIO_DR(_PORTOF(portpin))); |
58 | if (value) | 58 | if (value) |
59 | d |= mask; | 59 | d |= mask; |
60 | else | 60 | else |
61 | d &= ~mask; | 61 | d &= ~mask; |
62 | outw(d, GPIO_DR(_PORTOF(portpin))); | 62 | outw(d, GPIO_DR(_PORTOF(portpin))); |
63 | } | 63 | } |
64 | 64 | ||
65 | unsigned int hd64465_gpio_get_pin(int portpin) | 65 | unsigned int hd64465_gpio_get_pin(int portpin) |
66 | { | 66 | { |
67 | return inw(GPIO_DR(_PORTOF(portpin))) & (1<<(_PINOF(portpin))); | 67 | return inw(GPIO_DR(_PORTOF(portpin))) & (1<<(_PINOF(portpin))); |
68 | } | 68 | } |
69 | 69 | ||
70 | /* TODO: for cleaner atomicity semantics, add a mask to this routine */ | 70 | /* TODO: for cleaner atomicity semantics, add a mask to this routine */ |
71 | 71 | ||
72 | void hd64465_gpio_set_port(int port, unsigned int value) | 72 | void hd64465_gpio_set_port(int port, unsigned int value) |
73 | { | 73 | { |
74 | outw(value, GPIO_DR(port)); | 74 | outw(value, GPIO_DR(port)); |
75 | } | 75 | } |
76 | 76 | ||
77 | unsigned int hd64465_gpio_get_port(int port) | 77 | unsigned int hd64465_gpio_get_port(int port) |
78 | { | 78 | { |
79 | return inw(GPIO_DR(port)); | 79 | return inw(GPIO_DR(port)); |
80 | } | 80 | } |
81 | 81 | ||
82 | 82 | ||
83 | static struct { | 83 | static struct { |
84 | void (*func)(int portpin, void *dev); | 84 | void (*func)(int portpin, void *dev); |
85 | void *dev; | 85 | void *dev; |
86 | } handlers[GPIO_NPORTS * 8]; | 86 | } handlers[GPIO_NPORTS * 8]; |
87 | 87 | ||
88 | static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs) | 88 | static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs) |
89 | { | 89 | { |
90 | unsigned short port, pin, isr, mask, portpin; | 90 | unsigned short port, pin, isr, mask, portpin; |
91 | 91 | ||
92 | for (port=0 ; port<GPIO_NPORTS ; port++) { | 92 | for (port=0 ; port<GPIO_NPORTS ; port++) { |
93 | isr = inw(GPIO_ISR(port)); | 93 | isr = inw(GPIO_ISR(port)); |
94 | 94 | ||
95 | for (pin=0 ; pin<8 ; pin++) { | 95 | for (pin=0 ; pin<8 ; pin++) { |
96 | mask = 1<<pin; | 96 | mask = 1<<pin; |
97 | if (isr & mask) { | 97 | if (isr & mask) { |
98 | portpin = (port<<3)|pin; | 98 | portpin = (port<<3)|pin; |
99 | if (handlers[portpin].func != 0) | 99 | if (handlers[portpin].func != 0) |
100 | handlers[portpin].func(portpin, handlers[portpin].dev); | 100 | handlers[portpin].func(portpin, handlers[portpin].dev); |
101 | else | 101 | else |
102 | printk(KERN_NOTICE "unexpected GPIO interrupt, pin %c%d\n", | 102 | printk(KERN_NOTICE "unexpected GPIO interrupt, pin %c%d\n", |
103 | port+'A', (int)pin); | 103 | port+'A', (int)pin); |
104 | } | 104 | } |
105 | } | 105 | } |
106 | 106 | ||
107 | /* Write 1s back to ISR to clear it? That's what the manual says.. */ | 107 | /* Write 1s back to ISR to clear it? That's what the manual says.. */ |
108 | outw(isr, GPIO_ISR(port)); | 108 | outw(isr, GPIO_ISR(port)); |
109 | } | 109 | } |
110 | 110 | ||
111 | return IRQ_HANDLED; | 111 | return IRQ_HANDLED; |
112 | } | 112 | } |
113 | 113 | ||
114 | void hd64465_gpio_register_irq(int portpin, int mode, | 114 | void hd64465_gpio_register_irq(int portpin, int mode, |
115 | void (*handler)(int portpin, void *dev), void *dev) | 115 | void (*handler)(int portpin, void *dev), void *dev) |
116 | { | 116 | { |
117 | unsigned long flags; | 117 | unsigned long flags; |
118 | unsigned short icr, mask; | 118 | unsigned short icr, mask; |
119 | 119 | ||
120 | if (handler == 0) | 120 | if (handler == 0) |
121 | return; | 121 | return; |
122 | 122 | ||
123 | local_irq_save(flags); | 123 | local_irq_save(flags); |
124 | 124 | ||
125 | handlers[portpin].func = handler; | 125 | handlers[portpin].func = handler; |
126 | handlers[portpin].dev = dev; | 126 | handlers[portpin].dev = dev; |
127 | 127 | ||
128 | /* | 128 | /* |
129 | * Configure Interrupt Control Register | 129 | * Configure Interrupt Control Register |
130 | */ | 130 | */ |
131 | icr = inw(GPIO_ICR(_PORTOF(portpin))); | 131 | icr = inw(GPIO_ICR(_PORTOF(portpin))); |
132 | mask = (1<<_PINOF(portpin)); | 132 | mask = (1<<_PINOF(portpin)); |
133 | 133 | ||
134 | /* unmask interrupt */ | 134 | /* unmask interrupt */ |
135 | icr &= ~mask; | 135 | icr &= ~mask; |
136 | 136 | ||
137 | /* set TS bit */ | 137 | /* set TS bit */ |
138 | mask <<= 8; | 138 | mask <<= 8; |
139 | icr &= ~mask; | 139 | icr &= ~mask; |
140 | if (mode == HD64465_GPIO_RISING) | 140 | if (mode == HD64465_GPIO_RISING) |
141 | icr |= mask; | 141 | icr |= mask; |
142 | 142 | ||
143 | outw(icr, GPIO_ICR(_PORTOF(portpin))); | 143 | outw(icr, GPIO_ICR(_PORTOF(portpin))); |
144 | 144 | ||
145 | local_irq_restore(flags); | 145 | local_irq_restore(flags); |
146 | } | 146 | } |
147 | 147 | ||
148 | void hd64465_gpio_unregister_irq(int portpin) | 148 | void hd64465_gpio_unregister_irq(int portpin) |
149 | { | 149 | { |
150 | unsigned long flags; | 150 | unsigned long flags; |
151 | unsigned short icr; | 151 | unsigned short icr; |
152 | 152 | ||
153 | local_irq_save(flags); | 153 | local_irq_save(flags); |
154 | 154 | ||
155 | /* | 155 | /* |
156 | * Configure Interrupt Control Register | 156 | * Configure Interrupt Control Register |
157 | */ | 157 | */ |
158 | icr = inw(GPIO_ICR(_PORTOF(portpin))); | 158 | icr = inw(GPIO_ICR(_PORTOF(portpin))); |
159 | icr |= (1<<_PINOF(portpin)); /* mask interrupt */ | 159 | icr |= (1<<_PINOF(portpin)); /* mask interrupt */ |
160 | outw(icr, GPIO_ICR(_PORTOF(portpin))); | 160 | outw(icr, GPIO_ICR(_PORTOF(portpin))); |
161 | 161 | ||
162 | handlers[portpin].func = 0; | 162 | handlers[portpin].func = 0; |
163 | handlers[portpin].dev = 0; | 163 | handlers[portpin].dev = 0; |
164 | 164 | ||
165 | local_irq_restore(flags); | 165 | local_irq_restore(flags); |
166 | } | 166 | } |
167 | 167 | ||
168 | static int __init hd64465_gpio_init(void) | 168 | static int __init hd64465_gpio_init(void) |
169 | { | 169 | { |
170 | if (!request_region(HD64465_REG_GPACR, 0x1000, MODNAME)) | 170 | if (!request_region(HD64465_REG_GPACR, 0x1000, MODNAME)) |
171 | return -EBUSY; | 171 | return -EBUSY; |
172 | if (request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt, | 172 | if (request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt, |
173 | SA_INTERRUPT, MODNAME, 0)) | 173 | IRQF_DISABLED, MODNAME, 0)) |
174 | goto out_irqfailed; | 174 | goto out_irqfailed; |
175 | 175 | ||
176 | printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO); | 176 | printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO); |
177 | 177 | ||
178 | return 0; | 178 | return 0; |
179 | 179 | ||
180 | out_irqfailed: | 180 | out_irqfailed: |
181 | release_region(HD64465_REG_GPACR, 0x1000); | 181 | release_region(HD64465_REG_GPACR, 0x1000); |
182 | 182 | ||
183 | return -EINVAL; | 183 | return -EINVAL; |
184 | } | 184 | } |
185 | 185 | ||
186 | static void __exit hd64465_gpio_exit(void) | 186 | static void __exit hd64465_gpio_exit(void) |
187 | { | 187 | { |
188 | release_region(HD64465_REG_GPACR, 0x1000); | 188 | release_region(HD64465_REG_GPACR, 0x1000); |
189 | free_irq(HD64465_IRQ_GPIO, 0); | 189 | free_irq(HD64465_IRQ_GPIO, 0); |
190 | } | 190 | } |
191 | 191 | ||
192 | module_init(hd64465_gpio_init); | 192 | module_init(hd64465_gpio_init); |
193 | module_exit(hd64465_gpio_exit); | 193 | module_exit(hd64465_gpio_exit); |
194 | 194 | ||
195 | MODULE_LICENSE("GPL"); | 195 | MODULE_LICENSE("GPL"); |
196 | 196 | ||
197 | 197 |
arch/sh/cchips/hd6446x/hd64465/setup.c
1 | /* | 1 | /* |
2 | * $Id: setup.c,v 1.4 2003/08/03 03:05:10 lethal Exp $ | 2 | * $Id: setup.c,v 1.4 2003/08/03 03:05:10 lethal Exp $ |
3 | * | 3 | * |
4 | * Setup and IRQ handling code for the HD64465 companion chip. | 4 | * Setup and IRQ handling code for the HD64465 companion chip. |
5 | * by Greg Banks <gbanks@pocketpenguins.com> | 5 | * by Greg Banks <gbanks@pocketpenguins.com> |
6 | * Copyright (c) 2000 PocketPenguins Inc | 6 | * Copyright (c) 2000 PocketPenguins Inc |
7 | * | 7 | * |
8 | * Derived from setup_hd64461.c which bore the message: | 8 | * Derived from setup_hd64461.c which bore the message: |
9 | * Copyright (C) 2000 YAEGASHI Takeshi | 9 | * Copyright (C) 2000 YAEGASHI Takeshi |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/param.h> | 15 | #include <linux/param.h> |
16 | #include <linux/ioport.h> | 16 | #include <linux/ioport.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | 20 | ||
21 | #include <asm/io.h> | 21 | #include <asm/io.h> |
22 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
23 | 23 | ||
24 | #include <asm/hd64465/hd64465.h> | 24 | #include <asm/hd64465/hd64465.h> |
25 | 25 | ||
26 | static void disable_hd64465_irq(unsigned int irq) | 26 | static void disable_hd64465_irq(unsigned int irq) |
27 | { | 27 | { |
28 | unsigned long flags; | 28 | unsigned long flags; |
29 | unsigned short nimr; | 29 | unsigned short nimr; |
30 | unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); | 30 | unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); |
31 | 31 | ||
32 | pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask); | 32 | pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask); |
33 | local_irq_save(flags); | 33 | local_irq_save(flags); |
34 | nimr = inw(HD64465_REG_NIMR); | 34 | nimr = inw(HD64465_REG_NIMR); |
35 | nimr |= mask; | 35 | nimr |= mask; |
36 | outw(nimr, HD64465_REG_NIMR); | 36 | outw(nimr, HD64465_REG_NIMR); |
37 | local_irq_restore(flags); | 37 | local_irq_restore(flags); |
38 | } | 38 | } |
39 | 39 | ||
40 | 40 | ||
41 | static void enable_hd64465_irq(unsigned int irq) | 41 | static void enable_hd64465_irq(unsigned int irq) |
42 | { | 42 | { |
43 | unsigned long flags; | 43 | unsigned long flags; |
44 | unsigned short nimr; | 44 | unsigned short nimr; |
45 | unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); | 45 | unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); |
46 | 46 | ||
47 | pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask); | 47 | pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask); |
48 | local_irq_save(flags); | 48 | local_irq_save(flags); |
49 | nimr = inw(HD64465_REG_NIMR); | 49 | nimr = inw(HD64465_REG_NIMR); |
50 | nimr &= ~mask; | 50 | nimr &= ~mask; |
51 | outw(nimr, HD64465_REG_NIMR); | 51 | outw(nimr, HD64465_REG_NIMR); |
52 | local_irq_restore(flags); | 52 | local_irq_restore(flags); |
53 | } | 53 | } |
54 | 54 | ||
55 | 55 | ||
56 | static void mask_and_ack_hd64465(unsigned int irq) | 56 | static void mask_and_ack_hd64465(unsigned int irq) |
57 | { | 57 | { |
58 | disable_hd64465_irq(irq); | 58 | disable_hd64465_irq(irq); |
59 | } | 59 | } |
60 | 60 | ||
61 | 61 | ||
62 | static void end_hd64465_irq(unsigned int irq) | 62 | static void end_hd64465_irq(unsigned int irq) |
63 | { | 63 | { |
64 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 64 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
65 | enable_hd64465_irq(irq); | 65 | enable_hd64465_irq(irq); |
66 | } | 66 | } |
67 | 67 | ||
68 | 68 | ||
69 | static unsigned int startup_hd64465_irq(unsigned int irq) | 69 | static unsigned int startup_hd64465_irq(unsigned int irq) |
70 | { | 70 | { |
71 | enable_hd64465_irq(irq); | 71 | enable_hd64465_irq(irq); |
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
75 | 75 | ||
76 | static void shutdown_hd64465_irq(unsigned int irq) | 76 | static void shutdown_hd64465_irq(unsigned int irq) |
77 | { | 77 | { |
78 | disable_hd64465_irq(irq); | 78 | disable_hd64465_irq(irq); |
79 | } | 79 | } |
80 | 80 | ||
81 | 81 | ||
82 | static struct hw_interrupt_type hd64465_irq_type = { | 82 | static struct hw_interrupt_type hd64465_irq_type = { |
83 | .typename = "HD64465-IRQ", | 83 | .typename = "HD64465-IRQ", |
84 | .startup = startup_hd64465_irq, | 84 | .startup = startup_hd64465_irq, |
85 | .shutdown = shutdown_hd64465_irq, | 85 | .shutdown = shutdown_hd64465_irq, |
86 | .enable = enable_hd64465_irq, | 86 | .enable = enable_hd64465_irq, |
87 | .disable = disable_hd64465_irq, | 87 | .disable = disable_hd64465_irq, |
88 | .ack = mask_and_ack_hd64465, | 88 | .ack = mask_and_ack_hd64465, |
89 | .end = end_hd64465_irq, | 89 | .end = end_hd64465_irq, |
90 | }; | 90 | }; |
91 | 91 | ||
92 | 92 | ||
93 | static irqreturn_t hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 93 | static irqreturn_t hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
94 | { | 94 | { |
95 | printk(KERN_INFO | 95 | printk(KERN_INFO |
96 | "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", | 96 | "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", |
97 | inw(HD64465_REG_NIRR), inw(HD64465_REG_NIMR)); | 97 | inw(HD64465_REG_NIRR), inw(HD64465_REG_NIMR)); |
98 | 98 | ||
99 | return IRQ_NONE; | 99 | return IRQ_NONE; |
100 | } | 100 | } |
101 | 101 | ||
102 | 102 | ||
103 | /*====================================================*/ | 103 | /*====================================================*/ |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * Support for a secondary IRQ demux step. This is necessary | 106 | * Support for a secondary IRQ demux step. This is necessary |
107 | * because the HD64465 presents a very thin interface to the | 107 | * because the HD64465 presents a very thin interface to the |
108 | * PCMCIA bus; a lot of features (such as remapping interrupts) | 108 | * PCMCIA bus; a lot of features (such as remapping interrupts) |
109 | * normally done in hardware by other PCMCIA host bridges is | 109 | * normally done in hardware by other PCMCIA host bridges is |
110 | * instead done in software. | 110 | * instead done in software. |
111 | */ | 111 | */ |
112 | static struct | 112 | static struct |
113 | { | 113 | { |
114 | int (*func)(int, void *); | 114 | int (*func)(int, void *); |
115 | void *dev; | 115 | void *dev; |
116 | } hd64465_demux[HD64465_IRQ_NUM]; | 116 | } hd64465_demux[HD64465_IRQ_NUM]; |
117 | 117 | ||
118 | void hd64465_register_irq_demux(int irq, | 118 | void hd64465_register_irq_demux(int irq, |
119 | int (*demux)(int irq, void *dev), void *dev) | 119 | int (*demux)(int irq, void *dev), void *dev) |
120 | { | 120 | { |
121 | hd64465_demux[irq - HD64465_IRQ_BASE].func = demux; | 121 | hd64465_demux[irq - HD64465_IRQ_BASE].func = demux; |
122 | hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev; | 122 | hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev; |
123 | } | 123 | } |
124 | EXPORT_SYMBOL(hd64465_register_irq_demux); | 124 | EXPORT_SYMBOL(hd64465_register_irq_demux); |
125 | 125 | ||
126 | void hd64465_unregister_irq_demux(int irq) | 126 | void hd64465_unregister_irq_demux(int irq) |
127 | { | 127 | { |
128 | hd64465_demux[irq - HD64465_IRQ_BASE].func = 0; | 128 | hd64465_demux[irq - HD64465_IRQ_BASE].func = 0; |
129 | } | 129 | } |
130 | EXPORT_SYMBOL(hd64465_unregister_irq_demux); | 130 | EXPORT_SYMBOL(hd64465_unregister_irq_demux); |
131 | 131 | ||
132 | 132 | ||
133 | 133 | ||
134 | int hd64465_irq_demux(int irq) | 134 | int hd64465_irq_demux(int irq) |
135 | { | 135 | { |
136 | if (irq == CONFIG_HD64465_IRQ) { | 136 | if (irq == CONFIG_HD64465_IRQ) { |
137 | unsigned short i, bit; | 137 | unsigned short i, bit; |
138 | unsigned short nirr = inw(HD64465_REG_NIRR); | 138 | unsigned short nirr = inw(HD64465_REG_NIRR); |
139 | unsigned short nimr = inw(HD64465_REG_NIMR); | 139 | unsigned short nimr = inw(HD64465_REG_NIMR); |
140 | 140 | ||
141 | pr_debug("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr); | 141 | pr_debug("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr); |
142 | nirr &= ~nimr; | 142 | nirr &= ~nimr; |
143 | for (bit = 1, i = 0 ; i < HD64465_IRQ_NUM ; bit <<= 1, i++) | 143 | for (bit = 1, i = 0 ; i < HD64465_IRQ_NUM ; bit <<= 1, i++) |
144 | if (nirr & bit) | 144 | if (nirr & bit) |
145 | break; | 145 | break; |
146 | 146 | ||
147 | if (i < HD64465_IRQ_NUM) { | 147 | if (i < HD64465_IRQ_NUM) { |
148 | irq = HD64465_IRQ_BASE + i; | 148 | irq = HD64465_IRQ_BASE + i; |
149 | if (hd64465_demux[i].func != 0) | 149 | if (hd64465_demux[i].func != 0) |
150 | irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev); | 150 | irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev); |
151 | } | 151 | } |
152 | } | 152 | } |
153 | return irq; | 153 | return irq; |
154 | } | 154 | } |
155 | 155 | ||
156 | static struct irqaction irq0 = { hd64465_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "HD64465", NULL, NULL}; | 156 | static struct irqaction irq0 = { hd64465_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "HD64465", NULL, NULL}; |
157 | 157 | ||
158 | 158 | ||
159 | static int __init setup_hd64465(void) | 159 | static int __init setup_hd64465(void) |
160 | { | 160 | { |
161 | int i; | 161 | int i; |
162 | unsigned short rev; | 162 | unsigned short rev; |
163 | unsigned short smscr; | 163 | unsigned short smscr; |
164 | 164 | ||
165 | if (!MACH_HD64465) | 165 | if (!MACH_HD64465) |
166 | return 0; | 166 | return 0; |
167 | 167 | ||
168 | printk(KERN_INFO "HD64465 configured at 0x%x on irq %d(mapped into %d to %d)\n", | 168 | printk(KERN_INFO "HD64465 configured at 0x%x on irq %d(mapped into %d to %d)\n", |
169 | CONFIG_HD64465_IOBASE, | 169 | CONFIG_HD64465_IOBASE, |
170 | CONFIG_HD64465_IRQ, | 170 | CONFIG_HD64465_IRQ, |
171 | HD64465_IRQ_BASE, | 171 | HD64465_IRQ_BASE, |
172 | HD64465_IRQ_BASE+HD64465_IRQ_NUM-1); | 172 | HD64465_IRQ_BASE+HD64465_IRQ_NUM-1); |
173 | 173 | ||
174 | if (inw(HD64465_REG_SDID) != HD64465_SDID) { | 174 | if (inw(HD64465_REG_SDID) != HD64465_SDID) { |
175 | printk(KERN_ERR "HD64465 device ID not found, check base address\n"); | 175 | printk(KERN_ERR "HD64465 device ID not found, check base address\n"); |
176 | } | 176 | } |
177 | 177 | ||
178 | rev = inw(HD64465_REG_SRR); | 178 | rev = inw(HD64465_REG_SRR); |
179 | printk(KERN_INFO "HD64465 hardware revision %d.%d\n", (rev >> 8) & 0xff, rev & 0xff); | 179 | printk(KERN_INFO "HD64465 hardware revision %d.%d\n", (rev >> 8) & 0xff, rev & 0xff); |
180 | 180 | ||
181 | outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */ | 181 | outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */ |
182 | 182 | ||
183 | for (i = 0; i < HD64465_IRQ_NUM ; i++) { | 183 | for (i = 0; i < HD64465_IRQ_NUM ; i++) { |
184 | irq_desc[HD64465_IRQ_BASE + i].chip = &hd64465_irq_type; | 184 | irq_desc[HD64465_IRQ_BASE + i].chip = &hd64465_irq_type; |
185 | } | 185 | } |
186 | 186 | ||
187 | setup_irq(CONFIG_HD64465_IRQ, &irq0); | 187 | setup_irq(CONFIG_HD64465_IRQ, &irq0); |
188 | 188 | ||
189 | #ifdef CONFIG_SERIAL | 189 | #ifdef CONFIG_SERIAL |
190 | /* wake up the UART from STANDBY at this point */ | 190 | /* wake up the UART from STANDBY at this point */ |
191 | smscr = inw(HD64465_REG_SMSCR); | 191 | smscr = inw(HD64465_REG_SMSCR); |
192 | outw(smscr & (~HD64465_SMSCR_UARTST), HD64465_REG_SMSCR); | 192 | outw(smscr & (~HD64465_SMSCR_UARTST), HD64465_REG_SMSCR); |
193 | 193 | ||
194 | /* remap IO ports for first ISA serial port to HD64465 UART */ | 194 | /* remap IO ports for first ISA serial port to HD64465 UART */ |
195 | hd64465_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1); | 195 | hd64465_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1); |
196 | #endif | 196 | #endif |
197 | 197 | ||
198 | return 0; | 198 | return 0; |
199 | } | 199 | } |
200 | 200 | ||
201 | module_init(setup_hd64465); | 201 | module_init(setup_hd64465); |
202 | 202 |
arch/sh/cchips/voyagergx/irq.c
1 | /* -------------------------------------------------------------------- */ | 1 | /* -------------------------------------------------------------------- */ |
2 | /* setup_voyagergx.c: */ | 2 | /* setup_voyagergx.c: */ |
3 | /* -------------------------------------------------------------------- */ | 3 | /* -------------------------------------------------------------------- */ |
4 | /* This program is free software; you can redistribute it and/or modify | 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 | 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 | 6 | the Free Software Foundation; either version 2 of the License, or |
7 | (at your option) any later version. | 7 | (at your option) any later version. |
8 | 8 | ||
9 | This program is distributed in the hope that it will be useful, | 9 | This program is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | GNU General Public License for more details. | 12 | GNU General Public License for more details. |
13 | 13 | ||
14 | You should have received a copy of the GNU General Public License | 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 | 15 | along with this program; if not, write to the Free Software |
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | 17 | ||
18 | Copyright 2003 (c) Lineo uSolutions,Inc. | 18 | Copyright 2003 (c) Lineo uSolutions,Inc. |
19 | */ | 19 | */ |
20 | /* -------------------------------------------------------------------- */ | 20 | /* -------------------------------------------------------------------- */ |
21 | 21 | ||
22 | #undef DEBUG | 22 | #undef DEBUG |
23 | 23 | ||
24 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/param.h> | 27 | #include <linux/param.h> |
28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/irq.h> | 31 | #include <linux/irq.h> |
32 | 32 | ||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/irq.h> | 34 | #include <asm/irq.h> |
35 | #include <asm/rts7751r2d/rts7751r2d.h> | 35 | #include <asm/rts7751r2d/rts7751r2d.h> |
36 | #include <asm/rts7751r2d/voyagergx_reg.h> | 36 | #include <asm/rts7751r2d/voyagergx_reg.h> |
37 | 37 | ||
38 | static void disable_voyagergx_irq(unsigned int irq) | 38 | static void disable_voyagergx_irq(unsigned int irq) |
39 | { | 39 | { |
40 | unsigned long flags, val; | 40 | unsigned long flags, val; |
41 | unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); | 41 | unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); |
42 | 42 | ||
43 | pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask); | 43 | pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask); |
44 | local_irq_save(flags); | 44 | local_irq_save(flags); |
45 | val = inl(VOYAGER_INT_MASK); | 45 | val = inl(VOYAGER_INT_MASK); |
46 | val &= ~mask; | 46 | val &= ~mask; |
47 | outl(val, VOYAGER_INT_MASK); | 47 | outl(val, VOYAGER_INT_MASK); |
48 | local_irq_restore(flags); | 48 | local_irq_restore(flags); |
49 | } | 49 | } |
50 | 50 | ||
51 | 51 | ||
52 | static void enable_voyagergx_irq(unsigned int irq) | 52 | static void enable_voyagergx_irq(unsigned int irq) |
53 | { | 53 | { |
54 | unsigned long flags, val; | 54 | unsigned long flags, val; |
55 | unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); | 55 | unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); |
56 | 56 | ||
57 | pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask); | 57 | pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask); |
58 | local_irq_save(flags); | 58 | local_irq_save(flags); |
59 | val = inl(VOYAGER_INT_MASK); | 59 | val = inl(VOYAGER_INT_MASK); |
60 | val |= mask; | 60 | val |= mask; |
61 | outl(val, VOYAGER_INT_MASK); | 61 | outl(val, VOYAGER_INT_MASK); |
62 | local_irq_restore(flags); | 62 | local_irq_restore(flags); |
63 | } | 63 | } |
64 | 64 | ||
65 | 65 | ||
66 | static void mask_and_ack_voyagergx(unsigned int irq) | 66 | static void mask_and_ack_voyagergx(unsigned int irq) |
67 | { | 67 | { |
68 | disable_voyagergx_irq(irq); | 68 | disable_voyagergx_irq(irq); |
69 | } | 69 | } |
70 | 70 | ||
71 | static void end_voyagergx_irq(unsigned int irq) | 71 | static void end_voyagergx_irq(unsigned int irq) |
72 | { | 72 | { |
73 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 73 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
74 | enable_voyagergx_irq(irq); | 74 | enable_voyagergx_irq(irq); |
75 | } | 75 | } |
76 | 76 | ||
77 | static unsigned int startup_voyagergx_irq(unsigned int irq) | 77 | static unsigned int startup_voyagergx_irq(unsigned int irq) |
78 | { | 78 | { |
79 | enable_voyagergx_irq(irq); | 79 | enable_voyagergx_irq(irq); |
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | static void shutdown_voyagergx_irq(unsigned int irq) | 83 | static void shutdown_voyagergx_irq(unsigned int irq) |
84 | { | 84 | { |
85 | disable_voyagergx_irq(irq); | 85 | disable_voyagergx_irq(irq); |
86 | } | 86 | } |
87 | 87 | ||
88 | static struct hw_interrupt_type voyagergx_irq_type = { | 88 | static struct hw_interrupt_type voyagergx_irq_type = { |
89 | .typename = "VOYAGERGX-IRQ", | 89 | .typename = "VOYAGERGX-IRQ", |
90 | .startup = startup_voyagergx_irq, | 90 | .startup = startup_voyagergx_irq, |
91 | .shutdown = shutdown_voyagergx_irq, | 91 | .shutdown = shutdown_voyagergx_irq, |
92 | .enable = enable_voyagergx_irq, | 92 | .enable = enable_voyagergx_irq, |
93 | .disable = disable_voyagergx_irq, | 93 | .disable = disable_voyagergx_irq, |
94 | .ack = mask_and_ack_voyagergx, | 94 | .ack = mask_and_ack_voyagergx, |
95 | .end = end_voyagergx_irq, | 95 | .end = end_voyagergx_irq, |
96 | }; | 96 | }; |
97 | 97 | ||
98 | static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 98 | static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
99 | { | 99 | { |
100 | printk(KERN_INFO | 100 | printk(KERN_INFO |
101 | "VoyagerGX: spurious interrupt, status: 0x%x\n", | 101 | "VoyagerGX: spurious interrupt, status: 0x%x\n", |
102 | inl(INT_STATUS)); | 102 | inl(INT_STATUS)); |
103 | return IRQ_HANDLED; | 103 | return IRQ_HANDLED; |
104 | } | 104 | } |
105 | 105 | ||
106 | 106 | ||
107 | /*====================================================*/ | 107 | /*====================================================*/ |
108 | 108 | ||
109 | static struct { | 109 | static struct { |
110 | int (*func)(int, void *); | 110 | int (*func)(int, void *); |
111 | void *dev; | 111 | void *dev; |
112 | } voyagergx_demux[VOYAGER_IRQ_NUM]; | 112 | } voyagergx_demux[VOYAGER_IRQ_NUM]; |
113 | 113 | ||
114 | void voyagergx_register_irq_demux(int irq, | 114 | void voyagergx_register_irq_demux(int irq, |
115 | int (*demux)(int irq, void *dev), void *dev) | 115 | int (*demux)(int irq, void *dev), void *dev) |
116 | { | 116 | { |
117 | voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux; | 117 | voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux; |
118 | voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev; | 118 | voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev; |
119 | } | 119 | } |
120 | 120 | ||
121 | void voyagergx_unregister_irq_demux(int irq) | 121 | void voyagergx_unregister_irq_demux(int irq) |
122 | { | 122 | { |
123 | voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0; | 123 | voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0; |
124 | } | 124 | } |
125 | 125 | ||
126 | int voyagergx_irq_demux(int irq) | 126 | int voyagergx_irq_demux(int irq) |
127 | { | 127 | { |
128 | 128 | ||
129 | if (irq == IRQ_VOYAGER ) { | 129 | if (irq == IRQ_VOYAGER ) { |
130 | unsigned long i = 0, bit __attribute__ ((unused)); | 130 | unsigned long i = 0, bit __attribute__ ((unused)); |
131 | unsigned long val = inl(INT_STATUS); | 131 | unsigned long val = inl(INT_STATUS); |
132 | #if 1 | 132 | #if 1 |
133 | if ( val & ( 1 << 1 )){ | 133 | if ( val & ( 1 << 1 )){ |
134 | i = 1; | 134 | i = 1; |
135 | } else if ( val & ( 1 << 2 )){ | 135 | } else if ( val & ( 1 << 2 )){ |
136 | i = 2; | 136 | i = 2; |
137 | } else if ( val & ( 1 << 6 )){ | 137 | } else if ( val & ( 1 << 6 )){ |
138 | i = 6; | 138 | i = 6; |
139 | } else if( val & ( 1 << 10 )){ | 139 | } else if( val & ( 1 << 10 )){ |
140 | i = 10; | 140 | i = 10; |
141 | } else if( val & ( 1 << 11 )){ | 141 | } else if( val & ( 1 << 11 )){ |
142 | i = 11; | 142 | i = 11; |
143 | } else if( val & ( 1 << 12 )){ | 143 | } else if( val & ( 1 << 12 )){ |
144 | i = 12; | 144 | i = 12; |
145 | } else if( val & ( 1 << 17 )){ | 145 | } else if( val & ( 1 << 17 )){ |
146 | i = 17; | 146 | i = 17; |
147 | } else { | 147 | } else { |
148 | printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val); | 148 | printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val); |
149 | } | 149 | } |
150 | pr_debug("voyagergx_irq_demux %d \n", i); | 150 | pr_debug("voyagergx_irq_demux %d \n", i); |
151 | #else | 151 | #else |
152 | for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++) | 152 | for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++) |
153 | if (val & bit) | 153 | if (val & bit) |
154 | break; | 154 | break; |
155 | #endif | 155 | #endif |
156 | if (i < VOYAGER_IRQ_NUM) { | 156 | if (i < VOYAGER_IRQ_NUM) { |
157 | irq = VOYAGER_IRQ_BASE + i; | 157 | irq = VOYAGER_IRQ_BASE + i; |
158 | if (voyagergx_demux[i].func != 0) | 158 | if (voyagergx_demux[i].func != 0) |
159 | irq = voyagergx_demux[i].func(irq, voyagergx_demux[i].dev); | 159 | irq = voyagergx_demux[i].func(irq, voyagergx_demux[i].dev); |
160 | } | 160 | } |
161 | } | 161 | } |
162 | return irq; | 162 | return irq; |
163 | } | 163 | } |
164 | 164 | ||
165 | static struct irqaction irq0 = { | 165 | static struct irqaction irq0 = { |
166 | .name = "voyagergx", | 166 | .name = "voyagergx", |
167 | .handler = voyagergx_interrupt, | 167 | .handler = voyagergx_interrupt, |
168 | .flags = SA_INTERRUPT, | 168 | .flags = IRQF_DISABLED, |
169 | .mask = CPU_MASK_NONE, | 169 | .mask = CPU_MASK_NONE, |
170 | }; | 170 | }; |
171 | 171 | ||
172 | void __init setup_voyagergx_irq(void) | 172 | void __init setup_voyagergx_irq(void) |
173 | { | 173 | { |
174 | int i, flag; | 174 | int i, flag; |
175 | 175 | ||
176 | printk(KERN_INFO "VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n", | 176 | printk(KERN_INFO "VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n", |
177 | VOYAGER_BASE, | 177 | VOYAGER_BASE, |
178 | IRQ_VOYAGER, | 178 | IRQ_VOYAGER, |
179 | VOYAGER_IRQ_BASE, | 179 | VOYAGER_IRQ_BASE, |
180 | VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1); | 180 | VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1); |
181 | 181 | ||
182 | for (i=0; i<VOYAGER_IRQ_NUM; i++) { | 182 | for (i=0; i<VOYAGER_IRQ_NUM; i++) { |
183 | flag = 0; | 183 | flag = 0; |
184 | switch (VOYAGER_IRQ_BASE + i) { | 184 | switch (VOYAGER_IRQ_BASE + i) { |
185 | case VOYAGER_USBH_IRQ: | 185 | case VOYAGER_USBH_IRQ: |
186 | case VOYAGER_8051_IRQ: | 186 | case VOYAGER_8051_IRQ: |
187 | case VOYAGER_UART0_IRQ: | 187 | case VOYAGER_UART0_IRQ: |
188 | case VOYAGER_UART1_IRQ: | 188 | case VOYAGER_UART1_IRQ: |
189 | case VOYAGER_AC97_IRQ: | 189 | case VOYAGER_AC97_IRQ: |
190 | flag = 1; | 190 | flag = 1; |
191 | } | 191 | } |
192 | if (flag == 1) | 192 | if (flag == 1) |
193 | irq_desc[VOYAGER_IRQ_BASE + i].chip = &voyagergx_irq_type; | 193 | irq_desc[VOYAGER_IRQ_BASE + i].chip = &voyagergx_irq_type; |
194 | } | 194 | } |
195 | 195 | ||
196 | setup_irq(IRQ_VOYAGER, &irq0); | 196 | setup_irq(IRQ_VOYAGER, &irq0); |
197 | } | 197 | } |
198 | 198 | ||
199 | 199 |
arch/sh/drivers/dma/dma-g2.c
1 | /* | 1 | /* |
2 | * arch/sh/drivers/dma/dma-g2.c | 2 | * arch/sh/drivers/dma/dma-g2.c |
3 | * | 3 | * |
4 | * G2 bus DMA support | 4 | * G2 bus DMA support |
5 | * | 5 | * |
6 | * Copyright (C) 2003, 2004 Paul Mundt | 6 | * Copyright (C) 2003, 2004 Paul Mundt |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file "COPYING" in the main directory of this archive | 9 | * License. See the file "COPYING" in the main directory of this archive |
10 | * for more details. | 10 | * for more details. |
11 | */ | 11 | */ |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | 16 | ||
17 | #include <asm/mach/sysasic.h> | 17 | #include <asm/mach/sysasic.h> |
18 | #include <asm/mach/dma.h> | 18 | #include <asm/mach/dma.h> |
19 | #include <asm/dma.h> | 19 | #include <asm/dma.h> |
20 | 20 | ||
21 | struct g2_channel { | 21 | struct g2_channel { |
22 | unsigned long g2_addr; /* G2 bus address */ | 22 | unsigned long g2_addr; /* G2 bus address */ |
23 | unsigned long root_addr; /* Root bus (SH-4) address */ | 23 | unsigned long root_addr; /* Root bus (SH-4) address */ |
24 | unsigned long size; /* Size (in bytes), 32-byte aligned */ | 24 | unsigned long size; /* Size (in bytes), 32-byte aligned */ |
25 | unsigned long direction; /* Transfer direction */ | 25 | unsigned long direction; /* Transfer direction */ |
26 | unsigned long ctrl; /* Transfer control */ | 26 | unsigned long ctrl; /* Transfer control */ |
27 | unsigned long chan_enable; /* Channel enable */ | 27 | unsigned long chan_enable; /* Channel enable */ |
28 | unsigned long xfer_enable; /* Transfer enable */ | 28 | unsigned long xfer_enable; /* Transfer enable */ |
29 | unsigned long xfer_stat; /* Transfer status */ | 29 | unsigned long xfer_stat; /* Transfer status */ |
30 | } __attribute__ ((aligned(32))); | 30 | } __attribute__ ((aligned(32))); |
31 | 31 | ||
32 | struct g2_status { | 32 | struct g2_status { |
33 | unsigned long g2_addr; | 33 | unsigned long g2_addr; |
34 | unsigned long root_addr; | 34 | unsigned long root_addr; |
35 | unsigned long size; | 35 | unsigned long size; |
36 | unsigned long status; | 36 | unsigned long status; |
37 | } __attribute__ ((aligned(16))); | 37 | } __attribute__ ((aligned(16))); |
38 | 38 | ||
39 | struct g2_dma_info { | 39 | struct g2_dma_info { |
40 | struct g2_channel channel[G2_NR_DMA_CHANNELS]; | 40 | struct g2_channel channel[G2_NR_DMA_CHANNELS]; |
41 | unsigned long pad1[G2_NR_DMA_CHANNELS]; | 41 | unsigned long pad1[G2_NR_DMA_CHANNELS]; |
42 | unsigned long wait_state; | 42 | unsigned long wait_state; |
43 | unsigned long pad2[10]; | 43 | unsigned long pad2[10]; |
44 | unsigned long magic; | 44 | unsigned long magic; |
45 | struct g2_status status[G2_NR_DMA_CHANNELS]; | 45 | struct g2_status status[G2_NR_DMA_CHANNELS]; |
46 | } __attribute__ ((aligned(256))); | 46 | } __attribute__ ((aligned(256))); |
47 | 47 | ||
48 | static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800; | 48 | static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800; |
49 | 49 | ||
50 | static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 50 | static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
51 | { | 51 | { |
52 | /* FIXME: Do some meaningful completion work here.. */ | 52 | /* FIXME: Do some meaningful completion work here.. */ |
53 | return IRQ_HANDLED; | 53 | return IRQ_HANDLED; |
54 | } | 54 | } |
55 | 55 | ||
56 | static struct irqaction g2_dma_irq = { | 56 | static struct irqaction g2_dma_irq = { |
57 | .name = "g2 DMA handler", | 57 | .name = "g2 DMA handler", |
58 | .handler = g2_dma_interrupt, | 58 | .handler = g2_dma_interrupt, |
59 | .flags = SA_INTERRUPT, | 59 | .flags = IRQF_DISABLED, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static int g2_enable_dma(struct dma_channel *chan) | 62 | static int g2_enable_dma(struct dma_channel *chan) |
63 | { | 63 | { |
64 | unsigned int chan_nr = chan->chan; | 64 | unsigned int chan_nr = chan->chan; |
65 | 65 | ||
66 | g2_dma->channel[chan_nr].chan_enable = 1; | 66 | g2_dma->channel[chan_nr].chan_enable = 1; |
67 | g2_dma->channel[chan_nr].xfer_enable = 1; | 67 | g2_dma->channel[chan_nr].xfer_enable = 1; |
68 | 68 | ||
69 | return 0; | 69 | return 0; |
70 | } | 70 | } |
71 | 71 | ||
72 | static int g2_disable_dma(struct dma_channel *chan) | 72 | static int g2_disable_dma(struct dma_channel *chan) |
73 | { | 73 | { |
74 | unsigned int chan_nr = chan->chan; | 74 | unsigned int chan_nr = chan->chan; |
75 | 75 | ||
76 | g2_dma->channel[chan_nr].chan_enable = 0; | 76 | g2_dma->channel[chan_nr].chan_enable = 0; |
77 | g2_dma->channel[chan_nr].xfer_enable = 0; | 77 | g2_dma->channel[chan_nr].xfer_enable = 0; |
78 | 78 | ||
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
82 | static int g2_xfer_dma(struct dma_channel *chan) | 82 | static int g2_xfer_dma(struct dma_channel *chan) |
83 | { | 83 | { |
84 | unsigned int chan_nr = chan->chan; | 84 | unsigned int chan_nr = chan->chan; |
85 | 85 | ||
86 | if (chan->sar & 31) { | 86 | if (chan->sar & 31) { |
87 | printk("g2dma: unaligned source 0x%lx\n", chan->sar); | 87 | printk("g2dma: unaligned source 0x%lx\n", chan->sar); |
88 | return -EINVAL; | 88 | return -EINVAL; |
89 | } | 89 | } |
90 | 90 | ||
91 | if (chan->dar & 31) { | 91 | if (chan->dar & 31) { |
92 | printk("g2dma: unaligned dest 0x%lx\n", chan->dar); | 92 | printk("g2dma: unaligned dest 0x%lx\n", chan->dar); |
93 | return -EINVAL; | 93 | return -EINVAL; |
94 | } | 94 | } |
95 | 95 | ||
96 | /* Align the count */ | 96 | /* Align the count */ |
97 | if (chan->count & 31) | 97 | if (chan->count & 31) |
98 | chan->count = (chan->count + (32 - 1)) & ~(32 - 1); | 98 | chan->count = (chan->count + (32 - 1)) & ~(32 - 1); |
99 | 99 | ||
100 | /* Fixup destination */ | 100 | /* Fixup destination */ |
101 | chan->dar += 0xa0800000; | 101 | chan->dar += 0xa0800000; |
102 | 102 | ||
103 | /* Fixup direction */ | 103 | /* Fixup direction */ |
104 | chan->mode = !chan->mode; | 104 | chan->mode = !chan->mode; |
105 | 105 | ||
106 | flush_icache_range((unsigned long)chan->sar, chan->count); | 106 | flush_icache_range((unsigned long)chan->sar, chan->count); |
107 | 107 | ||
108 | g2_disable_dma(chan); | 108 | g2_disable_dma(chan); |
109 | 109 | ||
110 | g2_dma->channel[chan_nr].g2_addr = chan->dar & 0x1fffffe0; | 110 | g2_dma->channel[chan_nr].g2_addr = chan->dar & 0x1fffffe0; |
111 | g2_dma->channel[chan_nr].root_addr = chan->sar & 0x1fffffe0; | 111 | g2_dma->channel[chan_nr].root_addr = chan->sar & 0x1fffffe0; |
112 | g2_dma->channel[chan_nr].size = (chan->count & ~31) | 0x80000000; | 112 | g2_dma->channel[chan_nr].size = (chan->count & ~31) | 0x80000000; |
113 | g2_dma->channel[chan_nr].direction = chan->mode; | 113 | g2_dma->channel[chan_nr].direction = chan->mode; |
114 | 114 | ||
115 | /* | 115 | /* |
116 | * bit 0 - ??? | 116 | * bit 0 - ??? |
117 | * bit 1 - if set, generate a hardware event on transfer completion | 117 | * bit 1 - if set, generate a hardware event on transfer completion |
118 | * bit 2 - ??? something to do with suspend? | 118 | * bit 2 - ??? something to do with suspend? |
119 | */ | 119 | */ |
120 | g2_dma->channel[chan_nr].ctrl = 5; /* ?? */ | 120 | g2_dma->channel[chan_nr].ctrl = 5; /* ?? */ |
121 | 121 | ||
122 | g2_enable_dma(chan); | 122 | g2_enable_dma(chan); |
123 | 123 | ||
124 | /* debug cruft */ | 124 | /* debug cruft */ |
125 | pr_debug("count, sar, dar, mode, ctrl, chan, xfer: %ld, 0x%08lx, " | 125 | pr_debug("count, sar, dar, mode, ctrl, chan, xfer: %ld, 0x%08lx, " |
126 | "0x%08lx, %ld, %ld, %ld, %ld\n", | 126 | "0x%08lx, %ld, %ld, %ld, %ld\n", |
127 | g2_dma->channel[chan_nr].size, | 127 | g2_dma->channel[chan_nr].size, |
128 | g2_dma->channel[chan_nr].root_addr, | 128 | g2_dma->channel[chan_nr].root_addr, |
129 | g2_dma->channel[chan_nr].g2_addr, | 129 | g2_dma->channel[chan_nr].g2_addr, |
130 | g2_dma->channel[chan_nr].direction, | 130 | g2_dma->channel[chan_nr].direction, |
131 | g2_dma->channel[chan_nr].ctrl, | 131 | g2_dma->channel[chan_nr].ctrl, |
132 | g2_dma->channel[chan_nr].chan_enable, | 132 | g2_dma->channel[chan_nr].chan_enable, |
133 | g2_dma->channel[chan_nr].xfer_enable); | 133 | g2_dma->channel[chan_nr].xfer_enable); |
134 | 134 | ||
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
137 | 137 | ||
138 | static struct dma_ops g2_dma_ops = { | 138 | static struct dma_ops g2_dma_ops = { |
139 | .xfer = g2_xfer_dma, | 139 | .xfer = g2_xfer_dma, |
140 | }; | 140 | }; |
141 | 141 | ||
142 | static struct dma_info g2_dma_info = { | 142 | static struct dma_info g2_dma_info = { |
143 | .name = "g2_dmac", | 143 | .name = "g2_dmac", |
144 | .nr_channels = 4, | 144 | .nr_channels = 4, |
145 | .ops = &g2_dma_ops, | 145 | .ops = &g2_dma_ops, |
146 | .flags = DMAC_CHANNELS_TEI_CAPABLE, | 146 | .flags = DMAC_CHANNELS_TEI_CAPABLE, |
147 | }; | 147 | }; |
148 | 148 | ||
149 | static int __init g2_dma_init(void) | 149 | static int __init g2_dma_init(void) |
150 | { | 150 | { |
151 | setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq); | 151 | setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq); |
152 | 152 | ||
153 | /* Magic */ | 153 | /* Magic */ |
154 | g2_dma->wait_state = 27; | 154 | g2_dma->wait_state = 27; |
155 | g2_dma->magic = 0x4659404f; | 155 | g2_dma->magic = 0x4659404f; |
156 | 156 | ||
157 | return register_dmac(&g2_dma_info); | 157 | return register_dmac(&g2_dma_info); |
158 | } | 158 | } |
159 | 159 | ||
160 | static void __exit g2_dma_exit(void) | 160 | static void __exit g2_dma_exit(void) |
161 | { | 161 | { |
162 | free_irq(HW_EVENT_G2_DMA, 0); | 162 | free_irq(HW_EVENT_G2_DMA, 0); |
163 | unregister_dmac(&g2_dma_info); | 163 | unregister_dmac(&g2_dma_info); |
164 | } | 164 | } |
165 | 165 | ||
166 | subsys_initcall(g2_dma_init); | 166 | subsys_initcall(g2_dma_init); |
167 | module_exit(g2_dma_exit); | 167 | module_exit(g2_dma_exit); |
168 | 168 | ||
169 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); | 169 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); |
170 | MODULE_DESCRIPTION("G2 bus DMA driver"); | 170 | MODULE_DESCRIPTION("G2 bus DMA driver"); |
171 | MODULE_LICENSE("GPL"); | 171 | MODULE_LICENSE("GPL"); |
172 | 172 | ||
173 | 173 |
arch/sh/drivers/dma/dma-pvr2.c
1 | /* | 1 | /* |
2 | * arch/sh/boards/dreamcast/dma-pvr2.c | 2 | * arch/sh/boards/dreamcast/dma-pvr2.c |
3 | * | 3 | * |
4 | * NEC PowerVR 2 (Dreamcast) DMA support | 4 | * NEC PowerVR 2 (Dreamcast) DMA support |
5 | * | 5 | * |
6 | * Copyright (C) 2003, 2004 Paul Mundt | 6 | * Copyright (C) 2003, 2004 Paul Mundt |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file "COPYING" in the main directory of this archive | 9 | * License. See the file "COPYING" in the main directory of this archive |
10 | * for more details. | 10 | * for more details. |
11 | */ | 11 | */ |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <asm/mach/sysasic.h> | 16 | #include <asm/mach/sysasic.h> |
17 | #include <asm/mach/dma.h> | 17 | #include <asm/mach/dma.h> |
18 | #include <asm/dma.h> | 18 | #include <asm/dma.h> |
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | 20 | ||
21 | static unsigned int xfer_complete = 0; | 21 | static unsigned int xfer_complete = 0; |
22 | static int count = 0; | 22 | static int count = 0; |
23 | 23 | ||
24 | static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 24 | static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
25 | { | 25 | { |
26 | if (get_dma_residue(PVR2_CASCADE_CHAN)) { | 26 | if (get_dma_residue(PVR2_CASCADE_CHAN)) { |
27 | printk(KERN_WARNING "DMA: SH DMAC did not complete transfer " | 27 | printk(KERN_WARNING "DMA: SH DMAC did not complete transfer " |
28 | "on channel %d, waiting..\n", PVR2_CASCADE_CHAN); | 28 | "on channel %d, waiting..\n", PVR2_CASCADE_CHAN); |
29 | dma_wait_for_completion(PVR2_CASCADE_CHAN); | 29 | dma_wait_for_completion(PVR2_CASCADE_CHAN); |
30 | } | 30 | } |
31 | 31 | ||
32 | if (count++ < 10) | 32 | if (count++ < 10) |
33 | pr_debug("Got a pvr2 dma interrupt for channel %d\n", | 33 | pr_debug("Got a pvr2 dma interrupt for channel %d\n", |
34 | irq - HW_EVENT_PVR2_DMA); | 34 | irq - HW_EVENT_PVR2_DMA); |
35 | 35 | ||
36 | xfer_complete = 1; | 36 | xfer_complete = 1; |
37 | 37 | ||
38 | return IRQ_HANDLED; | 38 | return IRQ_HANDLED; |
39 | } | 39 | } |
40 | 40 | ||
41 | static int pvr2_request_dma(struct dma_channel *chan) | 41 | static int pvr2_request_dma(struct dma_channel *chan) |
42 | { | 42 | { |
43 | if (ctrl_inl(PVR2_DMA_MODE) != 0) | 43 | if (ctrl_inl(PVR2_DMA_MODE) != 0) |
44 | return -EBUSY; | 44 | return -EBUSY; |
45 | 45 | ||
46 | ctrl_outl(0, PVR2_DMA_LMMODE0); | 46 | ctrl_outl(0, PVR2_DMA_LMMODE0); |
47 | 47 | ||
48 | return 0; | 48 | return 0; |
49 | } | 49 | } |
50 | 50 | ||
51 | static int pvr2_get_dma_residue(struct dma_channel *chan) | 51 | static int pvr2_get_dma_residue(struct dma_channel *chan) |
52 | { | 52 | { |
53 | return xfer_complete == 0; | 53 | return xfer_complete == 0; |
54 | } | 54 | } |
55 | 55 | ||
56 | static int pvr2_xfer_dma(struct dma_channel *chan) | 56 | static int pvr2_xfer_dma(struct dma_channel *chan) |
57 | { | 57 | { |
58 | if (chan->sar || !chan->dar) | 58 | if (chan->sar || !chan->dar) |
59 | return -EINVAL; | 59 | return -EINVAL; |
60 | 60 | ||
61 | xfer_complete = 0; | 61 | xfer_complete = 0; |
62 | 62 | ||
63 | ctrl_outl(chan->dar, PVR2_DMA_ADDR); | 63 | ctrl_outl(chan->dar, PVR2_DMA_ADDR); |
64 | ctrl_outl(chan->count, PVR2_DMA_COUNT); | 64 | ctrl_outl(chan->count, PVR2_DMA_COUNT); |
65 | ctrl_outl(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE); | 65 | ctrl_outl(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE); |
66 | 66 | ||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | static struct irqaction pvr2_dma_irq = { | 70 | static struct irqaction pvr2_dma_irq = { |
71 | .name = "pvr2 DMA handler", | 71 | .name = "pvr2 DMA handler", |
72 | .handler = pvr2_dma_interrupt, | 72 | .handler = pvr2_dma_interrupt, |
73 | .flags = SA_INTERRUPT, | 73 | .flags = IRQF_DISABLED, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | static struct dma_ops pvr2_dma_ops = { | 76 | static struct dma_ops pvr2_dma_ops = { |
77 | .request = pvr2_request_dma, | 77 | .request = pvr2_request_dma, |
78 | .get_residue = pvr2_get_dma_residue, | 78 | .get_residue = pvr2_get_dma_residue, |
79 | .xfer = pvr2_xfer_dma, | 79 | .xfer = pvr2_xfer_dma, |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static struct dma_info pvr2_dma_info = { | 82 | static struct dma_info pvr2_dma_info = { |
83 | .name = "pvr2_dmac", | 83 | .name = "pvr2_dmac", |
84 | .nr_channels = 1, | 84 | .nr_channels = 1, |
85 | .ops = &pvr2_dma_ops, | 85 | .ops = &pvr2_dma_ops, |
86 | .flags = DMAC_CHANNELS_TEI_CAPABLE, | 86 | .flags = DMAC_CHANNELS_TEI_CAPABLE, |
87 | }; | 87 | }; |
88 | 88 | ||
89 | static int __init pvr2_dma_init(void) | 89 | static int __init pvr2_dma_init(void) |
90 | { | 90 | { |
91 | setup_irq(HW_EVENT_PVR2_DMA, &pvr2_dma_irq); | 91 | setup_irq(HW_EVENT_PVR2_DMA, &pvr2_dma_irq); |
92 | request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade"); | 92 | request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade"); |
93 | 93 | ||
94 | return register_dmac(&pvr2_dma_info); | 94 | return register_dmac(&pvr2_dma_info); |
95 | } | 95 | } |
96 | 96 | ||
97 | static void __exit pvr2_dma_exit(void) | 97 | static void __exit pvr2_dma_exit(void) |
98 | { | 98 | { |
99 | free_dma(PVR2_CASCADE_CHAN); | 99 | free_dma(PVR2_CASCADE_CHAN); |
100 | free_irq(HW_EVENT_PVR2_DMA, 0); | 100 | free_irq(HW_EVENT_PVR2_DMA, 0); |
101 | unregister_dmac(&pvr2_dma_info); | 101 | unregister_dmac(&pvr2_dma_info); |
102 | } | 102 | } |
103 | 103 | ||
104 | subsys_initcall(pvr2_dma_init); | 104 | subsys_initcall(pvr2_dma_init); |
105 | module_exit(pvr2_dma_exit); | 105 | module_exit(pvr2_dma_exit); |
106 | 106 | ||
107 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); | 107 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); |
108 | MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver"); | 108 | MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver"); |
109 | MODULE_LICENSE("GPL"); | 109 | MODULE_LICENSE("GPL"); |
110 | 110 | ||
111 | 111 |
arch/sh/drivers/dma/dma-sh.c
1 | /* | 1 | /* |
2 | * arch/sh/drivers/dma/dma-sh.c | 2 | * arch/sh/drivers/dma/dma-sh.c |
3 | * | 3 | * |
4 | * SuperH On-chip DMAC Support | 4 | * SuperH On-chip DMAC Support |
5 | * | 5 | * |
6 | * Copyright (C) 2000 Takashi YOSHII | 6 | * Copyright (C) 2000 Takashi YOSHII |
7 | * Copyright (C) 2003, 2004 Paul Mundt | 7 | * Copyright (C) 2003, 2004 Paul Mundt |
8 | * Copyright (C) 2005 Andriy Skulysh | 8 | * Copyright (C) 2005 Andriy Skulysh |
9 | * | 9 | * |
10 | * This file is subject to the terms and conditions of the GNU General Public | 10 | * This file is subject to the terms and conditions of the GNU General Public |
11 | * License. See the file "COPYING" in the main directory of this archive | 11 | * License. See the file "COPYING" in the main directory of this archive |
12 | * for more details. | 12 | * for more details. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <asm/dreamcast/dma.h> | 19 | #include <asm/dreamcast/dma.h> |
20 | #include <asm/signal.h> | 20 | #include <asm/signal.h> |
21 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
22 | #include <asm/dma.h> | 22 | #include <asm/dma.h> |
23 | #include <asm/io.h> | 23 | #include <asm/io.h> |
24 | #include "dma-sh.h" | 24 | #include "dma-sh.h" |
25 | 25 | ||
26 | static inline unsigned int get_dmte_irq(unsigned int chan) | 26 | static inline unsigned int get_dmte_irq(unsigned int chan) |
27 | { | 27 | { |
28 | unsigned int irq = 0; | 28 | unsigned int irq = 0; |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Normally we could just do DMTE0_IRQ + chan outright, though in the | 31 | * Normally we could just do DMTE0_IRQ + chan outright, though in the |
32 | * case of the 7751R, the DMTE IRQs for channels > 4 start right above | 32 | * case of the 7751R, the DMTE IRQs for channels > 4 start right above |
33 | * the SCIF | 33 | * the SCIF |
34 | */ | 34 | */ |
35 | if (chan < 4) { | 35 | if (chan < 4) { |
36 | irq = DMTE0_IRQ + chan; | 36 | irq = DMTE0_IRQ + chan; |
37 | } else { | 37 | } else { |
38 | #ifdef DMTE4_IRQ | 38 | #ifdef DMTE4_IRQ |
39 | irq = DMTE4_IRQ + chan - 4; | 39 | irq = DMTE4_IRQ + chan - 4; |
40 | #endif | 40 | #endif |
41 | } | 41 | } |
42 | 42 | ||
43 | return irq; | 43 | return irq; |
44 | } | 44 | } |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * We determine the correct shift size based off of the CHCR transmit size | 47 | * We determine the correct shift size based off of the CHCR transmit size |
48 | * for the given channel. Since we know that it will take: | 48 | * for the given channel. Since we know that it will take: |
49 | * | 49 | * |
50 | * info->count >> ts_shift[transmit_size] | 50 | * info->count >> ts_shift[transmit_size] |
51 | * | 51 | * |
52 | * iterations to complete the transfer. | 52 | * iterations to complete the transfer. |
53 | */ | 53 | */ |
54 | static inline unsigned int calc_xmit_shift(struct dma_channel *chan) | 54 | static inline unsigned int calc_xmit_shift(struct dma_channel *chan) |
55 | { | 55 | { |
56 | u32 chcr = ctrl_inl(CHCR[chan->chan]); | 56 | u32 chcr = ctrl_inl(CHCR[chan->chan]); |
57 | 57 | ||
58 | return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT]; | 58 | return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT]; |
59 | } | 59 | } |
60 | 60 | ||
61 | /* | 61 | /* |
62 | * The transfer end interrupt must read the chcr register to end the | 62 | * The transfer end interrupt must read the chcr register to end the |
63 | * hardware interrupt active condition. | 63 | * hardware interrupt active condition. |
64 | * Besides that it needs to waken any waiting process, which should handle | 64 | * Besides that it needs to waken any waiting process, which should handle |
65 | * setting up the next transfer. | 65 | * setting up the next transfer. |
66 | */ | 66 | */ |
67 | static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) | 67 | static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) |
68 | { | 68 | { |
69 | struct dma_channel *chan = (struct dma_channel *)dev_id; | 69 | struct dma_channel *chan = (struct dma_channel *)dev_id; |
70 | u32 chcr; | 70 | u32 chcr; |
71 | 71 | ||
72 | chcr = ctrl_inl(CHCR[chan->chan]); | 72 | chcr = ctrl_inl(CHCR[chan->chan]); |
73 | 73 | ||
74 | if (!(chcr & CHCR_TE)) | 74 | if (!(chcr & CHCR_TE)) |
75 | return IRQ_NONE; | 75 | return IRQ_NONE; |
76 | 76 | ||
77 | chcr &= ~(CHCR_IE | CHCR_DE); | 77 | chcr &= ~(CHCR_IE | CHCR_DE); |
78 | ctrl_outl(chcr, CHCR[chan->chan]); | 78 | ctrl_outl(chcr, CHCR[chan->chan]); |
79 | 79 | ||
80 | wake_up(&chan->wait_queue); | 80 | wake_up(&chan->wait_queue); |
81 | 81 | ||
82 | return IRQ_HANDLED; | 82 | return IRQ_HANDLED; |
83 | } | 83 | } |
84 | 84 | ||
85 | static int sh_dmac_request_dma(struct dma_channel *chan) | 85 | static int sh_dmac_request_dma(struct dma_channel *chan) |
86 | { | 86 | { |
87 | char name[32]; | 87 | char name[32]; |
88 | 88 | ||
89 | snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)", | 89 | snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)", |
90 | chan->chan); | 90 | chan->chan); |
91 | 91 | ||
92 | return request_irq(get_dmte_irq(chan->chan), dma_tei, | 92 | return request_irq(get_dmte_irq(chan->chan), dma_tei, |
93 | SA_INTERRUPT, name, chan); | 93 | IRQF_DISABLED, name, chan); |
94 | } | 94 | } |
95 | 95 | ||
96 | static void sh_dmac_free_dma(struct dma_channel *chan) | 96 | static void sh_dmac_free_dma(struct dma_channel *chan) |
97 | { | 97 | { |
98 | free_irq(get_dmte_irq(chan->chan), chan); | 98 | free_irq(get_dmte_irq(chan->chan), chan); |
99 | } | 99 | } |
100 | 100 | ||
101 | static void | 101 | static void |
102 | sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) | 102 | sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) |
103 | { | 103 | { |
104 | if (!chcr) | 104 | if (!chcr) |
105 | chcr = RS_DUAL | CHCR_IE; | 105 | chcr = RS_DUAL | CHCR_IE; |
106 | 106 | ||
107 | if (chcr & CHCR_IE) { | 107 | if (chcr & CHCR_IE) { |
108 | chcr &= ~CHCR_IE; | 108 | chcr &= ~CHCR_IE; |
109 | chan->flags |= DMA_TEI_CAPABLE; | 109 | chan->flags |= DMA_TEI_CAPABLE; |
110 | } else { | 110 | } else { |
111 | chan->flags &= ~DMA_TEI_CAPABLE; | 111 | chan->flags &= ~DMA_TEI_CAPABLE; |
112 | } | 112 | } |
113 | 113 | ||
114 | ctrl_outl(chcr, CHCR[chan->chan]); | 114 | ctrl_outl(chcr, CHCR[chan->chan]); |
115 | 115 | ||
116 | chan->flags |= DMA_CONFIGURED; | 116 | chan->flags |= DMA_CONFIGURED; |
117 | } | 117 | } |
118 | 118 | ||
119 | static void sh_dmac_enable_dma(struct dma_channel *chan) | 119 | static void sh_dmac_enable_dma(struct dma_channel *chan) |
120 | { | 120 | { |
121 | int irq; | 121 | int irq; |
122 | u32 chcr; | 122 | u32 chcr; |
123 | 123 | ||
124 | chcr = ctrl_inl(CHCR[chan->chan]); | 124 | chcr = ctrl_inl(CHCR[chan->chan]); |
125 | chcr |= CHCR_DE; | 125 | chcr |= CHCR_DE; |
126 | 126 | ||
127 | if (chan->flags & DMA_TEI_CAPABLE) | 127 | if (chan->flags & DMA_TEI_CAPABLE) |
128 | chcr |= CHCR_IE; | 128 | chcr |= CHCR_IE; |
129 | 129 | ||
130 | ctrl_outl(chcr, CHCR[chan->chan]); | 130 | ctrl_outl(chcr, CHCR[chan->chan]); |
131 | 131 | ||
132 | if (chan->flags & DMA_TEI_CAPABLE) { | 132 | if (chan->flags & DMA_TEI_CAPABLE) { |
133 | irq = get_dmte_irq(chan->chan); | 133 | irq = get_dmte_irq(chan->chan); |
134 | enable_irq(irq); | 134 | enable_irq(irq); |
135 | } | 135 | } |
136 | } | 136 | } |
137 | 137 | ||
138 | static void sh_dmac_disable_dma(struct dma_channel *chan) | 138 | static void sh_dmac_disable_dma(struct dma_channel *chan) |
139 | { | 139 | { |
140 | int irq; | 140 | int irq; |
141 | u32 chcr; | 141 | u32 chcr; |
142 | 142 | ||
143 | if (chan->flags & DMA_TEI_CAPABLE) { | 143 | if (chan->flags & DMA_TEI_CAPABLE) { |
144 | irq = get_dmte_irq(chan->chan); | 144 | irq = get_dmte_irq(chan->chan); |
145 | disable_irq(irq); | 145 | disable_irq(irq); |
146 | } | 146 | } |
147 | 147 | ||
148 | chcr = ctrl_inl(CHCR[chan->chan]); | 148 | chcr = ctrl_inl(CHCR[chan->chan]); |
149 | chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); | 149 | chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); |
150 | ctrl_outl(chcr, CHCR[chan->chan]); | 150 | ctrl_outl(chcr, CHCR[chan->chan]); |
151 | } | 151 | } |
152 | 152 | ||
153 | static int sh_dmac_xfer_dma(struct dma_channel *chan) | 153 | static int sh_dmac_xfer_dma(struct dma_channel *chan) |
154 | { | 154 | { |
155 | /* | 155 | /* |
156 | * If we haven't pre-configured the channel with special flags, use | 156 | * If we haven't pre-configured the channel with special flags, use |
157 | * the defaults. | 157 | * the defaults. |
158 | */ | 158 | */ |
159 | if (unlikely(!(chan->flags & DMA_CONFIGURED))) | 159 | if (unlikely(!(chan->flags & DMA_CONFIGURED))) |
160 | sh_dmac_configure_channel(chan, 0); | 160 | sh_dmac_configure_channel(chan, 0); |
161 | 161 | ||
162 | sh_dmac_disable_dma(chan); | 162 | sh_dmac_disable_dma(chan); |
163 | 163 | ||
164 | /* | 164 | /* |
165 | * Single-address mode usage note! | 165 | * Single-address mode usage note! |
166 | * | 166 | * |
167 | * It's important that we don't accidentally write any value to SAR/DAR | 167 | * It's important that we don't accidentally write any value to SAR/DAR |
168 | * (this includes 0) that hasn't been directly specified by the user if | 168 | * (this includes 0) that hasn't been directly specified by the user if |
169 | * we're in single-address mode. | 169 | * we're in single-address mode. |
170 | * | 170 | * |
171 | * In this case, only one address can be defined, anything else will | 171 | * In this case, only one address can be defined, anything else will |
172 | * result in a DMA address error interrupt (at least on the SH-4), | 172 | * result in a DMA address error interrupt (at least on the SH-4), |
173 | * which will subsequently halt the transfer. | 173 | * which will subsequently halt the transfer. |
174 | * | 174 | * |
175 | * Channel 2 on the Dreamcast is a special case, as this is used for | 175 | * Channel 2 on the Dreamcast is a special case, as this is used for |
176 | * cascading to the PVR2 DMAC. In this case, we still need to write | 176 | * cascading to the PVR2 DMAC. In this case, we still need to write |
177 | * SAR and DAR, regardless of value, in order for cascading to work. | 177 | * SAR and DAR, regardless of value, in order for cascading to work. |
178 | */ | 178 | */ |
179 | if (chan->sar || (mach_is_dreamcast() && | 179 | if (chan->sar || (mach_is_dreamcast() && |
180 | chan->chan == PVR2_CASCADE_CHAN)) | 180 | chan->chan == PVR2_CASCADE_CHAN)) |
181 | ctrl_outl(chan->sar, SAR[chan->chan]); | 181 | ctrl_outl(chan->sar, SAR[chan->chan]); |
182 | if (chan->dar || (mach_is_dreamcast() && | 182 | if (chan->dar || (mach_is_dreamcast() && |
183 | chan->chan == PVR2_CASCADE_CHAN)) | 183 | chan->chan == PVR2_CASCADE_CHAN)) |
184 | ctrl_outl(chan->dar, DAR[chan->chan]); | 184 | ctrl_outl(chan->dar, DAR[chan->chan]); |
185 | 185 | ||
186 | ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]); | 186 | ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]); |
187 | 187 | ||
188 | sh_dmac_enable_dma(chan); | 188 | sh_dmac_enable_dma(chan); |
189 | 189 | ||
190 | return 0; | 190 | return 0; |
191 | } | 191 | } |
192 | 192 | ||
193 | static int sh_dmac_get_dma_residue(struct dma_channel *chan) | 193 | static int sh_dmac_get_dma_residue(struct dma_channel *chan) |
194 | { | 194 | { |
195 | if (!(ctrl_inl(CHCR[chan->chan]) & CHCR_DE)) | 195 | if (!(ctrl_inl(CHCR[chan->chan]) & CHCR_DE)) |
196 | return 0; | 196 | return 0; |
197 | 197 | ||
198 | return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan); | 198 | return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan); |
199 | } | 199 | } |
200 | 200 | ||
201 | #ifdef CONFIG_CPU_SUBTYPE_SH7780 | 201 | #ifdef CONFIG_CPU_SUBTYPE_SH7780 |
202 | #define dmaor_read_reg() ctrl_inw(DMAOR) | 202 | #define dmaor_read_reg() ctrl_inw(DMAOR) |
203 | #define dmaor_write_reg(data) ctrl_outw(data, DMAOR) | 203 | #define dmaor_write_reg(data) ctrl_outw(data, DMAOR) |
204 | #else | 204 | #else |
205 | #define dmaor_read_reg() ctrl_inl(DMAOR) | 205 | #define dmaor_read_reg() ctrl_inl(DMAOR) |
206 | #define dmaor_write_reg(data) ctrl_outl(data, DMAOR) | 206 | #define dmaor_write_reg(data) ctrl_outl(data, DMAOR) |
207 | #endif | 207 | #endif |
208 | 208 | ||
209 | static inline int dmaor_reset(void) | 209 | static inline int dmaor_reset(void) |
210 | { | 210 | { |
211 | unsigned long dmaor = dmaor_read_reg(); | 211 | unsigned long dmaor = dmaor_read_reg(); |
212 | 212 | ||
213 | /* Try to clear the error flags first, incase they are set */ | 213 | /* Try to clear the error flags first, incase they are set */ |
214 | dmaor &= ~(DMAOR_NMIF | DMAOR_AE); | 214 | dmaor &= ~(DMAOR_NMIF | DMAOR_AE); |
215 | dmaor_write_reg(dmaor); | 215 | dmaor_write_reg(dmaor); |
216 | 216 | ||
217 | dmaor |= DMAOR_INIT; | 217 | dmaor |= DMAOR_INIT; |
218 | dmaor_write_reg(dmaor); | 218 | dmaor_write_reg(dmaor); |
219 | 219 | ||
220 | /* See if we got an error again */ | 220 | /* See if we got an error again */ |
221 | if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) { | 221 | if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) { |
222 | printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n"); | 222 | printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n"); |
223 | return -EINVAL; | 223 | return -EINVAL; |
224 | } | 224 | } |
225 | 225 | ||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | #if defined(CONFIG_CPU_SH4) | 229 | #if defined(CONFIG_CPU_SH4) |
230 | static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) | 230 | static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) |
231 | { | 231 | { |
232 | dmaor_reset(); | 232 | dmaor_reset(); |
233 | disable_irq(irq); | 233 | disable_irq(irq); |
234 | 234 | ||
235 | return IRQ_HANDLED; | 235 | return IRQ_HANDLED; |
236 | } | 236 | } |
237 | #endif | 237 | #endif |
238 | 238 | ||
239 | static struct dma_ops sh_dmac_ops = { | 239 | static struct dma_ops sh_dmac_ops = { |
240 | .request = sh_dmac_request_dma, | 240 | .request = sh_dmac_request_dma, |
241 | .free = sh_dmac_free_dma, | 241 | .free = sh_dmac_free_dma, |
242 | .get_residue = sh_dmac_get_dma_residue, | 242 | .get_residue = sh_dmac_get_dma_residue, |
243 | .xfer = sh_dmac_xfer_dma, | 243 | .xfer = sh_dmac_xfer_dma, |
244 | .configure = sh_dmac_configure_channel, | 244 | .configure = sh_dmac_configure_channel, |
245 | }; | 245 | }; |
246 | 246 | ||
247 | static struct dma_info sh_dmac_info = { | 247 | static struct dma_info sh_dmac_info = { |
248 | .name = "sh_dmac", | 248 | .name = "sh_dmac", |
249 | .nr_channels = CONFIG_NR_ONCHIP_DMA_CHANNELS, | 249 | .nr_channels = CONFIG_NR_ONCHIP_DMA_CHANNELS, |
250 | .ops = &sh_dmac_ops, | 250 | .ops = &sh_dmac_ops, |
251 | .flags = DMAC_CHANNELS_TEI_CAPABLE, | 251 | .flags = DMAC_CHANNELS_TEI_CAPABLE, |
252 | }; | 252 | }; |
253 | 253 | ||
254 | static int __init sh_dmac_init(void) | 254 | static int __init sh_dmac_init(void) |
255 | { | 255 | { |
256 | struct dma_info *info = &sh_dmac_info; | 256 | struct dma_info *info = &sh_dmac_info; |
257 | int i; | 257 | int i; |
258 | 258 | ||
259 | #ifdef CONFIG_CPU_SH4 | 259 | #ifdef CONFIG_CPU_SH4 |
260 | make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); | 260 | make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); |
261 | i = request_irq(DMAE_IRQ, dma_err, SA_INTERRUPT, "DMAC Address Error", 0); | 261 | i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0); |
262 | if (i < 0) | 262 | if (i < 0) |
263 | return i; | 263 | return i; |
264 | #endif | 264 | #endif |
265 | 265 | ||
266 | for (i = 0; i < info->nr_channels; i++) { | 266 | for (i = 0; i < info->nr_channels; i++) { |
267 | int irq = get_dmte_irq(i); | 267 | int irq = get_dmte_irq(i); |
268 | 268 | ||
269 | make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); | 269 | make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); |
270 | } | 270 | } |
271 | 271 | ||
272 | /* | 272 | /* |
273 | * Initialize DMAOR, and clean up any error flags that may have | 273 | * Initialize DMAOR, and clean up any error flags that may have |
274 | * been set. | 274 | * been set. |
275 | */ | 275 | */ |
276 | i = dmaor_reset(); | 276 | i = dmaor_reset(); |
277 | if (i < 0) | 277 | if (i < 0) |
278 | return i; | 278 | return i; |
279 | 279 | ||
280 | return register_dmac(info); | 280 | return register_dmac(info); |
281 | } | 281 | } |
282 | 282 | ||
283 | static void __exit sh_dmac_exit(void) | 283 | static void __exit sh_dmac_exit(void) |
284 | { | 284 | { |
285 | #ifdef CONFIG_CPU_SH4 | 285 | #ifdef CONFIG_CPU_SH4 |
286 | free_irq(DMAE_IRQ, 0); | 286 | free_irq(DMAE_IRQ, 0); |
287 | #endif | 287 | #endif |
288 | unregister_dmac(&sh_dmac_info); | 288 | unregister_dmac(&sh_dmac_info); |
289 | } | 289 | } |
290 | 290 | ||
291 | subsys_initcall(sh_dmac_init); | 291 | subsys_initcall(sh_dmac_init); |
292 | module_exit(sh_dmac_exit); | 292 | module_exit(sh_dmac_exit); |
293 | 293 | ||
294 | MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh"); | 294 | MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh"); |
295 | MODULE_DESCRIPTION("SuperH On-Chip DMAC Support"); | 295 | MODULE_DESCRIPTION("SuperH On-Chip DMAC Support"); |
296 | MODULE_LICENSE("GPL"); | 296 | MODULE_LICENSE("GPL"); |
297 | 297 |
arch/sh/drivers/pci/pci-st40.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) | 2 | * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) |
3 | * | 3 | * |
4 | * May be copied or modified under the terms of the GNU General Public | 4 | * May be copied or modified under the terms of the GNU General Public |
5 | * License. See linux/COPYING for more information. | 5 | * License. See linux/COPYING for more information. |
6 | * | 6 | * |
7 | * Support functions for the ST40 PCI hardware. | 7 | * Support functions for the ST40 PCI hardware. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/smp.h> | 11 | #include <linux/smp.h> |
12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <asm/pci.h> | 18 | #include <asm/pci.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <linux/interrupt.h> /* irqreturn_t */ | 20 | #include <linux/interrupt.h> /* irqreturn_t */ |
21 | 21 | ||
22 | #include "pci-st40.h" | 22 | #include "pci-st40.h" |
23 | 23 | ||
24 | /* This is in P2 of course */ | 24 | /* This is in P2 of course */ |
25 | #define ST40PCI_BASE_ADDRESS (0xb0000000) | 25 | #define ST40PCI_BASE_ADDRESS (0xb0000000) |
26 | #define ST40PCI_MEM_ADDRESS (ST40PCI_BASE_ADDRESS+0x0) | 26 | #define ST40PCI_MEM_ADDRESS (ST40PCI_BASE_ADDRESS+0x0) |
27 | #define ST40PCI_IO_ADDRESS (ST40PCI_BASE_ADDRESS+0x06000000) | 27 | #define ST40PCI_IO_ADDRESS (ST40PCI_BASE_ADDRESS+0x06000000) |
28 | #define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000) | 28 | #define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000) |
29 | 29 | ||
30 | #define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x)) | 30 | #define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x)) |
31 | #define ST40PCI_REG_INDEXED(reg, index) \ | 31 | #define ST40PCI_REG_INDEXED(reg, index) \ |
32 | (ST40PCI_REG(reg##0) + \ | 32 | (ST40PCI_REG(reg##0) + \ |
33 | ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index)) | 33 | ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index)) |
34 | 34 | ||
35 | #define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg)) | 35 | #define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg)) |
36 | #define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg)) | 36 | #define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg)) |
37 | #define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg)) | 37 | #define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg)) |
38 | #define ST40PCI_WRITE_INDEXED(reg, index, val) \ | 38 | #define ST40PCI_WRITE_INDEXED(reg, index, val) \ |
39 | writel((val), ST40PCI_REG_INDEXED(reg, index)); | 39 | writel((val), ST40PCI_REG_INDEXED(reg, index)); |
40 | 40 | ||
41 | #define ST40PCI_READ(reg) readl(ST40PCI_REG(reg)) | 41 | #define ST40PCI_READ(reg) readl(ST40PCI_REG(reg)) |
42 | #define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg)) | 42 | #define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg)) |
43 | #define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg)) | 43 | #define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg)) |
44 | 44 | ||
45 | #define ST40PCI_SERR_IRQ 64 | 45 | #define ST40PCI_SERR_IRQ 64 |
46 | #define ST40PCI_ERR_IRQ 65 | 46 | #define ST40PCI_ERR_IRQ 65 |
47 | 47 | ||
48 | 48 | ||
49 | /* Macros to extract PLL params */ | 49 | /* Macros to extract PLL params */ |
50 | #define PLL_MDIV(reg) ( ((unsigned)reg) & 0xff ) | 50 | #define PLL_MDIV(reg) ( ((unsigned)reg) & 0xff ) |
51 | #define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff ) | 51 | #define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff ) |
52 | #define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 ) | 52 | #define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 ) |
53 | #define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff ) | 53 | #define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff ) |
54 | 54 | ||
55 | /* Build up the appropriate settings */ | 55 | /* Build up the appropriate settings */ |
56 | #define PLL_SET(mdiv,ndiv,pdiv,setup) \ | 56 | #define PLL_SET(mdiv,ndiv,pdiv,setup) \ |
57 | ( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19)) | 57 | ( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19)) |
58 | 58 | ||
59 | #define PLLPCICR (0xbb040000+0x10) | 59 | #define PLLPCICR (0xbb040000+0x10) |
60 | 60 | ||
61 | #define PLLPCICR_POWERON (1<<28) | 61 | #define PLLPCICR_POWERON (1<<28) |
62 | #define PLLPCICR_OUT_EN (1<<29) | 62 | #define PLLPCICR_OUT_EN (1<<29) |
63 | #define PLLPCICR_LOCKSELECT (1<<30) | 63 | #define PLLPCICR_LOCKSELECT (1<<30) |
64 | #define PLLPCICR_LOCK (1<<31) | 64 | #define PLLPCICR_LOCK (1<<31) |
65 | 65 | ||
66 | 66 | ||
67 | #define PLL_25MHZ 0x793c8512 | 67 | #define PLL_25MHZ 0x793c8512 |
68 | #define PLL_33MHZ PLL_SET(18,88,3,295) | 68 | #define PLL_33MHZ PLL_SET(18,88,3,295) |
69 | 69 | ||
70 | static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, | 70 | static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, |
71 | unsigned long pciOffset, unsigned long regionSize); | 71 | unsigned long pciOffset, unsigned long regionSize); |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * The pcibios_map_platform_irq function is defined in the appropriate | 74 | * The pcibios_map_platform_irq function is defined in the appropriate |
75 | * board specific code and referenced here | 75 | * board specific code and referenced here |
76 | */ | 76 | */ |
77 | extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin); | 77 | extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin); |
78 | 78 | ||
79 | static __init void SetPCIPLL(void) | 79 | static __init void SetPCIPLL(void) |
80 | { | 80 | { |
81 | { | 81 | { |
82 | /* Lets play with the PLL values */ | 82 | /* Lets play with the PLL values */ |
83 | unsigned long pll1cr1; | 83 | unsigned long pll1cr1; |
84 | unsigned long mdiv, ndiv, pdiv; | 84 | unsigned long mdiv, ndiv, pdiv; |
85 | unsigned long muxcr; | 85 | unsigned long muxcr; |
86 | unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 }; | 86 | unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 }; |
87 | unsigned int freq; | 87 | unsigned int freq; |
88 | 88 | ||
89 | #define CLKGENA 0xbb040000 | 89 | #define CLKGENA 0xbb040000 |
90 | #define CLKGENA_PLL2_MUXCR CLKGENA + 0x48 | 90 | #define CLKGENA_PLL2_MUXCR CLKGENA + 0x48 |
91 | pll1cr1 = ctrl_inl(PLLPCICR); | 91 | pll1cr1 = ctrl_inl(PLLPCICR); |
92 | printk("PLL1CR1 %08lx\n", pll1cr1); | 92 | printk("PLL1CR1 %08lx\n", pll1cr1); |
93 | mdiv = PLL_MDIV(pll1cr1); | 93 | mdiv = PLL_MDIV(pll1cr1); |
94 | ndiv = PLL_NDIV(pll1cr1); | 94 | ndiv = PLL_NDIV(pll1cr1); |
95 | pdiv = PLL_PDIV(pll1cr1); | 95 | pdiv = PLL_PDIV(pll1cr1); |
96 | printk("mdiv %02lx ndiv %02lx pdiv %02lx\n", mdiv, ndiv, pdiv); | 96 | printk("mdiv %02lx ndiv %02lx pdiv %02lx\n", mdiv, ndiv, pdiv); |
97 | freq = ((2*27*ndiv)/mdiv) / (1 << pdiv); | 97 | freq = ((2*27*ndiv)/mdiv) / (1 << pdiv); |
98 | printk("PLL freq %dMHz\n", freq); | 98 | printk("PLL freq %dMHz\n", freq); |
99 | muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR); | 99 | muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR); |
100 | printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]); | 100 | printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]); |
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | 104 | ||
105 | struct pci_err { | 105 | struct pci_err { |
106 | unsigned mask; | 106 | unsigned mask; |
107 | const char *error_string; | 107 | const char *error_string; |
108 | }; | 108 | }; |
109 | 109 | ||
110 | static struct pci_err int_error[]={ | 110 | static struct pci_err int_error[]={ |
111 | { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"}, | 111 | { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"}, |
112 | { INT_TTADI, "TTADI: Illegal byte enable in I/O transfer"}, | 112 | { INT_TTADI, "TTADI: Illegal byte enable in I/O transfer"}, |
113 | { INT_TMTO, "TMTO: Target memory read/write timeout"}, | 113 | { INT_TMTO, "TMTO: Target memory read/write timeout"}, |
114 | { INT_MDEI, "MDEI: Master function disable error"}, | 114 | { INT_MDEI, "MDEI: Master function disable error"}, |
115 | { INT_APEDI, "APEDI: Address parity error"}, | 115 | { INT_APEDI, "APEDI: Address parity error"}, |
116 | { INT_SDI, "SDI: SERR detected"}, | 116 | { INT_SDI, "SDI: SERR detected"}, |
117 | { INT_DPEITW, "DPEITW: Data parity error target write"}, | 117 | { INT_DPEITW, "DPEITW: Data parity error target write"}, |
118 | { INT_PEDITR, "PEDITR: PERR detected"}, | 118 | { INT_PEDITR, "PEDITR: PERR detected"}, |
119 | { INT_TADIM, "TADIM: Target abort detected"}, | 119 | { INT_TADIM, "TADIM: Target abort detected"}, |
120 | { INT_MADIM, "MADIM: Master abort detected"}, | 120 | { INT_MADIM, "MADIM: Master abort detected"}, |
121 | { INT_MWPDI, "MWPDI: PERR from target at data write"}, | 121 | { INT_MWPDI, "MWPDI: PERR from target at data write"}, |
122 | { INT_MRDPEI, "MRDPEI: Master read data parity error"} | 122 | { INT_MRDPEI, "MRDPEI: Master read data parity error"} |
123 | }; | 123 | }; |
124 | #define NUM_PCI_INT_ERRS (sizeof(int_error)/sizeof(struct pci_err)) | 124 | #define NUM_PCI_INT_ERRS (sizeof(int_error)/sizeof(struct pci_err)) |
125 | 125 | ||
126 | static struct pci_err aint_error[]={ | 126 | static struct pci_err aint_error[]={ |
127 | { AINT_MBI, "MBI: Master broken"}, | 127 | { AINT_MBI, "MBI: Master broken"}, |
128 | { AINT_TBTOI, "TBTOI: Target bus timeout"}, | 128 | { AINT_TBTOI, "TBTOI: Target bus timeout"}, |
129 | { AINT_MBTOI, "MBTOI: Master bus timeout"}, | 129 | { AINT_MBTOI, "MBTOI: Master bus timeout"}, |
130 | { AINT_TAI, "TAI: Target abort"}, | 130 | { AINT_TAI, "TAI: Target abort"}, |
131 | { AINT_MAI, "MAI: Master abort"}, | 131 | { AINT_MAI, "MAI: Master abort"}, |
132 | { AINT_RDPEI, "RDPEI: Read data parity"}, | 132 | { AINT_RDPEI, "RDPEI: Read data parity"}, |
133 | { AINT_WDPE, "WDPE: Write data parity"} | 133 | { AINT_WDPE, "WDPE: Write data parity"} |
134 | }; | 134 | }; |
135 | 135 | ||
136 | #define NUM_PCI_AINT_ERRS (sizeof(aint_error)/sizeof(struct pci_err)) | 136 | #define NUM_PCI_AINT_ERRS (sizeof(aint_error)/sizeof(struct pci_err)) |
137 | 137 | ||
138 | static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors) | 138 | static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors) |
139 | { | 139 | { |
140 | int i; | 140 | int i; |
141 | 141 | ||
142 | for(i=0;i<num_errors;i++) { | 142 | for(i=0;i<num_errors;i++) { |
143 | if(reg & error[i].mask) { | 143 | if(reg & error[i].mask) { |
144 | printk("%s\n",error[i].error_string); | 144 | printk("%s\n",error[i].error_string); |
145 | } | 145 | } |
146 | } | 146 | } |
147 | 147 | ||
148 | } | 148 | } |
149 | 149 | ||
150 | 150 | ||
151 | static char * pci_commands[16]={ | 151 | static char * pci_commands[16]={ |
152 | "Int Ack", | 152 | "Int Ack", |
153 | "Special Cycle", | 153 | "Special Cycle", |
154 | "I/O Read", | 154 | "I/O Read", |
155 | "I/O Write", | 155 | "I/O Write", |
156 | "Reserved", | 156 | "Reserved", |
157 | "Reserved", | 157 | "Reserved", |
158 | "Memory Read", | 158 | "Memory Read", |
159 | "Memory Write", | 159 | "Memory Write", |
160 | "Reserved", | 160 | "Reserved", |
161 | "Reserved", | 161 | "Reserved", |
162 | "Configuration Read", | 162 | "Configuration Read", |
163 | "Configuration Write", | 163 | "Configuration Write", |
164 | "Memory Read Multiple", | 164 | "Memory Read Multiple", |
165 | "Dual Address Cycle", | 165 | "Dual Address Cycle", |
166 | "Memory Read Line", | 166 | "Memory Read Line", |
167 | "Memory Write-and-Invalidate" | 167 | "Memory Write-and-Invalidate" |
168 | }; | 168 | }; |
169 | 169 | ||
170 | static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs) | 170 | static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs) |
171 | { | 171 | { |
172 | unsigned pci_int, pci_air, pci_cir, pci_aint; | 172 | unsigned pci_int, pci_air, pci_cir, pci_aint; |
173 | static int count=0; | 173 | static int count=0; |
174 | 174 | ||
175 | 175 | ||
176 | pci_int = ST40PCI_READ(INT);pci_aint = ST40PCI_READ(AINT); | 176 | pci_int = ST40PCI_READ(INT);pci_aint = ST40PCI_READ(AINT); |
177 | pci_cir = ST40PCI_READ(CIR);pci_air = ST40PCI_READ(AIR); | 177 | pci_cir = ST40PCI_READ(CIR);pci_air = ST40PCI_READ(AIR); |
178 | 178 | ||
179 | /* Reset state to stop multiple interrupts */ | 179 | /* Reset state to stop multiple interrupts */ |
180 | ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0); | 180 | ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0); |
181 | 181 | ||
182 | 182 | ||
183 | if(++count>1) return IRQ_HANDLED; | 183 | if(++count>1) return IRQ_HANDLED; |
184 | 184 | ||
185 | printk("** PCI ERROR **\n"); | 185 | printk("** PCI ERROR **\n"); |
186 | 186 | ||
187 | if(pci_int) { | 187 | if(pci_int) { |
188 | printk("** INT register status\n"); | 188 | printk("** INT register status\n"); |
189 | print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS); | 189 | print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS); |
190 | } | 190 | } |
191 | 191 | ||
192 | if(pci_aint) { | 192 | if(pci_aint) { |
193 | printk("** AINT register status\n"); | 193 | printk("** AINT register status\n"); |
194 | print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS); | 194 | print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS); |
195 | } | 195 | } |
196 | 196 | ||
197 | printk("** Address and command info\n"); | 197 | printk("** Address and command info\n"); |
198 | 198 | ||
199 | printk("** Command %s : Address 0x%x\n", | 199 | printk("** Command %s : Address 0x%x\n", |
200 | pci_commands[pci_cir&0xf],pci_air); | 200 | pci_commands[pci_cir&0xf],pci_air); |
201 | 201 | ||
202 | if(pci_cir&CIR_PIOTEM) { | 202 | if(pci_cir&CIR_PIOTEM) { |
203 | printk("CIR_PIOTEM:PIO transfer error for master\n"); | 203 | printk("CIR_PIOTEM:PIO transfer error for master\n"); |
204 | } | 204 | } |
205 | if(pci_cir&CIR_RWTET) { | 205 | if(pci_cir&CIR_RWTET) { |
206 | printk("CIR_RWTET:Read/Write transfer error for target\n"); | 206 | printk("CIR_RWTET:Read/Write transfer error for target\n"); |
207 | } | 207 | } |
208 | 208 | ||
209 | return IRQ_HANDLED; | 209 | return IRQ_HANDLED; |
210 | } | 210 | } |
211 | 211 | ||
212 | 212 | ||
213 | /* Rounds a number UP to the nearest power of two. Used for | 213 | /* Rounds a number UP to the nearest power of two. Used for |
214 | * sizing the PCI window. | 214 | * sizing the PCI window. |
215 | */ | 215 | */ |
216 | static u32 r2p2(u32 num) | 216 | static u32 r2p2(u32 num) |
217 | { | 217 | { |
218 | int i = 31; | 218 | int i = 31; |
219 | u32 tmp = num; | 219 | u32 tmp = num; |
220 | 220 | ||
221 | if (num == 0) | 221 | if (num == 0) |
222 | return 0; | 222 | return 0; |
223 | 223 | ||
224 | do { | 224 | do { |
225 | if (tmp & (1 << 31)) | 225 | if (tmp & (1 << 31)) |
226 | break; | 226 | break; |
227 | i--; | 227 | i--; |
228 | tmp <<= 1; | 228 | tmp <<= 1; |
229 | } while (i >= 0); | 229 | } while (i >= 0); |
230 | 230 | ||
231 | tmp = 1 << i; | 231 | tmp = 1 << i; |
232 | /* If the original number isn't a power of 2, round it up */ | 232 | /* If the original number isn't a power of 2, round it up */ |
233 | if (tmp != num) | 233 | if (tmp != num) |
234 | tmp <<= 1; | 234 | tmp <<= 1; |
235 | 235 | ||
236 | return tmp; | 236 | return tmp; |
237 | } | 237 | } |
238 | 238 | ||
239 | static void __init pci_fixup_ide_bases(struct pci_dev *d) | 239 | static void __init pci_fixup_ide_bases(struct pci_dev *d) |
240 | { | 240 | { |
241 | int i; | 241 | int i; |
242 | 242 | ||
243 | /* | 243 | /* |
244 | * PCI IDE controllers use non-standard I/O port decoding, respect it. | 244 | * PCI IDE controllers use non-standard I/O port decoding, respect it. |
245 | */ | 245 | */ |
246 | if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) | 246 | if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) |
247 | return; | 247 | return; |
248 | printk("PCI: IDE base address fixup for %s\n", pci_name(d)); | 248 | printk("PCI: IDE base address fixup for %s\n", pci_name(d)); |
249 | for(i=0; i<4; i++) { | 249 | for(i=0; i<4; i++) { |
250 | struct resource *r = &d->resource[i]; | 250 | struct resource *r = &d->resource[i]; |
251 | if ((r->start & ~0x80) == 0x374) { | 251 | if ((r->start & ~0x80) == 0x374) { |
252 | r->start |= 2; | 252 | r->start |= 2; |
253 | r->end = r->start; | 253 | r->end = r->start; |
254 | } | 254 | } |
255 | } | 255 | } |
256 | } | 256 | } |
257 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); | 257 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); |
258 | 258 | ||
259 | int __init st40pci_init(unsigned memStart, unsigned memSize) | 259 | int __init st40pci_init(unsigned memStart, unsigned memSize) |
260 | { | 260 | { |
261 | u32 lsr0; | 261 | u32 lsr0; |
262 | 262 | ||
263 | SetPCIPLL(); | 263 | SetPCIPLL(); |
264 | 264 | ||
265 | /* Initialises the ST40 pci subsystem, performing a reset, then programming | 265 | /* Initialises the ST40 pci subsystem, performing a reset, then programming |
266 | * up the address space decoders appropriately | 266 | * up the address space decoders appropriately |
267 | */ | 267 | */ |
268 | 268 | ||
269 | /* Should reset core here as well methink */ | 269 | /* Should reset core here as well methink */ |
270 | 270 | ||
271 | ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET); | 271 | ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET); |
272 | 272 | ||
273 | /* Loop while core resets */ | 273 | /* Loop while core resets */ |
274 | while (ST40PCI_READ(CR) & CR_SOFT_RESET); | 274 | while (ST40PCI_READ(CR) & CR_SOFT_RESET); |
275 | 275 | ||
276 | /* Switch off interrupts */ | 276 | /* Switch off interrupts */ |
277 | ST40PCI_WRITE(INTM, 0); | 277 | ST40PCI_WRITE(INTM, 0); |
278 | ST40PCI_WRITE(AINT, 0); | 278 | ST40PCI_WRITE(AINT, 0); |
279 | 279 | ||
280 | /* Now, lets reset all the cards on the bus with extreme prejudice */ | 280 | /* Now, lets reset all the cards on the bus with extreme prejudice */ |
281 | ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL); | 281 | ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL); |
282 | udelay(250); | 282 | udelay(250); |
283 | 283 | ||
284 | /* Set bus active, take it out of reset */ | 284 | /* Set bus active, take it out of reset */ |
285 | ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE); | 285 | ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE); |
286 | 286 | ||
287 | /* The PCI spec says that no access must be made to the bus until 1 second | 287 | /* The PCI spec says that no access must be made to the bus until 1 second |
288 | * after reset. This seem ludicrously long, but some delay is needed here | 288 | * after reset. This seem ludicrously long, but some delay is needed here |
289 | */ | 289 | */ |
290 | mdelay(1000); | 290 | mdelay(1000); |
291 | 291 | ||
292 | /* Switch off interrupts */ | 292 | /* Switch off interrupts */ |
293 | ST40PCI_WRITE(INTM, 0); | 293 | ST40PCI_WRITE(INTM, 0); |
294 | ST40PCI_WRITE(AINT, 0); | 294 | ST40PCI_WRITE(AINT, 0); |
295 | 295 | ||
296 | /* Allow it to be a master */ | 296 | /* Allow it to be a master */ |
297 | 297 | ||
298 | ST40PCI_WRITE_SHORT(CSR_CMD, | 298 | ST40PCI_WRITE_SHORT(CSR_CMD, |
299 | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | | 299 | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | |
300 | PCI_COMMAND_IO); | 300 | PCI_COMMAND_IO); |
301 | 301 | ||
302 | /* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000 | 302 | /* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000 |
303 | * on the PCI bus. This allows a nice 1-1 bus to phys mapping. | 303 | * on the PCI bus. This allows a nice 1-1 bus to phys mapping. |
304 | */ | 304 | */ |
305 | 305 | ||
306 | 306 | ||
307 | ST40PCI_WRITE(MBR, 0x10000000); | 307 | ST40PCI_WRITE(MBR, 0x10000000); |
308 | /* Always set the max size 128M (actually, it is only 96MB wide) */ | 308 | /* Always set the max size 128M (actually, it is only 96MB wide) */ |
309 | ST40PCI_WRITE(MBMR, 0x07ff0000); | 309 | ST40PCI_WRITE(MBMR, 0x07ff0000); |
310 | 310 | ||
311 | /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to | 311 | /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to |
312 | * allow cards that have legacy io such as vga to function correctly. This gives a | 312 | * allow cards that have legacy io such as vga to function correctly. This gives a |
313 | * maximum of 64K of io/space as only the bottom 16 bits of the address are copied | 313 | * maximum of 64K of io/space as only the bottom 16 bits of the address are copied |
314 | * over to the bus when the transaction is made. 64K of io space is more than enough | 314 | * over to the bus when the transaction is made. 64K of io space is more than enough |
315 | */ | 315 | */ |
316 | ST40PCI_WRITE(IOBR, 0x0); | 316 | ST40PCI_WRITE(IOBR, 0x0); |
317 | /* Set up the 64K window */ | 317 | /* Set up the 64K window */ |
318 | ST40PCI_WRITE(IOBMR, 0x0); | 318 | ST40PCI_WRITE(IOBMR, 0x0); |
319 | 319 | ||
320 | /* Now we set up the mbars so the PCI bus can see the local memory */ | 320 | /* Now we set up the mbars so the PCI bus can see the local memory */ |
321 | /* Expose a 256M window starting at PCI address 0... */ | 321 | /* Expose a 256M window starting at PCI address 0... */ |
322 | ST40PCI_WRITE(CSR_MBAR0, 0); | 322 | ST40PCI_WRITE(CSR_MBAR0, 0); |
323 | ST40PCI_WRITE(LSR0, 0x0fff0001); | 323 | ST40PCI_WRITE(LSR0, 0x0fff0001); |
324 | 324 | ||
325 | /* ... and set up the initial incomming window to expose all of RAM */ | 325 | /* ... and set up the initial incomming window to expose all of RAM */ |
326 | pci_set_rbar_region(7, memStart, memStart, memSize); | 326 | pci_set_rbar_region(7, memStart, memStart, memSize); |
327 | 327 | ||
328 | /* Maximise timeout values */ | 328 | /* Maximise timeout values */ |
329 | ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff); | 329 | ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff); |
330 | ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff); | 330 | ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff); |
331 | ST40PCI_WRITE_BYTE(CSR_MIT, 0xff); | 331 | ST40PCI_WRITE_BYTE(CSR_MIT, 0xff); |
332 | 332 | ||
333 | ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING); | 333 | ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING); |
334 | 334 | ||
335 | return 1; | 335 | return 1; |
336 | } | 336 | } |
337 | 337 | ||
338 | char * __init pcibios_setup(char *str) | 338 | char * __init pcibios_setup(char *str) |
339 | { | 339 | { |
340 | return str; | 340 | return str; |
341 | } | 341 | } |
342 | 342 | ||
343 | 343 | ||
344 | #define SET_CONFIG_BITS(bus,devfn,where)\ | 344 | #define SET_CONFIG_BITS(bus,devfn,where)\ |
345 | (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0)) | 345 | (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0)) |
346 | 346 | ||
347 | #define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where) | 347 | #define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where) |
348 | 348 | ||
349 | 349 | ||
350 | static int CheckForMasterAbort(void) | 350 | static int CheckForMasterAbort(void) |
351 | { | 351 | { |
352 | if (ST40PCI_READ(INT) & INT_MADIM) { | 352 | if (ST40PCI_READ(INT) & INT_MADIM) { |
353 | /* Should we clear config space version as well ??? */ | 353 | /* Should we clear config space version as well ??? */ |
354 | ST40PCI_WRITE(INT, INT_MADIM); | 354 | ST40PCI_WRITE(INT, INT_MADIM); |
355 | ST40PCI_WRITE_SHORT(CSR_STATUS, 0); | 355 | ST40PCI_WRITE_SHORT(CSR_STATUS, 0); |
356 | return 1; | 356 | return 1; |
357 | } | 357 | } |
358 | 358 | ||
359 | return 0; | 359 | return 0; |
360 | } | 360 | } |
361 | 361 | ||
362 | /* Write to config register */ | 362 | /* Write to config register */ |
363 | static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) | 363 | static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) |
364 | { | 364 | { |
365 | ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); | 365 | ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); |
366 | switch (size) { | 366 | switch (size) { |
367 | case 1: | 367 | case 1: |
368 | *val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3)); | 368 | *val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3)); |
369 | break; | 369 | break; |
370 | case 2: | 370 | case 2: |
371 | *val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2)); | 371 | *val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2)); |
372 | break; | 372 | break; |
373 | case 4: | 373 | case 4: |
374 | *val = ST40PCI_READ(PDR); | 374 | *val = ST40PCI_READ(PDR); |
375 | break; | 375 | break; |
376 | } | 376 | } |
377 | 377 | ||
378 | if (CheckForMasterAbort()){ | 378 | if (CheckForMasterAbort()){ |
379 | switch (size) { | 379 | switch (size) { |
380 | case 1: | 380 | case 1: |
381 | *val = (u8)0xff; | 381 | *val = (u8)0xff; |
382 | break; | 382 | break; |
383 | case 2: | 383 | case 2: |
384 | *val = (u16)0xffff; | 384 | *val = (u16)0xffff; |
385 | break; | 385 | break; |
386 | case 4: | 386 | case 4: |
387 | *val = 0xffffffff; | 387 | *val = 0xffffffff; |
388 | break; | 388 | break; |
389 | } | 389 | } |
390 | } | 390 | } |
391 | 391 | ||
392 | return PCIBIOS_SUCCESSFUL; | 392 | return PCIBIOS_SUCCESSFUL; |
393 | } | 393 | } |
394 | 394 | ||
395 | static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) | 395 | static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) |
396 | { | 396 | { |
397 | ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); | 397 | ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); |
398 | 398 | ||
399 | switch (size) { | 399 | switch (size) { |
400 | case 1: | 400 | case 1: |
401 | ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); | 401 | ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); |
402 | break; | 402 | break; |
403 | case 2: | 403 | case 2: |
404 | ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); | 404 | ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); |
405 | break; | 405 | break; |
406 | case 4: | 406 | case 4: |
407 | ST40PCI_WRITE(PDR, val); | 407 | ST40PCI_WRITE(PDR, val); |
408 | break; | 408 | break; |
409 | } | 409 | } |
410 | 410 | ||
411 | CheckForMasterAbort(); | 411 | CheckForMasterAbort(); |
412 | 412 | ||
413 | return PCIBIOS_SUCCESSFUL; | 413 | return PCIBIOS_SUCCESSFUL; |
414 | } | 414 | } |
415 | 415 | ||
416 | struct pci_ops st40pci_config_ops = { | 416 | struct pci_ops st40pci_config_ops = { |
417 | .read = st40pci_read, | 417 | .read = st40pci_read, |
418 | .write = st40pci_write, | 418 | .write = st40pci_write, |
419 | }; | 419 | }; |
420 | 420 | ||
421 | 421 | ||
422 | /* Everything hangs off this */ | 422 | /* Everything hangs off this */ |
423 | static struct pci_bus *pci_root_bus; | 423 | static struct pci_bus *pci_root_bus; |
424 | 424 | ||
425 | 425 | ||
426 | static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) | 426 | static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) |
427 | { | 427 | { |
428 | return PCI_SLOT(dev->devfn); | 428 | return PCI_SLOT(dev->devfn); |
429 | } | 429 | } |
430 | 430 | ||
431 | 431 | ||
432 | static int __init pcibios_init(void) | 432 | static int __init pcibios_init(void) |
433 | { | 433 | { |
434 | extern unsigned long memory_start, memory_end; | 434 | extern unsigned long memory_start, memory_end; |
435 | 435 | ||
436 | printk(KERN_ALERT "pci-st40.c: pcibios_init\n"); | 436 | printk(KERN_ALERT "pci-st40.c: pcibios_init\n"); |
437 | 437 | ||
438 | if (sh_mv.mv_init_pci != NULL) { | 438 | if (sh_mv.mv_init_pci != NULL) { |
439 | sh_mv.mv_init_pci(); | 439 | sh_mv.mv_init_pci(); |
440 | } | 440 | } |
441 | 441 | ||
442 | /* The pci subsytem needs to know where memory is and how much | 442 | /* The pci subsytem needs to know where memory is and how much |
443 | * of it there is. I've simply made these globals. A better mechanism | 443 | * of it there is. I've simply made these globals. A better mechanism |
444 | * is probably needed. | 444 | * is probably needed. |
445 | */ | 445 | */ |
446 | st40pci_init(PHYSADDR(memory_start), | 446 | st40pci_init(PHYSADDR(memory_start), |
447 | PHYSADDR(memory_end) - PHYSADDR(memory_start)); | 447 | PHYSADDR(memory_end) - PHYSADDR(memory_start)); |
448 | 448 | ||
449 | if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, | 449 | if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, |
450 | SA_INTERRUPT, "st40pci", NULL)) { | 450 | IRQF_DISABLED, "st40pci", NULL)) { |
451 | printk(KERN_ERR "st40pci: Cannot hook interrupt\n"); | 451 | printk(KERN_ERR "st40pci: Cannot hook interrupt\n"); |
452 | return -EIO; | 452 | return -EIO; |
453 | } | 453 | } |
454 | 454 | ||
455 | /* Enable the PCI interrupts on the device */ | 455 | /* Enable the PCI interrupts on the device */ |
456 | ST40PCI_WRITE(INTM, ~0); | 456 | ST40PCI_WRITE(INTM, ~0); |
457 | ST40PCI_WRITE(AINT, ~0); | 457 | ST40PCI_WRITE(AINT, ~0); |
458 | 458 | ||
459 | /* Map the io address apprioately */ | 459 | /* Map the io address apprioately */ |
460 | #ifdef CONFIG_HD64465 | 460 | #ifdef CONFIG_HD64465 |
461 | hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1, | 461 | hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1, |
462 | ST40_IO_ADDR + PCIBIOS_MIN_IO, 0); | 462 | ST40_IO_ADDR + PCIBIOS_MIN_IO, 0); |
463 | #endif | 463 | #endif |
464 | 464 | ||
465 | /* ok, do the scan man */ | 465 | /* ok, do the scan man */ |
466 | pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL); | 466 | pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL); |
467 | pci_assign_unassigned_resources(); | 467 | pci_assign_unassigned_resources(); |
468 | pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq); | 468 | pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq); |
469 | 469 | ||
470 | return 0; | 470 | return 0; |
471 | } | 471 | } |
472 | 472 | ||
473 | subsys_initcall(pcibios_init); | 473 | subsys_initcall(pcibios_init); |
474 | 474 | ||
475 | void __init pcibios_fixup_bus(struct pci_bus *bus) | 475 | void __init pcibios_fixup_bus(struct pci_bus *bus) |
476 | { | 476 | { |
477 | } | 477 | } |
478 | 478 | ||
479 | /* | 479 | /* |
480 | * Publish a region of local address space over the PCI bus | 480 | * Publish a region of local address space over the PCI bus |
481 | * to other devices. | 481 | * to other devices. |
482 | */ | 482 | */ |
483 | static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, | 483 | static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, |
484 | unsigned long pciOffset, unsigned long regionSize) | 484 | unsigned long pciOffset, unsigned long regionSize) |
485 | { | 485 | { |
486 | unsigned long mask; | 486 | unsigned long mask; |
487 | 487 | ||
488 | if (region > 7) | 488 | if (region > 7) |
489 | return; | 489 | return; |
490 | 490 | ||
491 | if (regionSize > (512 * 1024 * 1024)) | 491 | if (regionSize > (512 * 1024 * 1024)) |
492 | return; | 492 | return; |
493 | 493 | ||
494 | mask = r2p2(regionSize) - 0x10000; | 494 | mask = r2p2(regionSize) - 0x10000; |
495 | 495 | ||
496 | /* Diable the region (in case currently in use, should never happen) */ | 496 | /* Diable the region (in case currently in use, should never happen) */ |
497 | ST40PCI_WRITE_INDEXED(RSR, region, 0); | 497 | ST40PCI_WRITE_INDEXED(RSR, region, 0); |
498 | 498 | ||
499 | /* Start of local address space to publish */ | 499 | /* Start of local address space to publish */ |
500 | ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) ); | 500 | ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) ); |
501 | 501 | ||
502 | /* Start of region in PCI address space as an offset from MBAR0 */ | 502 | /* Start of region in PCI address space as an offset from MBAR0 */ |
503 | ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset); | 503 | ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset); |
504 | 504 | ||
505 | /* Size of region */ | 505 | /* Size of region */ |
506 | ST40PCI_WRITE_INDEXED(RSR, region, mask | 1); | 506 | ST40PCI_WRITE_INDEXED(RSR, region, mask | 1); |
507 | } | 507 | } |
508 | 508 | ||
509 | 509 |
arch/sh/kernel/timers/timer-tmu.c
1 | /* | 1 | /* |
2 | * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support | 2 | * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Paul Mundt | 4 | * Copyright (C) 2005 Paul Mundt |
5 | * | 5 | * |
6 | * TMU handling code hacked out of arch/sh/kernel/time.c | 6 | * TMU handling code hacked out of arch/sh/kernel/time.c |
7 | * | 7 | * |
8 | * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka | 8 | * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka |
9 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> | 9 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> |
10 | * Copyright (C) 2002, 2003, 2004 Paul Mundt | 10 | * Copyright (C) 2002, 2003, 2004 Paul Mundt |
11 | * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> | 11 | * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> |
12 | * | 12 | * |
13 | * This file is subject to the terms and conditions of the GNU General Public | 13 | * This file is subject to the terms and conditions of the GNU General Public |
14 | * License. See the file "COPYING" in the main directory of this archive | 14 | * License. See the file "COPYING" in the main directory of this archive |
15 | * for more details. | 15 | * for more details. |
16 | */ | 16 | */ |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
21 | #include <linux/seqlock.h> | 21 | #include <linux/seqlock.h> |
22 | #include <asm/timer.h> | 22 | #include <asm/timer.h> |
23 | #include <asm/rtc.h> | 23 | #include <asm/rtc.h> |
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
26 | #include <asm/clock.h> | 26 | #include <asm/clock.h> |
27 | 27 | ||
28 | #define TMU_TOCR_INIT 0x00 | 28 | #define TMU_TOCR_INIT 0x00 |
29 | #define TMU0_TCR_INIT 0x0020 | 29 | #define TMU0_TCR_INIT 0x0020 |
30 | #define TMU_TSTR_INIT 1 | 30 | #define TMU_TSTR_INIT 1 |
31 | 31 | ||
32 | #define TMU0_TCR_CALIB 0x0000 | 32 | #define TMU0_TCR_CALIB 0x0000 |
33 | 33 | ||
34 | static DEFINE_SPINLOCK(tmu0_lock); | 34 | static DEFINE_SPINLOCK(tmu0_lock); |
35 | 35 | ||
36 | static unsigned long tmu_timer_get_offset(void) | 36 | static unsigned long tmu_timer_get_offset(void) |
37 | { | 37 | { |
38 | int count; | 38 | int count; |
39 | unsigned long flags; | 39 | unsigned long flags; |
40 | 40 | ||
41 | static int count_p = 0x7fffffff; /* for the first call after boot */ | 41 | static int count_p = 0x7fffffff; /* for the first call after boot */ |
42 | static unsigned long jiffies_p = 0; | 42 | static unsigned long jiffies_p = 0; |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * cache volatile jiffies temporarily; we have IRQs turned off. | 45 | * cache volatile jiffies temporarily; we have IRQs turned off. |
46 | */ | 46 | */ |
47 | unsigned long jiffies_t; | 47 | unsigned long jiffies_t; |
48 | 48 | ||
49 | spin_lock_irqsave(&tmu0_lock, flags); | 49 | spin_lock_irqsave(&tmu0_lock, flags); |
50 | /* timer count may underflow right here */ | 50 | /* timer count may underflow right here */ |
51 | count = ctrl_inl(TMU0_TCNT); /* read the latched count */ | 51 | count = ctrl_inl(TMU0_TCNT); /* read the latched count */ |
52 | 52 | ||
53 | jiffies_t = jiffies; | 53 | jiffies_t = jiffies; |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * avoiding timer inconsistencies (they are rare, but they happen)... | 56 | * avoiding timer inconsistencies (they are rare, but they happen)... |
57 | * there is one kind of problem that must be avoided here: | 57 | * there is one kind of problem that must be avoided here: |
58 | * 1. the timer counter underflows | 58 | * 1. the timer counter underflows |
59 | */ | 59 | */ |
60 | 60 | ||
61 | if (jiffies_t == jiffies_p) { | 61 | if (jiffies_t == jiffies_p) { |
62 | if (count > count_p) { | 62 | if (count > count_p) { |
63 | /* the nutcase */ | 63 | /* the nutcase */ |
64 | if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ | 64 | if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ |
65 | count -= LATCH; | 65 | count -= LATCH; |
66 | } else { | 66 | } else { |
67 | printk("%s (): hardware timer problem?\n", | 67 | printk("%s (): hardware timer problem?\n", |
68 | __FUNCTION__); | 68 | __FUNCTION__); |
69 | } | 69 | } |
70 | } | 70 | } |
71 | } else | 71 | } else |
72 | jiffies_p = jiffies_t; | 72 | jiffies_p = jiffies_t; |
73 | 73 | ||
74 | count_p = count; | 74 | count_p = count; |
75 | spin_unlock_irqrestore(&tmu0_lock, flags); | 75 | spin_unlock_irqrestore(&tmu0_lock, flags); |
76 | 76 | ||
77 | count = ((LATCH-1) - count) * TICK_SIZE; | 77 | count = ((LATCH-1) - count) * TICK_SIZE; |
78 | count = (count + LATCH/2) / LATCH; | 78 | count = (count + LATCH/2) / LATCH; |
79 | 79 | ||
80 | return count; | 80 | return count; |
81 | } | 81 | } |
82 | 82 | ||
83 | static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id, | 83 | static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id, |
84 | struct pt_regs *regs) | 84 | struct pt_regs *regs) |
85 | { | 85 | { |
86 | unsigned long timer_status; | 86 | unsigned long timer_status; |
87 | 87 | ||
88 | /* Clear UNF bit */ | 88 | /* Clear UNF bit */ |
89 | timer_status = ctrl_inw(TMU0_TCR); | 89 | timer_status = ctrl_inw(TMU0_TCR); |
90 | timer_status &= ~0x100; | 90 | timer_status &= ~0x100; |
91 | ctrl_outw(timer_status, TMU0_TCR); | 91 | ctrl_outw(timer_status, TMU0_TCR); |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * Here we are in the timer irq handler. We just have irqs locally | 94 | * Here we are in the timer irq handler. We just have irqs locally |
95 | * disabled but we don't know if the timer_bh is running on the other | 95 | * disabled but we don't know if the timer_bh is running on the other |
96 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need | 96 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need |
97 | * the irq version of write_lock because as just said we have irq | 97 | * the irq version of write_lock because as just said we have irq |
98 | * locally disabled. -arca | 98 | * locally disabled. -arca |
99 | */ | 99 | */ |
100 | write_seqlock(&xtime_lock); | 100 | write_seqlock(&xtime_lock); |
101 | handle_timer_tick(regs); | 101 | handle_timer_tick(regs); |
102 | write_sequnlock(&xtime_lock); | 102 | write_sequnlock(&xtime_lock); |
103 | 103 | ||
104 | return IRQ_HANDLED; | 104 | return IRQ_HANDLED; |
105 | } | 105 | } |
106 | 106 | ||
107 | static struct irqaction tmu_irq = { | 107 | static struct irqaction tmu_irq = { |
108 | .name = "timer", | 108 | .name = "timer", |
109 | .handler = tmu_timer_interrupt, | 109 | .handler = tmu_timer_interrupt, |
110 | .flags = SA_INTERRUPT, | 110 | .flags = IRQF_DISABLED, |
111 | .mask = CPU_MASK_NONE, | 111 | .mask = CPU_MASK_NONE, |
112 | }; | 112 | }; |
113 | 113 | ||
114 | /* | 114 | /* |
115 | * Hah! We'll see if this works (switching from usecs to nsecs). | 115 | * Hah! We'll see if this works (switching from usecs to nsecs). |
116 | */ | 116 | */ |
117 | static unsigned long tmu_timer_get_frequency(void) | 117 | static unsigned long tmu_timer_get_frequency(void) |
118 | { | 118 | { |
119 | u32 freq; | 119 | u32 freq; |
120 | struct timespec ts1, ts2; | 120 | struct timespec ts1, ts2; |
121 | unsigned long diff_nsec; | 121 | unsigned long diff_nsec; |
122 | unsigned long factor; | 122 | unsigned long factor; |
123 | 123 | ||
124 | /* Setup the timer: We don't want to generate interrupts, just | 124 | /* Setup the timer: We don't want to generate interrupts, just |
125 | * have it count down at its natural rate. | 125 | * have it count down at its natural rate. |
126 | */ | 126 | */ |
127 | ctrl_outb(0, TMU_TSTR); | 127 | ctrl_outb(0, TMU_TSTR); |
128 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) | 128 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) |
129 | ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); | 129 | ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); |
130 | #endif | 130 | #endif |
131 | ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR); | 131 | ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR); |
132 | ctrl_outl(0xffffffff, TMU0_TCOR); | 132 | ctrl_outl(0xffffffff, TMU0_TCOR); |
133 | ctrl_outl(0xffffffff, TMU0_TCNT); | 133 | ctrl_outl(0xffffffff, TMU0_TCNT); |
134 | 134 | ||
135 | rtc_get_time(&ts2); | 135 | rtc_get_time(&ts2); |
136 | 136 | ||
137 | do { | 137 | do { |
138 | rtc_get_time(&ts1); | 138 | rtc_get_time(&ts1); |
139 | } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); | 139 | } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); |
140 | 140 | ||
141 | /* actually start the timer */ | 141 | /* actually start the timer */ |
142 | ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); | 142 | ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); |
143 | 143 | ||
144 | do { | 144 | do { |
145 | rtc_get_time(&ts2); | 145 | rtc_get_time(&ts2); |
146 | } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); | 146 | } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); |
147 | 147 | ||
148 | freq = 0xffffffff - ctrl_inl(TMU0_TCNT); | 148 | freq = 0xffffffff - ctrl_inl(TMU0_TCNT); |
149 | if (ts2.tv_nsec < ts1.tv_nsec) { | 149 | if (ts2.tv_nsec < ts1.tv_nsec) { |
150 | ts2.tv_nsec += 1000000000; | 150 | ts2.tv_nsec += 1000000000; |
151 | ts2.tv_sec--; | 151 | ts2.tv_sec--; |
152 | } | 152 | } |
153 | 153 | ||
154 | diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); | 154 | diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); |
155 | 155 | ||
156 | /* this should work well if the RTC has a precision of n Hz, where | 156 | /* this should work well if the RTC has a precision of n Hz, where |
157 | * n is an integer. I don't think we have to worry about the other | 157 | * n is an integer. I don't think we have to worry about the other |
158 | * cases. */ | 158 | * cases. */ |
159 | factor = (1000000000 + diff_nsec/2) / diff_nsec; | 159 | factor = (1000000000 + diff_nsec/2) / diff_nsec; |
160 | 160 | ||
161 | if (factor * diff_nsec > 1100000000 || | 161 | if (factor * diff_nsec > 1100000000 || |
162 | factor * diff_nsec < 900000000) | 162 | factor * diff_nsec < 900000000) |
163 | panic("weird RTC (diff_nsec %ld)", diff_nsec); | 163 | panic("weird RTC (diff_nsec %ld)", diff_nsec); |
164 | 164 | ||
165 | return freq * factor; | 165 | return freq * factor; |
166 | } | 166 | } |
167 | 167 | ||
168 | static void tmu_clk_init(struct clk *clk) | 168 | static void tmu_clk_init(struct clk *clk) |
169 | { | 169 | { |
170 | u8 divisor = TMU0_TCR_INIT & 0x7; | 170 | u8 divisor = TMU0_TCR_INIT & 0x7; |
171 | ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); | 171 | ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); |
172 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); | 172 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); |
173 | } | 173 | } |
174 | 174 | ||
175 | static void tmu_clk_recalc(struct clk *clk) | 175 | static void tmu_clk_recalc(struct clk *clk) |
176 | { | 176 | { |
177 | u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; | 177 | u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; |
178 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); | 178 | clk->rate = clk->parent->rate / (4 << (divisor << 1)); |
179 | } | 179 | } |
180 | 180 | ||
181 | static struct clk_ops tmu_clk_ops = { | 181 | static struct clk_ops tmu_clk_ops = { |
182 | .init = tmu_clk_init, | 182 | .init = tmu_clk_init, |
183 | .recalc = tmu_clk_recalc, | 183 | .recalc = tmu_clk_recalc, |
184 | }; | 184 | }; |
185 | 185 | ||
186 | static struct clk tmu0_clk = { | 186 | static struct clk tmu0_clk = { |
187 | .name = "tmu0_clk", | 187 | .name = "tmu0_clk", |
188 | .ops = &tmu_clk_ops, | 188 | .ops = &tmu_clk_ops, |
189 | }; | 189 | }; |
190 | 190 | ||
191 | static int tmu_timer_init(void) | 191 | static int tmu_timer_init(void) |
192 | { | 192 | { |
193 | unsigned long interval; | 193 | unsigned long interval; |
194 | 194 | ||
195 | setup_irq(TIMER_IRQ, &tmu_irq); | 195 | setup_irq(TIMER_IRQ, &tmu_irq); |
196 | 196 | ||
197 | tmu0_clk.parent = clk_get("module_clk"); | 197 | tmu0_clk.parent = clk_get("module_clk"); |
198 | 198 | ||
199 | /* Start TMU0 */ | 199 | /* Start TMU0 */ |
200 | ctrl_outb(0, TMU_TSTR); | 200 | ctrl_outb(0, TMU_TSTR); |
201 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) | 201 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) |
202 | ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); | 202 | ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); |
203 | #endif | 203 | #endif |
204 | 204 | ||
205 | clk_register(&tmu0_clk); | 205 | clk_register(&tmu0_clk); |
206 | clk_enable(&tmu0_clk); | 206 | clk_enable(&tmu0_clk); |
207 | 207 | ||
208 | interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; | 208 | interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; |
209 | printk(KERN_INFO "Interval = %ld\n", interval); | 209 | printk(KERN_INFO "Interval = %ld\n", interval); |
210 | 210 | ||
211 | ctrl_outl(interval, TMU0_TCOR); | 211 | ctrl_outl(interval, TMU0_TCOR); |
212 | ctrl_outl(interval, TMU0_TCNT); | 212 | ctrl_outl(interval, TMU0_TCNT); |
213 | 213 | ||
214 | ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); | 214 | ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); |
215 | 215 | ||
216 | return 0; | 216 | return 0; |
217 | } | 217 | } |
218 | 218 | ||
219 | struct sys_timer_ops tmu_timer_ops = { | 219 | struct sys_timer_ops tmu_timer_ops = { |
220 | .init = tmu_timer_init, | 220 | .init = tmu_timer_init, |
221 | .get_frequency = tmu_timer_get_frequency, | 221 | .get_frequency = tmu_timer_get_frequency, |
222 | .get_offset = tmu_timer_get_offset, | 222 | .get_offset = tmu_timer_get_offset, |
223 | }; | 223 | }; |
224 | 224 | ||
225 | struct sys_timer tmu_timer = { | 225 | struct sys_timer tmu_timer = { |
226 | .name = "tmu", | 226 | .name = "tmu", |
227 | .ops = &tmu_timer_ops, | 227 | .ops = &tmu_timer_ops, |
228 | }; | 228 | }; |
229 | 229 | ||
230 | 230 |
include/asm-sh/floppy.h
1 | /* | 1 | /* |
2 | * Architecture specific parts of the Floppy driver | 2 | * Architecture specific parts of the Floppy driver |
3 | * include/asm-i386/floppy.h | 3 | * include/asm-i386/floppy.h |
4 | * | 4 | * |
5 | * This file is subject to the terms and conditions of the GNU General Public | 5 | * This file is subject to the terms and conditions of the GNU General Public |
6 | * License. See the file "COPYING" in the main directory of this archive | 6 | * License. See the file "COPYING" in the main directory of this archive |
7 | * for more details. | 7 | * for more details. |
8 | * | 8 | * |
9 | * Copyright (C) 1995 | 9 | * Copyright (C) 1995 |
10 | */ | 10 | */ |
11 | #ifndef __ASM_SH_FLOPPY_H | 11 | #ifndef __ASM_SH_FLOPPY_H |
12 | #define __ASM_SH_FLOPPY_H | 12 | #define __ASM_SH_FLOPPY_H |
13 | 13 | ||
14 | #include <linux/vmalloc.h> | 14 | #include <linux/vmalloc.h> |
15 | 15 | ||
16 | 16 | ||
17 | /* | 17 | /* |
18 | * The DMA channel used by the floppy controller cannot access data at | 18 | * The DMA channel used by the floppy controller cannot access data at |
19 | * addresses >= 16MB | 19 | * addresses >= 16MB |
20 | * | 20 | * |
21 | * Went back to the 1MB limit, as some people had problems with the floppy | 21 | * Went back to the 1MB limit, as some people had problems with the floppy |
22 | * driver otherwise. It doesn't matter much for performance anyway, as most | 22 | * driver otherwise. It doesn't matter much for performance anyway, as most |
23 | * floppy accesses go through the track buffer. | 23 | * floppy accesses go through the track buffer. |
24 | */ | 24 | */ |
25 | #define _CROSS_64KB(a,s,vdma) \ | 25 | #define _CROSS_64KB(a,s,vdma) \ |
26 | (!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)) | 26 | (!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)) |
27 | 27 | ||
28 | #define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1) | 28 | #define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1) |
29 | 29 | ||
30 | 30 | ||
31 | #define SW fd_routine[use_virtual_dma&1] | 31 | #define SW fd_routine[use_virtual_dma&1] |
32 | #define CSW fd_routine[can_use_virtual_dma & 1] | 32 | #define CSW fd_routine[can_use_virtual_dma & 1] |
33 | 33 | ||
34 | 34 | ||
35 | #define fd_inb(port) inb_p(port) | 35 | #define fd_inb(port) inb_p(port) |
36 | #define fd_outb(value,port) outb_p(value,port) | 36 | #define fd_outb(value,port) outb_p(value,port) |
37 | 37 | ||
38 | #define fd_request_dma() CSW._request_dma(FLOPPY_DMA,"floppy") | 38 | #define fd_request_dma() CSW._request_dma(FLOPPY_DMA,"floppy") |
39 | #define fd_free_dma() CSW._free_dma(FLOPPY_DMA) | 39 | #define fd_free_dma() CSW._free_dma(FLOPPY_DMA) |
40 | #define fd_enable_irq() enable_irq(FLOPPY_IRQ) | 40 | #define fd_enable_irq() enable_irq(FLOPPY_IRQ) |
41 | #define fd_disable_irq() disable_irq(FLOPPY_IRQ) | 41 | #define fd_disable_irq() disable_irq(FLOPPY_IRQ) |
42 | #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) | 42 | #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) |
43 | #define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA) | 43 | #define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA) |
44 | #define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size) | 44 | #define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size) |
45 | #define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io) | 45 | #define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io) |
46 | 46 | ||
47 | #define FLOPPY_CAN_FALLBACK_ON_NODMA | 47 | #define FLOPPY_CAN_FALLBACK_ON_NODMA |
48 | 48 | ||
49 | static int virtual_dma_count; | 49 | static int virtual_dma_count; |
50 | static int virtual_dma_residue; | 50 | static int virtual_dma_residue; |
51 | static char *virtual_dma_addr; | 51 | static char *virtual_dma_addr; |
52 | static int virtual_dma_mode; | 52 | static int virtual_dma_mode; |
53 | static int doing_pdma; | 53 | static int doing_pdma; |
54 | 54 | ||
55 | static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) | 55 | static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) |
56 | { | 56 | { |
57 | register unsigned char st; | 57 | register unsigned char st; |
58 | 58 | ||
59 | #undef TRACE_FLPY_INT | 59 | #undef TRACE_FLPY_INT |
60 | 60 | ||
61 | #ifdef TRACE_FLPY_INT | 61 | #ifdef TRACE_FLPY_INT |
62 | static int calls=0; | 62 | static int calls=0; |
63 | static int bytes=0; | 63 | static int bytes=0; |
64 | static int dma_wait=0; | 64 | static int dma_wait=0; |
65 | #endif | 65 | #endif |
66 | if(!doing_pdma) { | 66 | if(!doing_pdma) { |
67 | floppy_interrupt(irq, dev_id, regs); | 67 | floppy_interrupt(irq, dev_id, regs); |
68 | return; | 68 | return; |
69 | } | 69 | } |
70 | 70 | ||
71 | #ifdef TRACE_FLPY_INT | 71 | #ifdef TRACE_FLPY_INT |
72 | if(!calls) | 72 | if(!calls) |
73 | bytes = virtual_dma_count; | 73 | bytes = virtual_dma_count; |
74 | #endif | 74 | #endif |
75 | 75 | ||
76 | { | 76 | { |
77 | register int lcount; | 77 | register int lcount; |
78 | register char *lptr; | 78 | register char *lptr; |
79 | 79 | ||
80 | st = 1; | 80 | st = 1; |
81 | for(lcount=virtual_dma_count, lptr=virtual_dma_addr; | 81 | for(lcount=virtual_dma_count, lptr=virtual_dma_addr; |
82 | lcount; lcount--, lptr++) { | 82 | lcount; lcount--, lptr++) { |
83 | st=inb(virtual_dma_port+4) & 0xa0 ; | 83 | st=inb(virtual_dma_port+4) & 0xa0 ; |
84 | if(st != 0xa0) | 84 | if(st != 0xa0) |
85 | break; | 85 | break; |
86 | if(virtual_dma_mode) | 86 | if(virtual_dma_mode) |
87 | outb_p(*lptr, virtual_dma_port+5); | 87 | outb_p(*lptr, virtual_dma_port+5); |
88 | else | 88 | else |
89 | *lptr = inb_p(virtual_dma_port+5); | 89 | *lptr = inb_p(virtual_dma_port+5); |
90 | } | 90 | } |
91 | virtual_dma_count = lcount; | 91 | virtual_dma_count = lcount; |
92 | virtual_dma_addr = lptr; | 92 | virtual_dma_addr = lptr; |
93 | st = inb(virtual_dma_port+4); | 93 | st = inb(virtual_dma_port+4); |
94 | } | 94 | } |
95 | 95 | ||
96 | #ifdef TRACE_FLPY_INT | 96 | #ifdef TRACE_FLPY_INT |
97 | calls++; | 97 | calls++; |
98 | #endif | 98 | #endif |
99 | if(st == 0x20) | 99 | if(st == 0x20) |
100 | return; | 100 | return; |
101 | if(!(st & 0x20)) { | 101 | if(!(st & 0x20)) { |
102 | virtual_dma_residue += virtual_dma_count; | 102 | virtual_dma_residue += virtual_dma_count; |
103 | virtual_dma_count=0; | 103 | virtual_dma_count=0; |
104 | #ifdef TRACE_FLPY_INT | 104 | #ifdef TRACE_FLPY_INT |
105 | printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", | 105 | printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", |
106 | virtual_dma_count, virtual_dma_residue, calls, bytes, | 106 | virtual_dma_count, virtual_dma_residue, calls, bytes, |
107 | dma_wait); | 107 | dma_wait); |
108 | calls = 0; | 108 | calls = 0; |
109 | dma_wait=0; | 109 | dma_wait=0; |
110 | #endif | 110 | #endif |
111 | doing_pdma = 0; | 111 | doing_pdma = 0; |
112 | floppy_interrupt(irq, dev_id, regs); | 112 | floppy_interrupt(irq, dev_id, regs); |
113 | return; | 113 | return; |
114 | } | 114 | } |
115 | #ifdef TRACE_FLPY_INT | 115 | #ifdef TRACE_FLPY_INT |
116 | if(!virtual_dma_count) | 116 | if(!virtual_dma_count) |
117 | dma_wait++; | 117 | dma_wait++; |
118 | #endif | 118 | #endif |
119 | } | 119 | } |
120 | 120 | ||
121 | static void fd_disable_dma(void) | 121 | static void fd_disable_dma(void) |
122 | { | 122 | { |
123 | if(! (can_use_virtual_dma & 1)) | 123 | if(! (can_use_virtual_dma & 1)) |
124 | disable_dma(FLOPPY_DMA); | 124 | disable_dma(FLOPPY_DMA); |
125 | doing_pdma = 0; | 125 | doing_pdma = 0; |
126 | virtual_dma_residue += virtual_dma_count; | 126 | virtual_dma_residue += virtual_dma_count; |
127 | virtual_dma_count=0; | 127 | virtual_dma_count=0; |
128 | } | 128 | } |
129 | 129 | ||
130 | static int vdma_request_dma(unsigned int dmanr, const char * device_id) | 130 | static int vdma_request_dma(unsigned int dmanr, const char * device_id) |
131 | { | 131 | { |
132 | return 0; | 132 | return 0; |
133 | } | 133 | } |
134 | 134 | ||
135 | static void vdma_nop(unsigned int dummy) | 135 | static void vdma_nop(unsigned int dummy) |
136 | { | 136 | { |
137 | } | 137 | } |
138 | 138 | ||
139 | 139 | ||
140 | static int vdma_get_dma_residue(unsigned int dummy) | 140 | static int vdma_get_dma_residue(unsigned int dummy) |
141 | { | 141 | { |
142 | return virtual_dma_count + virtual_dma_residue; | 142 | return virtual_dma_count + virtual_dma_residue; |
143 | } | 143 | } |
144 | 144 | ||
145 | 145 | ||
146 | static int fd_request_irq(void) | 146 | static int fd_request_irq(void) |
147 | { | 147 | { |
148 | if(can_use_virtual_dma) | 148 | if(can_use_virtual_dma) |
149 | return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, | 149 | return request_irq(FLOPPY_IRQ, floppy_hardint, |
150 | "floppy", NULL); | 150 | IRQF_DISABLED, "floppy", NULL); |
151 | else | 151 | else |
152 | return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT, | 152 | return request_irq(FLOPPY_IRQ, floppy_interrupt, |
153 | "floppy", NULL); | 153 | IRQF_DISABLED, "floppy", NULL); |
154 | |||
155 | } | 154 | } |
156 | 155 | ||
157 | static unsigned long dma_mem_alloc(unsigned long size) | 156 | static unsigned long dma_mem_alloc(unsigned long size) |
158 | { | 157 | { |
159 | return __get_dma_pages(GFP_KERNEL,get_order(size)); | 158 | return __get_dma_pages(GFP_KERNEL,get_order(size)); |
160 | } | 159 | } |
161 | 160 | ||
162 | 161 | ||
163 | static unsigned long vdma_mem_alloc(unsigned long size) | 162 | static unsigned long vdma_mem_alloc(unsigned long size) |
164 | { | 163 | { |
165 | return (unsigned long) vmalloc(size); | 164 | return (unsigned long) vmalloc(size); |
166 | 165 | ||
167 | } | 166 | } |
168 | 167 | ||
169 | #define nodma_mem_alloc(size) vdma_mem_alloc(size) | 168 | #define nodma_mem_alloc(size) vdma_mem_alloc(size) |
170 | 169 | ||
171 | static void _fd_dma_mem_free(unsigned long addr, unsigned long size) | 170 | static void _fd_dma_mem_free(unsigned long addr, unsigned long size) |
172 | { | 171 | { |
173 | if((unsigned int) addr >= (unsigned int) high_memory) | 172 | if((unsigned int) addr >= (unsigned int) high_memory) |
174 | return vfree((void *)addr); | 173 | return vfree((void *)addr); |
175 | else | 174 | else |
176 | free_pages(addr, get_order(size)); | 175 | free_pages(addr, get_order(size)); |
177 | } | 176 | } |
178 | 177 | ||
179 | #define fd_dma_mem_free(addr, size) _fd_dma_mem_free(addr, size) | 178 | #define fd_dma_mem_free(addr, size) _fd_dma_mem_free(addr, size) |
180 | 179 | ||
181 | static void _fd_chose_dma_mode(char *addr, unsigned long size) | 180 | static void _fd_chose_dma_mode(char *addr, unsigned long size) |
182 | { | 181 | { |
183 | if(can_use_virtual_dma == 2) { | 182 | if(can_use_virtual_dma == 2) { |
184 | if((unsigned int) addr >= (unsigned int) high_memory || | 183 | if((unsigned int) addr >= (unsigned int) high_memory || |
185 | virt_to_bus(addr) >= 0x10000000) | 184 | virt_to_bus(addr) >= 0x10000000) |
186 | use_virtual_dma = 1; | 185 | use_virtual_dma = 1; |
187 | else | 186 | else |
188 | use_virtual_dma = 0; | 187 | use_virtual_dma = 0; |
189 | } else { | 188 | } else { |
190 | use_virtual_dma = can_use_virtual_dma & 1; | 189 | use_virtual_dma = can_use_virtual_dma & 1; |
191 | } | 190 | } |
192 | } | 191 | } |
193 | 192 | ||
194 | #define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size) | 193 | #define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size) |
195 | 194 | ||
196 | 195 | ||
197 | static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) | 196 | static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) |
198 | { | 197 | { |
199 | doing_pdma = 1; | 198 | doing_pdma = 1; |
200 | virtual_dma_port = io; | 199 | virtual_dma_port = io; |
201 | virtual_dma_mode = (mode == DMA_MODE_WRITE); | 200 | virtual_dma_mode = (mode == DMA_MODE_WRITE); |
202 | virtual_dma_addr = addr; | 201 | virtual_dma_addr = addr; |
203 | virtual_dma_count = size; | 202 | virtual_dma_count = size; |
204 | virtual_dma_residue = 0; | 203 | virtual_dma_residue = 0; |
205 | return 0; | 204 | return 0; |
206 | } | 205 | } |
207 | 206 | ||
208 | static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) | 207 | static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) |
209 | { | 208 | { |
210 | #ifdef FLOPPY_SANITY_CHECK | 209 | #ifdef FLOPPY_SANITY_CHECK |
211 | if (CROSS_64KB(addr, size)) { | 210 | if (CROSS_64KB(addr, size)) { |
212 | printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size); | 211 | printk("DMA crossing 64-K boundary %p-%p\n", addr, addr+size); |
213 | return -1; | 212 | return -1; |
214 | } | 213 | } |
215 | #endif | 214 | #endif |
216 | 215 | ||
217 | dma_cache_wback_inv(addr, size); | 216 | dma_cache_wback_inv(addr, size); |
218 | 217 | ||
219 | /* actual, physical DMA */ | 218 | /* actual, physical DMA */ |
220 | doing_pdma = 0; | 219 | doing_pdma = 0; |
221 | clear_dma_ff(FLOPPY_DMA); | 220 | clear_dma_ff(FLOPPY_DMA); |
222 | set_dma_mode(FLOPPY_DMA,mode); | 221 | set_dma_mode(FLOPPY_DMA,mode); |
223 | set_dma_addr(FLOPPY_DMA,virt_to_bus(addr)); | 222 | set_dma_addr(FLOPPY_DMA,virt_to_bus(addr)); |
224 | set_dma_count(FLOPPY_DMA,size); | 223 | set_dma_count(FLOPPY_DMA,size); |
225 | enable_dma(FLOPPY_DMA); | 224 | enable_dma(FLOPPY_DMA); |
226 | return 0; | 225 | return 0; |
227 | } | 226 | } |
228 | 227 | ||
229 | static struct fd_routine_l { | 228 | static struct fd_routine_l { |
230 | int (*_request_dma)(unsigned int dmanr, const char * device_id); | 229 | int (*_request_dma)(unsigned int dmanr, const char * device_id); |
231 | void (*_free_dma)(unsigned int dmanr); | 230 | void (*_free_dma)(unsigned int dmanr); |
232 | int (*_get_dma_residue)(unsigned int dummy); | 231 | int (*_get_dma_residue)(unsigned int dummy); |
233 | unsigned long (*_dma_mem_alloc) (unsigned long size); | 232 | unsigned long (*_dma_mem_alloc) (unsigned long size); |
234 | int (*_dma_setup)(char *addr, unsigned long size, int mode, int io); | 233 | int (*_dma_setup)(char *addr, unsigned long size, int mode, int io); |
235 | } fd_routine[] = { | 234 | } fd_routine[] = { |
236 | { | 235 | { |
237 | request_dma, | 236 | request_dma, |
238 | free_dma, | 237 | free_dma, |
239 | get_dma_residue, | 238 | get_dma_residue, |
240 | dma_mem_alloc, | 239 | dma_mem_alloc, |
241 | hard_dma_setup | 240 | hard_dma_setup |
242 | }, | 241 | }, |
243 | { | 242 | { |
244 | vdma_request_dma, | 243 | vdma_request_dma, |
245 | vdma_nop, | 244 | vdma_nop, |
246 | vdma_get_dma_residue, | 245 | vdma_get_dma_residue, |
247 | vdma_mem_alloc, | 246 | vdma_mem_alloc, |
248 | vdma_dma_setup | 247 | vdma_dma_setup |
249 | } | 248 | } |
250 | }; | 249 | }; |
251 | 250 | ||
252 | 251 | ||
253 | static int FDC1 = 0x3f0; | 252 | static int FDC1 = 0x3f0; |
254 | static int FDC2 = -1; | 253 | static int FDC2 = -1; |
255 | 254 | ||
256 | /* | 255 | /* |
257 | * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock | 256 | * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock |
258 | * is needed to prevent corrupted CMOS RAM in case "insmod floppy" | 257 | * is needed to prevent corrupted CMOS RAM in case "insmod floppy" |
259 | * coincides with another rtc CMOS user. Paul G. | 258 | * coincides with another rtc CMOS user. Paul G. |
260 | */ | 259 | */ |
261 | #define FLOPPY0_TYPE (4) | 260 | #define FLOPPY0_TYPE (4) |
262 | #define FLOPPY1_TYPE (0) | 261 | #define FLOPPY1_TYPE (0) |
263 | 262 | ||
264 | #define N_FDC 2 | 263 | #define N_FDC 2 |
265 | #define N_DRIVE 8 | 264 | #define N_DRIVE 8 |
266 | 265 | ||
267 | #define FLOPPY_MOTOR_MASK 0xf0 | 266 | #define FLOPPY_MOTOR_MASK 0xf0 |
268 | 267 | ||
269 | #define AUTO_DMA | 268 | #define AUTO_DMA |
270 | 269 | ||
271 | #define EXTRA_FLOPPY_PARAMS | 270 | #define EXTRA_FLOPPY_PARAMS |
272 | 271 | ||
273 | #endif /* __ASM_SH_FLOPPY_H */ | 272 | #endif /* __ASM_SH_FLOPPY_H */ |
274 | 273 |
include/asm-sh/mpc1211/keyboard.h
1 | /* | 1 | /* |
2 | * MPC1211 specific keybord definitions | 2 | * MPC1211 specific keybord definitions |
3 | * Taken from the old asm-i386/keybord.h for PC/AT-style definitions | 3 | * Taken from the old asm-i386/keybord.h for PC/AT-style definitions |
4 | * created 3 Nov 1996 by Geert Uytterhoeven. | 4 | * created 3 Nov 1996 by Geert Uytterhoeven. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #ifdef __KERNEL__ | 7 | #ifdef __KERNEL__ |
8 | 8 | ||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/ioport.h> | 10 | #include <linux/ioport.h> |
11 | #include <linux/kd.h> | 11 | #include <linux/kd.h> |
12 | #include <linux/pm.h> | 12 | #include <linux/pm.h> |
13 | #include <asm/io.h> | 13 | #include <asm/io.h> |
14 | 14 | ||
15 | #define KEYBOARD_IRQ 1 | 15 | #define KEYBOARD_IRQ 1 |
16 | #define DISABLE_KBD_DURING_INTERRUPTS 0 | 16 | #define DISABLE_KBD_DURING_INTERRUPTS 0 |
17 | 17 | ||
18 | extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); | 18 | extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); |
19 | extern int pckbd_getkeycode(unsigned int scancode); | 19 | extern int pckbd_getkeycode(unsigned int scancode); |
20 | extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, | 20 | extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, |
21 | char raw_mode); | 21 | char raw_mode); |
22 | extern char pckbd_unexpected_up(unsigned char keycode); | 22 | extern char pckbd_unexpected_up(unsigned char keycode); |
23 | extern void pckbd_leds(unsigned char leds); | 23 | extern void pckbd_leds(unsigned char leds); |
24 | extern void pckbd_init_hw(void); | 24 | extern void pckbd_init_hw(void); |
25 | extern int pckbd_pm_resume(struct pm_dev *, pm_request_t, void *); | 25 | extern int pckbd_pm_resume(struct pm_dev *, pm_request_t, void *); |
26 | extern pm_callback pm_kbd_request_override; | 26 | extern pm_callback pm_kbd_request_override; |
27 | extern unsigned char pckbd_sysrq_xlate[128]; | 27 | extern unsigned char pckbd_sysrq_xlate[128]; |
28 | 28 | ||
29 | #define kbd_setkeycode pckbd_setkeycode | 29 | #define kbd_setkeycode pckbd_setkeycode |
30 | #define kbd_getkeycode pckbd_getkeycode | 30 | #define kbd_getkeycode pckbd_getkeycode |
31 | #define kbd_translate pckbd_translate | 31 | #define kbd_translate pckbd_translate |
32 | #define kbd_unexpected_up pckbd_unexpected_up | 32 | #define kbd_unexpected_up pckbd_unexpected_up |
33 | #define kbd_leds pckbd_leds | 33 | #define kbd_leds pckbd_leds |
34 | #define kbd_init_hw pckbd_init_hw | 34 | #define kbd_init_hw pckbd_init_hw |
35 | #define kbd_sysrq_xlate pckbd_sysrq_xlate | 35 | #define kbd_sysrq_xlate pckbd_sysrq_xlate |
36 | 36 | ||
37 | #define SYSRQ_KEY 0x54 | 37 | #define SYSRQ_KEY 0x54 |
38 | 38 | ||
39 | /* resource allocation */ | 39 | /* resource allocation */ |
40 | #define kbd_request_region() | 40 | #define kbd_request_region() |
41 | #define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \ | 41 | #define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \ |
42 | "keyboard", NULL) | 42 | "keyboard", NULL) |
43 | 43 | ||
44 | /* How to access the keyboard macros on this platform. */ | 44 | /* How to access the keyboard macros on this platform. */ |
45 | #define kbd_read_input() inb(KBD_DATA_REG) | 45 | #define kbd_read_input() inb(KBD_DATA_REG) |
46 | #define kbd_read_status() inb(KBD_STATUS_REG) | 46 | #define kbd_read_status() inb(KBD_STATUS_REG) |
47 | #define kbd_write_output(val) outb(val, KBD_DATA_REG) | 47 | #define kbd_write_output(val) outb(val, KBD_DATA_REG) |
48 | #define kbd_write_command(val) outb(val, KBD_CNTL_REG) | 48 | #define kbd_write_command(val) outb(val, KBD_CNTL_REG) |
49 | 49 | ||
50 | /* Some stoneage hardware needs delays after some operations. */ | 50 | /* Some stoneage hardware needs delays after some operations. */ |
51 | #define kbd_pause() do { } while(0) | 51 | #define kbd_pause() do { } while(0) |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * Machine specific bits for the PS/2 driver | 54 | * Machine specific bits for the PS/2 driver |
55 | */ | 55 | */ |
56 | 56 | ||
57 | #define AUX_IRQ 12 | 57 | #define AUX_IRQ 12 |
58 | 58 | ||
59 | #define aux_request_irq(hand, dev_id) \ | 59 | #define aux_request_irq(hand, dev_id) \ |
60 | request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS2 Mouse", dev_id) | 60 | request_irq(AUX_IRQ, hand, IRQF_SHARED, "PS2 Mouse", dev_id) |
61 | 61 | ||
62 | #define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id) | 62 | #define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id) |
63 | 63 | ||
64 | #endif /* __KERNEL__ */ | 64 | #endif /* __KERNEL__ */ |
65 | 65 |
include/asm-sh/signal.h
1 | #ifndef __ASM_SH_SIGNAL_H | 1 | #ifndef __ASM_SH_SIGNAL_H |
2 | #define __ASM_SH_SIGNAL_H | 2 | #define __ASM_SH_SIGNAL_H |
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
6 | /* Avoid too many header ordering problems. */ | 6 | /* Avoid too many header ordering problems. */ |
7 | struct pt_regs; | 7 | struct pt_regs; |
8 | struct siginfo; | 8 | struct siginfo; |
9 | 9 | ||
10 | #ifdef __KERNEL__ | 10 | #ifdef __KERNEL__ |
11 | /* Most things should be clean enough to redefine this at will, if care | 11 | /* Most things should be clean enough to redefine this at will, if care |
12 | is taken to make libc match. */ | 12 | is taken to make libc match. */ |
13 | 13 | ||
14 | #define _NSIG 64 | 14 | #define _NSIG 64 |
15 | #define _NSIG_BPW 32 | 15 | #define _NSIG_BPW 32 |
16 | #define _NSIG_WORDS (_NSIG / _NSIG_BPW) | 16 | #define _NSIG_WORDS (_NSIG / _NSIG_BPW) |
17 | 17 | ||
18 | typedef unsigned long old_sigset_t; /* at least 32 bits */ | 18 | typedef unsigned long old_sigset_t; /* at least 32 bits */ |
19 | 19 | ||
20 | typedef struct { | 20 | typedef struct { |
21 | unsigned long sig[_NSIG_WORDS]; | 21 | unsigned long sig[_NSIG_WORDS]; |
22 | } sigset_t; | 22 | } sigset_t; |
23 | 23 | ||
24 | #else | 24 | #else |
25 | /* Here we must cater to libcs that poke about in kernel headers. */ | 25 | /* Here we must cater to libcs that poke about in kernel headers. */ |
26 | 26 | ||
27 | #define NSIG 32 | 27 | #define NSIG 32 |
28 | typedef unsigned long sigset_t; | 28 | typedef unsigned long sigset_t; |
29 | 29 | ||
30 | #endif /* __KERNEL__ */ | 30 | #endif /* __KERNEL__ */ |
31 | 31 | ||
32 | #define SIGHUP 1 | 32 | #define SIGHUP 1 |
33 | #define SIGINT 2 | 33 | #define SIGINT 2 |
34 | #define SIGQUIT 3 | 34 | #define SIGQUIT 3 |
35 | #define SIGILL 4 | 35 | #define SIGILL 4 |
36 | #define SIGTRAP 5 | 36 | #define SIGTRAP 5 |
37 | #define SIGABRT 6 | 37 | #define SIGABRT 6 |
38 | #define SIGIOT 6 | 38 | #define SIGIOT 6 |
39 | #define SIGBUS 7 | 39 | #define SIGBUS 7 |
40 | #define SIGFPE 8 | 40 | #define SIGFPE 8 |
41 | #define SIGKILL 9 | 41 | #define SIGKILL 9 |
42 | #define SIGUSR1 10 | 42 | #define SIGUSR1 10 |
43 | #define SIGSEGV 11 | 43 | #define SIGSEGV 11 |
44 | #define SIGUSR2 12 | 44 | #define SIGUSR2 12 |
45 | #define SIGPIPE 13 | 45 | #define SIGPIPE 13 |
46 | #define SIGALRM 14 | 46 | #define SIGALRM 14 |
47 | #define SIGTERM 15 | 47 | #define SIGTERM 15 |
48 | #define SIGSTKFLT 16 | 48 | #define SIGSTKFLT 16 |
49 | #define SIGCHLD 17 | 49 | #define SIGCHLD 17 |
50 | #define SIGCONT 18 | 50 | #define SIGCONT 18 |
51 | #define SIGSTOP 19 | 51 | #define SIGSTOP 19 |
52 | #define SIGTSTP 20 | 52 | #define SIGTSTP 20 |
53 | #define SIGTTIN 21 | 53 | #define SIGTTIN 21 |
54 | #define SIGTTOU 22 | 54 | #define SIGTTOU 22 |
55 | #define SIGURG 23 | 55 | #define SIGURG 23 |
56 | #define SIGXCPU 24 | 56 | #define SIGXCPU 24 |
57 | #define SIGXFSZ 25 | 57 | #define SIGXFSZ 25 |
58 | #define SIGVTALRM 26 | 58 | #define SIGVTALRM 26 |
59 | #define SIGPROF 27 | 59 | #define SIGPROF 27 |
60 | #define SIGWINCH 28 | 60 | #define SIGWINCH 28 |
61 | #define SIGIO 29 | 61 | #define SIGIO 29 |
62 | #define SIGPOLL SIGIO | 62 | #define SIGPOLL SIGIO |
63 | /* | 63 | /* |
64 | #define SIGLOST 29 | 64 | #define SIGLOST 29 |
65 | */ | 65 | */ |
66 | #define SIGPWR 30 | 66 | #define SIGPWR 30 |
67 | #define SIGSYS 31 | 67 | #define SIGSYS 31 |
68 | #define SIGUNUSED 31 | 68 | #define SIGUNUSED 31 |
69 | 69 | ||
70 | /* These should not be considered constants from userland. */ | 70 | /* These should not be considered constants from userland. */ |
71 | #define SIGRTMIN 32 | 71 | #define SIGRTMIN 32 |
72 | #define SIGRTMAX _NSIG | 72 | #define SIGRTMAX _NSIG |
73 | 73 | ||
74 | /* | 74 | /* |
75 | * SA_FLAGS values: | 75 | * SA_FLAGS values: |
76 | * | 76 | * |
77 | * SA_ONSTACK indicates that a registered stack_t will be used. | 77 | * SA_ONSTACK indicates that a registered stack_t will be used. |
78 | * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the | ||
79 | * SA_RESTART flag to get restarting signals (which were the default long ago) | 78 | * SA_RESTART flag to get restarting signals (which were the default long ago) |
80 | * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. | 79 | * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. |
81 | * SA_RESETHAND clears the handler when the signal is delivered. | 80 | * SA_RESETHAND clears the handler when the signal is delivered. |
82 | * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. | 81 | * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. |
83 | * SA_NODEFER prevents the current signal from being masked in the handler. | 82 | * SA_NODEFER prevents the current signal from being masked in the handler. |
84 | * | 83 | * |
85 | * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single | 84 | * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single |
86 | * Unix names RESETHAND and NODEFER respectively. | 85 | * Unix names RESETHAND and NODEFER respectively. |
87 | */ | 86 | */ |
88 | #define SA_NOCLDSTOP 0x00000001 | 87 | #define SA_NOCLDSTOP 0x00000001 |
89 | #define SA_NOCLDWAIT 0x00000002 | 88 | #define SA_NOCLDWAIT 0x00000002 |
90 | #define SA_SIGINFO 0x00000004 | 89 | #define SA_SIGINFO 0x00000004 |
91 | #define SA_ONSTACK 0x08000000 | 90 | #define SA_ONSTACK 0x08000000 |
92 | #define SA_RESTART 0x10000000 | 91 | #define SA_RESTART 0x10000000 |
93 | #define SA_NODEFER 0x40000000 | 92 | #define SA_NODEFER 0x40000000 |
94 | #define SA_RESETHAND 0x80000000 | 93 | #define SA_RESETHAND 0x80000000 |
95 | 94 | ||
96 | #define SA_NOMASK SA_NODEFER | 95 | #define SA_NOMASK SA_NODEFER |
97 | #define SA_ONESHOT SA_RESETHAND | 96 | #define SA_ONESHOT SA_RESETHAND |
98 | #define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ | ||
99 | 97 | ||
100 | #define SA_RESTORER 0x04000000 | 98 | #define SA_RESTORER 0x04000000 |
101 | 99 | ||
102 | /* | 100 | /* |
103 | * sigaltstack controls | 101 | * sigaltstack controls |
104 | */ | 102 | */ |
105 | #define SS_ONSTACK 1 | 103 | #define SS_ONSTACK 1 |
106 | #define SS_DISABLE 2 | 104 | #define SS_DISABLE 2 |
107 | 105 | ||
108 | #define MINSIGSTKSZ 2048 | 106 | #define MINSIGSTKSZ 2048 |
109 | #define SIGSTKSZ 8192 | 107 | #define SIGSTKSZ 8192 |
110 | 108 | ||
111 | #include <asm-generic/signal.h> | 109 | #include <asm-generic/signal.h> |
112 | 110 | ||
113 | #ifdef __KERNEL__ | 111 | #ifdef __KERNEL__ |
114 | struct old_sigaction { | 112 | struct old_sigaction { |
115 | __sighandler_t sa_handler; | 113 | __sighandler_t sa_handler; |
116 | old_sigset_t sa_mask; | 114 | old_sigset_t sa_mask; |
117 | unsigned long sa_flags; | 115 | unsigned long sa_flags; |
118 | void (*sa_restorer)(void); | 116 | void (*sa_restorer)(void); |
119 | }; | 117 | }; |
120 | 118 | ||
121 | struct sigaction { | 119 | struct sigaction { |
122 | __sighandler_t sa_handler; | 120 | __sighandler_t sa_handler; |
123 | unsigned long sa_flags; | 121 | unsigned long sa_flags; |
124 | void (*sa_restorer)(void); | 122 | void (*sa_restorer)(void); |
125 | sigset_t sa_mask; /* mask last for extensibility */ | 123 | sigset_t sa_mask; /* mask last for extensibility */ |
126 | }; | 124 | }; |
127 | 125 | ||
128 | struct k_sigaction { | 126 | struct k_sigaction { |
129 | struct sigaction sa; | 127 | struct sigaction sa; |
130 | }; | 128 | }; |
131 | #else | 129 | #else |
132 | /* Here we must cater to libcs that poke about in kernel headers. */ | 130 | /* Here we must cater to libcs that poke about in kernel headers. */ |
133 | 131 | ||
134 | struct sigaction { | 132 | struct sigaction { |
135 | union { | 133 | union { |
136 | __sighandler_t _sa_handler; | 134 | __sighandler_t _sa_handler; |
137 | void (*_sa_sigaction)(int, struct siginfo *, void *); | 135 | void (*_sa_sigaction)(int, struct siginfo *, void *); |
138 | } _u; | 136 | } _u; |
139 | sigset_t sa_mask; | 137 | sigset_t sa_mask; |
140 | unsigned long sa_flags; | 138 | unsigned long sa_flags; |
141 | void (*sa_restorer)(void); | 139 | void (*sa_restorer)(void); |
142 | }; | 140 | }; |
143 | 141 | ||
144 | #define sa_handler _u._sa_handler | 142 | #define sa_handler _u._sa_handler |
145 | #define sa_sigaction _u._sa_sigaction | 143 | #define sa_sigaction _u._sa_sigaction |
146 | 144 | ||
147 | #endif /* __KERNEL__ */ | 145 | #endif /* __KERNEL__ */ |
148 | 146 | ||
149 | typedef struct sigaltstack { | 147 | typedef struct sigaltstack { |
150 | void *ss_sp; | 148 | void *ss_sp; |
151 | int ss_flags; | 149 | int ss_flags; |
152 | size_t ss_size; | 150 | size_t ss_size; |
153 | } stack_t; | 151 | } stack_t; |
154 | 152 | ||
155 | #ifdef __KERNEL__ | 153 | #ifdef __KERNEL__ |
156 | #include <asm/sigcontext.h> | 154 | #include <asm/sigcontext.h> |
157 | 155 | ||
158 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | 156 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) |
159 | 157 | ||
160 | #endif /* __KERNEL__ */ | 158 | #endif /* __KERNEL__ */ |
161 | 159 | ||
162 | #endif /* __ASM_SH_SIGNAL_H */ | 160 | #endif /* __ASM_SH_SIGNAL_H */ |
163 | 161 |