]>
Commit | Line | Data |
---|---|---|
d865fd09 RR |
1 | /* |
2 | * (C) Copyright 2000-2002 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * (C) Copyright 2002 (440 port) | |
6 | * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com | |
7 | * | |
8 | * (C) Copyright 2003 (440GX port) | |
9 | * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com | |
10 | * | |
11 | * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX) | |
12 | * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es | |
13 | * Work supported by Qtechnology (htpp://qtec.com) | |
14 | * | |
1a459660 | 15 | * SPDX-License-Identifier: GPL-2.0+ |
d865fd09 RR |
16 | */ |
17 | ||
18 | #include <common.h> | |
19 | #include <watchdog.h> | |
20 | #include <command.h> | |
21 | #include <asm/processor.h> | |
22 | #include <asm/interrupt.h> | |
b36df561 | 23 | #include <asm/ppc4xx.h> |
d865fd09 RR |
24 | #include <ppc_asm.tmpl> |
25 | #include <commproc.h> | |
26 | ||
27 | #if (UIC_MAX > 3) | |
28 | #define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \ | |
29 | UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI) | \ | |
30 | UIC_MASK(VECNUM_UIC3CI) | UIC_MASK(VECNUM_UIC3NCI)) | |
31 | #elif (UIC_MAX > 2) | |
32 | #define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \ | |
33 | UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI)) | |
34 | #elif (UIC_MAX > 1) | |
35 | #define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI)) | |
36 | #else | |
37 | #define UICB0_ALL 0 | |
38 | #endif | |
39 | ||
40 | u32 get_dcr(u16); | |
41 | ||
42 | DECLARE_GLOBAL_DATA_PTR; | |
43 | ||
44 | void pic_enable(void) | |
45 | { | |
d865fd09 RR |
46 | #if (UIC_MAX > 1) |
47 | /* Install the UIC1 handlers */ | |
60204d06 SR |
48 | irq_install_handler(VECNUM_UIC1NCI, (void *)(void *)external_interrupt, 0); |
49 | irq_install_handler(VECNUM_UIC1CI, (void *)(void *)external_interrupt, 0); | |
d865fd09 RR |
50 | #endif |
51 | #if (UIC_MAX > 2) | |
60204d06 SR |
52 | irq_install_handler(VECNUM_UIC2NCI, (void *)(void *)external_interrupt, 0); |
53 | irq_install_handler(VECNUM_UIC2CI, (void *)(void *)external_interrupt, 0); | |
d865fd09 RR |
54 | #endif |
55 | #if (UIC_MAX > 3) | |
60204d06 SR |
56 | irq_install_handler(VECNUM_UIC3NCI, (void *)(void *)external_interrupt, 0); |
57 | irq_install_handler(VECNUM_UIC3CI, (void *)(void *)external_interrupt, 0); | |
d865fd09 | 58 | #endif |
d865fd09 RR |
59 | } |
60 | ||
61 | /* Handler for UIC interrupt */ | |
62 | static void uic_interrupt(u32 uic_base, int vec_base) | |
63 | { | |
64 | u32 uic_msr; | |
65 | u32 msr_shift; | |
66 | int vec; | |
67 | ||
68 | /* | |
69 | * Read masked interrupt status register to determine interrupt source | |
70 | */ | |
71 | uic_msr = get_dcr(uic_base + UIC_MSR); | |
72 | msr_shift = uic_msr; | |
73 | vec = vec_base; | |
74 | ||
75 | while (msr_shift != 0) { | |
76 | if (msr_shift & 0x80000000) | |
77 | interrupt_run_handler(vec); | |
78 | /* | |
79 | * Shift msr to next position and increment vector | |
80 | */ | |
81 | msr_shift <<= 1; | |
82 | vec++; | |
83 | } | |
84 | } | |
85 | ||
86 | /* | |
87 | * Handle external interrupts | |
88 | */ | |
89 | void external_interrupt(struct pt_regs *regs) | |
90 | { | |
91 | u32 uic_msr; | |
92 | ||
93 | /* | |
94 | * Read masked interrupt status register to determine interrupt source | |
95 | */ | |
952e7760 | 96 | uic_msr = mfdcr(UIC0MSR); |
d865fd09 RR |
97 | |
98 | #if (UIC_MAX > 1) | |
99 | if ((UIC_MASK(VECNUM_UIC1CI) & uic_msr) || | |
100 | (UIC_MASK(VECNUM_UIC1NCI) & uic_msr)) | |
101 | uic_interrupt(UIC1_DCR_BASE, 32); | |
102 | #endif | |
103 | ||
104 | #if (UIC_MAX > 2) | |
105 | if ((UIC_MASK(VECNUM_UIC2CI) & uic_msr) || | |
106 | (UIC_MASK(VECNUM_UIC2NCI) & uic_msr)) | |
107 | uic_interrupt(UIC2_DCR_BASE, 64); | |
108 | #endif | |
109 | ||
110 | #if (UIC_MAX > 3) | |
111 | if ((UIC_MASK(VECNUM_UIC3CI) & uic_msr) || | |
112 | (UIC_MASK(VECNUM_UIC3NCI) & uic_msr)) | |
113 | uic_interrupt(UIC3_DCR_BASE, 96); | |
114 | #endif | |
115 | ||
952e7760 | 116 | mtdcr(UIC0SR, (uic_msr & UICB0_ALL)); |
5bc542a5 | 117 | |
d865fd09 RR |
118 | if (uic_msr & ~(UICB0_ALL)) |
119 | uic_interrupt(UIC0_DCR_BASE, 0); | |
120 | ||
d865fd09 RR |
121 | return; |
122 | } | |
123 | ||
124 | void pic_irq_ack(unsigned int vec) | |
125 | { | |
d865fd09 | 126 | if ((vec >= 0) && (vec < 32)) |
952e7760 | 127 | mtdcr(UIC0SR, UIC_MASK(vec)); |
d865fd09 | 128 | else if ((vec >= 32) && (vec < 64)) |
952e7760 | 129 | mtdcr(UIC1SR, UIC_MASK(vec)); |
d865fd09 | 130 | else if ((vec >= 64) && (vec < 96)) |
952e7760 | 131 | mtdcr(UIC2SR, UIC_MASK(vec)); |
d865fd09 | 132 | else if (vec >= 96) |
952e7760 | 133 | mtdcr(UIC3SR, UIC_MASK(vec)); |
d865fd09 RR |
134 | } |
135 | ||
136 | /* | |
137 | * Install and free a interrupt handler. | |
138 | */ | |
139 | void pic_irq_enable(unsigned int vec) | |
140 | { | |
141 | ||
142 | if ((vec >= 0) && (vec < 32)) | |
952e7760 | 143 | mtdcr(UIC0ER, mfdcr(UIC0ER) | UIC_MASK(vec)); |
d865fd09 | 144 | else if ((vec >= 32) && (vec < 64)) |
952e7760 | 145 | mtdcr(UIC1ER, mfdcr(UIC1ER) | UIC_MASK(vec)); |
d865fd09 | 146 | else if ((vec >= 64) && (vec < 96)) |
952e7760 | 147 | mtdcr(UIC2ER, mfdcr(UIC2ER) | UIC_MASK(vec)); |
d865fd09 | 148 | else if (vec >= 96) |
952e7760 | 149 | mtdcr(UIC3ER, mfdcr(UIC3ER) | UIC_MASK(vec)); |
d865fd09 | 150 | |
04ddae91 | 151 | debug("Install interrupt vector %d\n", vec); |
d865fd09 RR |
152 | } |
153 | ||
154 | void pic_irq_disable(unsigned int vec) | |
155 | { | |
d865fd09 | 156 | if ((vec >= 0) && (vec < 32)) |
952e7760 | 157 | mtdcr(UIC0ER, mfdcr(UIC0ER) & ~UIC_MASK(vec)); |
d865fd09 | 158 | else if ((vec >= 32) && (vec < 64)) |
952e7760 | 159 | mtdcr(UIC1ER, mfdcr(UIC1ER) & ~UIC_MASK(vec)); |
d865fd09 | 160 | else if ((vec >= 64) && (vec < 96)) |
952e7760 | 161 | mtdcr(UIC2ER, mfdcr(UIC2ER) & ~UIC_MASK(vec)); |
d865fd09 | 162 | else if (vec >= 96) |
952e7760 | 163 | mtdcr(UIC3ER, mfdcr(UIC3ER) & ~UIC_MASK(vec)); |
d865fd09 | 164 | } |