diff options
Diffstat (limited to 'arch/powerpc/platforms/pasemi/setup.c')
-rw-r--r-- | arch/powerpc/platforms/pasemi/setup.c | 105 |
1 files changed, 86 insertions, 19 deletions
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index bea7d1bb1a3b..449cf1a08291 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2006 PA Semi, Inc | 2 | * Copyright (C) 2006-2007 PA Semi, Inc |
3 | * | 3 | * |
4 | * Authors: Kip Walker, PA Semi | 4 | * Authors: Kip Walker, PA Semi |
5 | * Olof Johansson, PA Semi | 5 | * Olof Johansson, PA Semi |
@@ -38,31 +38,46 @@ | |||
38 | 38 | ||
39 | #include "pasemi.h" | 39 | #include "pasemi.h" |
40 | 40 | ||
41 | static void __iomem *reset_reg; | ||
42 | |||
41 | static void pas_restart(char *cmd) | 43 | static void pas_restart(char *cmd) |
42 | { | 44 | { |
43 | printk("restart unimplemented, looping...\n"); | 45 | printk("Restarting...\n"); |
44 | for (;;) ; | 46 | while (1) |
47 | out_le32(reset_reg, 0x6000000); | ||
45 | } | 48 | } |
46 | 49 | ||
47 | static void pas_power_off(void) | 50 | #ifdef CONFIG_SMP |
51 | static DEFINE_SPINLOCK(timebase_lock); | ||
52 | |||
53 | static void __devinit pas_give_timebase(void) | ||
48 | { | 54 | { |
49 | printk("power off unimplemented, looping...\n"); | 55 | unsigned long tb; |
50 | for (;;) ; | 56 | |
57 | spin_lock(&timebase_lock); | ||
58 | mtspr(SPRN_TBCTL, TBCTL_FREEZE); | ||
59 | tb = mftb(); | ||
60 | mtspr(SPRN_TBCTL, TBCTL_UPDATE_LOWER | (tb & 0xffffffff)); | ||
61 | mtspr(SPRN_TBCTL, TBCTL_UPDATE_UPPER | (tb >> 32)); | ||
62 | mtspr(SPRN_TBCTL, TBCTL_RESTART); | ||
63 | spin_unlock(&timebase_lock); | ||
64 | pr_debug("pas_give_timebase: cpu %d gave tb %lx\n", | ||
65 | smp_processor_id(), tb); | ||
51 | } | 66 | } |
52 | 67 | ||
53 | static void pas_halt(void) | 68 | static void __devinit pas_take_timebase(void) |
54 | { | 69 | { |
55 | pas_power_off(); | 70 | pr_debug("pas_take_timebase: cpu %d has tb %lx\n", |
71 | smp_processor_id(), mftb()); | ||
56 | } | 72 | } |
57 | 73 | ||
58 | #ifdef CONFIG_SMP | ||
59 | struct smp_ops_t pas_smp_ops = { | 74 | struct smp_ops_t pas_smp_ops = { |
60 | .probe = smp_mpic_probe, | 75 | .probe = smp_mpic_probe, |
61 | .message_pass = smp_mpic_message_pass, | 76 | .message_pass = smp_mpic_message_pass, |
62 | .kick_cpu = smp_generic_kick_cpu, | 77 | .kick_cpu = smp_generic_kick_cpu, |
63 | .setup_cpu = smp_mpic_setup_cpu, | 78 | .setup_cpu = smp_mpic_setup_cpu, |
64 | .give_timebase = smp_generic_give_timebase, | 79 | .give_timebase = pas_give_timebase, |
65 | .take_timebase = smp_generic_take_timebase, | 80 | .take_timebase = pas_take_timebase, |
66 | }; | 81 | }; |
67 | #endif /* CONFIG_SMP */ | 82 | #endif /* CONFIG_SMP */ |
68 | 83 | ||
@@ -72,9 +87,6 @@ void __init pas_setup_arch(void) | |||
72 | /* Setup SMP callback */ | 87 | /* Setup SMP callback */ |
73 | smp_ops = &pas_smp_ops; | 88 | smp_ops = &pas_smp_ops; |
74 | #endif | 89 | #endif |
75 | /* no iommu yet */ | ||
76 | pci_dma_ops = &dma_direct_ops; | ||
77 | |||
78 | /* Lookup PCI hosts */ | 90 | /* Lookup PCI hosts */ |
79 | pas_pci_init(); | 91 | pas_pci_init(); |
80 | 92 | ||
@@ -82,7 +94,11 @@ void __init pas_setup_arch(void) | |||
82 | conswitchp = &dummy_con; | 94 | conswitchp = &dummy_con; |
83 | #endif | 95 | #endif |
84 | 96 | ||
85 | printk(KERN_DEBUG "Using default idle loop\n"); | 97 | /* Remap SDC register for doing reset */ |
98 | /* XXXOJN This should maybe come out of the device tree */ | ||
99 | reset_reg = ioremap(0xfc101100, 4); | ||
100 | |||
101 | pasemi_idle_init(); | ||
86 | } | 102 | } |
87 | 103 | ||
88 | /* No legacy IO on our parts */ | 104 | /* No legacy IO on our parts */ |
@@ -130,8 +146,9 @@ static __init void pas_init_IRQ(void) | |||
130 | openpic_addr = of_read_number(opprop, naddr); | 146 | openpic_addr = of_read_number(opprop, naddr); |
131 | printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); | 147 | printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); |
132 | 148 | ||
133 | mpic = mpic_alloc(mpic_node, openpic_addr, MPIC_PRIMARY, 0, 0, | 149 | mpic = mpic_alloc(mpic_node, openpic_addr, |
134 | " PAS-OPIC "); | 150 | MPIC_PRIMARY|MPIC_LARGE_VECTORS, |
151 | 0, 0, " PAS-OPIC "); | ||
135 | BUG_ON(!mpic); | 152 | BUG_ON(!mpic); |
136 | 153 | ||
137 | mpic_assign_isu(mpic, 0, openpic_addr + 0x10000); | 154 | mpic_assign_isu(mpic, 0, openpic_addr + 0x10000); |
@@ -146,6 +163,53 @@ static void __init pas_progress(char *s, unsigned short hex) | |||
146 | } | 163 | } |
147 | 164 | ||
148 | 165 | ||
166 | static int pas_machine_check_handler(struct pt_regs *regs) | ||
167 | { | ||
168 | int cpu = smp_processor_id(); | ||
169 | unsigned long srr0, srr1, dsisr; | ||
170 | |||
171 | srr0 = regs->nip; | ||
172 | srr1 = regs->msr; | ||
173 | dsisr = mfspr(SPRN_DSISR); | ||
174 | printk(KERN_ERR "Machine Check on CPU %d\n", cpu); | ||
175 | printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1); | ||
176 | printk(KERN_ERR "DSISR 0x%016lx DAR 0x%016lx\n", dsisr, regs->dar); | ||
177 | printk(KERN_ERR "Cause:\n"); | ||
178 | |||
179 | if (srr1 & 0x200000) | ||
180 | printk(KERN_ERR "Signalled by SDC\n"); | ||
181 | if (srr1 & 0x100000) { | ||
182 | printk(KERN_ERR "Load/Store detected error:\n"); | ||
183 | if (dsisr & 0x8000) | ||
184 | printk(KERN_ERR "D-cache ECC double-bit error or bus error\n"); | ||
185 | if (dsisr & 0x4000) | ||
186 | printk(KERN_ERR "LSU snoop response error\n"); | ||
187 | if (dsisr & 0x2000) | ||
188 | printk(KERN_ERR "MMU SLB multi-hit or invalid B field\n"); | ||
189 | if (dsisr & 0x1000) | ||
190 | printk(KERN_ERR "Recoverable Duptags\n"); | ||
191 | if (dsisr & 0x800) | ||
192 | printk(KERN_ERR "Recoverable D-cache parity error count overflow\n"); | ||
193 | if (dsisr & 0x400) | ||
194 | printk(KERN_ERR "TLB parity error count overflow\n"); | ||
195 | } | ||
196 | if (srr1 & 0x80000) | ||
197 | printk(KERN_ERR "Bus Error\n"); | ||
198 | if (srr1 & 0x40000) | ||
199 | printk(KERN_ERR "I-side SLB multiple hit\n"); | ||
200 | if (srr1 & 0x20000) | ||
201 | printk(KERN_ERR "I-cache parity error hit\n"); | ||
202 | |||
203 | /* SRR1[62] is from MSR[62] if recoverable, so pass that back */ | ||
204 | return !!(srr1 & 0x2); | ||
205 | } | ||
206 | |||
207 | static void __init pas_init_early(void) | ||
208 | { | ||
209 | iommu_init_early_pasemi(); | ||
210 | } | ||
211 | |||
212 | |||
149 | /* | 213 | /* |
150 | * Called very early, MMU is off, device-tree isn't unflattened | 214 | * Called very early, MMU is off, device-tree isn't unflattened |
151 | */ | 215 | */ |
@@ -158,6 +222,8 @@ static int __init pas_probe(void) | |||
158 | 222 | ||
159 | hpte_init_native(); | 223 | hpte_init_native(); |
160 | 224 | ||
225 | alloc_iobmap_l2(); | ||
226 | |||
161 | return 1; | 227 | return 1; |
162 | } | 228 | } |
163 | 229 | ||
@@ -165,13 +231,14 @@ define_machine(pas) { | |||
165 | .name = "PA Semi PA6T-1682M", | 231 | .name = "PA Semi PA6T-1682M", |
166 | .probe = pas_probe, | 232 | .probe = pas_probe, |
167 | .setup_arch = pas_setup_arch, | 233 | .setup_arch = pas_setup_arch, |
234 | .init_early = pas_init_early, | ||
168 | .init_IRQ = pas_init_IRQ, | 235 | .init_IRQ = pas_init_IRQ, |
169 | .get_irq = mpic_get_irq, | 236 | .get_irq = mpic_get_irq, |
170 | .restart = pas_restart, | 237 | .restart = pas_restart, |
171 | .power_off = pas_power_off, | ||
172 | .halt = pas_halt, | ||
173 | .get_boot_time = pas_get_boot_time, | 238 | .get_boot_time = pas_get_boot_time, |
174 | .calibrate_decr = generic_calibrate_decr, | 239 | .calibrate_decr = generic_calibrate_decr, |
175 | .check_legacy_ioport = pas_check_legacy_ioport, | 240 | .check_legacy_ioport = pas_check_legacy_ioport, |
176 | .progress = pas_progress, | 241 | .progress = pas_progress, |
242 | .machine_check_exception = pas_machine_check_handler, | ||
243 | .pci_irq_fixup = pas_pci_irq_fixup, | ||
177 | }; | 244 | }; |