diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-13 12:49:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-13 12:49:04 -0400 |
commit | dcf397f037f52add9945eced57ca300ab6a4413c (patch) | |
tree | e78767d164589e9097a54bf564b072fb01f80820 /arch/sh/cchips | |
parent | 6faf035cf9fdd8283c2b2b2c34b76b5445ec6fc4 (diff) | |
parent | 68ee0f9c98a42e36f9eab29155b2bb0e7e409ac6 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (124 commits)
sh: allow building for both r2d boards in same binary.
sh: fix r2d board detection
sh: Discard .exit.text/.exit.data at runtime.
sh: Fix up some section alignments in linker script.
sh: Fix SH-4 DMAC CHCR masking.
sh: Rip out left-over nommu cond syscall cruft.
sh: Make kgdb i-cache flushing less inept.
sh: kgdb section mismatches and tidying.
sh: cleanup struct irqaction initializers.
sh: early_printk tidying.
video: pvr2fb: Add TV (RGB) support to Dreamcast PVR driver.
sh: Conditionalize gUSA support.
sh: Follow gUSA preempt changes in __switch_to().
sh: Tidy up gUSA preempt handling.
sh: __copy_user() optimizations for small copies.
sh: clkfwk: Support multi-level clock propagation.
sh: Fix URAM start address on SH7785.
sh: Use boot_cpu_data for CPU probe.
sh: Support extended mode TLB on SH-X3.
sh: Bump MAX_ACTIVE_REGIONS for SH7785.
...
Diffstat (limited to 'arch/sh/cchips')
-rw-r--r-- | arch/sh/cchips/Kconfig | 13 | ||||
-rw-r--r-- | arch/sh/cchips/hd6446x/hd64461.c | 13 | ||||
-rw-r--r-- | arch/sh/cchips/hd6446x/hd64465/setup.c | 7 | ||||
-rw-r--r-- | arch/sh/cchips/voyagergx/irq.c | 188 |
4 files changed, 76 insertions, 145 deletions
diff --git a/arch/sh/cchips/Kconfig b/arch/sh/cchips/Kconfig index 2e516e9a6ede..7892361eedc8 100644 --- a/arch/sh/cchips/Kconfig +++ b/arch/sh/cchips/Kconfig | |||
@@ -1,18 +1,5 @@ | |||
1 | menu "Companion Chips" | 1 | menu "Companion Chips" |
2 | 2 | ||
3 | config VOYAGERGX | ||
4 | bool "VoyagerGX chip support" | ||
5 | depends on SH_RTS7751R2D | ||
6 | help | ||
7 | Selecting this option will support Silicon Motion, Inc. SM501. | ||
8 | Designed to complement needs for the embedded industry, it | ||
9 | provides video and 2D capability. To reduce system cost a | ||
10 | wide variety of include I/O is supported, including analog RGB | ||
11 | and digital LCD Panel interface, 8-bit parallel interface, USB, | ||
12 | UART, IrDA, Zoom Video, AC97 or I2S, SSP, PWM, and I2C. There | ||
13 | are additional GPIO bits that can be used to interface to | ||
14 | external as well. | ||
15 | |||
16 | config HD6446X_SERIES | 3 | config HD6446X_SERIES |
17 | bool | 4 | bool |
18 | 5 | ||
diff --git a/arch/sh/cchips/hd6446x/hd64461.c b/arch/sh/cchips/hd6446x/hd64461.c index 97f6512aa1b7..f1a4a0763c59 100644 --- a/arch/sh/cchips/hd6446x/hd64461.c +++ b/arch/sh/cchips/hd6446x/hd64461.c | |||
@@ -14,6 +14,9 @@ | |||
14 | #include <asm/irq.h> | 14 | #include <asm/irq.h> |
15 | #include <asm/hd64461.h> | 15 | #include <asm/hd64461.h> |
16 | 16 | ||
17 | /* This belongs in cpu specific */ | ||
18 | #define INTC_ICR1 0xA4140010UL | ||
19 | |||
17 | static void disable_hd64461_irq(unsigned int irq) | 20 | static void disable_hd64461_irq(unsigned int irq) |
18 | { | 21 | { |
19 | unsigned short nimr; | 22 | unsigned short nimr; |
@@ -121,10 +124,15 @@ int hd64461_irq_demux(int irq) | |||
121 | } | 124 | } |
122 | } | 125 | } |
123 | } | 126 | } |
124 | return __irq_demux(irq); | 127 | return irq; |
125 | } | 128 | } |
126 | 129 | ||
127 | static struct irqaction irq0 = { hd64461_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "HD64461", NULL, NULL }; | 130 | static struct irqaction irq0 = { |
131 | .handler = hd64461_interrupt, | ||
132 | .flags = IRQF_DISABLED, | ||
133 | .mask = CPU_MASK_NONE, | ||
134 | .name = "HD64461", | ||
135 | }; | ||
128 | 136 | ||
129 | int __init setup_hd64461(void) | 137 | int __init setup_hd64461(void) |
130 | { | 138 | { |
@@ -143,6 +151,7 @@ int __init setup_hd64461(void) | |||
143 | #endif | 151 | #endif |
144 | outw(0xffff, HD64461_NIMR); | 152 | outw(0xffff, HD64461_NIMR); |
145 | 153 | ||
154 | /* IRQ 80 -> 95 belongs to HD64461 */ | ||
146 | for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) { | 155 | for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) { |
147 | irq_desc[i].chip = &hd64461_irq_type; | 156 | irq_desc[i].chip = &hd64461_irq_type; |
148 | } | 157 | } |
diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c index d126e1f30dee..5cef0db4018b 100644 --- a/arch/sh/cchips/hd6446x/hd64465/setup.c +++ b/arch/sh/cchips/hd6446x/hd64465/setup.c | |||
@@ -147,7 +147,12 @@ int hd64465_irq_demux(int irq) | |||
147 | return irq; | 147 | return irq; |
148 | } | 148 | } |
149 | 149 | ||
150 | static struct irqaction irq0 = { hd64465_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "HD64465", NULL, NULL}; | 150 | static struct irqaction irq0 = { |
151 | .handler = hd64465_interrupt, | ||
152 | .flags = IRQF_DISABLED, | ||
153 | .mask = CPU_MASK_NONE, | ||
154 | .name = "HD64465", | ||
155 | }; | ||
151 | 156 | ||
152 | 157 | ||
153 | static int __init setup_hd64465(void) | 158 | static int __init setup_hd64465(void) |
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c index d70e5c8461b5..ade303876841 100644 --- a/arch/sh/cchips/voyagergx/irq.c +++ b/arch/sh/cchips/voyagergx/irq.c | |||
@@ -23,149 +23,79 @@ | |||
23 | #include <asm/voyagergx.h> | 23 | #include <asm/voyagergx.h> |
24 | #include <asm/rts7751r2d.h> | 24 | #include <asm/rts7751r2d.h> |
25 | 25 | ||
26 | static void disable_voyagergx_irq(unsigned int irq) | 26 | enum { |
27 | { | 27 | UNUSED = 0, |
28 | unsigned long val; | 28 | |
29 | unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); | 29 | /* voyager specific interrupt sources */ |
30 | 30 | UP, G54, G53, G52, G51, G50, G49, G48, | |
31 | pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask); | 31 | I2C, PW, DMA, PCI, I2S, AC, US, |
32 | val = readl((void __iomem *)VOYAGER_INT_MASK); | 32 | U1, U0, CV, MC, S1, S0, |
33 | val &= ~mask; | 33 | UH, TWOD, ZD, PV, CI, |
34 | writel(val, (void __iomem *)VOYAGER_INT_MASK); | ||
35 | } | ||
36 | |||
37 | static void enable_voyagergx_irq(unsigned int irq) | ||
38 | { | ||
39 | unsigned long val; | ||
40 | unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); | ||
41 | |||
42 | pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask); | ||
43 | val = readl((void __iomem *)VOYAGER_INT_MASK); | ||
44 | val |= mask; | ||
45 | writel(val, (void __iomem *)VOYAGER_INT_MASK); | ||
46 | } | ||
47 | |||
48 | static void mask_and_ack_voyagergx(unsigned int irq) | ||
49 | { | ||
50 | disable_voyagergx_irq(irq); | ||
51 | } | ||
52 | |||
53 | static void end_voyagergx_irq(unsigned int irq) | ||
54 | { | ||
55 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
56 | enable_voyagergx_irq(irq); | ||
57 | } | ||
58 | |||
59 | static unsigned int startup_voyagergx_irq(unsigned int irq) | ||
60 | { | ||
61 | enable_voyagergx_irq(irq); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static void shutdown_voyagergx_irq(unsigned int irq) | ||
66 | { | ||
67 | disable_voyagergx_irq(irq); | ||
68 | } | ||
69 | |||
70 | static struct hw_interrupt_type voyagergx_irq_type = { | ||
71 | .typename = "VOYAGERGX-IRQ", | ||
72 | .startup = startup_voyagergx_irq, | ||
73 | .shutdown = shutdown_voyagergx_irq, | ||
74 | .enable = enable_voyagergx_irq, | ||
75 | .disable = disable_voyagergx_irq, | ||
76 | .ack = mask_and_ack_voyagergx, | ||
77 | .end = end_voyagergx_irq, | ||
78 | }; | 34 | }; |
79 | 35 | ||
80 | static irqreturn_t voyagergx_interrupt(int irq, void *dev_id) | 36 | static struct intc_vect vectors[] __initdata = { |
81 | { | 37 | INTC_IRQ(UP, IRQ_SM501_UP), INTC_IRQ(G54, IRQ_SM501_G54), |
82 | printk(KERN_INFO | 38 | INTC_IRQ(G53, IRQ_SM501_G53), INTC_IRQ(G52, IRQ_SM501_G52), |
83 | "VoyagerGX: spurious interrupt, status: 0x%x\n", | 39 | INTC_IRQ(G51, IRQ_SM501_G51), INTC_IRQ(G50, IRQ_SM501_G50), |
84 | (unsigned int)readl((void __iomem *)INT_STATUS)); | 40 | INTC_IRQ(G49, IRQ_SM501_G49), INTC_IRQ(G48, IRQ_SM501_G48), |
85 | return IRQ_HANDLED; | 41 | INTC_IRQ(I2C, IRQ_SM501_I2C), INTC_IRQ(PW, IRQ_SM501_PW), |
86 | } | 42 | INTC_IRQ(DMA, IRQ_SM501_DMA), INTC_IRQ(PCI, IRQ_SM501_PCI), |
87 | 43 | INTC_IRQ(I2S, IRQ_SM501_I2S), INTC_IRQ(AC, IRQ_SM501_AC), | |
88 | static struct { | 44 | INTC_IRQ(US, IRQ_SM501_US), INTC_IRQ(U1, IRQ_SM501_U1), |
89 | int (*func)(int, void *); | 45 | INTC_IRQ(U0, IRQ_SM501_U0), INTC_IRQ(CV, IRQ_SM501_CV), |
90 | void *dev; | 46 | INTC_IRQ(MC, IRQ_SM501_MC), INTC_IRQ(S1, IRQ_SM501_S1), |
91 | } voyagergx_demux[VOYAGER_IRQ_NUM]; | 47 | INTC_IRQ(S0, IRQ_SM501_S0), INTC_IRQ(UH, IRQ_SM501_UH), |
48 | INTC_IRQ(TWOD, IRQ_SM501_2D), INTC_IRQ(ZD, IRQ_SM501_ZD), | ||
49 | INTC_IRQ(PV, IRQ_SM501_PV), INTC_IRQ(CI, IRQ_SM501_CI), | ||
50 | }; | ||
92 | 51 | ||
93 | void voyagergx_register_irq_demux(int irq, | 52 | static struct intc_mask_reg mask_registers[] __initdata = { |
94 | int (*demux)(int irq, void *dev), void *dev) | 53 | { VOYAGER_INT_MASK, 0, 32, /* "Interrupt Mask", MMIO_base + 0x30 */ |
95 | { | 54 | { UP, G54, G53, G52, G51, G50, G49, G48, |
96 | voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux; | 55 | I2C, PW, 0, DMA, PCI, I2S, AC, US, |
97 | voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev; | 56 | 0, 0, U1, U0, CV, MC, S1, S0, |
98 | } | 57 | 0, UH, 0, 0, TWOD, ZD, PV, CI } }, |
58 | }; | ||
99 | 59 | ||
100 | void voyagergx_unregister_irq_demux(int irq) | 60 | static DECLARE_INTC_DESC(intc_desc, "voyagergx", vectors, |
101 | { | 61 | NULL, NULL, mask_registers, NULL, NULL); |
102 | voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0; | 62 | |
103 | } | 63 | static unsigned int voyagergx_stat2irq[32] = { |
64 | IRQ_SM501_CI, IRQ_SM501_PV, IRQ_SM501_ZD, IRQ_SM501_2D, | ||
65 | 0, 0, IRQ_SM501_UH, 0, | ||
66 | IRQ_SM501_S0, IRQ_SM501_S1, IRQ_SM501_MC, IRQ_SM501_CV, | ||
67 | IRQ_SM501_U0, IRQ_SM501_U1, 0, 0, | ||
68 | IRQ_SM501_US, IRQ_SM501_AC, IRQ_SM501_I2S, IRQ_SM501_PCI, | ||
69 | IRQ_SM501_DMA, 0, IRQ_SM501_PW, IRQ_SM501_I2C, | ||
70 | IRQ_SM501_G48, IRQ_SM501_G49, IRQ_SM501_G50, IRQ_SM501_G51, | ||
71 | IRQ_SM501_G52, IRQ_SM501_G53, IRQ_SM501_G54, IRQ_SM501_UP | ||
72 | }; | ||
104 | 73 | ||
105 | int voyagergx_irq_demux(int irq) | 74 | static void voyagergx_irq_demux(unsigned int irq, struct irq_desc *desc) |
106 | { | 75 | { |
107 | 76 | unsigned long intv = ctrl_inl(INT_STATUS); | |
108 | if (irq == IRQ_VOYAGER ) { | 77 | struct irq_desc *ext_desc; |
109 | unsigned long i = 0, bit __attribute__ ((unused)); | 78 | unsigned int ext_irq; |
110 | unsigned long val = readl((void __iomem *)INT_STATUS); | 79 | unsigned int k = 0; |
111 | 80 | ||
112 | if (val & (1 << 1)) | 81 | while (intv) { |
113 | i = 1; | 82 | ext_irq = voyagergx_stat2irq[k]; |
114 | else if (val & (1 << 2)) | 83 | if (ext_irq && (intv & 1)) { |
115 | i = 2; | 84 | ext_desc = irq_desc + ext_irq; |
116 | else if (val & (1 << 6)) | 85 | handle_level_irq(ext_irq, ext_desc); |
117 | i = 6; | ||
118 | else if (val & (1 << 10)) | ||
119 | i = 10; | ||
120 | else if (val & (1 << 11)) | ||
121 | i = 11; | ||
122 | else if (val & (1 << 12)) | ||
123 | i = 12; | ||
124 | else if (val & (1 << 17)) | ||
125 | i = 17; | ||
126 | else | ||
127 | printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val); | ||
128 | pr_debug("voyagergx_irq_demux %ld \n", i); | ||
129 | if (i < VOYAGER_IRQ_NUM) { | ||
130 | irq = VOYAGER_IRQ_BASE + i; | ||
131 | if (voyagergx_demux[i].func != 0) | ||
132 | irq = voyagergx_demux[i].func(irq, | ||
133 | voyagergx_demux[i].dev); | ||
134 | } | 86 | } |
87 | intv >>= 1; | ||
88 | k++; | ||
135 | } | 89 | } |
136 | return irq; | ||
137 | } | 90 | } |
138 | 91 | ||
139 | static struct irqaction irq0 = { | ||
140 | .name = "voyagergx", | ||
141 | .handler = voyagergx_interrupt, | ||
142 | .flags = IRQF_DISABLED, | ||
143 | .mask = CPU_MASK_NONE, | ||
144 | }; | ||
145 | |||
146 | void __init setup_voyagergx_irq(void) | 92 | void __init setup_voyagergx_irq(void) |
147 | { | 93 | { |
148 | int i, flag; | 94 | printk(KERN_INFO "VoyagerGX on irq %d (mapped into %d to %d)\n", |
149 | |||
150 | printk(KERN_INFO "VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n", | ||
151 | VOYAGER_BASE, | ||
152 | IRQ_VOYAGER, | 95 | IRQ_VOYAGER, |
153 | VOYAGER_IRQ_BASE, | 96 | VOYAGER_IRQ_BASE, |
154 | VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1); | 97 | VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1); |
155 | 98 | ||
156 | for (i=0; i<VOYAGER_IRQ_NUM; i++) { | 99 | register_intc_controller(&intc_desc); |
157 | flag = 0; | 100 | set_irq_chained_handler(IRQ_VOYAGER, voyagergx_irq_demux); |
158 | switch (VOYAGER_IRQ_BASE + i) { | ||
159 | case VOYAGER_USBH_IRQ: | ||
160 | case VOYAGER_8051_IRQ: | ||
161 | case VOYAGER_UART0_IRQ: | ||
162 | case VOYAGER_UART1_IRQ: | ||
163 | case VOYAGER_AC97_IRQ: | ||
164 | flag = 1; | ||
165 | } | ||
166 | if (flag == 1) | ||
167 | irq_desc[VOYAGER_IRQ_BASE + i].chip = &voyagergx_irq_type; | ||
168 | } | ||
169 | |||
170 | setup_irq(IRQ_VOYAGER, &irq0); | ||
171 | } | 101 | } |