aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pasemi
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pasemi')
-rw-r--r--arch/powerpc/platforms/pasemi/Kconfig12
-rw-r--r--arch/powerpc/platforms/pasemi/Makefile1
-rw-r--r--arch/powerpc/platforms/pasemi/cpufreq.c19
-rw-r--r--arch/powerpc/platforms/pasemi/electra_ide.c96
-rw-r--r--arch/powerpc/platforms/pasemi/gpio_mdio.c96
-rw-r--r--arch/powerpc/platforms/pasemi/idle.c5
-rw-r--r--arch/powerpc/platforms/pasemi/pasemi.h6
-rw-r--r--arch/powerpc/platforms/pasemi/powersave.S11
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c61
9 files changed, 140 insertions, 167 deletions
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 735e1536cbfc..348e0619e3e5 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -3,6 +3,7 @@ config PPC_PASEMI
3 bool "PA Semi SoC-based platforms" 3 bool "PA Semi SoC-based platforms"
4 default n 4 default n
5 select MPIC 5 select MPIC
6 select PCI
6 select PPC_UDBG_16550 7 select PPC_UDBG_16550
7 select PPC_NATIVE 8 select PPC_NATIVE
8 select MPIC_BROKEN_REGREAD 9 select MPIC_BROKEN_REGREAD
@@ -17,7 +18,7 @@ config PPC_PASEMI_IOMMU
17 bool "PA Semi IOMMU support" 18 bool "PA Semi IOMMU support"
18 depends on PPC_PASEMI 19 depends on PPC_PASEMI
19 help 20 help
20 IOMMU support for PA6T-1682M 21 IOMMU support for PA Semi PWRficient
21 22
22config PPC_PASEMI_IOMMU_DMA_FORCE 23config PPC_PASEMI_IOMMU_DMA_FORCE
23 bool "Force DMA engine to use IOMMU" 24 bool "Force DMA engine to use IOMMU"
@@ -36,13 +37,4 @@ config PPC_PASEMI_MDIO
36 help 37 help
37 Driver for MDIO via GPIO on PWRficient platforms 38 Driver for MDIO via GPIO on PWRficient platforms
38 39
39config ELECTRA_IDE
40 tristate "Electra IDE driver"
41 default y
42 depends on PPC_PASEMI && ATA
43 select PATA_PLATFORM
44 help
45 This includes driver support for the Electra on-board IDE
46 interface.
47
48endmenu 40endmenu
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile
index e636daa7a80e..8f52d7515793 100644
--- a/arch/powerpc/platforms/pasemi/Makefile
+++ b/arch/powerpc/platforms/pasemi/Makefile
@@ -1,4 +1,3 @@
1obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o dma_lib.o 1obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o dma_lib.o
2obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o 2obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o
3obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
4obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o 3obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c
index 1cfb8b0c8fec..58556b028a4c 100644
--- a/arch/powerpc/platforms/pasemi/cpufreq.c
+++ b/arch/powerpc/platforms/pasemi/cpufreq.c
@@ -32,6 +32,7 @@
32#include <asm/io.h> 32#include <asm/io.h>
33#include <asm/prom.h> 33#include <asm/prom.h>
34#include <asm/time.h> 34#include <asm/time.h>
35#include <asm/smp.h>
35 36
36#define SDCASR_REG 0x0100 37#define SDCASR_REG 0x0100
37#define SDCASR_REG_STRIDE 0x1000 38#define SDCASR_REG_STRIDE 0x1000
@@ -124,6 +125,11 @@ static void set_astate(int cpu, unsigned int astate)
124 local_irq_restore(flags); 125 local_irq_restore(flags);
125} 126}
126 127
128int check_astate(void)
129{
130 return get_cur_astate(hard_smp_processor_id());
131}
132
127void restore_astate(int cpu) 133void restore_astate(int cpu)
128{ 134{
129 set_astate(cpu, current_astate); 135 set_astate(cpu, current_astate);
@@ -147,7 +153,10 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
147 if (!cpu) 153 if (!cpu)
148 goto out; 154 goto out;
149 155
150 dn = of_find_compatible_node(NULL, "sdc", "1682m-sdc"); 156 dn = of_find_compatible_node(NULL, NULL, "1682m-sdc");
157 if (!dn)
158 dn = of_find_compatible_node(NULL, NULL,
159 "pasemi,pwrficient-sdc");
151 if (!dn) 160 if (!dn)
152 goto out; 161 goto out;
153 err = of_address_to_resource(dn, 0, &res); 162 err = of_address_to_resource(dn, 0, &res);
@@ -160,7 +169,10 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
160 goto out; 169 goto out;
161 } 170 }
162 171
163 dn = of_find_compatible_node(NULL, "gizmo", "1682m-gizmo"); 172 dn = of_find_compatible_node(NULL, NULL, "1682m-gizmo");
173 if (!dn)
174 dn = of_find_compatible_node(NULL, NULL,
175 "pasemi,pwrficient-gizmo");
164 if (!dn) { 176 if (!dn) {
165 err = -ENODEV; 177 err = -ENODEV;
166 goto out_unmap_sdcasr; 178 goto out_unmap_sdcasr;
@@ -292,7 +304,8 @@ static struct cpufreq_driver pas_cpufreq_driver = {
292 304
293static int __init pas_cpufreq_init(void) 305static int __init pas_cpufreq_init(void)
294{ 306{
295 if (!machine_is_compatible("PA6T-1682M")) 307 if (!machine_is_compatible("PA6T-1682M") &&
308 !machine_is_compatible("pasemi,pwrficient"))
296 return -ENODEV; 309 return -ENODEV;
297 310
298 return cpufreq_register_driver(&pas_cpufreq_driver); 311 return cpufreq_register_driver(&pas_cpufreq_driver);
diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c
deleted file mode 100644
index 12fb0c949263..000000000000
--- a/arch/powerpc/platforms/pasemi/electra_ide.c
+++ /dev/null
@@ -1,96 +0,0 @@
1/*
2 * Copyright (C) 2007 PA Semi, Inc
3 *
4 * Maintained by: Olof Johansson <olof@lixom.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/platform_device.h>
21
22#include <asm/prom.h>
23#include <asm/system.h>
24
25/* The electra IDE interface is incredibly simple: Just a device on the localbus
26 * with interrupts hooked up to one of the GPIOs. The device tree contains the
27 * address window and interrupt mappings already, and the pata_platform driver handles
28 * the rest. We just need to hook the two up.
29 */
30
31#define MAX_IFS 4 /* really, we have only one */
32
33static struct platform_device *pdevs[MAX_IFS];
34
35static int __devinit electra_ide_init(void)
36{
37 struct device_node *np;
38 struct resource r[3];
39 int ret = 0;
40 int i;
41
42 np = of_find_compatible_node(NULL, "ide", "electra-ide");
43 i = 0;
44
45 while (np && i < MAX_IFS) {
46 memset(r, 0, sizeof(r));
47
48 /* pata_platform wants two address ranges: one for the base registers,
49 * another for the control (altstatus). It's located at offset 0x3f6 in
50 * the window, but the device tree only has one large register window
51 * that covers both ranges. So we need to split it up by hand here:
52 */
53
54 ret = of_address_to_resource(np, 0, &r[0]);
55 if (ret)
56 goto out;
57 ret = of_address_to_resource(np, 0, &r[1]);
58 if (ret)
59 goto out;
60
61 r[1].start += 0x3f6;
62 r[0].end = r[1].start-1;
63
64 r[2].start = irq_of_parse_and_map(np, 0);
65 r[2].end = irq_of_parse_and_map(np, 0);
66 r[2].flags = IORESOURCE_IRQ;
67
68 pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n",
69 r[0].start, r[1].start, r[2].start);
70 pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3);
71 if (IS_ERR(pdevs[i])) {
72 ret = PTR_ERR(pdevs[i]);
73 pdevs[i] = NULL;
74 goto out;
75 }
76 np = of_find_compatible_node(np, "ide", "electra-ide");
77 }
78out:
79 return ret;
80}
81module_init(electra_ide_init);
82
83static void __devexit electra_ide_exit(void)
84{
85 int i;
86
87 for (i = 0; i < MAX_IFS; i++)
88 if (pdevs[i])
89 platform_device_unregister(pdevs[i]);
90}
91module_exit(electra_ide_exit);
92
93
94MODULE_LICENSE("GPL");
95MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
96MODULE_DESCRIPTION("PA Semi Electra IDE driver");
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
index dae9f658122e..b46542990cf8 100644
--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -30,7 +30,7 @@
30#include <linux/interrupt.h> 30#include <linux/interrupt.h>
31#include <linux/phy.h> 31#include <linux/phy.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <asm/of_platform.h> 33#include <linux/of_platform.h>
34 34
35#define DELAY 1 35#define DELAY 1
36 36
@@ -218,45 +218,27 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
218 const struct of_device_id *match) 218 const struct of_device_id *match)
219{ 219{
220 struct device *dev = &ofdev->dev; 220 struct device *dev = &ofdev->dev;
221 struct device_node *np = ofdev->node; 221 struct device_node *phy_dn, *np = ofdev->node;
222 struct device_node *gpio_np;
223 struct mii_bus *new_bus; 222 struct mii_bus *new_bus;
224 struct resource res;
225 struct gpio_priv *priv; 223 struct gpio_priv *priv;
226 const unsigned int *prop; 224 const unsigned int *prop;
227 int err = 0; 225 int err;
228 int i; 226 int i;
229 227
230 gpio_np = of_find_compatible_node(NULL, "gpio", "1682m-gpio"); 228 err = -ENOMEM;
231
232 if (!gpio_np)
233 return -ENODEV;
234
235 err = of_address_to_resource(gpio_np, 0, &res);
236 of_node_put(gpio_np);
237
238 if (err)
239 return -EINVAL;
240
241 if (!gpio_regs)
242 gpio_regs = ioremap(res.start, 0x100);
243
244 if (!gpio_regs)
245 return -EPERM;
246
247 priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL); 229 priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL);
248 if (priv == NULL) 230 if (!priv)
249 return -ENOMEM; 231 goto out;
250 232
251 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); 233 new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
252 234
253 if (new_bus == NULL) 235 if (!new_bus)
254 return -ENOMEM; 236 goto out_free_priv;
255 237
256 new_bus->name = "pasemi gpio mdio bus", 238 new_bus->name = "pasemi gpio mdio bus";
257 new_bus->read = &gpio_mdio_read, 239 new_bus->read = &gpio_mdio_read;
258 new_bus->write = &gpio_mdio_write, 240 new_bus->write = &gpio_mdio_write;
259 new_bus->reset = &gpio_mdio_reset, 241 new_bus->reset = &gpio_mdio_reset;
260 242
261 prop = of_get_property(np, "reg", NULL); 243 prop = of_get_property(np, "reg", NULL);
262 new_bus->id = *prop; 244 new_bus->id = *prop;
@@ -265,9 +247,24 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
265 new_bus->phy_mask = 0; 247 new_bus->phy_mask = 0;
266 248
267 new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); 249 new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
268 for(i = 0; i < PHY_MAX_ADDR; ++i)
269 new_bus->irq[i] = irq_create_mapping(NULL, 10);
270 250
251 if (!new_bus->irq)
252 goto out_free_bus;
253
254 for (i = 0; i < PHY_MAX_ADDR; i++)
255 new_bus->irq[i] = NO_IRQ;
256
257 for (phy_dn = of_get_next_child(np, NULL);
258 phy_dn != NULL;
259 phy_dn = of_get_next_child(np, phy_dn)) {
260 const unsigned int *ip, *regp;
261
262 ip = of_get_property(phy_dn, "interrupts", NULL);
263 regp = of_get_property(phy_dn, "reg", NULL);
264 if (!ip || !regp || *regp >= PHY_MAX_ADDR)
265 continue;
266 new_bus->irq[*regp] = irq_create_mapping(NULL, *ip);
267 }
271 268
272 prop = of_get_property(np, "mdc-pin", NULL); 269 prop = of_get_property(np, "mdc-pin", NULL);
273 priv->mdc_pin = *prop; 270 priv->mdc_pin = *prop;
@@ -280,17 +277,21 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
280 277
281 err = mdiobus_register(new_bus); 278 err = mdiobus_register(new_bus);
282 279
283 if (0 != err) { 280 if (err != 0) {
284 printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n", 281 printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n",
285 new_bus->name, err); 282 new_bus->name, err);
286 goto bus_register_fail; 283 goto out_free_irq;
287 } 284 }
288 285
289 return 0; 286 return 0;
290 287
291bus_register_fail: 288out_free_irq:
289 kfree(new_bus->irq);
290out_free_bus:
292 kfree(new_bus); 291 kfree(new_bus);
293 292out_free_priv:
293 kfree(priv);
294out:
294 return err; 295 return err;
295} 296}
296 297
@@ -317,6 +318,7 @@ static struct of_device_id gpio_mdio_match[] =
317 }, 318 },
318 {}, 319 {},
319}; 320};
321MODULE_DEVICE_TABLE(of, gpio_mdio_match);
320 322
321static struct of_platform_driver gpio_mdio_driver = 323static struct of_platform_driver gpio_mdio_driver =
322{ 324{
@@ -330,12 +332,32 @@ static struct of_platform_driver gpio_mdio_driver =
330 332
331int gpio_mdio_init(void) 333int gpio_mdio_init(void)
332{ 334{
335 struct device_node *np;
336
337 np = of_find_compatible_node(NULL, NULL, "1682m-gpio");
338 if (!np)
339 np = of_find_compatible_node(NULL, NULL,
340 "pasemi,pwrficient-gpio");
341 if (!np)
342 return -ENODEV;
343 gpio_regs = of_iomap(np, 0);
344 of_node_put(np);
345
346 if (!gpio_regs)
347 return -ENODEV;
348
333 return of_register_platform_driver(&gpio_mdio_driver); 349 return of_register_platform_driver(&gpio_mdio_driver);
334} 350}
351module_init(gpio_mdio_init);
335 352
336void gpio_mdio_exit(void) 353void gpio_mdio_exit(void)
337{ 354{
338 of_unregister_platform_driver(&gpio_mdio_driver); 355 of_unregister_platform_driver(&gpio_mdio_driver);
356 if (gpio_regs)
357 iounmap(gpio_regs);
339} 358}
340device_initcall(gpio_mdio_init); 359module_exit(gpio_mdio_exit);
341 360
361MODULE_LICENSE("GPL");
362MODULE_AUTHOR("Olof Johansson <olof@lixom.net>");
363MODULE_DESCRIPTION("Driver for MDIO over GPIO on PA Semi PWRficient-based boards");
diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c
index d8e1fcc78513..43911d8b0206 100644
--- a/arch/powerpc/platforms/pasemi/idle.c
+++ b/arch/powerpc/platforms/pasemi/idle.c
@@ -74,9 +74,6 @@ static int pasemi_system_reset_exception(struct pt_regs *regs)
74 74
75static int __init pasemi_idle_init(void) 75static int __init pasemi_idle_init(void)
76{ 76{
77 if (!machine_is(pasemi))
78 return -ENODEV;
79
80#ifndef CONFIG_PPC_PASEMI_CPUFREQ 77#ifndef CONFIG_PPC_PASEMI_CPUFREQ
81 printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n"); 78 printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n");
82 current_mode = 0; 79 current_mode = 0;
@@ -88,7 +85,7 @@ static int __init pasemi_idle_init(void)
88 85
89 return 0; 86 return 0;
90} 87}
91late_initcall(pasemi_idle_init); 88machine_late_initcall(pasemi, pasemi_idle_init);
92 89
93static int __init idle_param(char *p) 90static int __init idle_param(char *p)
94{ 91{
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h
index 58b344c6fc38..b1e524f7489d 100644
--- a/arch/powerpc/platforms/pasemi/pasemi.h
+++ b/arch/powerpc/platforms/pasemi/pasemi.h
@@ -17,8 +17,14 @@ extern void idle_doze(void);
17 17
18/* Restore astate to last set */ 18/* Restore astate to last set */
19#ifdef CONFIG_PPC_PASEMI_CPUFREQ 19#ifdef CONFIG_PPC_PASEMI_CPUFREQ
20extern int check_astate(void);
20extern void restore_astate(int cpu); 21extern void restore_astate(int cpu);
21#else 22#else
23static inline int check_astate(void)
24{
25 /* Always return >0 so we never power save */
26 return 1;
27}
22static inline void restore_astate(int cpu) 28static inline void restore_astate(int cpu)
23{ 29{
24} 30}
diff --git a/arch/powerpc/platforms/pasemi/powersave.S b/arch/powerpc/platforms/pasemi/powersave.S
index 6d0fba6aab17..56f45adcd089 100644
--- a/arch/powerpc/platforms/pasemi/powersave.S
+++ b/arch/powerpc/platforms/pasemi/powersave.S
@@ -62,7 +62,16 @@ sleep_common:
62 mflr r0 62 mflr r0
63 std r0, 16(r1) 63 std r0, 16(r1)
64 stdu r1,-64(r1) 64 stdu r1,-64(r1)
65#ifdef CONFIG_PPC_PASEMI_CPUFREQ
66 std r3, 48(r1)
65 67
68 /* Only do power savings when in astate 0 */
69 bl .check_astate
70 cmpwi r3,0
71 bne 1f
72
73 ld r3, 48(r1)
74#endif
66 LOAD_REG_IMMEDIATE(r6,MSR_DR|MSR_IR|MSR_ME|MSR_EE) 75 LOAD_REG_IMMEDIATE(r6,MSR_DR|MSR_IR|MSR_ME|MSR_EE)
67 mfmsr r4 76 mfmsr r4
68 andc r5,r4,r6 77 andc r5,r4,r6
@@ -73,7 +82,7 @@ sleep_common:
73 82
74 mtmsrd r4,0 83 mtmsrd r4,0
75 84
76 addi r1,r1,64 851: addi r1,r1,64
77 ld r0,16(r1) 86 ld r0,16(r1)
78 mtlr r0 87 mtlr r0
79 blr 88 blr
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index 3d62060498b4..c64fb5bfb37e 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -27,6 +27,7 @@
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/console.h> 28#include <linux/console.h>
29#include <linux/pci.h> 29#include <linux/pci.h>
30#include <linux/of_platform.h>
30 31
31#include <asm/prom.h> 32#include <asm/prom.h>
32#include <asm/system.h> 33#include <asm/system.h>
@@ -35,7 +36,7 @@
35#include <asm/mpic.h> 36#include <asm/mpic.h>
36#include <asm/smp.h> 37#include <asm/smp.h>
37#include <asm/time.h> 38#include <asm/time.h>
38#include <asm/of_platform.h> 39#include <asm/mmu.h>
39 40
40#include <pcmcia/ss.h> 41#include <pcmcia/ss.h>
41#include <pcmcia/cistpl.h> 42#include <pcmcia/cistpl.h>
@@ -43,6 +44,10 @@
43 44
44#include "pasemi.h" 45#include "pasemi.h"
45 46
47#if !defined(CONFIG_SMP)
48static void smp_send_stop(void) {}
49#endif
50
46/* SDC reset register, must be pre-mapped at reset time */ 51/* SDC reset register, must be pre-mapped at reset time */
47static void __iomem *reset_reg; 52static void __iomem *reset_reg;
48 53
@@ -56,10 +61,14 @@ struct mce_regs {
56 61
57static struct mce_regs mce_regs[MAX_MCE_REGS]; 62static struct mce_regs mce_regs[MAX_MCE_REGS];
58static int num_mce_regs; 63static int num_mce_regs;
64static int nmi_virq = NO_IRQ;
59 65
60 66
61static void pas_restart(char *cmd) 67static void pas_restart(char *cmd)
62{ 68{
69 /* Need to put others cpu in hold loop so they're not sleeping */
70 smp_send_stop();
71 udelay(10000);
63 printk("Restarting...\n"); 72 printk("Restarting...\n");
64 while (1) 73 while (1)
65 out_le32(reset_reg, 0x6000000); 74 out_le32(reset_reg, 0x6000000);
@@ -126,9 +135,6 @@ static int __init pas_setup_mce_regs(void)
126 struct pci_dev *dev; 135 struct pci_dev *dev;
127 int reg; 136 int reg;
128 137
129 if (!machine_is(pasemi))
130 return -ENODEV;
131
132 /* Remap various SoC status registers for use by the MCE handler */ 138 /* Remap various SoC status registers for use by the MCE handler */
133 139
134 reg = 0; 140 reg = 0;
@@ -172,7 +178,7 @@ static int __init pas_setup_mce_regs(void)
172 178
173 return 0; 179 return 0;
174} 180}
175device_initcall(pas_setup_mce_regs); 181machine_device_initcall(pasemi, pas_setup_mce_regs);
176 182
177static __init void pas_init_IRQ(void) 183static __init void pas_init_IRQ(void)
178{ 184{
@@ -181,6 +187,8 @@ static __init void pas_init_IRQ(void)
181 unsigned long openpic_addr; 187 unsigned long openpic_addr;
182 const unsigned int *opprop; 188 const unsigned int *opprop;
183 int naddr, opplen; 189 int naddr, opplen;
190 int mpic_flags;
191 const unsigned int *nmiprop;
184 struct mpic *mpic; 192 struct mpic *mpic;
185 193
186 mpic_node = NULL; 194 mpic_node = NULL;
@@ -213,13 +221,26 @@ static __init void pas_init_IRQ(void)
213 openpic_addr = of_read_number(opprop, naddr); 221 openpic_addr = of_read_number(opprop, naddr);
214 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); 222 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
215 223
224 mpic_flags = MPIC_PRIMARY | MPIC_LARGE_VECTORS | MPIC_NO_BIAS;
225
226 nmiprop = of_get_property(mpic_node, "nmi-source", NULL);
227 if (nmiprop)
228 mpic_flags |= MPIC_ENABLE_MCK;
229
216 mpic = mpic_alloc(mpic_node, openpic_addr, 230 mpic = mpic_alloc(mpic_node, openpic_addr,
217 MPIC_PRIMARY|MPIC_LARGE_VECTORS, 231 mpic_flags, 0, 0, "PASEMI-OPIC");
218 0, 0, " PAS-OPIC ");
219 BUG_ON(!mpic); 232 BUG_ON(!mpic);
220 233
221 mpic_assign_isu(mpic, 0, openpic_addr + 0x10000); 234 mpic_assign_isu(mpic, 0, openpic_addr + 0x10000);
222 mpic_init(mpic); 235 mpic_init(mpic);
236 /* The NMI/MCK source needs to be prio 15 */
237 if (nmiprop) {
238 nmi_virq = irq_create_mapping(NULL, *nmiprop);
239 mpic_irq_set_priority(nmi_virq, 15);
240 set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
241 mpic_unmask_irq(nmi_virq);
242 }
243
223 of_node_put(mpic_node); 244 of_node_put(mpic_node);
224 of_node_put(root); 245 of_node_put(root);
225} 246}
@@ -239,6 +260,14 @@ static int pas_machine_check_handler(struct pt_regs *regs)
239 260
240 srr0 = regs->nip; 261 srr0 = regs->nip;
241 srr1 = regs->msr; 262 srr1 = regs->msr;
263
264 if (nmi_virq != NO_IRQ && mpic_get_mcirq() == nmi_virq) {
265 printk(KERN_ERR "NMI delivered\n");
266 debugger(regs);
267 mpic_end_irq(nmi_virq);
268 goto out;
269 }
270
242 dsisr = mfspr(SPRN_DSISR); 271 dsisr = mfspr(SPRN_DSISR);
243 printk(KERN_ERR "Machine Check on CPU %d\n", cpu); 272 printk(KERN_ERR "Machine Check on CPU %d\n", cpu);
244 printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1); 273 printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1);
@@ -295,14 +324,14 @@ static int pas_machine_check_handler(struct pt_regs *regs)
295 int i; 324 int i;
296 325
297 printk(KERN_ERR "slb contents:\n"); 326 printk(KERN_ERR "slb contents:\n");
298 for (i = 0; i < SLB_NUM_ENTRIES; i++) { 327 for (i = 0; i < mmu_slb_size; i++) {
299 asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i)); 328 asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i));
300 asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i)); 329 asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i));
301 printk(KERN_ERR "%02d %016lx %016lx\n", i, e, v); 330 printk(KERN_ERR "%02d %016lx %016lx\n", i, e, v);
302 } 331 }
303 } 332 }
304 333
305 334out:
306 /* SRR1[62] is from MSR[62] if recoverable, so pass that back */ 335 /* SRR1[62] is from MSR[62] if recoverable, so pass that back */
307 return !!(srr1 & 0x2); 336 return !!(srr1 & 0x2);
308} 337}
@@ -362,16 +391,17 @@ static inline void pasemi_pcmcia_init(void)
362 391
363 392
364static struct of_device_id pasemi_bus_ids[] = { 393static struct of_device_id pasemi_bus_ids[] = {
394 /* Unfortunately needed for legacy firmwares */
365 { .type = "localbus", }, 395 { .type = "localbus", },
366 { .type = "sdc", }, 396 { .type = "sdc", },
397 /* These are the proper entries, which newer firmware uses */
398 { .compatible = "pasemi,localbus", },
399 { .compatible = "pasemi,sdc", },
367 {}, 400 {},
368}; 401};
369 402
370static int __init pasemi_publish_devices(void) 403static int __init pasemi_publish_devices(void)
371{ 404{
372 if (!machine_is(pasemi))
373 return 0;
374
375 pasemi_pcmcia_init(); 405 pasemi_pcmcia_init();
376 406
377 /* Publish OF platform devices for SDC and other non-PCI devices */ 407 /* Publish OF platform devices for SDC and other non-PCI devices */
@@ -379,7 +409,7 @@ static int __init pasemi_publish_devices(void)
379 409
380 return 0; 410 return 0;
381} 411}
382device_initcall(pasemi_publish_devices); 412machine_device_initcall(pasemi, pasemi_publish_devices);
383 413
384 414
385/* 415/*
@@ -389,7 +419,8 @@ static int __init pas_probe(void)
389{ 419{
390 unsigned long root = of_get_flat_dt_root(); 420 unsigned long root = of_get_flat_dt_root();
391 421
392 if (!of_flat_dt_is_compatible(root, "PA6T-1682M")) 422 if (!of_flat_dt_is_compatible(root, "PA6T-1682M") &&
423 !of_flat_dt_is_compatible(root, "pasemi,pwrficient"))
393 return 0; 424 return 0;
394 425
395 hpte_init_native(); 426 hpte_init_native();
@@ -400,7 +431,7 @@ static int __init pas_probe(void)
400} 431}
401 432
402define_machine(pasemi) { 433define_machine(pasemi) {
403 .name = "PA Semi PA6T-1682M", 434 .name = "PA Semi PWRficient",
404 .probe = pas_probe, 435 .probe = pas_probe,
405 .setup_arch = pas_setup_arch, 436 .setup_arch = pas_setup_arch,
406 .init_early = pas_init_early, 437 .init_early = pas_init_early,