aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-04-06 03:02:57 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-06 03:02:57 -0400
commitf541ae326fa120fa5c57433e4d9a133df212ce41 (patch)
treebdbd94ec72cfc601118051cb35e8617d55510177 /arch/powerpc/platforms
parente255357764f92afcafafbd4879b222b8c752065a (diff)
parent0221c81b1b8eb0cbb6b30a0ced52ead32d2b4e4c (diff)
Merge branch 'linus' into perfcounters/core-v2
Merge reason: we have gathered quite a few conflicts, need to merge upstream Conflicts: arch/powerpc/kernel/Makefile arch/x86/ia32/ia32entry.S arch/x86/include/asm/hardirq.h arch/x86/include/asm/unistd_32.h arch/x86/include/asm/unistd_64.h arch/x86/kernel/cpu/common.c arch/x86/kernel/irq.c arch/x86/kernel/syscall_table_32.S arch/x86/mm/iomap_32.c include/linux/sched.h kernel/Makefile Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/44x/Kconfig19
-rw-r--r--arch/powerpc/platforms/44x/ppc44x_simple.c1
-rw-r--r--arch/powerpc/platforms/512x/Kconfig4
-rw-r--r--arch/powerpc/platforms/52xx/Kconfig15
-rw-r--r--arch/powerpc/platforms/52xx/Makefile3
-rw-r--r--arch/powerpc/platforms/52xx/media5200.c273
-rw-r--r--arch/powerpc/platforms/52xx/mpc5200_simple.c4
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c40
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_gpio.c85
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_gpt.c396
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pic.c170
-rw-r--r--arch/powerpc/platforms/82xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/83xx/asp834x.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc831x_rdb.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_rdb.c123
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_mds.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_mds.c11
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_rdb.c3
-rw-r--r--arch/powerpc/platforms/83xx/sbc834x.c1
-rw-r--r--arch/powerpc/platforms/83xx/usb.c3
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig6
-rw-r--r--arch/powerpc/platforms/85xx/Makefile1
-rw-r--r--arch/powerpc/platforms/85xx/ksi8560.c3
-rw-r--r--arch/powerpc/platforms/85xx/mpc8536_ds.c1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ds.c1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c1
-rw-r--r--arch/powerpc/platforms/85xx/sbc8548.c1
-rw-r--r--arch/powerpc/platforms/85xx/sbc8560.c1
-rw-r--r--arch/powerpc/platforms/85xx/smp.c43
-rw-r--r--arch/powerpc/platforms/85xx/socrates.c133
-rw-r--r--arch/powerpc/platforms/85xx/socrates_fpga_pic.c327
-rw-r--r--arch/powerpc/platforms/85xx/socrates_fpga_pic.h16
-rw-r--r--arch/powerpc/platforms/85xx/stx_gp3.c1
-rw-r--r--arch/powerpc/platforms/85xx/tqm85xx.c1
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig20
-rw-r--r--arch/powerpc/platforms/86xx/Makefile2
-rw-r--r--arch/powerpc/platforms/86xx/gef_gpio.c36
-rw-r--r--arch/powerpc/platforms/86xx/gef_ppc9a.c224
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc310.c235
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc610.c5
-rw-r--r--arch/powerpc/platforms/86xx/mpc8610_hpcd.c1
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c1
-rw-r--r--arch/powerpc/platforms/86xx/sbc8641d.c1
-rw-r--r--arch/powerpc/platforms/8xx/m8xx_setup.c1
-rw-r--r--arch/powerpc/platforms/Kconfig41
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype22
-rw-r--r--arch/powerpc/platforms/Makefile1
-rw-r--r--arch/powerpc/platforms/amigaone/Kconfig18
-rw-r--r--arch/powerpc/platforms/amigaone/Makefile1
-rw-r--r--arch/powerpc/platforms/amigaone/setup.c170
-rw-r--r--arch/powerpc/platforms/cell/Kconfig33
-rw-r--r--arch/powerpc/platforms/cell/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c4
-rw-r--r--arch/powerpc/platforms/cell/io-workarounds.c4
-rw-r--r--arch/powerpc/platforms/cell/iommu.c9
-rw-r--r--arch/powerpc/platforms/cell/qpace_setup.c15
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c2
-rw-r--r--arch/powerpc/platforms/cell/spu_fault.c48
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c20
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c7
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c3
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h8
-rw-r--r--arch/powerpc/platforms/chrp/Kconfig2
-rw-r--r--arch/powerpc/platforms/chrp/pegasos_eth.c72
-rw-r--r--arch/powerpc/platforms/chrp/setup.c1
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/embedded6xx/linkstation.c38
-rw-r--r--arch/powerpc/platforms/embedded6xx/storcenter.c32
-rw-r--r--arch/powerpc/platforms/iseries/Kconfig2
-rw-r--r--arch/powerpc/platforms/iseries/irq.c2
-rw-r--r--arch/powerpc/platforms/iseries/setup.c2
-rw-r--r--arch/powerpc/platforms/maple/Kconfig2
-rw-r--r--arch/powerpc/platforms/pasemi/Kconfig2
-rw-r--r--arch/powerpc/platforms/powermac/Kconfig2
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c5
-rw-r--r--arch/powerpc/platforms/powermac/pic.c2
-rw-r--r--arch/powerpc/platforms/powermac/pic.h2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c3
-rw-r--r--arch/powerpc/platforms/powermac/smp.c1
-rw-r--r--arch/powerpc/platforms/prep/Kconfig2
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig9
-rw-r--r--arch/powerpc/platforms/ps3/mm.c4
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c2
-rw-r--r--arch/powerpc/platforms/ps3/platform.h2
-rw-r--r--arch/powerpc/platforms/ps3/setup.c2
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c4
-rw-r--r--arch/powerpc/platforms/ps3/time.c26
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig17
-rw-r--r--arch/powerpc/platforms/pseries/Makefile3
-rw-r--r--arch/powerpc/platforms/pseries/dtl.c278
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c68
-rw-r--r--arch/powerpc/platforms/pseries/msi.c248
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c2
-rw-r--r--arch/powerpc/platforms/pseries/plpar_wrappers.h10
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c6
101 files changed, 2943 insertions, 551 deletions
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 3496bc05058e..bf5c7ff2e6e5 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -118,6 +118,17 @@ config GLACIER
118 help 118 help
119 This option enables support for the AMCC PPC460GT evaluation board. 119 This option enables support for the AMCC PPC460GT evaluation board.
120 120
121config REDWOOD
122 bool "Redwood"
123 depends on 44x
124 default n
125 select PPC44x_SIMPLE
126 select 460SX
127 select PCI
128 select PPC4xx_PCI_EXPRESS
129 help
130 This option enables support for the AMCC PPC460SX Redwood board.
131
121config YOSEMITE 132config YOSEMITE
122 bool "Yosemite" 133 bool "Yosemite"
123 depends on 44x 134 depends on 44x
@@ -220,6 +231,14 @@ config 460EX
220 select IBM_NEW_EMAC_EMAC4 231 select IBM_NEW_EMAC_EMAC4
221 select IBM_NEW_EMAC_TAH 232 select IBM_NEW_EMAC_TAH
222 233
234config 460SX
235 bool
236 select PPC_FPU
237 select IBM_NEW_EMAC_EMAC4
238 select IBM_NEW_EMAC_RGMII
239 select IBM_NEW_EMAC_ZMII
240 select IBM_NEW_EMAC_TAH
241
223# 44x errata/workaround config symbols, selected by the CPU models above 242# 44x errata/workaround config symbols, selected by the CPU models above
224config IBM440EP_ERR42 243config IBM440EP_ERR42
225 bool 244 bool
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index 76fdc51dac8b..5bcd441885e8 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -57,6 +57,7 @@ static char *board[] __initdata = {
57 "ibm,ebony", 57 "ibm,ebony",
58 "amcc,katmai", 58 "amcc,katmai",
59 "amcc,rainier", 59 "amcc,rainier",
60 "amcc,redwood",
60 "amcc,sequoia", 61 "amcc,sequoia",
61 "amcc,taishan", 62 "amcc,taishan",
62 "amcc,yosemite" 63 "amcc,yosemite"
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index 326852c78b8f..4dac9b0525a4 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -12,7 +12,7 @@ config PPC_MPC5121
12 12
13config MPC5121_ADS 13config MPC5121_ADS
14 bool "Freescale MPC5121E ADS" 14 bool "Freescale MPC5121E ADS"
15 depends on PPC_MULTIPLATFORM && PPC32 15 depends on 6xx
16 select DEFAULT_UIMAGE 16 select DEFAULT_UIMAGE
17 select PPC_MPC5121 17 select PPC_MPC5121
18 select MPC5121_ADS_CPLD 18 select MPC5121_ADS_CPLD
@@ -21,7 +21,7 @@ config MPC5121_ADS
21 21
22config MPC5121_GENERIC 22config MPC5121_GENERIC
23 bool "Generic support for simple MPC5121 based boards" 23 bool "Generic support for simple MPC5121 based boards"
24 depends on PPC_MULTIPLATFORM && PPC32 24 depends on 6xx
25 select DEFAULT_UIMAGE 25 select DEFAULT_UIMAGE
26 select PPC_MPC5121 26 select PPC_MPC5121
27 help 27 help
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index 696a5ee4962d..8b8e9560a315 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -1,6 +1,6 @@
1config PPC_MPC52xx 1config PPC_MPC52xx
2 bool "52xx-based boards" 2 bool "52xx-based boards"
3 depends on PPC_MULTIPLATFORM && PPC32 3 depends on 6xx
4 select PPC_CLOCK 4 select PPC_CLOCK
5 select PPC_PCI_CHOICE 5 select PPC_PCI_CHOICE
6 6
@@ -21,7 +21,13 @@ config PPC_MPC5200_SIMPLE
21 and if there is a PCI bus node defined in the device tree. 21 and if there is a PCI bus node defined in the device tree.
22 22
23 Boards that are compatible with this generic platform support 23 Boards that are compatible with this generic platform support
24 are: 'tqc,tqm5200', 'promess,motionpro', 'schindler,cm5200'. 24 are:
25 intercontrol,digsy-mtc
26 phytec,pcm030
27 phytec,pcm032
28 promess,motionpro
29 schindler,cm5200
30 tqc,tqm5200
25 31
26config PPC_EFIKA 32config PPC_EFIKA
27 bool "bPlan Efika 5k2. MPC5200B based computer" 33 bool "bPlan Efika 5k2. MPC5200B based computer"
@@ -35,6 +41,11 @@ config PPC_LITE5200
35 depends on PPC_MPC52xx 41 depends on PPC_MPC52xx
36 select DEFAULT_UIMAGE 42 select DEFAULT_UIMAGE
37 43
44config PPC_MEDIA5200
45 bool "Freescale Media5200 Eval Board"
46 depends on PPC_MPC52xx
47 select DEFAULT_UIMAGE
48
38config PPC_MPC5200_BUGFIX 49config PPC_MPC5200_BUGFIX
39 bool "MPC5200 (L25R) bugfix support" 50 bool "MPC5200 (L25R) bugfix support"
40 depends on PPC_MPC52xx 51 depends on PPC_MPC52xx
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index b8a52062738a..bfd4f52cf3dd 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -1,12 +1,13 @@
1# 1#
2# Makefile for 52xx based boards 2# Makefile for 52xx based boards
3# 3#
4obj-y += mpc52xx_pic.o mpc52xx_common.o 4obj-y += mpc52xx_pic.o mpc52xx_common.o mpc52xx_gpt.o
5obj-$(CONFIG_PCI) += mpc52xx_pci.o 5obj-$(CONFIG_PCI) += mpc52xx_pci.o
6 6
7obj-$(CONFIG_PPC_MPC5200_SIMPLE) += mpc5200_simple.o 7obj-$(CONFIG_PPC_MPC5200_SIMPLE) += mpc5200_simple.o
8obj-$(CONFIG_PPC_EFIKA) += efika.o 8obj-$(CONFIG_PPC_EFIKA) += efika.o
9obj-$(CONFIG_PPC_LITE5200) += lite5200.o 9obj-$(CONFIG_PPC_LITE5200) += lite5200.o
10obj-$(CONFIG_PPC_MEDIA5200) += media5200.o
10 11
11obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o 12obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o
12ifeq ($(CONFIG_PPC_LITE5200),y) 13ifeq ($(CONFIG_PPC_LITE5200),y)
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
new file mode 100644
index 000000000000..68e4f1696d14
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -0,0 +1,273 @@
1/*
2 * Support for 'media5200-platform' compatible boards.
3 *
4 * Copyright (C) 2008 Secret Lab Technologies Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Description:
12 * This code implements support for the Freescape Media5200 platform
13 * (built around the MPC5200 SoC).
14 *
15 * Notable characteristic of the Media5200 is the presence of an FPGA
16 * that has all external IRQ lines routed through it. This file implements
17 * a cascaded interrupt controller driver which attaches itself to the
18 * Virtual IRQ subsystem after the primary mpc5200 interrupt controller
19 * is initialized.
20 *
21 */
22
23#undef DEBUG
24
25#include <linux/irq.h>
26#include <linux/interrupt.h>
27#include <linux/io.h>
28#include <asm/time.h>
29#include <asm/prom.h>
30#include <asm/machdep.h>
31#include <asm/mpc52xx.h>
32
33static struct of_device_id mpc5200_gpio_ids[] __initdata = {
34 { .compatible = "fsl,mpc5200-gpio", },
35 { .compatible = "mpc5200-gpio", },
36 {}
37};
38
39/* FPGA register set */
40#define MEDIA5200_IRQ_ENABLE (0x40c)
41#define MEDIA5200_IRQ_STATUS (0x410)
42#define MEDIA5200_NUM_IRQS (6)
43#define MEDIA5200_IRQ_SHIFT (32 - MEDIA5200_NUM_IRQS)
44
45struct media5200_irq {
46 void __iomem *regs;
47 spinlock_t lock;
48 struct irq_host *irqhost;
49};
50struct media5200_irq media5200_irq;
51
52static void media5200_irq_unmask(unsigned int virq)
53{
54 unsigned long flags;
55 u32 val;
56
57 spin_lock_irqsave(&media5200_irq.lock, flags);
58 val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
59 val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq);
60 out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
61 spin_unlock_irqrestore(&media5200_irq.lock, flags);
62}
63
64static void media5200_irq_mask(unsigned int virq)
65{
66 unsigned long flags;
67 u32 val;
68
69 spin_lock_irqsave(&media5200_irq.lock, flags);
70 val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
71 val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq));
72 out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
73 spin_unlock_irqrestore(&media5200_irq.lock, flags);
74}
75
76static struct irq_chip media5200_irq_chip = {
77 .typename = "Media5200 FPGA",
78 .unmask = media5200_irq_unmask,
79 .mask = media5200_irq_mask,
80 .mask_ack = media5200_irq_mask,
81};
82
83void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
84{
85 int sub_virq, val;
86 u32 status, enable;
87
88 /* Mask off the cascaded IRQ */
89 spin_lock(&desc->lock);
90 desc->chip->mask(virq);
91 spin_unlock(&desc->lock);
92
93 /* Ask the FPGA for IRQ status. If 'val' is 0, then no irqs
94 * are pending. 'ffs()' is 1 based */
95 status = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
96 enable = in_be32(media5200_irq.regs + MEDIA5200_IRQ_STATUS);
97 val = ffs((status & enable) >> MEDIA5200_IRQ_SHIFT);
98 if (val) {
99 sub_virq = irq_linear_revmap(media5200_irq.irqhost, val - 1);
100 /* pr_debug("%s: virq=%i s=%.8x e=%.8x hwirq=%i subvirq=%i\n",
101 * __func__, virq, status, enable, val - 1, sub_virq);
102 */
103 generic_handle_irq(sub_virq);
104 }
105
106 /* Processing done; can reenable the cascade now */
107 spin_lock(&desc->lock);
108 desc->chip->ack(virq);
109 if (!(desc->status & IRQ_DISABLED))
110 desc->chip->unmask(virq);
111 spin_unlock(&desc->lock);
112}
113
114static int media5200_irq_map(struct irq_host *h, unsigned int virq,
115 irq_hw_number_t hw)
116{
117 struct irq_desc *desc = get_irq_desc(virq);
118
119 pr_debug("%s: h=%p, virq=%i, hwirq=%i\n", __func__, h, virq, (int)hw);
120 set_irq_chip_data(virq, &media5200_irq);
121 set_irq_chip_and_handler(virq, &media5200_irq_chip, handle_level_irq);
122 set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
123 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
124 desc->status |= IRQ_TYPE_LEVEL_LOW | IRQ_LEVEL;
125
126 return 0;
127}
128
129static int media5200_irq_xlate(struct irq_host *h, struct device_node *ct,
130 u32 *intspec, unsigned int intsize,
131 irq_hw_number_t *out_hwirq,
132 unsigned int *out_flags)
133{
134 if (intsize != 2)
135 return -1;
136
137 pr_debug("%s: bank=%i, number=%i\n", __func__, intspec[0], intspec[1]);
138 *out_hwirq = intspec[1];
139 *out_flags = IRQ_TYPE_NONE;
140 return 0;
141}
142
143static struct irq_host_ops media5200_irq_ops = {
144 .map = media5200_irq_map,
145 .xlate = media5200_irq_xlate,
146};
147
148/*
149 * Setup Media5200 IRQ mapping
150 */
151static void __init media5200_init_irq(void)
152{
153 struct device_node *fpga_np;
154 int cascade_virq;
155
156 /* First setup the regular MPC5200 interrupt controller */
157 mpc52xx_init_irq();
158
159 /* Now find the FPGA IRQ */
160 fpga_np = of_find_compatible_node(NULL, NULL, "fsl,media5200-fpga");
161 if (!fpga_np)
162 goto out;
163 pr_debug("%s: found fpga node: %s\n", __func__, fpga_np->full_name);
164
165 media5200_irq.regs = of_iomap(fpga_np, 0);
166 if (!media5200_irq.regs)
167 goto out;
168 pr_debug("%s: mapped to %p\n", __func__, media5200_irq.regs);
169
170 cascade_virq = irq_of_parse_and_map(fpga_np, 0);
171 if (!cascade_virq)
172 goto out;
173 pr_debug("%s: cascaded on virq=%i\n", __func__, cascade_virq);
174
175 /* Disable all FPGA IRQs */
176 out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, 0);
177
178 spin_lock_init(&media5200_irq.lock);
179
180 media5200_irq.irqhost = irq_alloc_host(fpga_np, IRQ_HOST_MAP_LINEAR,
181 MEDIA5200_NUM_IRQS,
182 &media5200_irq_ops, -1);
183 if (!media5200_irq.irqhost)
184 goto out;
185 pr_debug("%s: allocated irqhost\n", __func__);
186
187 media5200_irq.irqhost->host_data = &media5200_irq;
188
189 set_irq_data(cascade_virq, &media5200_irq);
190 set_irq_chained_handler(cascade_virq, media5200_irq_cascade);
191
192 return;
193
194 out:
195 pr_err("Could not find Media5200 FPGA; PCI interrupts will not work\n");
196}
197
198/*
199 * Setup the architecture
200 */
201static void __init media5200_setup_arch(void)
202{
203
204 struct device_node *np;
205 struct mpc52xx_gpio __iomem *gpio;
206 u32 port_config;
207
208 if (ppc_md.progress)
209 ppc_md.progress("media5200_setup_arch()", 0);
210
211 /* Map important registers from the internal memory map */
212 mpc52xx_map_common_devices();
213
214 /* Some mpc5200 & mpc5200b related configuration */
215 mpc5200_setup_xlb_arbiter();
216
217 mpc52xx_setup_pci();
218
219 np = of_find_matching_node(NULL, mpc5200_gpio_ids);
220 gpio = of_iomap(np, 0);
221 of_node_put(np);
222 if (!gpio) {
223 printk(KERN_ERR "%s() failed. expect abnormal behavior\n",
224 __func__);
225 return;
226 }
227
228 /* Set port config */
229 port_config = in_be32(&gpio->port_config);
230
231 port_config &= ~0x03000000; /* ATA CS is on csb_4/5 */
232 port_config |= 0x01000000;
233
234 out_be32(&gpio->port_config, port_config);
235
236 /* Unmap zone */
237 iounmap(gpio);
238
239}
240
241/* list of the supported boards */
242static char *board[] __initdata = {
243 "fsl,media5200",
244 NULL
245};
246
247/*
248 * Called very early, MMU is off, device-tree isn't unflattened
249 */
250static int __init media5200_probe(void)
251{
252 unsigned long node = of_get_flat_dt_root();
253 int i = 0;
254
255 while (board[i]) {
256 if (of_flat_dt_is_compatible(node, board[i]))
257 break;
258 i++;
259 }
260
261 return (board[i] != NULL);
262}
263
264define_machine(media5200_platform) {
265 .name = "media5200-platform",
266 .probe = media5200_probe,
267 .setup_arch = media5200_setup_arch,
268 .init = mpc52xx_declare_of_platform_devices,
269 .init_IRQ = media5200_init_irq,
270 .get_irq = mpc52xx_get_irq,
271 .restart = mpc52xx_restart,
272 .calibrate_decr = generic_calibrate_decr,
273};
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index a3bda0b9f1ff..c31e5b534f0a 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -50,8 +50,10 @@ static void __init mpc5200_simple_setup_arch(void)
50 50
51/* list of the supported boards */ 51/* list of the supported boards */
52static char *board[] __initdata = { 52static char *board[] __initdata = {
53 "promess,motionpro", 53 "intercontrol,digsy-mtc",
54 "phytec,pcm030", 54 "phytec,pcm030",
55 "phytec,pcm032",
56 "promess,motionpro",
55 "schindler,cm5200", 57 "schindler,cm5200",
56 "tqc,tqm5200", 58 "tqc,tqm5200",
57 NULL 59 NULL
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 98367a0255f3..8e3dd5a0f228 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -28,9 +28,10 @@ static struct of_device_id mpc52xx_xlb_ids[] __initdata = {
28static struct of_device_id mpc52xx_bus_ids[] __initdata = { 28static struct of_device_id mpc52xx_bus_ids[] __initdata = {
29 { .compatible = "fsl,mpc5200-immr", }, 29 { .compatible = "fsl,mpc5200-immr", },
30 { .compatible = "fsl,mpc5200b-immr", }, 30 { .compatible = "fsl,mpc5200b-immr", },
31 { .compatible = "fsl,lpb", }, 31 { .compatible = "simple-bus", },
32 32
33 /* depreciated matches; shouldn't be used in new device trees */ 33 /* depreciated matches; shouldn't be used in new device trees */
34 { .compatible = "fsl,lpb", },
34 { .type = "builtin", .compatible = "mpc5200", }, /* efika */ 35 { .type = "builtin", .compatible = "mpc5200", }, /* efika */
35 { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */ 36 { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
36 {} 37 {}
@@ -205,6 +206,43 @@ int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv)
205EXPORT_SYMBOL(mpc52xx_set_psc_clkdiv); 206EXPORT_SYMBOL(mpc52xx_set_psc_clkdiv);
206 207
207/** 208/**
209 * mpc52xx_get_xtal_freq - Get SYS_XTAL_IN frequency for a device
210 *
211 * @node: device node
212 *
213 * Returns the frequency of the external oscillator clock connected
214 * to the SYS_XTAL_IN pin, or 0 if it cannot be determined.
215 */
216unsigned int mpc52xx_get_xtal_freq(struct device_node *node)
217{
218 u32 val;
219 unsigned int freq;
220
221 if (!mpc52xx_cdm)
222 return 0;
223
224 freq = mpc52xx_find_ipb_freq(node);
225 if (!freq)
226 return 0;
227
228 if (in_8(&mpc52xx_cdm->ipb_clk_sel) & 0x1)
229 freq *= 2;
230
231 val = in_be32(&mpc52xx_cdm->rstcfg);
232 if (val & (1 << 5))
233 freq *= 8;
234 else
235 freq *= 4;
236 if (val & (1 << 6))
237 freq /= 12;
238 else
239 freq /= 16;
240
241 return freq;
242}
243EXPORT_SYMBOL(mpc52xx_get_xtal_freq);
244
245/**
208 * mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer 246 * mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer
209 */ 247 */
210void 248void
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
index 07f89ae46d04..2b8d8ef32e4e 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
@@ -354,88 +354,6 @@ static struct of_platform_driver mpc52xx_simple_gpiochip_driver = {
354 .remove = mpc52xx_gpiochip_remove, 354 .remove = mpc52xx_gpiochip_remove,
355}; 355};
356 356
357/*
358 * GPIO LIB API implementation for gpt GPIOs.
359 *
360 * Each gpt only has a single GPIO.
361 */
362static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio)
363{
364 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
365 struct mpc52xx_gpt __iomem *regs = mm_gc->regs;
366
367 return (in_be32(&regs->status) & (1 << (31 - 23))) ? 1 : 0;
368}
369
370static void
371mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
372{
373 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
374 struct mpc52xx_gpt __iomem *regs = mm_gc->regs;
375
376 if (val)
377 out_be32(&regs->mode, 0x34);
378 else
379 out_be32(&regs->mode, 0x24);
380
381 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
382}
383
384static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
385{
386 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
387 struct mpc52xx_gpt __iomem *regs = mm_gc->regs;
388
389 out_be32(&regs->mode, 0x04);
390
391 return 0;
392}
393
394static int
395mpc52xx_gpt_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
396{
397 mpc52xx_gpt_gpio_set(gc, gpio, val);
398 pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
399
400 return 0;
401}
402
403static int __devinit mpc52xx_gpt_gpiochip_probe(struct of_device *ofdev,
404 const struct of_device_id *match)
405{
406 struct of_mm_gpio_chip *mmchip;
407 struct of_gpio_chip *chip;
408
409 mmchip = kzalloc(sizeof(*mmchip), GFP_KERNEL);
410 if (!mmchip)
411 return -ENOMEM;
412
413 chip = &mmchip->of_gc;
414
415 chip->gpio_cells = 2;
416 chip->gc.ngpio = 1;
417 chip->gc.direction_input = mpc52xx_gpt_gpio_dir_in;
418 chip->gc.direction_output = mpc52xx_gpt_gpio_dir_out;
419 chip->gc.get = mpc52xx_gpt_gpio_get;
420 chip->gc.set = mpc52xx_gpt_gpio_set;
421
422 return of_mm_gpiochip_add(ofdev->node, mmchip);
423}
424
425static const struct of_device_id mpc52xx_gpt_gpiochip_match[] = {
426 {
427 .compatible = "fsl,mpc5200-gpt-gpio",
428 },
429 {}
430};
431
432static struct of_platform_driver mpc52xx_gpt_gpiochip_driver = {
433 .name = "gpio_gpt",
434 .match_table = mpc52xx_gpt_gpiochip_match,
435 .probe = mpc52xx_gpt_gpiochip_probe,
436 .remove = mpc52xx_gpiochip_remove,
437};
438
439static int __init mpc52xx_gpio_init(void) 357static int __init mpc52xx_gpio_init(void)
440{ 358{
441 if (of_register_platform_driver(&mpc52xx_wkup_gpiochip_driver)) 359 if (of_register_platform_driver(&mpc52xx_wkup_gpiochip_driver))
@@ -444,9 +362,6 @@ static int __init mpc52xx_gpio_init(void)
444 if (of_register_platform_driver(&mpc52xx_simple_gpiochip_driver)) 362 if (of_register_platform_driver(&mpc52xx_simple_gpiochip_driver))
445 printk(KERN_ERR "Unable to register simple GPIO driver\n"); 363 printk(KERN_ERR "Unable to register simple GPIO driver\n");
446 364
447 if (of_register_platform_driver(&mpc52xx_gpt_gpiochip_driver))
448 printk(KERN_ERR "Unable to register gpt GPIO driver\n");
449
450 return 0; 365 return 0;
451} 366}
452 367
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
new file mode 100644
index 000000000000..bfbcd418e690
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -0,0 +1,396 @@
1/*
2 * MPC5200 General Purpose Timer device driver
3 *
4 * Copyright (c) 2009 Secret Lab Technologies Ltd.
5 * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * This file is a driver for the the General Purpose Timer (gpt) devices
13 * found on the MPC5200 SoC. Each timer has an IO pin which can be used
14 * for GPIO or can be used to raise interrupts. The timer function can
15 * be used independently from the IO pin, or it can be used to control
16 * output signals or measure input signals.
17 *
18 * This driver supports the GPIO and IRQ controller functions of the GPT
19 * device. Timer functions are not yet supported, nor is the watchdog
20 * timer.
21 *
22 * To use the GPIO function, the following two properties must be added
23 * to the device tree node for the gpt device (typically in the .dts file
24 * for the board):
25 * gpio-controller;
26 * #gpio-cells = < 2 >;
27 * This driver will register the GPIO pin if it finds the gpio-controller
28 * property in the device tree.
29 *
30 * To use the IRQ controller function, the following two properties must
31 * be added to the device tree node for the gpt device:
32 * interrupt-controller;
33 * #interrupt-cells = < 1 >;
34 * The IRQ controller binding only uses one cell to specify the interrupt,
35 * and the IRQ flags are encoded in the cell. A cell is not used to encode
36 * the IRQ number because the GPT only has a single IRQ source. For flags,
37 * a value of '1' means rising edge sensitive and '2' means falling edge.
38 *
39 * The GPIO and the IRQ controller functions can be used at the same time,
40 * but in this use case the IO line will only work as an input. Trying to
41 * use it as a GPIO output will not work.
42 *
43 * When using the GPIO line as an output, it can either be driven as normal
44 * IO, or it can be an Open Collector (OC) output. At the moment it is the
45 * responsibility of either the bootloader or the platform setup code to set
46 * the output mode. This driver does not change the output mode setting.
47 */
48
49#include <linux/irq.h>
50#include <linux/interrupt.h>
51#include <linux/io.h>
52#include <linux/of.h>
53#include <linux/of_platform.h>
54#include <linux/of_gpio.h>
55#include <linux/kernel.h>
56#include <asm/mpc52xx.h>
57
58MODULE_DESCRIPTION("Freescale MPC52xx gpt driver");
59MODULE_AUTHOR("Sascha Hauer, Grant Likely");
60MODULE_LICENSE("GPL");
61
62/**
63 * struct mpc52xx_gpt - Private data structure for MPC52xx GPT driver
64 * @dev: pointer to device structure
65 * @regs: virtual address of GPT registers
66 * @lock: spinlock to coordinate between different functions.
67 * @of_gc: of_gpio_chip instance structure; used when GPIO is enabled
68 * @irqhost: Pointer to irq_host instance; used when IRQ mode is supported
69 */
70struct mpc52xx_gpt_priv {
71 struct device *dev;
72 struct mpc52xx_gpt __iomem *regs;
73 spinlock_t lock;
74 struct irq_host *irqhost;
75
76#if defined(CONFIG_GPIOLIB)
77 struct of_gpio_chip of_gc;
78#endif
79};
80
81#define MPC52xx_GPT_MODE_MS_MASK (0x07)
82#define MPC52xx_GPT_MODE_MS_IC (0x01)
83#define MPC52xx_GPT_MODE_MS_OC (0x02)
84#define MPC52xx_GPT_MODE_MS_PWM (0x03)
85#define MPC52xx_GPT_MODE_MS_GPIO (0x04)
86
87#define MPC52xx_GPT_MODE_GPIO_MASK (0x30)
88#define MPC52xx_GPT_MODE_GPIO_OUT_LOW (0x20)
89#define MPC52xx_GPT_MODE_GPIO_OUT_HIGH (0x30)
90
91#define MPC52xx_GPT_MODE_IRQ_EN (0x0100)
92
93#define MPC52xx_GPT_MODE_ICT_MASK (0x030000)
94#define MPC52xx_GPT_MODE_ICT_RISING (0x010000)
95#define MPC52xx_GPT_MODE_ICT_FALLING (0x020000)
96#define MPC52xx_GPT_MODE_ICT_TOGGLE (0x030000)
97
98#define MPC52xx_GPT_STATUS_IRQMASK (0x000f)
99
100/* ---------------------------------------------------------------------
101 * Cascaded interrupt controller hooks
102 */
103
104static void mpc52xx_gpt_irq_unmask(unsigned int virq)
105{
106 struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
107 unsigned long flags;
108
109 spin_lock_irqsave(&gpt->lock, flags);
110 setbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_IRQ_EN);
111 spin_unlock_irqrestore(&gpt->lock, flags);
112}
113
114static void mpc52xx_gpt_irq_mask(unsigned int virq)
115{
116 struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
117 unsigned long flags;
118
119 spin_lock_irqsave(&gpt->lock, flags);
120 clrbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_IRQ_EN);
121 spin_unlock_irqrestore(&gpt->lock, flags);
122}
123
124static void mpc52xx_gpt_irq_ack(unsigned int virq)
125{
126 struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
127
128 out_be32(&gpt->regs->status, MPC52xx_GPT_STATUS_IRQMASK);
129}
130
131static int mpc52xx_gpt_irq_set_type(unsigned int virq, unsigned int flow_type)
132{
133 struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
134 unsigned long flags;
135 u32 reg;
136
137 dev_dbg(gpt->dev, "%s: virq=%i type=%x\n", __func__, virq, flow_type);
138
139 spin_lock_irqsave(&gpt->lock, flags);
140 reg = in_be32(&gpt->regs->mode) & ~MPC52xx_GPT_MODE_ICT_MASK;
141 if (flow_type & IRQF_TRIGGER_RISING)
142 reg |= MPC52xx_GPT_MODE_ICT_RISING;
143 if (flow_type & IRQF_TRIGGER_FALLING)
144 reg |= MPC52xx_GPT_MODE_ICT_FALLING;
145 out_be32(&gpt->regs->mode, reg);
146 spin_unlock_irqrestore(&gpt->lock, flags);
147
148 return 0;
149}
150
151static struct irq_chip mpc52xx_gpt_irq_chip = {
152 .typename = "MPC52xx GPT",
153 .unmask = mpc52xx_gpt_irq_unmask,
154 .mask = mpc52xx_gpt_irq_mask,
155 .ack = mpc52xx_gpt_irq_ack,
156 .set_type = mpc52xx_gpt_irq_set_type,
157};
158
159void mpc52xx_gpt_irq_cascade(unsigned int virq, struct irq_desc *desc)
160{
161 struct mpc52xx_gpt_priv *gpt = get_irq_data(virq);
162 int sub_virq;
163 u32 status;
164
165 status = in_be32(&gpt->regs->status) & MPC52xx_GPT_STATUS_IRQMASK;
166 if (status) {
167 sub_virq = irq_linear_revmap(gpt->irqhost, 0);
168 generic_handle_irq(sub_virq);
169 }
170}
171
172static int mpc52xx_gpt_irq_map(struct irq_host *h, unsigned int virq,
173 irq_hw_number_t hw)
174{
175 struct mpc52xx_gpt_priv *gpt = h->host_data;
176
177 dev_dbg(gpt->dev, "%s: h=%p, virq=%i\n", __func__, h, virq);
178 set_irq_chip_data(virq, gpt);
179 set_irq_chip_and_handler(virq, &mpc52xx_gpt_irq_chip, handle_edge_irq);
180
181 return 0;
182}
183
184static int mpc52xx_gpt_irq_xlate(struct irq_host *h, struct device_node *ct,
185 u32 *intspec, unsigned int intsize,
186 irq_hw_number_t *out_hwirq,
187 unsigned int *out_flags)
188{
189 struct mpc52xx_gpt_priv *gpt = h->host_data;
190
191 dev_dbg(gpt->dev, "%s: flags=%i\n", __func__, intspec[0]);
192
193 if ((intsize < 1) || (intspec[0] < 1) || (intspec[0] > 3)) {
194 dev_err(gpt->dev, "bad irq specifier in %s\n", ct->full_name);
195 return -EINVAL;
196 }
197
198 *out_hwirq = 0; /* The GPT only has 1 IRQ line */
199 *out_flags = intspec[0];
200
201 return 0;
202}
203
204static struct irq_host_ops mpc52xx_gpt_irq_ops = {
205 .map = mpc52xx_gpt_irq_map,
206 .xlate = mpc52xx_gpt_irq_xlate,
207};
208
209static void
210mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node)
211{
212 int cascade_virq;
213 unsigned long flags;
214
215 /* Only setup cascaded IRQ if device tree claims the GPT is
216 * an interrupt controller */
217 if (!of_find_property(node, "interrupt-controller", NULL))
218 return;
219
220 cascade_virq = irq_of_parse_and_map(node, 0);
221
222 gpt->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, 1,
223 &mpc52xx_gpt_irq_ops, -1);
224 if (!gpt->irqhost) {
225 dev_err(gpt->dev, "irq_alloc_host() failed\n");
226 return;
227 }
228
229 gpt->irqhost->host_data = gpt;
230
231 set_irq_data(cascade_virq, gpt);
232 set_irq_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade);
233
234 /* Set to Input Capture mode */
235 spin_lock_irqsave(&gpt->lock, flags);
236 clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK,
237 MPC52xx_GPT_MODE_MS_IC);
238 spin_unlock_irqrestore(&gpt->lock, flags);
239
240 dev_dbg(gpt->dev, "%s() complete. virq=%i\n", __func__, cascade_virq);
241}
242
243
244/* ---------------------------------------------------------------------
245 * GPIOLIB hooks
246 */
247#if defined(CONFIG_GPIOLIB)
248static inline struct mpc52xx_gpt_priv *gc_to_mpc52xx_gpt(struct gpio_chip *gc)
249{
250 return container_of(to_of_gpio_chip(gc), struct mpc52xx_gpt_priv,of_gc);
251}
252
253static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio)
254{
255 struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc);
256
257 return (in_be32(&gpt->regs->status) >> 8) & 1;
258}
259
260static void
261mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v)
262{
263 struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc);
264 unsigned long flags;
265 u32 r;
266
267 dev_dbg(gpt->dev, "%s: gpio:%d v:%d\n", __func__, gpio, v);
268 r = v ? MPC52xx_GPT_MODE_GPIO_OUT_HIGH : MPC52xx_GPT_MODE_GPIO_OUT_LOW;
269
270 spin_lock_irqsave(&gpt->lock, flags);
271 clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_GPIO_MASK, r);
272 spin_unlock_irqrestore(&gpt->lock, flags);
273}
274
275static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
276{
277 struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc);
278 unsigned long flags;
279
280 dev_dbg(gpt->dev, "%s: gpio:%d\n", __func__, gpio);
281
282 spin_lock_irqsave(&gpt->lock, flags);
283 clrbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_GPIO_MASK);
284 spin_unlock_irqrestore(&gpt->lock, flags);
285
286 return 0;
287}
288
289static int
290mpc52xx_gpt_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
291{
292 mpc52xx_gpt_gpio_set(gc, gpio, val);
293 return 0;
294}
295
296static void
297mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node)
298{
299 int rc;
300
301 /* Only setup GPIO if the device tree claims the GPT is
302 * a GPIO controller */
303 if (!of_find_property(node, "gpio-controller", NULL))
304 return;
305
306 gpt->of_gc.gc.label = kstrdup(node->full_name, GFP_KERNEL);
307 if (!gpt->of_gc.gc.label) {
308 dev_err(gpt->dev, "out of memory\n");
309 return;
310 }
311
312 gpt->of_gc.gpio_cells = 2;
313 gpt->of_gc.gc.ngpio = 1;
314 gpt->of_gc.gc.direction_input = mpc52xx_gpt_gpio_dir_in;
315 gpt->of_gc.gc.direction_output = mpc52xx_gpt_gpio_dir_out;
316 gpt->of_gc.gc.get = mpc52xx_gpt_gpio_get;
317 gpt->of_gc.gc.set = mpc52xx_gpt_gpio_set;
318 gpt->of_gc.gc.base = -1;
319 gpt->of_gc.xlate = of_gpio_simple_xlate;
320 node->data = &gpt->of_gc;
321 of_node_get(node);
322
323 /* Setup external pin in GPIO mode */
324 clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK,
325 MPC52xx_GPT_MODE_MS_GPIO);
326
327 rc = gpiochip_add(&gpt->of_gc.gc);
328 if (rc)
329 dev_err(gpt->dev, "gpiochip_add() failed; rc=%i\n", rc);
330
331 dev_dbg(gpt->dev, "%s() complete.\n", __func__);
332}
333#else /* defined(CONFIG_GPIOLIB) */
334static void
335mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *p, struct device_node *np) { }
336#endif /* defined(CONFIG_GPIOLIB) */
337
338/* ---------------------------------------------------------------------
339 * of_platform bus binding code
340 */
341static int __devinit mpc52xx_gpt_probe(struct of_device *ofdev,
342 const struct of_device_id *match)
343{
344 struct mpc52xx_gpt_priv *gpt;
345
346 gpt = kzalloc(sizeof *gpt, GFP_KERNEL);
347 if (!gpt)
348 return -ENOMEM;
349
350 spin_lock_init(&gpt->lock);
351 gpt->dev = &ofdev->dev;
352 gpt->regs = of_iomap(ofdev->node, 0);
353 if (!gpt->regs) {
354 kfree(gpt);
355 return -ENOMEM;
356 }
357
358 dev_set_drvdata(&ofdev->dev, gpt);
359
360 mpc52xx_gpt_gpio_setup(gpt, ofdev->node);
361 mpc52xx_gpt_irq_setup(gpt, ofdev->node);
362
363 return 0;
364}
365
366static int mpc52xx_gpt_remove(struct of_device *ofdev)
367{
368 return -EBUSY;
369}
370
371static const struct of_device_id mpc52xx_gpt_match[] = {
372 { .compatible = "fsl,mpc5200-gpt", },
373
374 /* Depreciated compatible values; don't use for new dts files */
375 { .compatible = "fsl,mpc5200-gpt-gpio", },
376 { .compatible = "mpc5200-gpt", },
377 {}
378};
379
380static struct of_platform_driver mpc52xx_gpt_driver = {
381 .name = "mpc52xx-gpt",
382 .match_table = mpc52xx_gpt_match,
383 .probe = mpc52xx_gpt_probe,
384 .remove = mpc52xx_gpt_remove,
385};
386
387static int __init mpc52xx_gpt_init(void)
388{
389 if (of_register_platform_driver(&mpc52xx_gpt_driver))
390 pr_err("error registering MPC52xx GPT driver\n");
391
392 return 0;
393}
394
395/* Make sure GPIOs and IRQs get set up before anyone tries to use them */
396subsys_initcall(mpc52xx_gpt_init);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 0a093f03c758..480f806fd0a9 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -163,8 +163,6 @@ static void mpc52xx_extirq_mask(unsigned int virq)
163 irq = irq_map[virq].hwirq; 163 irq = irq_map[virq].hwirq;
164 l2irq = irq & MPC52xx_IRQ_L2_MASK; 164 l2irq = irq & MPC52xx_IRQ_L2_MASK;
165 165
166 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
167
168 io_be_clrbit(&intr->ctrl, 11 - l2irq); 166 io_be_clrbit(&intr->ctrl, 11 - l2irq);
169} 167}
170 168
@@ -176,8 +174,6 @@ static void mpc52xx_extirq_unmask(unsigned int virq)
176 irq = irq_map[virq].hwirq; 174 irq = irq_map[virq].hwirq;
177 l2irq = irq & MPC52xx_IRQ_L2_MASK; 175 l2irq = irq & MPC52xx_IRQ_L2_MASK;
178 176
179 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
180
181 io_be_setbit(&intr->ctrl, 11 - l2irq); 177 io_be_setbit(&intr->ctrl, 11 - l2irq);
182} 178}
183 179
@@ -189,17 +185,15 @@ static void mpc52xx_extirq_ack(unsigned int virq)
189 irq = irq_map[virq].hwirq; 185 irq = irq_map[virq].hwirq;
190 l2irq = irq & MPC52xx_IRQ_L2_MASK; 186 l2irq = irq & MPC52xx_IRQ_L2_MASK;
191 187
192 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
193
194 io_be_setbit(&intr->ctrl, 27-l2irq); 188 io_be_setbit(&intr->ctrl, 27-l2irq);
195} 189}
196 190
197static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type) 191static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
198{ 192{
199 struct irq_desc *desc = get_irq_desc(virq);
200 u32 ctrl_reg, type; 193 u32 ctrl_reg, type;
201 int irq; 194 int irq;
202 int l2irq; 195 int l2irq;
196 void *handler = handle_level_irq;
203 197
204 irq = irq_map[virq].hwirq; 198 irq = irq_map[virq].hwirq;
205 l2irq = irq & MPC52xx_IRQ_L2_MASK; 199 l2irq = irq & MPC52xx_IRQ_L2_MASK;
@@ -207,32 +201,21 @@ static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
207 pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type); 201 pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
208 202
209 switch (flow_type) { 203 switch (flow_type) {
210 case IRQF_TRIGGER_HIGH: 204 case IRQF_TRIGGER_HIGH: type = 0; break;
211 type = 0; 205 case IRQF_TRIGGER_RISING: type = 1; handler = handle_edge_irq; break;
212 break; 206 case IRQF_TRIGGER_FALLING: type = 2; handler = handle_edge_irq; break;
213 case IRQF_TRIGGER_RISING: 207 case IRQF_TRIGGER_LOW: type = 3; break;
214 type = 1;
215 break;
216 case IRQF_TRIGGER_FALLING:
217 type = 2;
218 break;
219 case IRQF_TRIGGER_LOW:
220 type = 3;
221 break;
222 default: 208 default:
223 type = 0; 209 type = 0;
224 } 210 }
225 211
226 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
227 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
228 if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
229 desc->status |= IRQ_LEVEL;
230
231 ctrl_reg = in_be32(&intr->ctrl); 212 ctrl_reg = in_be32(&intr->ctrl);
232 ctrl_reg &= ~(0x3 << (22 - (l2irq * 2))); 213 ctrl_reg &= ~(0x3 << (22 - (l2irq * 2)));
233 ctrl_reg |= (type << (22 - (l2irq * 2))); 214 ctrl_reg |= (type << (22 - (l2irq * 2)));
234 out_be32(&intr->ctrl, ctrl_reg); 215 out_be32(&intr->ctrl, ctrl_reg);
235 216
217 __set_irq_handler_unlocked(virq, handler);
218
236 return 0; 219 return 0;
237} 220}
238 221
@@ -247,6 +230,11 @@ static struct irq_chip mpc52xx_extirq_irqchip = {
247/* 230/*
248 * Main interrupt irq_chip 231 * Main interrupt irq_chip
249 */ 232 */
233static int mpc52xx_null_set_type(unsigned int virq, unsigned int flow_type)
234{
235 return 0; /* Do nothing so that the sense mask will get updated */
236}
237
250static void mpc52xx_main_mask(unsigned int virq) 238static void mpc52xx_main_mask(unsigned int virq)
251{ 239{
252 int irq; 240 int irq;
@@ -255,8 +243,6 @@ static void mpc52xx_main_mask(unsigned int virq)
255 irq = irq_map[virq].hwirq; 243 irq = irq_map[virq].hwirq;
256 l2irq = irq & MPC52xx_IRQ_L2_MASK; 244 l2irq = irq & MPC52xx_IRQ_L2_MASK;
257 245
258 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
259
260 io_be_setbit(&intr->main_mask, 16 - l2irq); 246 io_be_setbit(&intr->main_mask, 16 - l2irq);
261} 247}
262 248
@@ -268,8 +254,6 @@ static void mpc52xx_main_unmask(unsigned int virq)
268 irq = irq_map[virq].hwirq; 254 irq = irq_map[virq].hwirq;
269 l2irq = irq & MPC52xx_IRQ_L2_MASK; 255 l2irq = irq & MPC52xx_IRQ_L2_MASK;
270 256
271 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
272
273 io_be_clrbit(&intr->main_mask, 16 - l2irq); 257 io_be_clrbit(&intr->main_mask, 16 - l2irq);
274} 258}
275 259
@@ -278,6 +262,7 @@ static struct irq_chip mpc52xx_main_irqchip = {
278 .mask = mpc52xx_main_mask, 262 .mask = mpc52xx_main_mask,
279 .mask_ack = mpc52xx_main_mask, 263 .mask_ack = mpc52xx_main_mask,
280 .unmask = mpc52xx_main_unmask, 264 .unmask = mpc52xx_main_unmask,
265 .set_type = mpc52xx_null_set_type,
281}; 266};
282 267
283/* 268/*
@@ -291,8 +276,6 @@ static void mpc52xx_periph_mask(unsigned int virq)
291 irq = irq_map[virq].hwirq; 276 irq = irq_map[virq].hwirq;
292 l2irq = irq & MPC52xx_IRQ_L2_MASK; 277 l2irq = irq & MPC52xx_IRQ_L2_MASK;
293 278
294 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
295
296 io_be_setbit(&intr->per_mask, 31 - l2irq); 279 io_be_setbit(&intr->per_mask, 31 - l2irq);
297} 280}
298 281
@@ -304,8 +287,6 @@ static void mpc52xx_periph_unmask(unsigned int virq)
304 irq = irq_map[virq].hwirq; 287 irq = irq_map[virq].hwirq;
305 l2irq = irq & MPC52xx_IRQ_L2_MASK; 288 l2irq = irq & MPC52xx_IRQ_L2_MASK;
306 289
307 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
308
309 io_be_clrbit(&intr->per_mask, 31 - l2irq); 290 io_be_clrbit(&intr->per_mask, 31 - l2irq);
310} 291}
311 292
@@ -314,6 +295,7 @@ static struct irq_chip mpc52xx_periph_irqchip = {
314 .mask = mpc52xx_periph_mask, 295 .mask = mpc52xx_periph_mask,
315 .mask_ack = mpc52xx_periph_mask, 296 .mask_ack = mpc52xx_periph_mask,
316 .unmask = mpc52xx_periph_unmask, 297 .unmask = mpc52xx_periph_unmask,
298 .set_type = mpc52xx_null_set_type,
317}; 299};
318 300
319/* 301/*
@@ -327,8 +309,6 @@ static void mpc52xx_sdma_mask(unsigned int virq)
327 irq = irq_map[virq].hwirq; 309 irq = irq_map[virq].hwirq;
328 l2irq = irq & MPC52xx_IRQ_L2_MASK; 310 l2irq = irq & MPC52xx_IRQ_L2_MASK;
329 311
330 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
331
332 io_be_setbit(&sdma->IntMask, l2irq); 312 io_be_setbit(&sdma->IntMask, l2irq);
333} 313}
334 314
@@ -340,8 +320,6 @@ static void mpc52xx_sdma_unmask(unsigned int virq)
340 irq = irq_map[virq].hwirq; 320 irq = irq_map[virq].hwirq;
341 l2irq = irq & MPC52xx_IRQ_L2_MASK; 321 l2irq = irq & MPC52xx_IRQ_L2_MASK;
342 322
343 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
344
345 io_be_clrbit(&sdma->IntMask, l2irq); 323 io_be_clrbit(&sdma->IntMask, l2irq);
346} 324}
347 325
@@ -353,8 +331,6 @@ static void mpc52xx_sdma_ack(unsigned int virq)
353 irq = irq_map[virq].hwirq; 331 irq = irq_map[virq].hwirq;
354 l2irq = irq & MPC52xx_IRQ_L2_MASK; 332 l2irq = irq & MPC52xx_IRQ_L2_MASK;
355 333
356 pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
357
358 out_be32(&sdma->IntPend, 1 << l2irq); 334 out_be32(&sdma->IntPend, 1 << l2irq);
359} 335}
360 336
@@ -363,9 +339,19 @@ static struct irq_chip mpc52xx_sdma_irqchip = {
363 .mask = mpc52xx_sdma_mask, 339 .mask = mpc52xx_sdma_mask,
364 .unmask = mpc52xx_sdma_unmask, 340 .unmask = mpc52xx_sdma_unmask,
365 .ack = mpc52xx_sdma_ack, 341 .ack = mpc52xx_sdma_ack,
342 .set_type = mpc52xx_null_set_type,
366}; 343};
367 344
368/** 345/**
346 * mpc52xx_is_extirq - Returns true if hwirq number is for an external IRQ
347 */
348static int mpc52xx_is_extirq(int l1, int l2)
349{
350 return ((l1 == 0) && (l2 == 0)) ||
351 ((l1 == 1) && (l2 >= 1) && (l2 <= 3));
352}
353
354/**
369 * mpc52xx_irqhost_xlate - translate virq# from device tree interrupts property 355 * mpc52xx_irqhost_xlate - translate virq# from device tree interrupts property
370 */ 356 */
371static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, 357static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
@@ -383,38 +369,23 @@ static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
383 369
384 intrvect_l1 = (int)intspec[0]; 370 intrvect_l1 = (int)intspec[0];
385 intrvect_l2 = (int)intspec[1]; 371 intrvect_l2 = (int)intspec[1];
386 intrvect_type = (int)intspec[2]; 372 intrvect_type = (int)intspec[2] & 0x3;
387 373
388 intrvect_linux = (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & 374 intrvect_linux = (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) &
389 MPC52xx_IRQ_L1_MASK; 375 MPC52xx_IRQ_L1_MASK;
390 intrvect_linux |= intrvect_l2 & MPC52xx_IRQ_L2_MASK; 376 intrvect_linux |= intrvect_l2 & MPC52xx_IRQ_L2_MASK;
391 377
392 pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
393 intrvect_l2);
394
395 *out_hwirq = intrvect_linux; 378 *out_hwirq = intrvect_linux;
396 *out_flags = mpc52xx_map_senses[intrvect_type]; 379 *out_flags = IRQ_TYPE_LEVEL_LOW;
380 if (mpc52xx_is_extirq(intrvect_l1, intrvect_l2))
381 *out_flags = mpc52xx_map_senses[intrvect_type];
397 382
383 pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
384 intrvect_l2);
398 return 0; 385 return 0;
399} 386}
400 387
401/** 388/**
402 * mpc52xx_irqx_gettype - determine the IRQ sense type (level/edge)
403 *
404 * Only external IRQs need this.
405 */
406static int mpc52xx_irqx_gettype(int irq)
407{
408 int type;
409 u32 ctrl_reg;
410
411 ctrl_reg = in_be32(&intr->ctrl);
412 type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
413
414 return mpc52xx_map_senses[type];
415}
416
417/**
418 * mpc52xx_irqhost_map - Hook to map from virq to an irq_chip structure 389 * mpc52xx_irqhost_map - Hook to map from virq to an irq_chip structure
419 */ 390 */
420static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, 391static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
@@ -422,68 +393,46 @@ static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
422{ 393{
423 int l1irq; 394 int l1irq;
424 int l2irq; 395 int l2irq;
425 struct irq_chip *good_irqchip; 396 struct irq_chip *irqchip;
426 void *good_handle; 397 void *hndlr;
427 int type; 398 int type;
399 u32 reg;
428 400
429 l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET; 401 l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
430 l2irq = irq & MPC52xx_IRQ_L2_MASK; 402 l2irq = irq & MPC52xx_IRQ_L2_MASK;
431 403
432 /* 404 /*
433 * Most of ours IRQs will be level low 405 * External IRQs are handled differently by the hardware so they are
434 * Only external IRQs on some platform may be others 406 * handled by a dedicated irq_chip structure.
435 */ 407 */
436 type = IRQ_TYPE_LEVEL_LOW; 408 if (mpc52xx_is_extirq(l1irq, l2irq)) {
409 reg = in_be32(&intr->ctrl);
410 type = mpc52xx_map_senses[(reg >> (22 - l2irq * 2)) & 0x3];
411 if ((type == IRQ_TYPE_EDGE_FALLING) ||
412 (type == IRQ_TYPE_EDGE_RISING))
413 hndlr = handle_edge_irq;
414 else
415 hndlr = handle_level_irq;
416
417 set_irq_chip_and_handler(virq, &mpc52xx_extirq_irqchip, hndlr);
418 pr_debug("%s: External IRQ%i virq=%x, hw=%x. type=%x\n",
419 __func__, l2irq, virq, (int)irq, type);
420 return 0;
421 }
437 422
423 /* It is an internal SOC irq. Choose the correct irq_chip */
438 switch (l1irq) { 424 switch (l1irq) {
439 case MPC52xx_IRQ_L1_CRIT: 425 case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break;
440 pr_debug("%s: Critical. l2=%x\n", __func__, l2irq); 426 case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break;
441 427 case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break;
442 BUG_ON(l2irq != 0);
443
444 type = mpc52xx_irqx_gettype(l2irq);
445 good_irqchip = &mpc52xx_extirq_irqchip;
446 break;
447
448 case MPC52xx_IRQ_L1_MAIN:
449 pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
450
451 if ((l2irq >= 1) && (l2irq <= 3)) {
452 type = mpc52xx_irqx_gettype(l2irq);
453 good_irqchip = &mpc52xx_extirq_irqchip;
454 } else {
455 good_irqchip = &mpc52xx_main_irqchip;
456 }
457 break;
458
459 case MPC52xx_IRQ_L1_PERP:
460 pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
461 good_irqchip = &mpc52xx_periph_irqchip;
462 break;
463
464 case MPC52xx_IRQ_L1_SDMA:
465 pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
466 good_irqchip = &mpc52xx_sdma_irqchip;
467 break;
468
469 default: 428 default:
470 pr_err("%s: invalid virq requested (0x%x)\n", __func__, virq); 429 pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n",
430 __func__, virq, l1irq, l2irq);
471 return -EINVAL; 431 return -EINVAL;
472 } 432 }
473 433
474 switch (type) { 434 set_irq_chip_and_handler(virq, irqchip, handle_level_irq);
475 case IRQ_TYPE_EDGE_FALLING: 435 pr_debug("%s: virq=%x, l1=%i, l2=%i\n", __func__, virq, l1irq, l2irq);
476 case IRQ_TYPE_EDGE_RISING:
477 good_handle = handle_edge_irq;
478 break;
479 default:
480 good_handle = handle_level_irq;
481 }
482
483 set_irq_chip_and_handler(virq, good_irqchip, good_handle);
484
485 pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
486 (int)irq, type);
487 436
488 return 0; 437 return 0;
489} 438}
@@ -522,6 +471,8 @@ void __init mpc52xx_init_irq(void)
522 panic(__FILE__ ": find_and_map failed on 'mpc5200-bestcomm'. " 471 panic(__FILE__ ": find_and_map failed on 'mpc5200-bestcomm'. "
523 "Check node !"); 472 "Check node !");
524 473
474 pr_debug("MPC5200 IRQ controller mapped to 0x%p\n", intr);
475
525 /* Disable all interrupt sources. */ 476 /* Disable all interrupt sources. */
526 out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ 477 out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
527 out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */ 478 out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
@@ -613,8 +564,5 @@ unsigned int mpc52xx_get_irq(void)
613 } 564 }
614 } 565 }
615 566
616 pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
617 irq_linear_revmap(mpc52xx_irqhost, irq));
618
619 return irq_linear_revmap(mpc52xx_irqhost, irq); 567 return irq_linear_revmap(mpc52xx_irqhost, irq);
620} 568}
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index 30f008b2f92e..7c7df4003820 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -1,6 +1,6 @@
1menuconfig PPC_82xx 1menuconfig PPC_82xx
2 bool "82xx-based boards (PQ II)" 2 bool "82xx-based boards (PQ II)"
3 depends on 6xx && PPC_MULTIPLATFORM 3 depends on 6xx
4 4
5if PPC_82xx 5if PPC_82xx
6 6
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 83c664afc897..437d29a59d72 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -1,6 +1,6 @@
1menuconfig PPC_83xx 1menuconfig PPC_83xx
2 bool "83xx-based boards" 2 bool "83xx-based boards"
3 depends on 6xx && PPC_MULTIPLATFORM 3 depends on 6xx
4 select PPC_UDBG_16550 4 select PPC_UDBG_16550
5 select PPC_PCI_CHOICE 5 select PPC_PCI_CHOICE
6 select FSL_PCI if PCI 6 select FSL_PCI if PCI
diff --git a/arch/powerpc/platforms/83xx/asp834x.c b/arch/powerpc/platforms/83xx/asp834x.c
index bb30d67ad0a2..aa0d84d22585 100644
--- a/arch/powerpc/platforms/83xx/asp834x.c
+++ b/arch/powerpc/platforms/83xx/asp834x.c
@@ -58,6 +58,7 @@ static struct __initdata of_device_id asp8347_ids[] = {
58 { .type = "soc", }, 58 { .type = "soc", },
59 { .compatible = "soc", }, 59 { .compatible = "soc", },
60 { .compatible = "simple-bus", }, 60 { .compatible = "simple-bus", },
61 { .compatible = "gianfar", },
61 {}, 62 {},
62}; 63};
63 64
diff --git a/arch/powerpc/platforms/83xx/mpc831x_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
index 91a2c80b9d72..0b4f883b20eb 100644
--- a/arch/powerpc/platforms/83xx/mpc831x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
@@ -38,6 +38,8 @@ static void __init mpc831x_rdb_setup_arch(void)
38#ifdef CONFIG_PCI 38#ifdef CONFIG_PCI
39 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") 39 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
40 mpc83xx_add_bridge(np); 40 mpc83xx_add_bridge(np);
41 for_each_compatible_node(np, "pci", "fsl,mpc8314-pcie")
42 mpc83xx_add_bridge(np);
41#endif 43#endif
42 mpc831x_usb_cfg(); 44 mpc831x_usb_cfg();
43} 45}
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index 2a1295f19832..567ded7c3b9b 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -20,6 +20,7 @@
20#include <linux/spi/mmc_spi.h> 20#include <linux/spi/mmc_spi.h>
21#include <linux/mmc/host.h> 21#include <linux/mmc/host.h>
22#include <linux/of_platform.h> 22#include <linux/of_platform.h>
23#include <linux/fsl_devices.h>
23 24
24#include <asm/time.h> 25#include <asm/time.h>
25#include <asm/ipic.h> 26#include <asm/ipic.h>
@@ -39,16 +40,116 @@
39#endif 40#endif
40 41
41#ifdef CONFIG_QUICC_ENGINE 42#ifdef CONFIG_QUICC_ENGINE
42static void mpc83xx_spi_activate_cs(u8 cs, u8 polarity) 43static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk,
44 struct spi_board_info *board_infos,
45 unsigned int num_board_infos,
46 void (*cs_control)(struct spi_device *dev,
47 bool on))
43{ 48{
44 pr_debug("%s %d %d\n", __func__, cs, polarity); 49 struct device_node *np;
45 par_io_data_set(3, 13, polarity); 50 unsigned int i = 0;
51
52 for_each_compatible_node(np, type, compatible) {
53 int ret;
54 unsigned int j;
55 const void *prop;
56 struct resource res[2];
57 struct platform_device *pdev;
58 struct fsl_spi_platform_data pdata = {
59 .cs_control = cs_control,
60 };
61
62 memset(res, 0, sizeof(res));
63
64 pdata.sysclk = sysclk;
65
66 prop = of_get_property(np, "reg", NULL);
67 if (!prop)
68 goto err;
69 pdata.bus_num = *(u32 *)prop;
70
71 prop = of_get_property(np, "cell-index", NULL);
72 if (prop)
73 i = *(u32 *)prop;
74
75 prop = of_get_property(np, "mode", NULL);
76 if (prop && !strcmp(prop, "cpu-qe"))
77 pdata.qe_mode = 1;
78
79 for (j = 0; j < num_board_infos; j++) {
80 if (board_infos[j].bus_num == pdata.bus_num)
81 pdata.max_chipselect++;
82 }
83
84 if (!pdata.max_chipselect)
85 continue;
86
87 ret = of_address_to_resource(np, 0, &res[0]);
88 if (ret)
89 goto err;
90
91 ret = of_irq_to_resource(np, 0, &res[1]);
92 if (ret == NO_IRQ)
93 goto err;
94
95 pdev = platform_device_alloc("mpc83xx_spi", i);
96 if (!pdev)
97 goto err;
98
99 ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
100 if (ret)
101 goto unreg;
102
103 ret = platform_device_add_resources(pdev, res,
104 ARRAY_SIZE(res));
105 if (ret)
106 goto unreg;
107
108 ret = platform_device_add(pdev);
109 if (ret)
110 goto unreg;
111
112 goto next;
113unreg:
114 platform_device_del(pdev);
115err:
116 pr_err("%s: registration failed\n", np->full_name);
117next:
118 i++;
119 }
120
121 return i;
46} 122}
47 123
48static void mpc83xx_spi_deactivate_cs(u8 cs, u8 polarity) 124static int __init fsl_spi_init(struct spi_board_info *board_infos,
125 unsigned int num_board_infos,
126 void (*cs_control)(struct spi_device *spi,
127 bool on))
49{ 128{
50 pr_debug("%s %d %d\n", __func__, cs, polarity); 129 u32 sysclk = -1;
51 par_io_data_set(3, 13, !polarity); 130 int ret;
131
132 /* SPI controller is either clocked from QE or SoC clock */
133 sysclk = get_brgfreq();
134 if (sysclk == -1) {
135 sysclk = fsl_get_sys_freq();
136 if (sysclk == -1)
137 return -ENODEV;
138 }
139
140 ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos,
141 num_board_infos, cs_control);
142 if (!ret)
143 of_fsl_spi_probe("spi", "fsl_spi", sysclk, board_infos,
144 num_board_infos, cs_control);
145
146 return spi_register_board_info(board_infos, num_board_infos);
147}
148
149static void mpc83xx_spi_cs_control(struct spi_device *spi, bool on)
150{
151 pr_debug("%s %d %d\n", __func__, spi->chip_select, on);
152 par_io_data_set(3, 13, on);
52} 153}
53 154
54static struct mmc_spi_platform_data mpc832x_mmc_pdata = { 155static struct mmc_spi_platform_data mpc832x_mmc_pdata = {
@@ -74,9 +175,13 @@ static int __init mpc832x_spi_init(void)
74 par_io_config_pin(3, 14, 2, 0, 0, 0); /* SD_INSERT, I */ 175 par_io_config_pin(3, 14, 2, 0, 0, 0); /* SD_INSERT, I */
75 par_io_config_pin(3, 15, 2, 0, 0, 0); /* SD_PROTECT,I */ 176 par_io_config_pin(3, 15, 2, 0, 0, 0); /* SD_PROTECT,I */
76 177
77 return fsl_spi_init(&mpc832x_spi_boardinfo, 1, 178 /*
78 mpc83xx_spi_activate_cs, 179 * Don't bother with legacy stuff when device tree contains
79 mpc83xx_spi_deactivate_cs); 180 * mmc-spi-slot node.
181 */
182 if (of_find_compatible_node(NULL, NULL, "mmc-spi-slot"))
183 return 0;
184 return fsl_spi_init(&mpc832x_spi_boardinfo, 1, mpc83xx_spi_cs_control);
80} 185}
81machine_device_initcall(mpc832x_rdb, mpc832x_spi_init); 186machine_device_initcall(mpc832x_rdb, mpc832x_spi_init);
82#endif /* CONFIG_QUICC_ENGINE */ 187#endif /* CONFIG_QUICC_ENGINE */
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 76092d37c7d9..81e44fa1c644 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -42,6 +42,7 @@
42static struct of_device_id __initdata mpc834x_itx_ids[] = { 42static struct of_device_id __initdata mpc834x_itx_ids[] = {
43 { .compatible = "fsl,pq2pro-localbus", }, 43 { .compatible = "fsl,pq2pro-localbus", },
44 { .compatible = "simple-bus", }, 44 { .compatible = "simple-bus", },
45 { .compatible = "gianfar", },
45 {}, 46 {},
46}; 47};
47 48
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index fc3f2ed1f3e9..d0a634b056ca 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -112,6 +112,7 @@ static struct of_device_id mpc834x_ids[] = {
112 { .type = "soc", }, 112 { .type = "soc", },
113 { .compatible = "soc", }, 113 { .compatible = "soc", },
114 { .compatible = "simple-bus", }, 114 { .compatible = "simple-bus", },
115 { .compatible = "gianfar", },
115 {}, 116 {},
116}; 117};
117 118
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index 530ef990ca7c..51df7e754698 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -84,14 +84,10 @@ static void __init mpc837x_mds_setup_arch(void)
84 ppc_md.progress("mpc837x_mds_setup_arch()", 0); 84 ppc_md.progress("mpc837x_mds_setup_arch()", 0);
85 85
86#ifdef CONFIG_PCI 86#ifdef CONFIG_PCI
87 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") { 87 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
88 if (!of_device_is_available(np)) { 88 mpc83xx_add_bridge(np);
89 pr_warning("%s: disabled by the firmware.\n", 89 for_each_compatible_node(np, "pci", "fsl,mpc8314-pcie")
90 np->full_name);
91 continue;
92 }
93 mpc83xx_add_bridge(np); 90 mpc83xx_add_bridge(np);
94 }
95#endif 91#endif
96 mpc837xmds_usb_cfg(); 92 mpc837xmds_usb_cfg();
97} 93}
@@ -100,6 +96,7 @@ static struct of_device_id mpc837x_ids[] = {
100 { .type = "soc", }, 96 { .type = "soc", },
101 { .compatible = "soc", }, 97 { .compatible = "soc", },
102 { .compatible = "simple-bus", }, 98 { .compatible = "simple-bus", },
99 { .compatible = "gianfar", },
103 {}, 100 {},
104}; 101};
105 102
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
index 1d096545322b..76f3b32a155e 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
@@ -38,6 +38,8 @@ static void __init mpc837x_rdb_setup_arch(void)
38#ifdef CONFIG_PCI 38#ifdef CONFIG_PCI
39 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") 39 for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
40 mpc83xx_add_bridge(np); 40 mpc83xx_add_bridge(np);
41 for_each_compatible_node(np, "pci", "fsl,mpc8314-pcie")
42 mpc83xx_add_bridge(np);
41#endif 43#endif
42 mpc837x_usb_cfg(); 44 mpc837x_usb_cfg();
43} 45}
@@ -46,6 +48,7 @@ static struct of_device_id mpc837x_ids[] = {
46 { .type = "soc", }, 48 { .type = "soc", },
47 { .compatible = "soc", }, 49 { .compatible = "soc", },
48 { .compatible = "simple-bus", }, 50 { .compatible = "simple-bus", },
51 { .compatible = "gianfar", },
49 {}, 52 {},
50}; 53};
51 54
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c
index 156c4e218009..49023dbe1576 100644
--- a/arch/powerpc/platforms/83xx/sbc834x.c
+++ b/arch/powerpc/platforms/83xx/sbc834x.c
@@ -84,6 +84,7 @@ static struct __initdata of_device_id sbc834x_ids[] = {
84 { .type = "soc", }, 84 { .type = "soc", },
85 { .compatible = "soc", }, 85 { .compatible = "soc", },
86 { .compatible = "simple-bus", }, 86 { .compatible = "simple-bus", },
87 { .compatible = "gianfar", },
87 {}, 88 {},
88}; 89};
89 90
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
index cc99c280aad9..11e1fac17c7f 100644
--- a/arch/powerpc/platforms/83xx/usb.c
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -14,6 +14,7 @@
14#include <linux/stddef.h> 14#include <linux/stddef.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/errno.h> 16#include <linux/errno.h>
17#include <linux/of.h>
17 18
18#include <asm/io.h> 19#include <asm/io.h>
19#include <asm/prom.h> 20#include <asm/prom.h>
@@ -210,7 +211,7 @@ int mpc837x_usb_cfg(void)
210 int ret = 0; 211 int ret = 0;
211 212
212 np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr"); 213 np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
213 if (!np) 214 if (!np || !of_device_is_available(np))
214 return -ENODEV; 215 return -ENODEV;
215 prop = of_get_property(np, "phy_type", NULL); 216 prop = of_get_property(np, "phy_type", NULL);
216 217
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index b79dc710ed34..7f066adc068c 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -51,6 +51,12 @@ config MPC85xx_DS
51 help 51 help
52 This option enables support for the MPC85xx DS (MPC8544 DS) board 52 This option enables support for the MPC85xx DS (MPC8544 DS) board
53 53
54config SOCRATES
55 bool "Socrates"
56 select DEFAULT_UIMAGE
57 help
58 This option enables support for the Socrates board.
59
54config KSI8560 60config KSI8560
55 bool "Emerson KSI8560" 61 bool "Emerson KSI8560"
56 select DEFAULT_UIMAGE 62 select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index f0798c09980f..a857b35b9828 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -13,4 +13,5 @@ obj-$(CONFIG_STX_GP3) += stx_gp3.o
13obj-$(CONFIG_TQM85xx) += tqm85xx.o 13obj-$(CONFIG_TQM85xx) += tqm85xx.o
14obj-$(CONFIG_SBC8560) += sbc8560.o 14obj-$(CONFIG_SBC8560) += sbc8560.o
15obj-$(CONFIG_SBC8548) += sbc8548.o 15obj-$(CONFIG_SBC8548) += sbc8548.o
16obj-$(CONFIG_SOCRATES) += socrates.o socrates_fpga_pic.o
16obj-$(CONFIG_KSI8560) += ksi8560.o 17obj-$(CONFIG_KSI8560) += ksi8560.o
diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c
index 81cee7bbf2d2..f4d36b5a2e00 100644
--- a/arch/powerpc/platforms/85xx/ksi8560.c
+++ b/arch/powerpc/platforms/85xx/ksi8560.c
@@ -106,8 +106,6 @@ static void __init ksi8560_pic_init(void)
106 cpm2_pic_init(np); 106 cpm2_pic_init(np);
107 of_node_put(np); 107 of_node_put(np);
108 set_irq_chained_handler(irq, cpm2_cascade); 108 set_irq_chained_handler(irq, cpm2_cascade);
109
110 setup_irq(0, NULL);
111#endif 109#endif
112} 110}
113 111
@@ -221,6 +219,7 @@ static struct of_device_id __initdata of_bus_ids[] = {
221 { .type = "simple-bus", }, 219 { .type = "simple-bus", },
222 { .name = "cpm", }, 220 { .name = "cpm", },
223 { .name = "localbus", }, 221 { .name = "localbus", },
222 { .compatible = "gianfar", },
224 {}, 223 {},
225}; 224};
226 225
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index 1bf5aefdfeb1..63efca20d7bd 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -92,6 +92,7 @@ static struct of_device_id __initdata mpc8536_ds_ids[] = {
92 { .type = "soc", }, 92 { .type = "soc", },
93 { .compatible = "soc", }, 93 { .compatible = "soc", },
94 { .compatible = "simple-bus", }, 94 { .compatible = "simple-bus", },
95 { .compatible = "gianfar", },
95 {}, 96 {},
96}; 97};
97 98
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 21f009023e26..9438a892afc4 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -226,6 +226,7 @@ static struct of_device_id __initdata of_bus_ids[] = {
226 { .name = "cpm", }, 226 { .name = "cpm", },
227 { .name = "localbus", }, 227 { .name = "localbus", },
228 { .compatible = "simple-bus", }, 228 { .compatible = "simple-bus", },
229 { .compatible = "gianfar", },
229 {}, 230 {},
230}; 231};
231 232
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index aeb6a5bc5522..458d91fba91d 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -179,7 +179,6 @@ static irqreturn_t mpc85xx_8259_cascade_action(int irq, void *dev_id)
179static struct irqaction mpc85xxcds_8259_irqaction = { 179static struct irqaction mpc85xxcds_8259_irqaction = {
180 .handler = mpc85xx_8259_cascade_action, 180 .handler = mpc85xx_8259_cascade_action,
181 .flags = IRQF_SHARED, 181 .flags = IRQF_SHARED,
182 .mask = CPU_MASK_NONE,
183 .name = "8259 cascade", 182 .name = "8259 cascade",
184}; 183};
185#endif /* PPC_I8259 */ 184#endif /* PPC_I8259 */
@@ -336,6 +335,7 @@ static struct of_device_id __initdata of_bus_ids[] = {
336 { .type = "soc", }, 335 { .type = "soc", },
337 { .compatible = "soc", }, 336 { .compatible = "soc", },
338 { .compatible = "simple-bus", }, 337 { .compatible = "simple-bus", },
338 { .compatible = "gianfar", },
339 {}, 339 {},
340}; 340};
341 341
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 7326d904202c..de66de7a9ca2 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -204,6 +204,7 @@ static struct of_device_id __initdata mpc85xxds_ids[] = {
204 { .type = "soc", }, 204 { .type = "soc", },
205 { .compatible = "soc", }, 205 { .compatible = "soc", },
206 { .compatible = "simple-bus", }, 206 { .compatible = "simple-bus", },
207 { .compatible = "gianfar", },
207 {}, 208 {},
208}; 209};
209 210
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 658a36fab3ab..7dd029034aec 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -265,6 +265,7 @@ static struct of_device_id mpc85xx_ids[] = {
265 { .compatible = "simple-bus", }, 265 { .compatible = "simple-bus", },
266 { .type = "qe", }, 266 { .type = "qe", },
267 { .compatible = "fsl,qe", }, 267 { .compatible = "fsl,qe", },
268 { .compatible = "gianfar", },
268 {}, 269 {},
269}; 270};
270 271
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index 7ec77ce12dad..ecdd8c09e4ed 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -154,6 +154,7 @@ static struct of_device_id __initdata of_bus_ids[] = {
154 { .name = "soc", }, 154 { .name = "soc", },
155 { .type = "soc", }, 155 { .type = "soc", },
156 { .compatible = "simple-bus", }, 156 { .compatible = "simple-bus", },
157 { .compatible = "gianfar", },
157 {}, 158 {},
158}; 159};
159 160
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
index 472f254a19d2..cc27807a8b64 100644
--- a/arch/powerpc/platforms/85xx/sbc8560.c
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -213,6 +213,7 @@ static struct of_device_id __initdata of_bus_ids[] = {
213 { .name = "cpm", }, 213 { .name = "cpm", },
214 { .name = "localbus", }, 214 { .name = "localbus", },
215 { .compatible = "simple-bus", }, 215 { .compatible = "simple-bus", },
216 { .compatible = "gianfar", },
216 {}, 217 {},
217}; 218};
218 219
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 79a0df17078b..cc0b0db8a6f3 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -21,6 +21,7 @@
21#include <asm/page.h> 21#include <asm/page.h>
22#include <asm/mpic.h> 22#include <asm/mpic.h>
23#include <asm/cacheflush.h> 23#include <asm/cacheflush.h>
24#include <asm/dbell.h>
24 25
25#include <sysdev/fsl_soc.h> 26#include <sysdev/fsl_soc.h>
26 27
@@ -80,10 +81,8 @@ smp_85xx_kick_cpu(int nr)
80} 81}
81 82
82static void __init 83static void __init
83smp_85xx_setup_cpu(int cpu_nr) 84smp_85xx_basic_setup(int cpu_nr)
84{ 85{
85 mpic_setup_this_cpu();
86
87 /* Clear any pending timer interrupts */ 86 /* Clear any pending timer interrupts */
88 mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); 87 mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
89 88
@@ -91,15 +90,43 @@ smp_85xx_setup_cpu(int cpu_nr)
91 mtspr(SPRN_TCR, TCR_DIE); 90 mtspr(SPRN_TCR, TCR_DIE);
92} 91}
93 92
93static void __init
94smp_85xx_setup_cpu(int cpu_nr)
95{
96 mpic_setup_this_cpu();
97
98 smp_85xx_basic_setup(cpu_nr);
99}
100
94struct smp_ops_t smp_85xx_ops = { 101struct smp_ops_t smp_85xx_ops = {
95 .message_pass = smp_mpic_message_pass,
96 .probe = smp_mpic_probe,
97 .kick_cpu = smp_85xx_kick_cpu, 102 .kick_cpu = smp_85xx_kick_cpu,
98 .setup_cpu = smp_85xx_setup_cpu,
99}; 103};
100 104
101void __init 105static int __init smp_dummy_probe(void)
102mpc85xx_smp_init(void)
103{ 106{
107 return NR_CPUS;
108}
109
110void __init mpc85xx_smp_init(void)
111{
112 struct device_node *np;
113
114 smp_85xx_ops.message_pass = NULL;
115
116 np = of_find_node_by_type(NULL, "open-pic");
117 if (np) {
118 smp_85xx_ops.probe = smp_mpic_probe;
119 smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
120 smp_85xx_ops.message_pass = smp_mpic_message_pass;
121 } else {
122 smp_85xx_ops.probe = smp_dummy_probe;
123 smp_85xx_ops.setup_cpu = smp_85xx_basic_setup;
124 }
125
126 if (cpu_has_feature(CPU_FTR_DBELL))
127 smp_85xx_ops.message_pass = smp_dbell_message_pass;
128
129 BUG_ON(!smp_85xx_ops.message_pass);
130
104 smp_ops = &smp_85xx_ops; 131 smp_ops = &smp_85xx_ops;
105} 132}
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c
new file mode 100644
index 000000000000..d0e8443b12c6
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/socrates.c
@@ -0,0 +1,133 @@
1/*
2 * Copyright (c) 2008 Emcraft Systems
3 * Sergei Poselenov <sposelenov@emcraft.com>
4 *
5 * Based on MPC8560 ADS and arch/ppc tqm85xx ports
6 *
7 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
8 *
9 * Copyright 2008 Freescale Semiconductor Inc.
10 *
11 * Copyright (c) 2005-2006 DENX Software Engineering
12 * Stefan Roese <sr@denx.de>
13 *
14 * Based on original work by
15 * Kumar Gala <kumar.gala@freescale.com>
16 * Copyright 2004 Freescale Semiconductor Inc.
17 *
18 * This program is free software; you can redistribute it and/or modify it
19 * under the terms of the GNU General Public License as published by the
20 * Free Software Foundation; either version 2 of the License, or (at your
21 * option) any later version.
22 */
23
24#include <linux/stddef.h>
25#include <linux/kernel.h>
26#include <linux/pci.h>
27#include <linux/kdev_t.h>
28#include <linux/delay.h>
29#include <linux/seq_file.h>
30#include <linux/of_platform.h>
31
32#include <asm/system.h>
33#include <asm/time.h>
34#include <asm/machdep.h>
35#include <asm/pci-bridge.h>
36#include <asm/mpic.h>
37#include <asm/prom.h>
38#include <mm/mmu_decl.h>
39#include <asm/udbg.h>
40
41#include <sysdev/fsl_soc.h>
42#include <sysdev/fsl_pci.h>
43
44#include "socrates_fpga_pic.h"
45
46static void __init socrates_pic_init(void)
47{
48 struct mpic *mpic;
49 struct resource r;
50 struct device_node *np;
51
52 np = of_find_node_by_type(NULL, "open-pic");
53 if (!np) {
54 printk(KERN_ERR "Could not find open-pic node\n");
55 return;
56 }
57
58 if (of_address_to_resource(np, 0, &r)) {
59 printk(KERN_ERR "Could not map mpic register space\n");
60 of_node_put(np);
61 return;
62 }
63
64 mpic = mpic_alloc(np, r.start,
65 MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
66 0, 256, " OpenPIC ");
67 BUG_ON(mpic == NULL);
68 of_node_put(np);
69
70 mpic_init(mpic);
71
72 np = of_find_compatible_node(NULL, NULL, "abb,socrates-fpga-pic");
73 if (!np) {
74 printk(KERN_ERR "Could not find socrates-fpga-pic node\n");
75 return;
76 }
77 socrates_fpga_pic_init(np);
78 of_node_put(np);
79}
80
81/*
82 * Setup the architecture
83 */
84static void __init socrates_setup_arch(void)
85{
86#ifdef CONFIG_PCI
87 struct device_node *np;
88#endif
89
90 if (ppc_md.progress)
91 ppc_md.progress("socrates_setup_arch()", 0);
92
93#ifdef CONFIG_PCI
94 for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
95 fsl_add_bridge(np, 1);
96#endif
97}
98
99static struct of_device_id __initdata socrates_of_bus_ids[] = {
100 { .compatible = "simple-bus", },
101 { .compatible = "gianfar", },
102 {},
103};
104
105static void __init socrates_init(void)
106{
107 of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL);
108}
109
110/*
111 * Called very early, device-tree isn't unflattened
112 */
113static int __init socrates_probe(void)
114{
115 unsigned long root = of_get_flat_dt_root();
116
117 if (of_flat_dt_is_compatible(root, "abb,socrates"))
118 return 1;
119
120 return 0;
121}
122
123define_machine(socrates) {
124 .name = "Socrates",
125 .probe = socrates_probe,
126 .setup_arch = socrates_setup_arch,
127 .init = socrates_init,
128 .init_IRQ = socrates_pic_init,
129 .get_irq = mpic_get_irq,
130 .restart = fsl_rstcr_restart,
131 .calibrate_decr = generic_calibrate_decr,
132 .progress = udbg_progress,
133};
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
new file mode 100644
index 000000000000..60edf63d0157
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
@@ -0,0 +1,327 @@
1/*
2 * Copyright (C) 2008 Ilya Yanok, Emcraft Systems
3 *
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/irq.h>
12#include <linux/of_platform.h>
13#include <linux/io.h>
14
15/*
16 * The FPGA supports 9 interrupt sources, which can be routed to 3
17 * interrupt request lines of the MPIC. The line to be used can be
18 * specified through the third cell of FDT property "interrupts".
19 */
20
21#define SOCRATES_FPGA_NUM_IRQS 9
22
23#define FPGA_PIC_IRQCFG (0x0)
24#define FPGA_PIC_IRQMASK(n) (0x4 + 0x4 * (n))
25
26#define SOCRATES_FPGA_IRQ_MASK ((1 << SOCRATES_FPGA_NUM_IRQS) - 1)
27
28struct socrates_fpga_irq_info {
29 unsigned int irq_line;
30 int type;
31};
32
33/*
34 * Interrupt routing and type table
35 *
36 * IRQ_TYPE_NONE means the interrupt type is configurable,
37 * otherwise it's fixed to the specified value.
38 */
39static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
40 [0] = {0, IRQ_TYPE_NONE},
41 [1] = {0, IRQ_TYPE_LEVEL_HIGH},
42 [2] = {0, IRQ_TYPE_LEVEL_LOW},
43 [3] = {0, IRQ_TYPE_NONE},
44 [4] = {0, IRQ_TYPE_NONE},
45 [5] = {0, IRQ_TYPE_NONE},
46 [6] = {0, IRQ_TYPE_NONE},
47 [7] = {0, IRQ_TYPE_NONE},
48 [8] = {0, IRQ_TYPE_LEVEL_HIGH},
49};
50
51#define socrates_fpga_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
52
53static DEFINE_SPINLOCK(socrates_fpga_pic_lock);
54
55static void __iomem *socrates_fpga_pic_iobase;
56static struct irq_host *socrates_fpga_pic_irq_host;
57static unsigned int socrates_fpga_irqs[3];
58
59static inline uint32_t socrates_fpga_pic_read(int reg)
60{
61 return in_be32(socrates_fpga_pic_iobase + reg);
62}
63
64static inline void socrates_fpga_pic_write(int reg, uint32_t val)
65{
66 out_be32(socrates_fpga_pic_iobase + reg, val);
67}
68
69static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
70{
71 uint32_t cause;
72 unsigned long flags;
73 int i;
74
75 /* Check irq line routed to the MPIC */
76 for (i = 0; i < 3; i++) {
77 if (irq == socrates_fpga_irqs[i])
78 break;
79 }
80 if (i == 3)
81 return NO_IRQ;
82
83 spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
84 cause = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i));
85 spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
86 for (i = SOCRATES_FPGA_NUM_IRQS - 1; i >= 0; i--) {
87 if (cause >> (i + 16))
88 break;
89 }
90 return irq_linear_revmap(socrates_fpga_pic_irq_host,
91 (irq_hw_number_t)i);
92}
93
94void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
95{
96 unsigned int cascade_irq;
97
98 /*
99 * See if we actually have an interrupt, call generic handling code if
100 * we do.
101 */
102 cascade_irq = socrates_fpga_pic_get_irq(irq);
103
104 if (cascade_irq != NO_IRQ)
105 generic_handle_irq(cascade_irq);
106 desc->chip->eoi(irq);
107
108}
109
110static void socrates_fpga_pic_ack(unsigned int virq)
111{
112 unsigned long flags;
113 unsigned int hwirq, irq_line;
114 uint32_t mask;
115
116 hwirq = socrates_fpga_irq_to_hw(virq);
117
118 irq_line = fpga_irqs[hwirq].irq_line;
119 spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
120 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
121 & SOCRATES_FPGA_IRQ_MASK;
122 mask |= (1 << (hwirq + 16));
123 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
124 spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
125}
126
127static void socrates_fpga_pic_mask(unsigned int virq)
128{
129 unsigned long flags;
130 unsigned int hwirq;
131 int irq_line;
132 u32 mask;
133
134 hwirq = socrates_fpga_irq_to_hw(virq);
135
136 irq_line = fpga_irqs[hwirq].irq_line;
137 spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
138 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
139 & SOCRATES_FPGA_IRQ_MASK;
140 mask &= ~(1 << hwirq);
141 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
142 spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
143}
144
145static void socrates_fpga_pic_mask_ack(unsigned int virq)
146{
147 unsigned long flags;
148 unsigned int hwirq;
149 int irq_line;
150 u32 mask;
151
152 hwirq = socrates_fpga_irq_to_hw(virq);
153
154 irq_line = fpga_irqs[hwirq].irq_line;
155 spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
156 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
157 & SOCRATES_FPGA_IRQ_MASK;
158 mask &= ~(1 << hwirq);
159 mask |= (1 << (hwirq + 16));
160 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
161 spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
162}
163
164static void socrates_fpga_pic_unmask(unsigned int virq)
165{
166 unsigned long flags;
167 unsigned int hwirq;
168 int irq_line;
169 u32 mask;
170
171 hwirq = socrates_fpga_irq_to_hw(virq);
172
173 irq_line = fpga_irqs[hwirq].irq_line;
174 spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
175 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
176 & SOCRATES_FPGA_IRQ_MASK;
177 mask |= (1 << hwirq);
178 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
179 spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
180}
181
182static void socrates_fpga_pic_eoi(unsigned int virq)
183{
184 unsigned long flags;
185 unsigned int hwirq;
186 int irq_line;
187 u32 mask;
188
189 hwirq = socrates_fpga_irq_to_hw(virq);
190
191 irq_line = fpga_irqs[hwirq].irq_line;
192 spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
193 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
194 & SOCRATES_FPGA_IRQ_MASK;
195 mask |= (1 << (hwirq + 16));
196 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
197 spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
198}
199
200static int socrates_fpga_pic_set_type(unsigned int virq,
201 unsigned int flow_type)
202{
203 unsigned long flags;
204 unsigned int hwirq;
205 int polarity;
206 u32 mask;
207
208 hwirq = socrates_fpga_irq_to_hw(virq);
209
210 if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
211 return -EINVAL;
212
213 switch (flow_type & IRQ_TYPE_SENSE_MASK) {
214 case IRQ_TYPE_LEVEL_HIGH:
215 polarity = 1;
216 break;
217 case IRQ_TYPE_LEVEL_LOW:
218 polarity = 0;
219 break;
220 default:
221 return -EINVAL;
222 }
223 spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
224 mask = socrates_fpga_pic_read(FPGA_PIC_IRQCFG);
225 if (polarity)
226 mask |= (1 << hwirq);
227 else
228 mask &= ~(1 << hwirq);
229 socrates_fpga_pic_write(FPGA_PIC_IRQCFG, mask);
230 spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
231 return 0;
232}
233
234static struct irq_chip socrates_fpga_pic_chip = {
235 .typename = " FPGA-PIC ",
236 .ack = socrates_fpga_pic_ack,
237 .mask = socrates_fpga_pic_mask,
238 .mask_ack = socrates_fpga_pic_mask_ack,
239 .unmask = socrates_fpga_pic_unmask,
240 .eoi = socrates_fpga_pic_eoi,
241 .set_type = socrates_fpga_pic_set_type,
242};
243
244static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,
245 irq_hw_number_t hwirq)
246{
247 /* All interrupts are LEVEL sensitive */
248 get_irq_desc(virq)->status |= IRQ_LEVEL;
249 set_irq_chip_and_handler(virq, &socrates_fpga_pic_chip,
250 handle_fasteoi_irq);
251
252 return 0;
253}
254
255static int socrates_fpga_pic_host_xlate(struct irq_host *h,
256 struct device_node *ct, u32 *intspec, unsigned int intsize,
257 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
258{
259 struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]];
260
261 *out_hwirq = intspec[0];
262 if (fpga_irq->type == IRQ_TYPE_NONE) {
263 /* type is configurable */
264 if (intspec[1] != IRQ_TYPE_LEVEL_LOW &&
265 intspec[1] != IRQ_TYPE_LEVEL_HIGH) {
266 pr_warning("FPGA PIC: invalid irq type, "
267 "setting default active low\n");
268 *out_flags = IRQ_TYPE_LEVEL_LOW;
269 } else {
270 *out_flags = intspec[1];
271 }
272 } else {
273 /* type is fixed */
274 *out_flags = fpga_irq->type;
275 }
276
277 /* Use specified interrupt routing */
278 if (intspec[2] <= 2)
279 fpga_irq->irq_line = intspec[2];
280 else
281 pr_warning("FPGA PIC: invalid irq routing\n");
282
283 return 0;
284}
285
286static struct irq_host_ops socrates_fpga_pic_host_ops = {
287 .map = socrates_fpga_pic_host_map,
288 .xlate = socrates_fpga_pic_host_xlate,
289};
290
291void socrates_fpga_pic_init(struct device_node *pic)
292{
293 unsigned long flags;
294 int i;
295
296 /* Setup an irq_host structure */
297 socrates_fpga_pic_irq_host = irq_alloc_host(pic, IRQ_HOST_MAP_LINEAR,
298 SOCRATES_FPGA_NUM_IRQS, &socrates_fpga_pic_host_ops,
299 SOCRATES_FPGA_NUM_IRQS);
300 if (socrates_fpga_pic_irq_host == NULL) {
301 pr_err("FPGA PIC: Unable to allocate host\n");
302 return;
303 }
304
305 for (i = 0; i < 3; i++) {
306 socrates_fpga_irqs[i] = irq_of_parse_and_map(pic, i);
307 if (socrates_fpga_irqs[i] == NO_IRQ) {
308 pr_warning("FPGA PIC: can't get irq%d.\n", i);
309 continue;
310 }
311 set_irq_chained_handler(socrates_fpga_irqs[i],
312 socrates_fpga_pic_cascade);
313 }
314
315 socrates_fpga_pic_iobase = of_iomap(pic, 0);
316
317 spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
318 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0),
319 SOCRATES_FPGA_IRQ_MASK << 16);
320 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1),
321 SOCRATES_FPGA_IRQ_MASK << 16);
322 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2),
323 SOCRATES_FPGA_IRQ_MASK << 16);
324 spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
325
326 pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n");
327}
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.h b/arch/powerpc/platforms/85xx/socrates_fpga_pic.h
new file mode 100644
index 000000000000..21d7d8e42199
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.h
@@ -0,0 +1,16 @@
1/*
2 * Copyright (C) 2008 Ilya Yanok, Emcraft Systems
3 *
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#ifndef SOCRATES_FPGA_PIC_H
12#define SOCRATES_FPGA_PIC_H
13
14void socrates_fpga_pic_init(struct device_node *pic);
15
16#endif
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index 0cca8f5cb272..f559918f3c6f 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -145,6 +145,7 @@ static void stx_gp3_show_cpuinfo(struct seq_file *m)
145 145
146static struct of_device_id __initdata of_bus_ids[] = { 146static struct of_device_id __initdata of_bus_ids[] = {
147 { .compatible = "simple-bus", }, 147 { .compatible = "simple-bus", },
148 { .compatible = "gianfar", },
148 {}, 149 {},
149}; 150};
150 151
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index 2933a8e827d9..5b0ab9966e90 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -153,6 +153,7 @@ static void tqm85xx_show_cpuinfo(struct seq_file *m)
153 153
154static struct of_device_id __initdata of_bus_ids[] = { 154static struct of_device_id __initdata of_bus_ids[] = {
155 { .compatible = "simple-bus", }, 155 { .compatible = "simple-bus", },
156 { .compatible = "gianfar", },
156 {}, 157 {},
157}; 158};
158 159
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 8e5693935975..fdaf4ddaa955 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -1,7 +1,7 @@
1config PPC_86xx 1config PPC_86xx
2menuconfig PPC_86xx 2menuconfig PPC_86xx
3 bool "86xx-based boards" 3 bool "86xx-based boards"
4 depends on 6xx && PPC_MULTIPLATFORM 4 depends on 6xx
5 select FSL_SOC 5 select FSL_SOC
6 select ALTIVEC 6 select ALTIVEC
7 help 7 help
@@ -31,6 +31,22 @@ config MPC8610_HPCD
31 help 31 help
32 This option enables support for the MPC8610 HPCD board. 32 This option enables support for the MPC8610 HPCD board.
33 33
34config GEF_PPC9A
35 bool "GE Fanuc PPC9A"
36 select DEFAULT_UIMAGE
37 select GENERIC_GPIO
38 select ARCH_REQUIRE_GPIOLIB
39 help
40 This option enables support for GE Fanuc's PPC9A.
41
42config GEF_SBC310
43 bool "GE Fanuc SBC310"
44 select DEFAULT_UIMAGE
45 select GENERIC_GPIO
46 select ARCH_REQUIRE_GPIOLIB
47 help
48 This option enables support for GE Fanuc's SBC310.
49
34config GEF_SBC610 50config GEF_SBC610
35 bool "GE Fanuc SBC610" 51 bool "GE Fanuc SBC610"
36 select DEFAULT_UIMAGE 52 select DEFAULT_UIMAGE
@@ -48,7 +64,7 @@ config MPC8641
48 select FSL_PCI if PCI 64 select FSL_PCI if PCI
49 select PPC_UDBG_16550 65 select PPC_UDBG_16550
50 select MPIC 66 select MPIC
51 default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 67 default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 || GEF_SBC310 || GEF_PPC9A
52 68
53config MPC8610 69config MPC8610
54 bool 70 bool
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index 31e540c2ebbc..4b0d7b1aa005 100644
--- a/arch/powerpc/platforms/86xx/Makefile
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -9,3 +9,5 @@ obj-$(CONFIG_SBC8641D) += sbc8641d.o
9obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o 9obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o
10gef-gpio-$(CONFIG_GPIOLIB) += gef_gpio.o 10gef-gpio-$(CONFIG_GPIOLIB) += gef_gpio.o
11obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o gef_pic.o $(gef-gpio-y) 11obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o gef_pic.o $(gef-gpio-y)
12obj-$(CONFIG_GEF_SBC310) += gef_sbc310.o gef_pic.o $(gef-gpio-y)
13obj-$(CONFIG_GEF_PPC9A) += gef_ppc9a.o gef_pic.o $(gef-gpio-y)
diff --git a/arch/powerpc/platforms/86xx/gef_gpio.c b/arch/powerpc/platforms/86xx/gef_gpio.c
index 85b2800f4cb7..b2ea8875adba 100644
--- a/arch/powerpc/platforms/86xx/gef_gpio.c
+++ b/arch/powerpc/platforms/86xx/gef_gpio.c
@@ -37,8 +37,6 @@
37#define GEF_GPIO_OVERRUN 0x1C 37#define GEF_GPIO_OVERRUN 0x1C
38#define GEF_GPIO_MODE 0x20 38#define GEF_GPIO_MODE 0x20
39 39
40#define NUM_GPIO 19
41
42static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value) 40static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
43{ 41{
44 unsigned int data; 42 unsigned int data;
@@ -103,10 +101,10 @@ static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
103static int __init gef_gpio_init(void) 101static int __init gef_gpio_init(void)
104{ 102{
105 struct device_node *np; 103 struct device_node *np;
104 int retval;
105 struct of_mm_gpio_chip *gef_gpio_chip;
106 106
107 for_each_compatible_node(np, NULL, "gef,sbc610-gpio") { 107 for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
108 int retval;
109 struct of_mm_gpio_chip *gef_gpio_chip;
110 108
111 pr_debug("%s: Initialising GEF GPIO\n", np->full_name); 109 pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
112 110
@@ -120,7 +118,35 @@ static int __init gef_gpio_init(void)
120 118
121 /* Setup pointers to chip functions */ 119 /* Setup pointers to chip functions */
122 gef_gpio_chip->of_gc.gpio_cells = 2; 120 gef_gpio_chip->of_gc.gpio_cells = 2;
123 gef_gpio_chip->of_gc.gc.ngpio = NUM_GPIO; 121 gef_gpio_chip->of_gc.gc.ngpio = 19;
122 gef_gpio_chip->of_gc.gc.direction_input = gef_gpio_dir_in;
123 gef_gpio_chip->of_gc.gc.direction_output = gef_gpio_dir_out;
124 gef_gpio_chip->of_gc.gc.get = gef_gpio_get;
125 gef_gpio_chip->of_gc.gc.set = gef_gpio_set;
126
127 /* This function adds a memory mapped GPIO chip */
128 retval = of_mm_gpiochip_add(np, gef_gpio_chip);
129 if (retval) {
130 kfree(gef_gpio_chip);
131 pr_err("%s: Unable to add GPIO\n", np->full_name);
132 }
133 }
134
135 for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
136
137 pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
138
139 /* Allocate chip structure */
140 gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
141 if (!gef_gpio_chip) {
142 pr_err("%s: Unable to allocate structure\n",
143 np->full_name);
144 continue;
145 }
146
147 /* Setup pointers to chip functions */
148 gef_gpio_chip->of_gc.gpio_cells = 2;
149 gef_gpio_chip->of_gc.gc.ngpio = 6;
124 gef_gpio_chip->of_gc.gc.direction_input = gef_gpio_dir_in; 150 gef_gpio_chip->of_gc.gc.direction_input = gef_gpio_dir_in;
125 gef_gpio_chip->of_gc.gc.direction_output = gef_gpio_dir_out; 151 gef_gpio_chip->of_gc.gc.direction_output = gef_gpio_dir_out;
126 gef_gpio_chip->of_gc.gc.get = gef_gpio_get; 152 gef_gpio_chip->of_gc.gc.get = gef_gpio_get;
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
new file mode 100644
index 000000000000..d79104669cdc
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -0,0 +1,224 @@
1/*
2 * GE Fanuc PPC9A board support
3 *
4 * Author: Martyn Welch <martyn.welch@gefanuc.com>
5 *
6 * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines)
14 * Copyright 2006 Freescale Semiconductor Inc.
15 *
16 * NEC fixup adapted from arch/mips/pci/fixup-lm2e.c
17 */
18
19#include <linux/stddef.h>
20#include <linux/kernel.h>
21#include <linux/pci.h>
22#include <linux/kdev_t.h>
23#include <linux/delay.h>
24#include <linux/seq_file.h>
25#include <linux/of_platform.h>
26
27#include <asm/system.h>
28#include <asm/time.h>
29#include <asm/machdep.h>
30#include <asm/pci-bridge.h>
31#include <asm/mpc86xx.h>
32#include <asm/prom.h>
33#include <mm/mmu_decl.h>
34#include <asm/udbg.h>
35
36#include <asm/mpic.h>
37
38#include <sysdev/fsl_pci.h>
39#include <sysdev/fsl_soc.h>
40
41#include "mpc86xx.h"
42#include "gef_pic.h"
43
44#undef DEBUG
45
46#ifdef DEBUG
47#define DBG (fmt...) do { printk(KERN_ERR "PPC9A: " fmt); } while (0)
48#else
49#define DBG (fmt...) do { } while (0)
50#endif
51
52void __iomem *ppc9a_regs;
53
54static void __init gef_ppc9a_init_irq(void)
55{
56 struct device_node *cascade_node = NULL;
57
58 mpc86xx_init_irq();
59
60 /*
61 * There is a simple interrupt handler in the main FPGA, this needs
62 * to be cascaded into the MPIC
63 */
64 cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic-1.00");
65 if (!cascade_node) {
66 printk(KERN_WARNING "PPC9A: No FPGA PIC\n");
67 return;
68 }
69
70 gef_pic_init(cascade_node);
71 of_node_put(cascade_node);
72}
73
74static void __init gef_ppc9a_setup_arch(void)
75{
76 struct device_node *regs;
77#ifdef CONFIG_PCI
78 struct device_node *np;
79
80 for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
81 fsl_add_bridge(np, 1);
82 }
83#endif
84
85 printk(KERN_INFO "GE Fanuc Intelligent Platforms PPC9A 6U VME SBC\n");
86
87#ifdef CONFIG_SMP
88 mpc86xx_smp_init();
89#endif
90
91 /* Remap basic board registers */
92 regs = of_find_compatible_node(NULL, NULL, "gef,ppc9a-fpga-regs");
93 if (regs) {
94 ppc9a_regs = of_iomap(regs, 0);
95 if (ppc9a_regs == NULL)
96 printk(KERN_WARNING "Unable to map board registers\n");
97 of_node_put(regs);
98 }
99}
100
101/* Return the PCB revision */
102static unsigned int gef_ppc9a_get_pcb_rev(void)
103{
104 unsigned int reg;
105
106 reg = ioread32(ppc9a_regs);
107 return (reg >> 8) & 0xff;
108}
109
110/* Return the board (software) revision */
111static unsigned int gef_ppc9a_get_board_rev(void)
112{
113 unsigned int reg;
114
115 reg = ioread32(ppc9a_regs);
116 return (reg >> 16) & 0xff;
117}
118
119/* Return the FPGA revision */
120static unsigned int gef_ppc9a_get_fpga_rev(void)
121{
122 unsigned int reg;
123
124 reg = ioread32(ppc9a_regs);
125 return (reg >> 24) & 0xf;
126}
127
128static void gef_ppc9a_show_cpuinfo(struct seq_file *m)
129{
130 uint svid = mfspr(SPRN_SVR);
131
132 seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n");
133
134 seq_printf(m, "Revision\t: %u%c\n", gef_ppc9a_get_pcb_rev(),
135 ('A' + gef_ppc9a_get_board_rev() - 1));
136 seq_printf(m, "FPGA Revision\t: %u\n", gef_ppc9a_get_fpga_rev());
137
138 seq_printf(m, "SVR\t\t: 0x%x\n", svid);
139}
140
141static void __init gef_ppc9a_nec_fixup(struct pci_dev *pdev)
142{
143 unsigned int val;
144
145 /* Do not do the fixup on other platforms! */
146 if (!machine_is(gef_ppc9a))
147 return;
148
149 printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
150
151 /* Ensure ports 1, 2, 3, 4 & 5 are enabled */
152 pci_read_config_dword(pdev, 0xe0, &val);
153 pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x5);
154
155 /* System clock is 48-MHz Oscillator and EHCI Enabled. */
156 pci_write_config_dword(pdev, 0xe4, 1 << 5);
157}
158DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
159 gef_ppc9a_nec_fixup);
160
161/*
162 * Called very early, device-tree isn't unflattened
163 *
164 * This function is called to determine whether the BSP is compatible with the
165 * supplied device-tree, which is assumed to be the correct one for the actual
166 * board. It is expected thati, in the future, a kernel may support multiple
167 * boards.
168 */
169static int __init gef_ppc9a_probe(void)
170{
171 unsigned long root = of_get_flat_dt_root();
172
173 if (of_flat_dt_is_compatible(root, "gef,ppc9a"))
174 return 1;
175
176 return 0;
177}
178
179static long __init mpc86xx_time_init(void)
180{
181 unsigned int temp;
182
183 /* Set the time base to zero */
184 mtspr(SPRN_TBWL, 0);
185 mtspr(SPRN_TBWU, 0);
186
187 temp = mfspr(SPRN_HID0);
188 temp |= HID0_TBEN;
189 mtspr(SPRN_HID0, temp);
190 asm volatile("isync");
191
192 return 0;
193}
194
195static __initdata struct of_device_id of_bus_ids[] = {
196 { .compatible = "simple-bus", },
197 { .compatible = "gianfar", },
198 {},
199};
200
201static int __init declare_of_platform_devices(void)
202{
203 printk(KERN_DEBUG "Probe platform devices\n");
204 of_platform_bus_probe(NULL, of_bus_ids, NULL);
205
206 return 0;
207}
208machine_device_initcall(gef_ppc9a, declare_of_platform_devices);
209
210define_machine(gef_ppc9a) {
211 .name = "GE Fanuc PPC9A",
212 .probe = gef_ppc9a_probe,
213 .setup_arch = gef_ppc9a_setup_arch,
214 .init_IRQ = gef_ppc9a_init_irq,
215 .show_cpuinfo = gef_ppc9a_show_cpuinfo,
216 .get_irq = mpic_get_irq,
217 .restart = fsl_rstcr_restart,
218 .time_init = mpc86xx_time_init,
219 .calibrate_decr = generic_calibrate_decr,
220 .progress = udbg_progress,
221#ifdef CONFIG_PCI
222 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
223#endif
224};
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
new file mode 100644
index 000000000000..af14f852d747
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -0,0 +1,235 @@
1/*
2 * GE Fanuc SBC310 board support
3 *
4 * Author: Martyn Welch <martyn.welch@gefanuc.com>
5 *
6 * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines)
14 * Copyright 2006 Freescale Semiconductor Inc.
15 *
16 * NEC fixup adapted from arch/mips/pci/fixup-lm2e.c
17 */
18
19#include <linux/stddef.h>
20#include <linux/kernel.h>
21#include <linux/pci.h>
22#include <linux/kdev_t.h>
23#include <linux/delay.h>
24#include <linux/seq_file.h>
25#include <linux/of_platform.h>
26
27#include <asm/system.h>
28#include <asm/time.h>
29#include <asm/machdep.h>
30#include <asm/pci-bridge.h>
31#include <asm/mpc86xx.h>
32#include <asm/prom.h>
33#include <mm/mmu_decl.h>
34#include <asm/udbg.h>
35
36#include <asm/mpic.h>
37
38#include <sysdev/fsl_pci.h>
39#include <sysdev/fsl_soc.h>
40
41#include "mpc86xx.h"
42#include "gef_pic.h"
43
44#undef DEBUG
45
46#ifdef DEBUG
47#define DBG (fmt...) do { printk(KERN_ERR "SBC310: " fmt); } while (0)
48#else
49#define DBG (fmt...) do { } while (0)
50#endif
51
52void __iomem *sbc310_regs;
53
54static void __init gef_sbc310_init_irq(void)
55{
56 struct device_node *cascade_node = NULL;
57
58 mpc86xx_init_irq();
59
60 /*
61 * There is a simple interrupt handler in the main FPGA, this needs
62 * to be cascaded into the MPIC
63 */
64 cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic");
65 if (!cascade_node) {
66 printk(KERN_WARNING "SBC310: No FPGA PIC\n");
67 return;
68 }
69
70 gef_pic_init(cascade_node);
71 of_node_put(cascade_node);
72}
73
74static void __init gef_sbc310_setup_arch(void)
75{
76 struct device_node *regs;
77#ifdef CONFIG_PCI
78 struct device_node *np;
79
80 for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
81 fsl_add_bridge(np, 1);
82 }
83#endif
84
85 printk(KERN_INFO "GE Fanuc Intelligent Platforms SBC310 6U VPX SBC\n");
86
87#ifdef CONFIG_SMP
88 mpc86xx_smp_init();
89#endif
90
91 /* Remap basic board registers */
92 regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
93 if (regs) {
94 sbc310_regs = of_iomap(regs, 0);
95 if (sbc310_regs == NULL)
96 printk(KERN_WARNING "Unable to map board registers\n");
97 of_node_put(regs);
98 }
99}
100
101/* Return the PCB revision */
102static unsigned int gef_sbc310_get_board_id(void)
103{
104 unsigned int reg;
105
106 reg = ioread32(sbc310_regs);
107 return reg & 0xff;
108}
109
110/* Return the PCB revision */
111static unsigned int gef_sbc310_get_pcb_rev(void)
112{
113 unsigned int reg;
114
115 reg = ioread32(sbc310_regs);
116 return (reg >> 8) & 0xff;
117}
118
119/* Return the board (software) revision */
120static unsigned int gef_sbc310_get_board_rev(void)
121{
122 unsigned int reg;
123
124 reg = ioread32(sbc310_regs);
125 return (reg >> 16) & 0xff;
126}
127
128/* Return the FPGA revision */
129static unsigned int gef_sbc310_get_fpga_rev(void)
130{
131 unsigned int reg;
132
133 reg = ioread32(sbc310_regs);
134 return (reg >> 24) & 0xf;
135}
136
137static void gef_sbc310_show_cpuinfo(struct seq_file *m)
138{
139 uint svid = mfspr(SPRN_SVR);
140
141 seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n");
142
143 seq_printf(m, "Board ID\t: 0x%2.2x\n", gef_sbc310_get_board_id());
144 seq_printf(m, "Revision\t: %u%c\n", gef_sbc310_get_pcb_rev(),
145 ('A' + gef_sbc310_get_board_rev() - 1));
146 seq_printf(m, "FPGA Revision\t: %u\n", gef_sbc310_get_fpga_rev());
147
148 seq_printf(m, "SVR\t\t: 0x%x\n", svid);
149
150}
151
152static void __init gef_sbc310_nec_fixup(struct pci_dev *pdev)
153{
154 unsigned int val;
155
156 /* Do not do the fixup on other platforms! */
157 if (!machine_is(gef_sbc310))
158 return;
159
160 printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
161
162 /* Ensure only ports 1 & 2 are enabled */
163 pci_read_config_dword(pdev, 0xe0, &val);
164 pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x2);
165
166 /* System clock is 48-MHz Oscillator and EHCI Enabled. */
167 pci_write_config_dword(pdev, 0xe4, 1 << 5);
168}
169DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
170 gef_sbc310_nec_fixup);
171
172/*
173 * Called very early, device-tree isn't unflattened
174 *
175 * This function is called to determine whether the BSP is compatible with the
176 * supplied device-tree, which is assumed to be the correct one for the actual
177 * board. It is expected thati, in the future, a kernel may support multiple
178 * boards.
179 */
180static int __init gef_sbc310_probe(void)
181{
182 unsigned long root = of_get_flat_dt_root();
183
184 if (of_flat_dt_is_compatible(root, "gef,sbc310"))
185 return 1;
186
187 return 0;
188}
189
190static long __init mpc86xx_time_init(void)
191{
192 unsigned int temp;
193
194 /* Set the time base to zero */
195 mtspr(SPRN_TBWL, 0);
196 mtspr(SPRN_TBWU, 0);
197
198 temp = mfspr(SPRN_HID0);
199 temp |= HID0_TBEN;
200 mtspr(SPRN_HID0, temp);
201 asm volatile("isync");
202
203 return 0;
204}
205
206static __initdata struct of_device_id of_bus_ids[] = {
207 { .compatible = "simple-bus", },
208 { .compatible = "gianfar", },
209 {},
210};
211
212static int __init declare_of_platform_devices(void)
213{
214 printk(KERN_DEBUG "Probe platform devices\n");
215 of_platform_bus_probe(NULL, of_bus_ids, NULL);
216
217 return 0;
218}
219machine_device_initcall(gef_sbc310, declare_of_platform_devices);
220
221define_machine(gef_sbc310) {
222 .name = "GE Fanuc SBC310",
223 .probe = gef_sbc310_probe,
224 .setup_arch = gef_sbc310_setup_arch,
225 .init_IRQ = gef_sbc310_init_irq,
226 .show_cpuinfo = gef_sbc310_show_cpuinfo,
227 .get_irq = mpic_get_irq,
228 .restart = fsl_rstcr_restart,
229 .time_init = mpc86xx_time_init,
230 .calibrate_decr = generic_calibrate_decr,
231 .progress = udbg_progress,
232#ifdef CONFIG_PCI
233 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
234#endif
235};
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
index fb371f5ce132..ea2360639652 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc610.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -142,6 +142,10 @@ static void __init gef_sbc610_nec_fixup(struct pci_dev *pdev)
142{ 142{
143 unsigned int val; 143 unsigned int val;
144 144
145 /* Do not do the fixup on other platforms! */
146 if (!machine_is(gef_sbc610))
147 return;
148
145 printk(KERN_INFO "Running NEC uPD720101 Fixup\n"); 149 printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
146 150
147 /* Ensure ports 1, 2, 3, 4 & 5 are enabled */ 151 /* Ensure ports 1, 2, 3, 4 & 5 are enabled */
@@ -190,6 +194,7 @@ static long __init mpc86xx_time_init(void)
190 194
191static __initdata struct of_device_id of_bus_ids[] = { 195static __initdata struct of_device_id of_bus_ids[] = {
192 { .compatible = "simple-bus", }, 196 { .compatible = "simple-bus", },
197 { .compatible = "gianfar", },
193 {}, 198 {},
194}; 199};
195 200
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index e8d54ac5292c..3f49a6f893a3 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -46,6 +46,7 @@ static unsigned char *pixis_bdcfg0, *pixis_arch;
46static struct of_device_id __initdata mpc8610_ids[] = { 46static struct of_device_id __initdata mpc8610_ids[] = {
47 { .compatible = "fsl,mpc8610-immr", }, 47 { .compatible = "fsl,mpc8610-immr", },
48 { .compatible = "simple-bus", }, 48 { .compatible = "simple-bus", },
49 { .compatible = "gianfar", },
49 {} 50 {}
50}; 51};
51 52
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 27e0e682d8e1..c4ec49b5f7f8 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -148,6 +148,7 @@ mpc86xx_time_init(void)
148static __initdata struct of_device_id of_bus_ids[] = { 148static __initdata struct of_device_id of_bus_ids[] = {
149 { .compatible = "simple-bus", }, 149 { .compatible = "simple-bus", },
150 { .compatible = "fsl,rapidio-delta", }, 150 { .compatible = "fsl,rapidio-delta", },
151 { .compatible = "gianfar", },
151 {}, 152 {},
152}; 153};
153 154
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
index 5fd7ed40986f..2886a36fc085 100644
--- a/arch/powerpc/platforms/86xx/sbc8641d.c
+++ b/arch/powerpc/platforms/86xx/sbc8641d.c
@@ -103,6 +103,7 @@ mpc86xx_time_init(void)
103 103
104static __initdata struct of_device_id of_bus_ids[] = { 104static __initdata struct of_device_id of_bus_ids[] = {
105 { .compatible = "simple-bus", }, 105 { .compatible = "simple-bus", },
106 { .compatible = "gianfar", },
106 {}, 107 {},
107}; 108};
108 109
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 0d9f75c74f8c..385acfc48397 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -44,7 +44,6 @@ static irqreturn_t timebase_interrupt(int irq, void *dev)
44 44
45static struct irqaction tbint_irqaction = { 45static struct irqaction tbint_irqaction = {
46 .handler = timebase_interrupt, 46 .handler = timebase_interrupt,
47 .mask = CPU_MASK_NONE,
48 .name = "tbint", 47 .name = "tbint",
49}; 48};
50 49
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 200b9cb900ea..e3e87078d03f 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -1,14 +1,5 @@
1menu "Platform support" 1menu "Platform support"
2 2
3config PPC_MULTIPLATFORM
4 bool
5 depends on PPC64 || 6xx
6 default y
7
8config CLASSIC32
9 def_bool y
10 depends on 6xx && PPC_MULTIPLATFORM
11
12source "arch/powerpc/platforms/pseries/Kconfig" 3source "arch/powerpc/platforms/pseries/Kconfig"
13source "arch/powerpc/platforms/iseries/Kconfig" 4source "arch/powerpc/platforms/iseries/Kconfig"
14source "arch/powerpc/platforms/chrp/Kconfig" 5source "arch/powerpc/platforms/chrp/Kconfig"
@@ -28,15 +19,28 @@ source "arch/powerpc/platforms/86xx/Kconfig"
28source "arch/powerpc/platforms/embedded6xx/Kconfig" 19source "arch/powerpc/platforms/embedded6xx/Kconfig"
29source "arch/powerpc/platforms/44x/Kconfig" 20source "arch/powerpc/platforms/44x/Kconfig"
30source "arch/powerpc/platforms/40x/Kconfig" 21source "arch/powerpc/platforms/40x/Kconfig"
22source "arch/powerpc/platforms/amigaone/Kconfig"
31 23
32config PPC_NATIVE 24config PPC_NATIVE
33 bool 25 bool
34 depends on PPC_MULTIPLATFORM 26 depends on 6xx || PPC64
35 help 27 help
36 Support for running natively on the hardware, i.e. without 28 Support for running natively on the hardware, i.e. without
37 a hypervisor. This option is not user-selectable but should 29 a hypervisor. This option is not user-selectable but should
38 be selected by all platforms that need it. 30 be selected by all platforms that need it.
39 31
32config PPC_OF_BOOT_TRAMPOLINE
33 bool "Support booting from Open Firmware or yaboot"
34 depends on 6xx || PPC64
35 default y
36 help
37 Support from booting from Open Firmware or yaboot using an
38 Open Firmware client interface. This enables the kernel to
39 communicate with open firmware to retrieve system informations
40 such as the device tree.
41
42 In case of doubt, say Y
43
40config UDBG_RTAS_CONSOLE 44config UDBG_RTAS_CONSOLE
41 bool "RTAS based debug console" 45 bool "RTAS based debug console"
42 depends on PPC_RTAS 46 depends on PPC_RTAS
@@ -70,7 +74,7 @@ config PPC_I8259
70 74
71config U3_DART 75config U3_DART
72 bool 76 bool
73 depends on PPC_MULTIPLATFORM && PPC64 77 depends on PPC64
74 default n 78 default n
75 79
76config PPC_RTAS 80config PPC_RTAS
@@ -91,15 +95,6 @@ config RTAS_FLASH
91 tristate "Firmware flash interface" 95 tristate "Firmware flash interface"
92 depends on PPC64 && RTAS_PROC 96 depends on PPC64 && RTAS_PROC
93 97
94config PPC_PMI
95 tristate "Support for PMI"
96 depends on PPC_IBM_CELL_BLADE
97 help
98 PMI (Platform Management Interrupt) is a way to
99 communicate with the BMC (Baseboard Management Controller).
100 It is used in some IBM Cell blades.
101 default m
102
103config MMIO_NVRAM 98config MMIO_NVRAM
104 bool 99 bool
105 default n 100 default n
@@ -196,7 +191,7 @@ config PPC601_SYNC_FIX
196 191
197config TAU 192config TAU
198 bool "On-chip CPU temperature sensor support" 193 bool "On-chip CPU temperature sensor support"
199 depends on CLASSIC32 194 depends on 6xx
200 help 195 help
201 G3 and G4 processors have an on-chip temperature sensor called the 196 G3 and G4 processors have an on-chip temperature sensor called the
202 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die 197 'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
@@ -274,7 +269,7 @@ config CPM2
274 269
275config AXON_RAM 270config AXON_RAM
276 tristate "Axon DDR2 memory device driver" 271 tristate "Axon DDR2 memory device driver"
277 depends on PPC_IBM_CELL_BLADE 272 depends on PPC_IBM_CELL_BLADE && BLOCK
278 default m 273 default m
279 help 274 help
280 It registers one block device per Axon's DDR2 memory bank found 275 It registers one block device per Axon's DDR2 memory bank found
@@ -298,7 +293,7 @@ config CPM
298config OF_RTC 293config OF_RTC
299 bool 294 bool
300 help 295 help
301 Uses information from the OF or flattened device tree to instatiate 296 Uses information from the OF or flattened device tree to instantiate
302 platform devices for direct mapped RTC chips like the DS1742 or DS1743. 297 platform devices for direct mapped RTC chips like the DS1742 or DS1743.
303 298
304source "arch/powerpc/sysdev/bestcomm/Kconfig" 299source "arch/powerpc/sysdev/bestcomm/Kconfig"
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index dc0f3c933518..732ee93a8e98 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -58,9 +58,17 @@ config E200
58 58
59endchoice 59endchoice
60 60
61# Until we have a choice of exclusive CPU types on 64-bit, we always
62# use PPC_BOOK3S. On 32-bit, this is equivalent to 6xx which is
63# "classic" MMU
64
65config PPC_BOOK3S
66 def_bool y
67 depends on PPC64 || 6xx
68
61config POWER4_ONLY 69config POWER4_ONLY
62 bool "Optimize for POWER4" 70 bool "Optimize for POWER4"
63 depends on PPC64 71 depends on PPC64 && PPC_BOOK3S
64 default n 72 default n
65 ---help--- 73 ---help---
66 Cause the compiler to optimize for POWER4/POWER5/PPC970 processors. 74 Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
@@ -69,16 +77,16 @@ config POWER4_ONLY
69 77
70config POWER3 78config POWER3
71 bool 79 bool
72 depends on PPC64 80 depends on PPC64 && PPC_BOOK3S
73 default y if !POWER4_ONLY 81 default y if !POWER4_ONLY
74 82
75config POWER4 83config POWER4
76 depends on PPC64 84 depends on PPC64 && PPC_BOOK3S
77 def_bool y 85 def_bool y
78 86
79config TUNE_CELL 87config TUNE_CELL
80 bool "Optimize for Cell Broadband Engine" 88 bool "Optimize for Cell Broadband Engine"
81 depends on PPC64 89 depends on PPC64 && PPC_BOOK3S
82 help 90 help
83 Cause the compiler to optimize for the PPE of the Cell Broadband 91 Cause the compiler to optimize for the PPE of the Cell Broadband
84 Engine. This will make the code run considerably faster on Cell 92 Engine. This will make the code run considerably faster on Cell
@@ -148,7 +156,7 @@ config PHYS_64BIT
148 156
149config ALTIVEC 157config ALTIVEC
150 bool "AltiVec Support" 158 bool "AltiVec Support"
151 depends on CLASSIC32 || POWER4 159 depends on 6xx || POWER4
152 ---help--- 160 ---help---
153 This option enables kernel support for the Altivec extensions to the 161 This option enables kernel support for the Altivec extensions to the
154 PowerPC processor. The kernel currently supports saving and restoring 162 PowerPC processor. The kernel currently supports saving and restoring
@@ -211,6 +219,10 @@ config PPC_MMU_NOHASH
211 def_bool y 219 def_bool y
212 depends on !PPC_STD_MMU 220 depends on !PPC_STD_MMU
213 221
222config PPC_BOOK3E_MMU
223 def_bool y
224 depends on FSL_BOOKE
225
214config PPC_MM_SLICES 226config PPC_MM_SLICES
215 bool 227 bool
216 default y if HUGETLB_PAGE || (PPC_STD_MMU_64 && PPC_64K_PAGES) 228 default y if HUGETLB_PAGE || (PPC_STD_MMU_64 && PPC_64K_PAGES)
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 8079e0b4fd69..f7419198e635 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_PPC_PASEMI) += pasemi/
19obj-$(CONFIG_PPC_CELL) += cell/ 19obj-$(CONFIG_PPC_CELL) += cell/
20obj-$(CONFIG_PPC_PS3) += ps3/ 20obj-$(CONFIG_PPC_PS3) += ps3/
21obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ 21obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
22obj-$(CONFIG_AMIGAONE) += amigaone/
diff --git a/arch/powerpc/platforms/amigaone/Kconfig b/arch/powerpc/platforms/amigaone/Kconfig
new file mode 100644
index 000000000000..022476717718
--- /dev/null
+++ b/arch/powerpc/platforms/amigaone/Kconfig
@@ -0,0 +1,18 @@
1config AMIGAONE
2 bool "Eyetech AmigaOne/MAI Teron"
3 depends on 6xx && BROKEN_ON_SMP
4 select PPC_I8259
5 select PPC_INDIRECT_PCI
6 select PPC_UDBG_16550
7 select PCI
8 select NOT_COHERENT_CACHE
9 select CHECK_CACHE_COHERENCY
10 select DEFAULT_UIMAGE
11 select PCSPKR_PLATFORM
12 help
13 Select AmigaOne for the following machines:
14 - AmigaOne SE/Teron CX (G3 only)
15 - AmigaOne XE/Teron PX
16 - uA1/Teron mini
17 More information is available at:
18 <http://amigaone-linux.sourceforge.net/>.
diff --git a/arch/powerpc/platforms/amigaone/Makefile b/arch/powerpc/platforms/amigaone/Makefile
new file mode 100644
index 000000000000..e6885b3b2ee7
--- /dev/null
+++ b/arch/powerpc/platforms/amigaone/Makefile
@@ -0,0 +1 @@
obj-y += setup.o
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c
new file mode 100644
index 000000000000..443035366c12
--- /dev/null
+++ b/arch/powerpc/platforms/amigaone/setup.c
@@ -0,0 +1,170 @@
1/*
2 * AmigaOne platform setup
3 *
4 * Copyright 2008 Gerhard Pircher (gerhard_pircher@gmx.net)
5 *
6 * Based on original amigaone_setup.c source code
7 * Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#include <linux/kernel.h>
16#include <linux/seq_file.h>
17#include <linux/utsrelease.h>
18
19#include <asm/machdep.h>
20#include <asm/cputable.h>
21#include <asm/prom.h>
22#include <asm/pci-bridge.h>
23#include <asm/i8259.h>
24#include <asm/time.h>
25#include <asm/udbg.h>
26
27extern void __flush_disable_L1(void);
28
29void amigaone_show_cpuinfo(struct seq_file *m)
30{
31 seq_printf(m, "vendor\t\t: Eyetech Ltd.\n");
32}
33
34static int __init amigaone_add_bridge(struct device_node *dev)
35{
36 const u32 *cfg_addr, *cfg_data;
37 int len;
38 const int *bus_range;
39 struct pci_controller *hose;
40
41 printk(KERN_INFO "Adding PCI host bridge %s\n", dev->full_name);
42
43 cfg_addr = of_get_address(dev, 0, NULL, NULL);
44 cfg_data = of_get_address(dev, 1, NULL, NULL);
45 if ((cfg_addr == NULL) || (cfg_data == NULL))
46 return -ENODEV;
47
48 bus_range = of_get_property(dev, "bus-range", &len);
49 if ((bus_range == NULL) || (len < 2 * sizeof(int)))
50 printk(KERN_WARNING "Can't get bus-range for %s, assume"
51 " bus 0\n", dev->full_name);
52
53 hose = pcibios_alloc_controller(dev);
54 if (hose == NULL)
55 return -ENOMEM;
56
57 hose->first_busno = bus_range ? bus_range[0] : 0;
58 hose->last_busno = bus_range ? bus_range[1] : 0xff;
59
60 setup_indirect_pci(hose, cfg_addr[0], cfg_data[0], 0);
61
62 /* Interpret the "ranges" property */
63 /* This also maps the I/O region and sets isa_io/mem_base */
64 pci_process_bridge_OF_ranges(hose, dev, 1);
65
66 return 0;
67}
68
69void __init amigaone_setup_arch(void)
70{
71 struct device_node *np;
72 int phb = -ENODEV;
73
74 /* Lookup PCI host bridges. */
75 for_each_compatible_node(np, "pci", "mai-logic,articia-s")
76 phb = amigaone_add_bridge(np);
77
78 BUG_ON(phb != 0);
79
80 if (ppc_md.progress)
81 ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0);
82}
83
84void __init amigaone_init_IRQ(void)
85{
86 struct device_node *pic, *np = NULL;
87 const unsigned long *prop = NULL;
88 unsigned long int_ack = 0;
89
90 /* Search for ISA interrupt controller. */
91 pic = of_find_compatible_node(NULL, "interrupt-controller",
92 "pnpPNP,000");
93 BUG_ON(pic == NULL);
94
95 /* Look for interrupt acknowledge address in the PCI root node. */
96 np = of_find_compatible_node(NULL, "pci", "mai-logic,articia-s");
97 if (np) {
98 prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
99 if (prop)
100 int_ack = prop[0];
101 of_node_put(np);
102 }
103
104 if (int_ack == 0)
105 printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
106 " address, polling\n");
107
108 i8259_init(pic, int_ack);
109 ppc_md.get_irq = i8259_irq;
110 irq_set_default_host(i8259_get_host());
111}
112
113void __init amigaone_init(void)
114{
115 request_region(0x00, 0x20, "dma1");
116 request_region(0x40, 0x20, "timer");
117 request_region(0x80, 0x10, "dma page reg");
118 request_region(0xc0, 0x20, "dma2");
119}
120
121void amigaone_restart(char *cmd)
122{
123 local_irq_disable();
124
125 /* Flush and disable caches. */
126 __flush_disable_L1();
127
128 /* Set SRR0 to the reset vector and turn on MSR_IP. */
129 mtspr(SPRN_SRR0, 0xfff00100);
130 mtspr(SPRN_SRR1, MSR_IP);
131
132 /* Do an rfi to jump back to firmware. */
133 __asm__ __volatile__("rfi" : : : "memory");
134
135 /* Not reached. */
136 while (1);
137}
138
139static int __init amigaone_probe(void)
140{
141 unsigned long root = of_get_flat_dt_root();
142
143 if (of_flat_dt_is_compatible(root, "eyetech,amigaone")) {
144 /*
145 * Coherent memory access cause complete system lockup! Thus
146 * disable this CPU feature, even if the CPU needs it.
147 */
148 cur_cpu_spec->cpu_features &= ~CPU_FTR_NEED_COHERENT;
149
150 ISA_DMA_THRESHOLD = 0x00ffffff;
151 DMA_MODE_READ = 0x44;
152 DMA_MODE_WRITE = 0x48;
153
154 return 1;
155 }
156
157 return 0;
158}
159
160define_machine(amigaone) {
161 .name = "AmigaOne",
162 .probe = amigaone_probe,
163 .setup_arch = amigaone_setup_arch,
164 .init = amigaone_init,
165 .show_cpuinfo = amigaone_show_cpuinfo,
166 .init_IRQ = amigaone_init_IRQ,
167 .restart = amigaone_restart,
168 .calibrate_decr = generic_calibrate_decr,
169 .progress = udbg_progress,
170};
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 5cc3279559a4..40e24c39ad06 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -23,7 +23,7 @@ config PPC_CELL_NATIVE
23 23
24config PPC_IBM_CELL_BLADE 24config PPC_IBM_CELL_BLADE
25 bool "IBM Cell Blade" 25 bool "IBM Cell Blade"
26 depends on PPC_MULTIPLATFORM && PPC64 26 depends on PPC64 && PPC_BOOK3S
27 select PPC_CELL_NATIVE 27 select PPC_CELL_NATIVE
28 select MMIO_NVRAM 28 select MMIO_NVRAM
29 select PPC_UDBG_16550 29 select PPC_UDBG_16550
@@ -31,7 +31,7 @@ config PPC_IBM_CELL_BLADE
31 31
32config PPC_CELLEB 32config PPC_CELLEB
33 bool "Toshiba's Cell Reference Set 'Celleb' Architecture" 33 bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
34 depends on PPC_MULTIPLATFORM && PPC64 34 depends on PPC64 && PPC_BOOK3S
35 select PPC_CELL_NATIVE 35 select PPC_CELL_NATIVE
36 select HAS_TXX9_SERIAL 36 select HAS_TXX9_SERIAL
37 select PPC_UDBG_BEAT 37 select PPC_UDBG_BEAT
@@ -40,9 +40,14 @@ config PPC_CELLEB
40 40
41config PPC_CELL_QPACE 41config PPC_CELL_QPACE
42 bool "IBM Cell - QPACE" 42 bool "IBM Cell - QPACE"
43 depends on PPC_MULTIPLATFORM && PPC64 43 depends on PPC64 && PPC_BOOK3S
44 select PPC_CELL_COMMON 44 select PPC_CELL_COMMON
45 45
46config AXON_MSI
47 bool
48 depends on PPC_IBM_CELL_BLADE && PCI_MSI
49 default y
50
46menu "Cell Broadband Engine options" 51menu "Cell Broadband Engine options"
47 depends on PPC_CELL 52 depends on PPC_CELL
48 53
@@ -98,7 +103,7 @@ config PPC_IBM_CELL_RESETBUTTON
98 103
99config PPC_IBM_CELL_POWERBUTTON 104config PPC_IBM_CELL_POWERBUTTON
100 tristate "IBM Cell Blade power button" 105 tristate "IBM Cell Blade power button"
101 depends on PPC_IBM_CELL_BLADE && PPC_PMI && INPUT_EVDEV 106 depends on PPC_IBM_CELL_BLADE && INPUT_EVDEV
102 default y 107 default y
103 help 108 help
104 Support Powerbutton on IBM Cell blades. 109 Support Powerbutton on IBM Cell blades.
@@ -118,9 +123,9 @@ config CBE_CPUFREQ
118 For details, take a look at <file:Documentation/cpu-freq/>. 123 For details, take a look at <file:Documentation/cpu-freq/>.
119 If you don't have such processor, say N 124 If you don't have such processor, say N
120 125
121config CBE_CPUFREQ_PMI 126config CBE_CPUFREQ_PMI_ENABLE
122 tristate "CBE frequency scaling using PMI interface" 127 bool "CBE frequency scaling using PMI interface"
123 depends on CBE_CPUFREQ && PPC_PMI && EXPERIMENTAL 128 depends on CBE_CPUFREQ && EXPERIMENTAL
124 default n 129 default n
125 help 130 help
126 Select this, if you want to use the PMI interface 131 Select this, if you want to use the PMI interface
@@ -128,6 +133,20 @@ config CBE_CPUFREQ_PMI
128 processor will not only be able to run at lower speed, 133 processor will not only be able to run at lower speed,
129 but also at lower core voltage. 134 but also at lower core voltage.
130 135
136config CBE_CPUFREQ_PMI
137 tristate
138 depends on CBE_CPUFREQ_PMI_ENABLE
139 default CBE_CPUFREQ
140
141config PPC_PMI
142 tristate
143 default y
144 depends on CBE_CPUFREQ_PMI || PPC_IBM_CELL_POWERBUTTON
145 help
146 PMI (Platform Management Interrupt) is a way to
147 communicate with the BMC (Baseboard Management Controller).
148 It is used in some IBM Cell blades.
149
131config CBE_CPUFREQ_SPU_GOVERNOR 150config CBE_CPUFREQ_SPU_GOVERNOR
132 tristate "CBE frequency scaling based on SPU usage" 151 tristate "CBE frequency scaling based on SPU usage"
133 depends on SPU_FS && CPU_FREQ 152 depends on SPU_FS && CPU_FREQ
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 43eccb270301..83fafe922641 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
28 $(spu-manage-y) \ 28 $(spu-manage-y) \
29 spufs/ 29 spufs/
30 30
31obj-$(CONFIG_PCI_MSI) += axon_msi.o 31obj-$(CONFIG_AXON_MSI) += axon_msi.o
32 32
33# qpace setup 33# qpace setup
34obj-$(CONFIG_PPC_CELL_QPACE) += qpace_setup.o 34obj-$(CONFIG_PPC_CELL_QPACE) += qpace_setup.o
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 28c04dab2633..882e47080e74 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -237,8 +237,6 @@ extern int noirqdebug;
237 237
238static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) 238static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
239{ 239{
240 const unsigned int cpu = smp_processor_id();
241
242 spin_lock(&desc->lock); 240 spin_lock(&desc->lock);
243 241
244 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); 242 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
@@ -254,7 +252,7 @@ static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
254 goto out_eoi; 252 goto out_eoi;
255 } 253 }
256 254
257 kstat_cpu(cpu).irqs[irq]++; 255 kstat_incr_irqs_this_cpu(irq, desc);
258 256
259 /* Mark the IRQ currently in progress.*/ 257 /* Mark the IRQ currently in progress.*/
260 desc->status |= IRQ_INPROGRESS; 258 desc->status |= IRQ_INPROGRESS;
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index 059cad6c3f69..5c1118e31940 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -131,10 +131,10 @@ static const struct ppc_pci_io __devinitconst iowa_pci_io = {
131}; 131};
132 132
133static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size, 133static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size,
134 unsigned long flags) 134 unsigned long flags, void *caller)
135{ 135{
136 struct iowa_bus *bus; 136 struct iowa_bus *bus;
137 void __iomem *res = __ioremap(addr, size, flags); 137 void __iomem *res = __ioremap_caller(addr, size, flags, caller);
138 int busno; 138 int busno;
139 139
140 bus = iowa_pci_find(0, (unsigned long)addr); 140 bus = iowa_pci_find(0, (unsigned long)addr);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index ee5033eddf01..5744527a7f2a 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -74,7 +74,7 @@
74#define IOC_IO_ExcpStat_V 0x8000000000000000ul 74#define IOC_IO_ExcpStat_V 0x8000000000000000ul
75#define IOC_IO_ExcpStat_SPF_Mask 0x6000000000000000ul 75#define IOC_IO_ExcpStat_SPF_Mask 0x6000000000000000ul
76#define IOC_IO_ExcpStat_SPF_S 0x6000000000000000ul 76#define IOC_IO_ExcpStat_SPF_S 0x6000000000000000ul
77#define IOC_IO_ExcpStat_SPF_P 0x4000000000000000ul 77#define IOC_IO_ExcpStat_SPF_P 0x2000000000000000ul
78#define IOC_IO_ExcpStat_ADDR_Mask 0x00000007fffff000ul 78#define IOC_IO_ExcpStat_ADDR_Mask 0x00000007fffff000ul
79#define IOC_IO_ExcpStat_RW_Mask 0x0000000000000800ul 79#define IOC_IO_ExcpStat_RW_Mask 0x0000000000000800ul
80#define IOC_IO_ExcpStat_IOID_Mask 0x00000000000007fful 80#define IOC_IO_ExcpStat_IOID_Mask 0x00000000000007fful
@@ -247,17 +247,18 @@ static void tce_free_cell(struct iommu_table *tbl, long index, long npages)
247 247
248static irqreturn_t ioc_interrupt(int irq, void *data) 248static irqreturn_t ioc_interrupt(int irq, void *data)
249{ 249{
250 unsigned long stat; 250 unsigned long stat, spf;
251 struct cbe_iommu *iommu = data; 251 struct cbe_iommu *iommu = data;
252 252
253 stat = in_be64(iommu->xlate_regs + IOC_IO_ExcpStat); 253 stat = in_be64(iommu->xlate_regs + IOC_IO_ExcpStat);
254 spf = stat & IOC_IO_ExcpStat_SPF_Mask;
254 255
255 /* Might want to rate limit it */ 256 /* Might want to rate limit it */
256 printk(KERN_ERR "iommu: DMA exception 0x%016lx\n", stat); 257 printk(KERN_ERR "iommu: DMA exception 0x%016lx\n", stat);
257 printk(KERN_ERR " V=%d, SPF=[%c%c], RW=%s, IOID=0x%04x\n", 258 printk(KERN_ERR " V=%d, SPF=[%c%c], RW=%s, IOID=0x%04x\n",
258 !!(stat & IOC_IO_ExcpStat_V), 259 !!(stat & IOC_IO_ExcpStat_V),
259 (stat & IOC_IO_ExcpStat_SPF_S) ? 'S' : ' ', 260 (spf == IOC_IO_ExcpStat_SPF_S) ? 'S' : ' ',
260 (stat & IOC_IO_ExcpStat_SPF_P) ? 'P' : ' ', 261 (spf == IOC_IO_ExcpStat_SPF_P) ? 'P' : ' ',
261 (stat & IOC_IO_ExcpStat_RW_Mask) ? "Read" : "Write", 262 (stat & IOC_IO_ExcpStat_RW_Mask) ? "Read" : "Write",
262 (unsigned int)(stat & IOC_IO_ExcpStat_IOID_Mask)); 263 (unsigned int)(stat & IOC_IO_ExcpStat_IOID_Mask));
263 printk(KERN_ERR " page=0x%016lx\n", 264 printk(KERN_ERR " page=0x%016lx\n",
diff --git a/arch/powerpc/platforms/cell/qpace_setup.c b/arch/powerpc/platforms/cell/qpace_setup.c
index be84e6a16b30..c5ce02e84c8e 100644
--- a/arch/powerpc/platforms/cell/qpace_setup.c
+++ b/arch/powerpc/platforms/cell/qpace_setup.c
@@ -81,16 +81,6 @@ static int __init qpace_publish_devices(void)
81} 81}
82machine_subsys_initcall(qpace, qpace_publish_devices); 82machine_subsys_initcall(qpace, qpace_publish_devices);
83 83
84extern int qpace_notify(struct device *dev)
85{
86 /* set dma_ops for of_platform bus */
87 if (dev->bus && dev->bus->name
88 && !strcmp(dev->bus->name, "of_platform"))
89 set_dma_ops(dev, &dma_direct_ops);
90
91 return 0;
92}
93
94static void __init qpace_setup_arch(void) 84static void __init qpace_setup_arch(void)
95{ 85{
96#ifdef CONFIG_SPU_BASE 86#ifdef CONFIG_SPU_BASE
@@ -115,9 +105,6 @@ static void __init qpace_setup_arch(void)
115#ifdef CONFIG_DUMMY_CONSOLE 105#ifdef CONFIG_DUMMY_CONSOLE
116 conswitchp = &dummy_con; 106 conswitchp = &dummy_con;
117#endif 107#endif
118
119 /* set notifier function */
120 platform_notify = &qpace_notify;
121} 108}
122 109
123static int __init qpace_probe(void) 110static int __init qpace_probe(void)
@@ -141,6 +128,8 @@ define_machine(qpace) {
141 .power_off = rtas_power_off, 128 .power_off = rtas_power_off,
142 .halt = rtas_halt, 129 .halt = rtas_halt,
143 .get_boot_time = rtas_get_boot_time, 130 .get_boot_time = rtas_get_boot_time,
131 .get_rtc_time = rtas_get_rtc_time,
132 .set_rtc_time = rtas_set_rtc_time,
144 .calibrate_decr = generic_calibrate_decr, 133 .calibrate_decr = generic_calibrate_decr,
145 .progress = qpace_progress, 134 .progress = qpace_progress,
146 .init_IRQ = iic_init_IRQ, 135 .init_IRQ = iic_init_IRQ,
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index e487ad68ac11..9abd210d87c1 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -114,7 +114,7 @@ static inline void mm_needs_global_tlbie(struct mm_struct *mm)
114 int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1; 114 int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1;
115 115
116 /* Global TLBIE broadcast required with SPEs. */ 116 /* Global TLBIE broadcast required with SPEs. */
117 __cpus_setall(&mm->cpu_vm_mask, nr); 117 bitmap_fill(cpumask_bits(mm_cpumask(mm)), nr);
118} 118}
119 119
120void spu_associate_mm(struct spu *spu, struct mm_struct *mm) 120void spu_associate_mm(struct spu *spu, struct mm_struct *mm)
diff --git a/arch/powerpc/platforms/cell/spu_fault.c b/arch/powerpc/platforms/cell/spu_fault.c
index c8b1cd42905d..95d8dadf2d87 100644
--- a/arch/powerpc/platforms/cell/spu_fault.c
+++ b/arch/powerpc/platforms/cell/spu_fault.c
@@ -39,60 +39,56 @@ int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
39 unsigned long is_write; 39 unsigned long is_write;
40 int ret; 40 int ret;
41 41
42#if 0 42 if (mm == NULL)
43 if (!IS_VALID_EA(ea)) {
44 return -EFAULT; 43 return -EFAULT;
45 } 44
46#endif /* XXX */ 45 if (mm->pgd == NULL)
47 if (mm == NULL) {
48 return -EFAULT;
49 }
50 if (mm->pgd == NULL) {
51 return -EFAULT; 46 return -EFAULT;
52 }
53 47
54 down_read(&mm->mmap_sem); 48 down_read(&mm->mmap_sem);
49 ret = -EFAULT;
55 vma = find_vma(mm, ea); 50 vma = find_vma(mm, ea);
56 if (!vma) 51 if (!vma)
57 goto bad_area; 52 goto out_unlock;
58 if (vma->vm_start <= ea) 53
59 goto good_area; 54 if (ea < vma->vm_start) {
60 if (!(vma->vm_flags & VM_GROWSDOWN)) 55 if (!(vma->vm_flags & VM_GROWSDOWN))
61 goto bad_area; 56 goto out_unlock;
62 if (expand_stack(vma, ea)) 57 if (expand_stack(vma, ea))
63 goto bad_area; 58 goto out_unlock;
64good_area: 59 }
60
65 is_write = dsisr & MFC_DSISR_ACCESS_PUT; 61 is_write = dsisr & MFC_DSISR_ACCESS_PUT;
66 if (is_write) { 62 if (is_write) {
67 if (!(vma->vm_flags & VM_WRITE)) 63 if (!(vma->vm_flags & VM_WRITE))
68 goto bad_area; 64 goto out_unlock;
69 } else { 65 } else {
70 if (dsisr & MFC_DSISR_ACCESS_DENIED) 66 if (dsisr & MFC_DSISR_ACCESS_DENIED)
71 goto bad_area; 67 goto out_unlock;
72 if (!(vma->vm_flags & (VM_READ | VM_EXEC))) 68 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
73 goto bad_area; 69 goto out_unlock;
74 } 70 }
71
75 ret = 0; 72 ret = 0;
76 *flt = handle_mm_fault(mm, vma, ea, is_write); 73 *flt = handle_mm_fault(mm, vma, ea, is_write);
77 if (unlikely(*flt & VM_FAULT_ERROR)) { 74 if (unlikely(*flt & VM_FAULT_ERROR)) {
78 if (*flt & VM_FAULT_OOM) { 75 if (*flt & VM_FAULT_OOM) {
79 ret = -ENOMEM; 76 ret = -ENOMEM;
80 goto bad_area; 77 goto out_unlock;
81 } else if (*flt & VM_FAULT_SIGBUS) { 78 } else if (*flt & VM_FAULT_SIGBUS) {
82 ret = -EFAULT; 79 ret = -EFAULT;
83 goto bad_area; 80 goto out_unlock;
84 } 81 }
85 BUG(); 82 BUG();
86 } 83 }
84
87 if (*flt & VM_FAULT_MAJOR) 85 if (*flt & VM_FAULT_MAJOR)
88 current->maj_flt++; 86 current->maj_flt++;
89 else 87 else
90 current->min_flt++; 88 current->min_flt++;
91 up_read(&mm->mmap_sem);
92 return ret;
93 89
94bad_area: 90out_unlock:
95 up_read(&mm->mmap_sem); 91 up_read(&mm->mmap_sem);
96 return -EFAULT; 92 return ret;
97} 93}
98EXPORT_SYMBOL_GPL(spu_handle_mm_fault); 94EXPORT_SYMBOL_GPL(spu_handle_mm_fault);
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 6653ddbed048..db5398c0339f 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -35,6 +35,8 @@ atomic_t nr_spu_contexts = ATOMIC_INIT(0);
35struct spu_context *alloc_spu_context(struct spu_gang *gang) 35struct spu_context *alloc_spu_context(struct spu_gang *gang)
36{ 36{
37 struct spu_context *ctx; 37 struct spu_context *ctx;
38 struct timespec ts;
39
38 ctx = kzalloc(sizeof *ctx, GFP_KERNEL); 40 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
39 if (!ctx) 41 if (!ctx)
40 goto out; 42 goto out;
@@ -64,6 +66,8 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
64 __spu_update_sched_info(ctx); 66 __spu_update_sched_info(ctx);
65 spu_set_timeslice(ctx); 67 spu_set_timeslice(ctx);
66 ctx->stats.util_state = SPU_UTIL_IDLE_LOADED; 68 ctx->stats.util_state = SPU_UTIL_IDLE_LOADED;
69 ktime_get_ts(&ts);
70 ctx->stats.tstamp = timespec_to_ns(&ts);
67 71
68 atomic_inc(&nr_spu_contexts); 72 atomic_inc(&nr_spu_contexts);
69 goto out; 73 goto out;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 0da7f2bf5ee1..d6a519e6e1c1 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -568,16 +568,17 @@ spufs_regs_write(struct file *file, const char __user *buffer,
568 struct spu_lscsa *lscsa = ctx->csa.lscsa; 568 struct spu_lscsa *lscsa = ctx->csa.lscsa;
569 int ret; 569 int ret;
570 570
571 size = min_t(ssize_t, sizeof lscsa->gprs - *pos, size); 571 if (*pos >= sizeof(lscsa->gprs))
572 if (size <= 0)
573 return -EFBIG; 572 return -EFBIG;
573
574 size = min_t(ssize_t, sizeof(lscsa->gprs) - *pos, size);
574 *pos += size; 575 *pos += size;
575 576
576 ret = spu_acquire_saved(ctx); 577 ret = spu_acquire_saved(ctx);
577 if (ret) 578 if (ret)
578 return ret; 579 return ret;
579 580
580 ret = copy_from_user(lscsa->gprs + *pos - size, 581 ret = copy_from_user((char *)lscsa->gprs + *pos - size,
581 buffer, size) ? -EFAULT : size; 582 buffer, size) ? -EFAULT : size;
582 583
583 spu_release_saved(ctx); 584 spu_release_saved(ctx);
@@ -623,10 +624,11 @@ spufs_fpcr_write(struct file *file, const char __user * buffer,
623 struct spu_lscsa *lscsa = ctx->csa.lscsa; 624 struct spu_lscsa *lscsa = ctx->csa.lscsa;
624 int ret; 625 int ret;
625 626
626 size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size); 627 if (*pos >= sizeof(lscsa->fpcr))
627 if (size <= 0)
628 return -EFBIG; 628 return -EFBIG;
629 629
630 size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
631
630 ret = spu_acquire_saved(ctx); 632 ret = spu_acquire_saved(ctx);
631 if (ret) 633 if (ret)
632 return ret; 634 return ret;
@@ -2665,7 +2667,7 @@ static const struct file_operations spufs_ctx_fops = {
2665 .release = single_release, 2667 .release = single_release,
2666}; 2668};
2667 2669
2668struct spufs_tree_descr spufs_dir_contents[] = { 2670const struct spufs_tree_descr spufs_dir_contents[] = {
2669 { "capabilities", &spufs_caps_fops, 0444, }, 2671 { "capabilities", &spufs_caps_fops, 0444, },
2670 { "mem", &spufs_mem_fops, 0666, LS_SIZE, }, 2672 { "mem", &spufs_mem_fops, 0666, LS_SIZE, },
2671 { "regs", &spufs_regs_fops, 0666, sizeof(struct spu_reg128[128]), }, 2673 { "regs", &spufs_regs_fops, 0666, sizeof(struct spu_reg128[128]), },
@@ -2706,7 +2708,7 @@ struct spufs_tree_descr spufs_dir_contents[] = {
2706 {}, 2708 {},
2707}; 2709};
2708 2710
2709struct spufs_tree_descr spufs_dir_nosched_contents[] = { 2711const struct spufs_tree_descr spufs_dir_nosched_contents[] = {
2710 { "capabilities", &spufs_caps_fops, 0444, }, 2712 { "capabilities", &spufs_caps_fops, 0444, },
2711 { "mem", &spufs_mem_fops, 0666, LS_SIZE, }, 2713 { "mem", &spufs_mem_fops, 0666, LS_SIZE, },
2712 { "mbox", &spufs_mbox_fops, 0444, }, 2714 { "mbox", &spufs_mbox_fops, 0444, },
@@ -2731,12 +2733,12 @@ struct spufs_tree_descr spufs_dir_nosched_contents[] = {
2731 {}, 2733 {},
2732}; 2734};
2733 2735
2734struct spufs_tree_descr spufs_dir_debug_contents[] = { 2736const struct spufs_tree_descr spufs_dir_debug_contents[] = {
2735 { ".ctx", &spufs_ctx_fops, 0444, }, 2737 { ".ctx", &spufs_ctx_fops, 0444, },
2736 {}, 2738 {},
2737}; 2739};
2738 2740
2739struct spufs_coredump_reader spufs_coredump_read[] = { 2741const struct spufs_coredump_reader spufs_coredump_read[] = {
2740 { "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])}, 2742 { "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])},
2741 { "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) }, 2743 { "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) },
2742 { "lslr", NULL, spufs_lslr_get, 19 }, 2744 { "lslr", NULL, spufs_lslr_get, 19 },
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index e309ef70a531..706eb5c7e2ee 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -186,8 +186,9 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir)
186 return simple_rmdir(parent, dir); 186 return simple_rmdir(parent, dir);
187} 187}
188 188
189static int spufs_fill_dir(struct dentry *dir, struct spufs_tree_descr *files, 189static int spufs_fill_dir(struct dentry *dir,
190 int mode, struct spu_context *ctx) 190 const struct spufs_tree_descr *files, int mode,
191 struct spu_context *ctx)
191{ 192{
192 struct dentry *dentry, *tmp; 193 struct dentry *dentry, *tmp;
193 int ret; 194 int ret;
@@ -634,7 +635,7 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
634 if (dentry->d_inode) 635 if (dentry->d_inode)
635 goto out_dput; 636 goto out_dput;
636 637
637 mode &= ~current->fs->umask; 638 mode &= ~current_umask();
638 639
639 if (flags & SPU_CREATE_GANG) 640 if (flags & SPU_CREATE_GANG)
640 ret = spufs_create_gang(nd->path.dentry->d_inode, 641 ret = spufs_create_gang(nd->path.dentry->d_inode,
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index c58bd36b0c5b..4ddf769a64e5 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -117,6 +117,9 @@ static int spu_setup_isolated(struct spu_context *ctx)
117 cond_resched(); 117 cond_resched();
118 } 118 }
119 119
120 /* clear purge status */
121 out_be64(mfc_cntl, 0);
122
120 /* put the SPE in kernel mode to allow access to the loader */ 123 /* put the SPE in kernel mode to allow access to the loader */
121 sr1 = spu_mfc_sr1_get(ctx->spu); 124 sr1 = spu_mfc_sr1_get(ctx->spu);
122 sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK; 125 sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 6a0ad196aeb3..f085369301b1 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -508,7 +508,7 @@ static void __spu_add_to_rq(struct spu_context *ctx)
508 list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]); 508 list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]);
509 set_bit(ctx->prio, spu_prio->bitmap); 509 set_bit(ctx->prio, spu_prio->bitmap);
510 if (!spu_prio->nr_waiting++) 510 if (!spu_prio->nr_waiting++)
511 __mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK); 511 mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
512 } 512 }
513} 513}
514 514
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 3bf908e2873a..ae31573bea4a 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -241,9 +241,9 @@ struct spufs_tree_descr {
241 size_t size; 241 size_t size;
242}; 242};
243 243
244extern struct spufs_tree_descr spufs_dir_contents[]; 244extern const struct spufs_tree_descr spufs_dir_contents[];
245extern struct spufs_tree_descr spufs_dir_nosched_contents[]; 245extern const struct spufs_tree_descr spufs_dir_nosched_contents[];
246extern struct spufs_tree_descr spufs_dir_debug_contents[]; 246extern const struct spufs_tree_descr spufs_dir_debug_contents[];
247 247
248/* system call implementation */ 248/* system call implementation */
249extern struct spufs_calls spufs_calls; 249extern struct spufs_calls spufs_calls;
@@ -358,7 +358,7 @@ struct spufs_coredump_reader {
358 u64 (*get)(struct spu_context *ctx); 358 u64 (*get)(struct spu_context *ctx);
359 size_t size; 359 size_t size;
360}; 360};
361extern struct spufs_coredump_reader spufs_coredump_read[]; 361extern const struct spufs_coredump_reader spufs_coredump_read[];
362extern int spufs_coredump_num_notes; 362extern int spufs_coredump_num_notes;
363 363
364extern int spu_init_csa(struct spu_state *csa); 364extern int spu_init_csa(struct spu_state *csa);
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig
index 22b4b4e3b6f0..37d438bd5b7a 100644
--- a/arch/powerpc/platforms/chrp/Kconfig
+++ b/arch/powerpc/platforms/chrp/Kconfig
@@ -1,6 +1,6 @@
1config PPC_CHRP 1config PPC_CHRP
2 bool "Common Hardware Reference Platform (CHRP) based machines" 2 bool "Common Hardware Reference Platform (CHRP) based machines"
3 depends on PPC_MULTIPLATFORM && PPC32 3 depends on 6xx
4 select MPIC 4 select MPIC
5 select PPC_I8259 5 select PPC_I8259
6 select PPC_INDIRECT_PCI 6 select PPC_INDIRECT_PCI
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
index 130ff72d99dd..039fc8e82199 100644
--- a/arch/powerpc/platforms/chrp/pegasos_eth.c
+++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
@@ -21,8 +21,8 @@
21#define PEGASOS2_SRAM_BASE (0xf2000000) 21#define PEGASOS2_SRAM_BASE (0xf2000000)
22#define PEGASOS2_SRAM_SIZE (256*1024) 22#define PEGASOS2_SRAM_SIZE (256*1024)
23 23
24#define PEGASOS2_SRAM_BASE_ETH0 (PEGASOS2_SRAM_BASE) 24#define PEGASOS2_SRAM_BASE_ETH_PORT0 (PEGASOS2_SRAM_BASE)
25#define PEGASOS2_SRAM_BASE_ETH1 (PEGASOS2_SRAM_BASE_ETH0 + (PEGASOS2_SRAM_SIZE / 2) ) 25#define PEGASOS2_SRAM_BASE_ETH_PORT1 (PEGASOS2_SRAM_BASE_ETH_PORT0 + (PEGASOS2_SRAM_SIZE / 2) )
26 26
27 27
28#define PEGASOS2_SRAM_RXRING_SIZE (PEGASOS2_SRAM_SIZE/4) 28#define PEGASOS2_SRAM_RXRING_SIZE (PEGASOS2_SRAM_SIZE/4)
@@ -47,75 +47,42 @@ static struct platform_device mv643xx_eth_shared_device = {
47 .resource = mv643xx_eth_shared_resources, 47 .resource = mv643xx_eth_shared_resources,
48}; 48};
49 49
50static struct resource mv643xx_eth0_resources[] = { 50static struct resource mv643xx_eth_port1_resources[] = {
51 [0] = { 51 [0] = {
52 .name = "eth0 irq", 52 .name = "eth port1 irq",
53 .start = 9, 53 .start = 9,
54 .end = 9, 54 .end = 9,
55 .flags = IORESOURCE_IRQ, 55 .flags = IORESOURCE_IRQ,
56 }, 56 },
57}; 57};
58 58
59 59static struct mv643xx_eth_platform_data eth_port1_pd = {
60static struct mv643xx_eth_platform_data eth0_pd = {
61 .shared = &mv643xx_eth_shared_device,
62 .port_number = 0,
63
64 .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0,
65 .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
66 .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
67
68 .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH0 + PEGASOS2_SRAM_TXRING_SIZE,
69 .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
70 .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
71};
72
73static struct platform_device eth0_device = {
74 .name = MV643XX_ETH_NAME,
75 .id = 0,
76 .num_resources = ARRAY_SIZE(mv643xx_eth0_resources),
77 .resource = mv643xx_eth0_resources,
78 .dev = {
79 .platform_data = &eth0_pd,
80 },
81};
82
83static struct resource mv643xx_eth1_resources[] = {
84 [0] = {
85 .name = "eth1 irq",
86 .start = 9,
87 .end = 9,
88 .flags = IORESOURCE_IRQ,
89 },
90};
91
92static struct mv643xx_eth_platform_data eth1_pd = {
93 .shared = &mv643xx_eth_shared_device, 60 .shared = &mv643xx_eth_shared_device,
94 .port_number = 1, 61 .port_number = 1,
62 .phy_addr = MV643XX_ETH_PHY_ADDR(7),
95 63
96 .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1, 64 .tx_sram_addr = PEGASOS2_SRAM_BASE_ETH_PORT1,
97 .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE, 65 .tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
98 .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16, 66 .tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
99 67
100 .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH1 + PEGASOS2_SRAM_TXRING_SIZE, 68 .rx_sram_addr = PEGASOS2_SRAM_BASE_ETH_PORT1 + PEGASOS2_SRAM_TXRING_SIZE,
101 .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE, 69 .rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
102 .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16, 70 .rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
103}; 71};
104 72
105static struct platform_device eth1_device = { 73static struct platform_device eth_port1_device = {
106 .name = MV643XX_ETH_NAME, 74 .name = MV643XX_ETH_NAME,
107 .id = 1, 75 .id = 1,
108 .num_resources = ARRAY_SIZE(mv643xx_eth1_resources), 76 .num_resources = ARRAY_SIZE(mv643xx_eth_port1_resources),
109 .resource = mv643xx_eth1_resources, 77 .resource = mv643xx_eth_port1_resources,
110 .dev = { 78 .dev = {
111 .platform_data = &eth1_pd, 79 .platform_data = &eth_port1_pd,
112 }, 80 },
113}; 81};
114 82
115static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { 83static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
116 &mv643xx_eth_shared_device, 84 &mv643xx_eth_shared_device,
117 &eth0_device, 85 &eth_port1_device,
118 &eth1_device,
119}; 86};
120 87
121/***********/ 88/***********/
@@ -191,15 +158,10 @@ static int __init mv643xx_eth_add_pds(void)
191 158
192 if ( Enable_SRAM() < 0) 159 if ( Enable_SRAM() < 0)
193 { 160 {
194 eth0_pd.tx_sram_addr = 0; 161 eth_port1_pd.tx_sram_addr = 0;
195 eth0_pd.tx_sram_size = 0; 162 eth_port1_pd.tx_sram_size = 0;
196 eth0_pd.rx_sram_addr = 0; 163 eth_port1_pd.rx_sram_addr = 0;
197 eth0_pd.rx_sram_size = 0; 164 eth_port1_pd.rx_sram_size = 0;
198
199 eth1_pd.tx_sram_addr = 0;
200 eth1_pd.tx_sram_size = 0;
201 eth1_pd.rx_sram_addr = 0;
202 eth1_pd.rx_sram_size = 0;
203 165
204#ifdef BE_VERBOSE 166#ifdef BE_VERBOSE
205 printk("Pegasos II/Marvell MV64361: Can't enable the " 167 printk("Pegasos II/Marvell MV64361: Can't enable the "
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 272d79a8d289..cd4ad9aea760 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -472,7 +472,6 @@ static void __init chrp_find_openpic(void)
472#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) 472#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON)
473static struct irqaction xmon_irqaction = { 473static struct irqaction xmon_irqaction = {
474 .handler = xmon_irq, 474 .handler = xmon_irq,
475 .mask = CPU_MASK_NONE,
476 .name = "XMON break", 475 .name = "XMON break",
477}; 476};
478#endif 477#endif
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 4f9f8184d164..291ac9d8cbee 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -1,6 +1,6 @@
1config EMBEDDED6xx 1config EMBEDDED6xx
2 bool "Embedded 6xx/7xx/7xxx-based boards" 2 bool "Embedded 6xx/7xx/7xxx-based boards"
3 depends on PPC32 && BROKEN_ON_SMP && PPC_MULTIPLATFORM 3 depends on 6xx && BROKEN_ON_SMP
4 4
5config LINKSTATION 5config LINKSTATION
6 bool "Linkstation / Kurobox(HG) from Buffalo" 6 bool "Linkstation / Kurobox(HG) from Buffalo"
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index 2ca7be65c2d2..244f997de791 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -12,7 +12,6 @@
12 12
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/initrd.h> 14#include <linux/initrd.h>
15#include <linux/mtd/physmap.h>
16#include <linux/of_platform.h> 15#include <linux/of_platform.h>
17 16
18#include <asm/time.h> 17#include <asm/time.h>
@@ -22,39 +21,6 @@
22 21
23#include "mpc10x.h" 22#include "mpc10x.h"
24 23
25static struct mtd_partition linkstation_physmap_partitions[] = {
26 {
27 .name = "mtd_firmimg",
28 .offset = 0x000000,
29 .size = 0x300000,
30 },
31 {
32 .name = "mtd_bootcode",
33 .offset = 0x300000,
34 .size = 0x070000,
35 },
36 {
37 .name = "mtd_status",
38 .offset = 0x370000,
39 .size = 0x010000,
40 },
41 {
42 .name = "mtd_conf",
43 .offset = 0x380000,
44 .size = 0x080000,
45 },
46 {
47 .name = "mtd_allflash",
48 .offset = 0x000000,
49 .size = 0x400000,
50 },
51 {
52 .name = "mtd_data",
53 .offset = 0x310000,
54 .size = 0x0f0000,
55 },
56};
57
58static __initdata struct of_device_id of_bus_ids[] = { 24static __initdata struct of_device_id of_bus_ids[] = {
59 { .type = "soc", }, 25 { .type = "soc", },
60 { .compatible = "simple-bus", }, 26 { .compatible = "simple-bus", },
@@ -99,10 +65,6 @@ static int __init linkstation_add_bridge(struct device_node *dev)
99static void __init linkstation_setup_arch(void) 65static void __init linkstation_setup_arch(void)
100{ 66{
101 struct device_node *np; 67 struct device_node *np;
102#ifdef CONFIG_MTD_PHYSMAP
103 physmap_set_partitions(linkstation_physmap_partitions,
104 ARRAY_SIZE(linkstation_physmap_partitions));
105#endif
106 68
107 /* Lookup PCI host bridges */ 69 /* Lookup PCI host bridges */
108 for_each_compatible_node(np, "pci", "mpc10x-pci") 70 for_each_compatible_node(np, "pci", "mpc10x-pci")
diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c
index 8864e4884980..613070e9ddbe 100644
--- a/arch/powerpc/platforms/embedded6xx/storcenter.c
+++ b/arch/powerpc/platforms/embedded6xx/storcenter.c
@@ -14,7 +14,6 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/pci.h> 15#include <linux/pci.h>
16#include <linux/initrd.h> 16#include <linux/initrd.h>
17#include <linux/mtd/physmap.h>
18#include <linux/of_platform.h> 17#include <linux/of_platform.h>
19 18
20#include <asm/system.h> 19#include <asm/system.h>
@@ -26,32 +25,6 @@
26#include "mpc10x.h" 25#include "mpc10x.h"
27 26
28 27
29#ifdef CONFIG_MTD_PHYSMAP
30static struct mtd_partition storcenter_physmap_partitions[] = {
31 {
32 .name = "kernel",
33 .offset = 0x000000,
34 .size = 0x170000,
35 },
36 {
37 .name = "rootfs",
38 .offset = 0x170000,
39 .size = 0x590000,
40 },
41 {
42 .name = "uboot",
43 .offset = 0x700000,
44 .size = 0x040000,
45 },
46 {
47 .name = "config",
48 .offset = 0x740000,
49 .size = 0x0c0000,
50 },
51};
52#endif
53
54
55static __initdata struct of_device_id storcenter_of_bus[] = { 28static __initdata struct of_device_id storcenter_of_bus[] = {
56 { .name = "soc", }, 29 { .name = "soc", },
57 {}, 30 {},
@@ -96,11 +69,6 @@ static void __init storcenter_setup_arch(void)
96{ 69{
97 struct device_node *np; 70 struct device_node *np;
98 71
99#ifdef CONFIG_MTD_PHYSMAP
100 physmap_set_partitions(storcenter_physmap_partitions,
101 ARRAY_SIZE(storcenter_physmap_partitions));
102#endif
103
104 /* Lookup PCI host bridges */ 72 /* Lookup PCI host bridges */
105 for_each_compatible_node(np, "pci", "mpc10x-pci") 73 for_each_compatible_node(np, "pci", "mpc10x-pci")
106 storcenter_add_bridge(np); 74 storcenter_add_bridge(np);
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
index 7ddd0a2c8027..647e87787437 100644
--- a/arch/powerpc/platforms/iseries/Kconfig
+++ b/arch/powerpc/platforms/iseries/Kconfig
@@ -1,6 +1,6 @@
1config PPC_ISERIES 1config PPC_ISERIES
2 bool "IBM Legacy iSeries" 2 bool "IBM Legacy iSeries"
3 depends on PPC_MULTIPLATFORM && PPC64 3 depends on PPC64 && PPC_BOOK3S
4 select PPC_INDIRECT_IO 4 select PPC_INDIRECT_IO
5 select PPC_PCI_CHOICE if EMBEDDED 5 select PPC_PCI_CHOICE if EMBEDDED
6 6
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 701d9297c207..94f444758836 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -214,7 +214,7 @@ void __init iSeries_activate_IRQs()
214 unsigned long flags; 214 unsigned long flags;
215 215
216 for_each_irq (irq) { 216 for_each_irq (irq) {
217 irq_desc_t *desc = get_irq_desc(irq); 217 struct irq_desc *desc = get_irq_desc(irq);
218 218
219 if (desc && desc->chip && desc->chip->startup) { 219 if (desc && desc->chip && desc->chip->startup) {
220 spin_lock_irqsave(&desc->lock, flags); 220 spin_lock_irqsave(&desc->lock, flags);
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 24519b96d6ad..a6cd3394feaa 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -617,7 +617,7 @@ static void iseries_dedicated_idle(void)
617} 617}
618 618
619static void __iomem *iseries_ioremap(phys_addr_t address, unsigned long size, 619static void __iomem *iseries_ioremap(phys_addr_t address, unsigned long size,
620 unsigned long flags) 620 unsigned long flags, void *caller)
621{ 621{
622 return (void __iomem *)address; 622 return (void __iomem *)address;
623} 623}
diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig
index a6467a5591fa..1ea621a94c3b 100644
--- a/arch/powerpc/platforms/maple/Kconfig
+++ b/arch/powerpc/platforms/maple/Kconfig
@@ -1,5 +1,5 @@
1config PPC_MAPLE 1config PPC_MAPLE
2 depends on PPC_MULTIPLATFORM && PPC64 2 depends on PPC64 && PPC_BOOK3S
3 bool "Maple 970FX Evaluation Board" 3 bool "Maple 970FX Evaluation Board"
4 select PCI 4 select PCI
5 select MPIC 5 select MPIC
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 348e0619e3e5..a2aeb327d185 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -1,5 +1,5 @@
1config PPC_PASEMI 1config PPC_PASEMI
2 depends on PPC_MULTIPLATFORM && PPC64 2 depends on PPC64 && PPC_BOOK3S
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
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig
index 055990ca8ce6..1e1a0873e1dd 100644
--- a/arch/powerpc/platforms/powermac/Kconfig
+++ b/arch/powerpc/platforms/powermac/Kconfig
@@ -1,6 +1,6 @@
1config PPC_PMAC 1config PPC_PMAC
2 bool "Apple PowerMac based machines" 2 bool "Apple PowerMac based machines"
3 depends on PPC_MULTIPLATFORM 3 depends on PPC_BOOK3S
4 select MPIC 4 select MPIC
5 select PCI 5 select PCI
6 select PPC_INDIRECT_PCI if PPC32 6 select PPC_INDIRECT_PCI if PPC32
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index beb38333b6d2..22ecfbe7183d 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -86,6 +86,7 @@ static int (*g5_query_freq)(void);
86 86
87static DEFINE_MUTEX(g5_switch_mutex); 87static DEFINE_MUTEX(g5_switch_mutex);
88 88
89static unsigned long transition_latency;
89 90
90#ifdef CONFIG_PMAC_SMU 91#ifdef CONFIG_PMAC_SMU
91 92
@@ -357,7 +358,7 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
357 358
358static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) 359static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
359{ 360{
360 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 361 policy->cpuinfo.transition_latency = transition_latency;
361 policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; 362 policy->cur = g5_cpu_freqs[g5_query_freq()].frequency;
362 /* secondary CPUs are tied to the primary one by the 363 /* secondary CPUs are tied to the primary one by the
363 * cpufreq core if in the secondary policy we tell it that 364 * cpufreq core if in the secondary policy we tell it that
@@ -500,6 +501,7 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
500 g5_cpu_freqs[1].frequency = max_freq/2; 501 g5_cpu_freqs[1].frequency = max_freq/2;
501 502
502 /* Set callbacks */ 503 /* Set callbacks */
504 transition_latency = 12000;
503 g5_switch_freq = g5_scom_switch_freq; 505 g5_switch_freq = g5_scom_switch_freq;
504 g5_query_freq = g5_scom_query_freq; 506 g5_query_freq = g5_scom_query_freq;
505 freq_method = "SCOM"; 507 freq_method = "SCOM";
@@ -675,6 +677,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
675 g5_cpu_freqs[1].frequency = min_freq; 677 g5_cpu_freqs[1].frequency = min_freq;
676 678
677 /* Set callbacks */ 679 /* Set callbacks */
680 transition_latency = CPUFREQ_ETERNAL;
678 g5_switch_volt = g5_pfunc_switch_volt; 681 g5_switch_volt = g5_pfunc_switch_volt;
679 g5_switch_freq = g5_pfunc_switch_freq; 682 g5_switch_freq = g5_pfunc_switch_freq;
680 g5_query_freq = g5_pfunc_query_freq; 683 g5_query_freq = g5_pfunc_query_freq;
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 6d149ae8ffa7..7039d8f1d3ba 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -266,7 +266,6 @@ static unsigned int pmac_pic_get_irq(void)
266static struct irqaction xmon_action = { 266static struct irqaction xmon_action = {
267 .handler = xmon_irq, 267 .handler = xmon_irq,
268 .flags = 0, 268 .flags = 0,
269 .mask = CPU_MASK_NONE,
270 .name = "NMI - XMON" 269 .name = "NMI - XMON"
271}; 270};
272#endif 271#endif
@@ -274,7 +273,6 @@ static struct irqaction xmon_action = {
274static struct irqaction gatwick_cascade_action = { 273static struct irqaction gatwick_cascade_action = {
275 .handler = gatwick_action, 274 .handler = gatwick_action,
276 .flags = IRQF_DISABLED, 275 .flags = IRQF_DISABLED,
277 .mask = CPU_MASK_NONE,
278 .name = "cascade", 276 .name = "cascade",
279}; 277};
280 278
diff --git a/arch/powerpc/platforms/powermac/pic.h b/arch/powerpc/platforms/powermac/pic.h
index c44c89f5e532..d622a8345aaa 100644
--- a/arch/powerpc/platforms/powermac/pic.h
+++ b/arch/powerpc/platforms/powermac/pic.h
@@ -3,7 +3,7 @@
3 3
4#include <linux/irq.h> 4#include <linux/irq.h>
5 5
6extern struct hw_interrupt_type pmac_pic; 6extern struct irq_chip pmac_pic;
7 7
8extern void pmac_pic_init(void); 8extern void pmac_pic_init(void);
9extern int pmac_get_irq(void); 9extern int pmac_get_irq(void);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 9b78f5300c24..45936c9ed0ec 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -746,4 +746,7 @@ define_machine(powermac) {
746#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) 746#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
747 .cpu_die = pmac_cpu_die, 747 .cpu_die = pmac_cpu_die,
748#endif 748#endif
749#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
750 .cpu_die = generic_mach_cpu_die,
751#endif
749}; 752};
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index bd8817b00fa4..cf1dbe758890 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -385,7 +385,6 @@ static void __init psurge_dual_sync_tb(int cpu_nr)
385static struct irqaction psurge_irqaction = { 385static struct irqaction psurge_irqaction = {
386 .handler = psurge_primary_intr, 386 .handler = psurge_primary_intr,
387 .flags = IRQF_DISABLED, 387 .flags = IRQF_DISABLED,
388 .mask = CPU_MASK_NONE,
389 .name = "primary IPI", 388 .name = "primary IPI",
390}; 389};
391 390
diff --git a/arch/powerpc/platforms/prep/Kconfig b/arch/powerpc/platforms/prep/Kconfig
index 29d411279b0c..bf8330ef2e76 100644
--- a/arch/powerpc/platforms/prep/Kconfig
+++ b/arch/powerpc/platforms/prep/Kconfig
@@ -1,6 +1,6 @@
1config PPC_PREP 1config PPC_PREP
2 bool "PowerPC Reference Platform (PReP) based machines" 2 bool "PowerPC Reference Platform (PReP) based machines"
3 depends on PPC_MULTIPLATFORM && PPC32 && BROKEN 3 depends on 6xx && BROKEN
4 select MPIC 4 select MPIC
5 select PPC_I8259 5 select PPC_I8259
6 select PPC_INDIRECT_PCI 6 select PPC_INDIRECT_PCI
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 920cf7a454b1..dfe316b161a9 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -1,6 +1,6 @@
1config PPC_PS3 1config PPC_PS3
2 bool "Sony PS3" 2 bool "Sony PS3"
3 depends on PPC_MULTIPLATFORM && PPC64 3 depends on PPC64 && PPC_BOOK3S
4 select PPC_CELL 4 select PPC_CELL
5 select USB_ARCH_HAS_OHCI 5 select USB_ARCH_HAS_OHCI
6 select USB_OHCI_LITTLE_ENDIAN 6 select USB_OHCI_LITTLE_ENDIAN
@@ -128,6 +128,13 @@ config PS3_FLASH
128 be disabled on the kernel command line using "ps3flash=off", to 128 be disabled on the kernel command line using "ps3flash=off", to
129 not allocate this fixed buffer. 129 not allocate this fixed buffer.
130 130
131config PS3_VRAM
132 tristate "PS3 Video RAM Storage Driver"
133 depends on FB_PS3=y && BLOCK && m
134 help
135 This driver allows you to use excess PS3 video RAM as volatile
136 storage or system swap.
137
131config PS3_LPM 138config PS3_LPM
132 tristate "PS3 Logical Performance Monitor support" 139 tristate "PS3 Logical Performance Monitor support"
133 depends on PPC_PS3 140 depends on PPC_PS3
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index d281cc0bca71..9a2b6d948610 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -311,7 +311,7 @@ static int __init ps3_mm_add_memory(void)
311 result = add_memory(0, start_addr, map.r1.size); 311 result = add_memory(0, start_addr, map.r1.size);
312 312
313 if (result) { 313 if (result) {
314 DBG("%s:%d: add_memory failed: (%d)\n", 314 pr_err("%s:%d: add_memory failed: (%d)\n",
315 __func__, __LINE__, result); 315 __func__, __LINE__, result);
316 return result; 316 return result;
317 } 317 }
@@ -322,7 +322,7 @@ static int __init ps3_mm_add_memory(void)
322 result = online_pages(start_pfn, nr_pages); 322 result = online_pages(start_pfn, nr_pages);
323 323
324 if (result) 324 if (result)
325 DBG("%s:%d: online_pages failed: (%d)\n", 325 pr_err("%s:%d: online_pages failed: (%d)\n",
326 __func__, __LINE__, result); 326 __func__, __LINE__, result);
327 327
328 return result; 328 return result;
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index e1c83c23b435..86e392b1b049 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -808,6 +808,7 @@ u64 ps3_os_area_get_rtc_diff(void)
808{ 808{
809 return saved_params.rtc_diff; 809 return saved_params.rtc_diff;
810} 810}
811EXPORT_SYMBOL(ps3_os_area_get_rtc_diff);
811 812
812/** 813/**
813 * ps3_os_area_set_rtc_diff - Set the rtc diff value. 814 * ps3_os_area_set_rtc_diff - Set the rtc diff value.
@@ -823,6 +824,7 @@ void ps3_os_area_set_rtc_diff(u64 rtc_diff)
823 os_area_queue_work(); 824 os_area_queue_work();
824 } 825 }
825} 826}
827EXPORT_SYMBOL(ps3_os_area_set_rtc_diff);
826 828
827/** 829/**
828 * ps3_os_area_get_av_multi_out - Returns the default video mode. 830 * ps3_os_area_get_av_multi_out - Returns the default video mode.
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index 235c13ebacd9..136aa0637d9c 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -64,8 +64,6 @@ int ps3_set_rtc_time(struct rtc_time *time);
64 64
65void __init ps3_os_area_save_params(void); 65void __init ps3_os_area_save_params(void);
66void __init ps3_os_area_init(void); 66void __init ps3_os_area_init(void);
67u64 ps3_os_area_get_rtc_diff(void);
68void ps3_os_area_set_rtc_diff(u64 rtc_diff);
69 67
70/* spu */ 68/* spu */
71 69
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 3331ccbb8d38..66181821322a 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -270,8 +270,6 @@ define_machine(ps3) {
270 .init_IRQ = ps3_init_IRQ, 270 .init_IRQ = ps3_init_IRQ,
271 .panic = ps3_panic, 271 .panic = ps3_panic,
272 .get_boot_time = ps3_get_boot_time, 272 .get_boot_time = ps3_get_boot_time,
273 .set_rtc_time = ps3_set_rtc_time,
274 .get_rtc_time = ps3_get_rtc_time,
275 .set_dabr = ps3_set_dabr, 273 .set_dabr = ps3_set_dabr,
276 .calibrate_decr = ps3_calibrate_decr, 274 .calibrate_decr = ps3_calibrate_decr,
277 .progress = ps3_progress, 275 .progress = ps3_progress,
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 58311a867851..a705fffbb498 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -376,7 +376,7 @@ static int ps3_system_bus_probe(struct device *_dev)
376 struct ps3_system_bus_driver *drv; 376 struct ps3_system_bus_driver *drv;
377 377
378 BUG_ON(!dev); 378 BUG_ON(!dev);
379 pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); 379 dev_dbg(_dev, "%s:%d\n", __func__, __LINE__);
380 380
381 drv = ps3_system_bus_dev_to_system_bus_drv(dev); 381 drv = ps3_system_bus_dev_to_system_bus_drv(dev);
382 BUG_ON(!drv); 382 BUG_ON(!drv);
@@ -398,7 +398,7 @@ static int ps3_system_bus_remove(struct device *_dev)
398 struct ps3_system_bus_driver *drv; 398 struct ps3_system_bus_driver *drv;
399 399
400 BUG_ON(!dev); 400 BUG_ON(!dev);
401 pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); 401 dev_dbg(_dev, "%s:%d\n", __func__, __LINE__);
402 402
403 drv = ps3_system_bus_dev_to_system_bus_drv(dev); 403 drv = ps3_system_bus_dev_to_system_bus_drv(dev);
404 BUG_ON(!drv); 404 BUG_ON(!drv);
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index d0daf7d6d3b2..b178a1e66c91 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -19,6 +19,7 @@
19 */ 19 */
20 20
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/platform_device.h>
22 23
23#include <asm/rtc.h> 24#include <asm/rtc.h>
24#include <asm/lv1call.h> 25#include <asm/lv1call.h>
@@ -74,23 +75,20 @@ static u64 read_rtc(void)
74 return rtc_val; 75 return rtc_val;
75} 76}
76 77
77int ps3_set_rtc_time(struct rtc_time *tm) 78unsigned long __init ps3_get_boot_time(void)
78{ 79{
79 u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 80 return read_rtc() + ps3_os_area_get_rtc_diff();
80 tm->tm_hour, tm->tm_min, tm->tm_sec);
81
82 ps3_os_area_set_rtc_diff(now - read_rtc());
83 return 0;
84} 81}
85 82
86void ps3_get_rtc_time(struct rtc_time *tm) 83static int __init ps3_rtc_init(void)
87{ 84{
88 to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm); 85 struct platform_device *pdev;
89 tm->tm_year -= 1900;
90 tm->tm_mon -= 1;
91}
92 86
93unsigned long __init ps3_get_boot_time(void) 87 pdev = platform_device_register_simple("rtc-ps3", -1, NULL, 0);
94{ 88 if (IS_ERR(pdev))
95 return read_rtc() + ps3_os_area_get_rtc_diff(); 89 return PTR_ERR(pdev);
90
91 return 0;
96} 92}
93
94module_init(ps3_rtc_init);
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index ddc2a307cd50..f0e6f28427bd 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -1,5 +1,5 @@
1config PPC_PSERIES 1config PPC_PSERIES
2 depends on PPC_MULTIPLATFORM && PPC64 2 depends on PPC64 && PPC_BOOK3S
3 bool "IBM pSeries & new (POWER5-based) iSeries" 3 bool "IBM pSeries & new (POWER5-based) iSeries"
4 select MPIC 4 select MPIC
5 select PPC_I8259 5 select PPC_I8259
@@ -25,6 +25,11 @@ config EEH
25 depends on PPC_PSERIES && PCI 25 depends on PPC_PSERIES && PCI
26 default y if !EMBEDDED 26 default y if !EMBEDDED
27 27
28config PSERIES_MSI
29 bool
30 depends on PCI_MSI && EEH
31 default y
32
28config SCANLOG 33config SCANLOG
29 tristate "Scanlog dump interface" 34 tristate "Scanlog dump interface"
30 depends on RTAS_PROC && PPC_PSERIES 35 depends on RTAS_PROC && PPC_PSERIES
@@ -63,3 +68,13 @@ config CMM
63 makes sense for a system running in an LPAR where the unused pages 68 makes sense for a system running in an LPAR where the unused pages
64 will be reused for other LPARs. The interface allows firmware to 69 will be reused for other LPARs. The interface allows firmware to
65 balance memory across many LPARs. 70 balance memory across many LPARs.
71
72config DTL
73 bool "Dispatch Trace Log"
74 depends on PPC_SPLPAR && DEBUG_FS
75 help
76 SPLPAR machines can log hypervisor preempt & dispatch events to a
77 kernel buffer. Saying Y here will enable logging these events,
78 which are accessible through a debugfs file.
79
80 Say N if you are unsure.
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index dfe574af2dc0..790c0b872d4f 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_SCANLOG) += scanlog.o
15obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o 15obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o
16obj-$(CONFIG_KEXEC) += kexec.o 16obj-$(CONFIG_KEXEC) += kexec.o
17obj-$(CONFIG_PCI) += pci.o pci_dlpar.o 17obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
18obj-$(CONFIG_PCI_MSI) += msi.o 18obj-$(CONFIG_PSERIES_MSI) += msi.o
19 19
20obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o 20obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
21obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o 21obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o
@@ -25,3 +25,4 @@ obj-$(CONFIG_HVCS) += hvcserver.o
25obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o 25obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
26obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o 26obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
27obj-$(CONFIG_CMM) += cmm.o 27obj-$(CONFIG_CMM) += cmm.o
28obj-$(CONFIG_DTL) += dtl.o
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
new file mode 100644
index 000000000000..fafcaa0e81ef
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -0,0 +1,278 @@
1/*
2 * Virtual Processor Dispatch Trace Log
3 *
4 * (C) Copyright IBM Corporation 2009
5 *
6 * Author: Jeremy Kerr <jk@ozlabs.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/init.h>
24#include <linux/debugfs.h>
25#include <asm/smp.h>
26#include <asm/system.h>
27#include <asm/uaccess.h>
28
29#include "plpar_wrappers.h"
30
31/*
32 * Layout of entries in the hypervisor's DTL buffer. Although we don't
33 * actually access the internals of an entry (we only need to know the size),
34 * we might as well define it here for reference.
35 */
36struct dtl_entry {
37 u8 dispatch_reason;
38 u8 preempt_reason;
39 u16 processor_id;
40 u32 enqueue_to_dispatch_time;
41 u32 ready_to_enqueue_time;
42 u32 waiting_to_ready_time;
43 u64 timebase;
44 u64 fault_addr;
45 u64 srr0;
46 u64 srr1;
47};
48
49struct dtl {
50 struct dtl_entry *buf;
51 struct dentry *file;
52 int cpu;
53 int buf_entries;
54 u64 last_idx;
55};
56static DEFINE_PER_CPU(struct dtl, dtl);
57
58/*
59 * Dispatch trace log event mask:
60 * 0x7: 0x1: voluntary virtual processor waits
61 * 0x2: time-slice preempts
62 * 0x4: virtual partition memory page faults
63 */
64static u8 dtl_event_mask = 0x7;
65
66
67/*
68 * Size of per-cpu log buffers. Default is just under 16 pages worth.
69 */
70static int dtl_buf_entries = (16 * 85);
71
72
73static int dtl_enable(struct dtl *dtl)
74{
75 unsigned long addr;
76 int ret, hwcpu;
77
78 /* only allow one reader */
79 if (dtl->buf)
80 return -EBUSY;
81
82 /* we need to store the original allocation size for use during read */
83 dtl->buf_entries = dtl_buf_entries;
84
85 dtl->buf = kmalloc_node(dtl->buf_entries * sizeof(struct dtl_entry),
86 GFP_KERNEL, cpu_to_node(dtl->cpu));
87 if (!dtl->buf) {
88 printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
89 __func__, dtl->cpu);
90 return -ENOMEM;
91 }
92
93 /* Register our dtl buffer with the hypervisor. The HV expects the
94 * buffer size to be passed in the second word of the buffer */
95 ((u32 *)dtl->buf)[1] = dtl->buf_entries * sizeof(struct dtl_entry);
96
97 hwcpu = get_hard_smp_processor_id(dtl->cpu);
98 addr = __pa(dtl->buf);
99 ret = register_dtl(hwcpu, addr);
100 if (ret) {
101 printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) "
102 "failed with %d\n", __func__, dtl->cpu, hwcpu, ret);
103 kfree(dtl->buf);
104 return -EIO;
105 }
106
107 /* set our initial buffer indices */
108 dtl->last_idx = lppaca[dtl->cpu].dtl_idx = 0;
109
110 /* ensure that our updates to the lppaca fields have occurred before
111 * we actually enable the logging */
112 smp_wmb();
113
114 /* enable event logging */
115 lppaca[dtl->cpu].dtl_enable_mask = dtl_event_mask;
116
117 return 0;
118}
119
120static void dtl_disable(struct dtl *dtl)
121{
122 int hwcpu = get_hard_smp_processor_id(dtl->cpu);
123
124 lppaca[dtl->cpu].dtl_enable_mask = 0x0;
125
126 unregister_dtl(hwcpu, __pa(dtl->buf));
127
128 kfree(dtl->buf);
129 dtl->buf = NULL;
130 dtl->buf_entries = 0;
131}
132
133/* file interface */
134
135static int dtl_file_open(struct inode *inode, struct file *filp)
136{
137 struct dtl *dtl = inode->i_private;
138 int rc;
139
140 rc = dtl_enable(dtl);
141 if (rc)
142 return rc;
143
144 filp->private_data = dtl;
145 return 0;
146}
147
148static int dtl_file_release(struct inode *inode, struct file *filp)
149{
150 struct dtl *dtl = inode->i_private;
151 dtl_disable(dtl);
152 return 0;
153}
154
155static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len,
156 loff_t *pos)
157{
158 int rc, cur_idx, last_idx, n_read, n_req, read_size;
159 struct dtl *dtl;
160
161 if ((len % sizeof(struct dtl_entry)) != 0)
162 return -EINVAL;
163
164 dtl = filp->private_data;
165
166 /* requested number of entries to read */
167 n_req = len / sizeof(struct dtl_entry);
168
169 /* actual number of entries read */
170 n_read = 0;
171
172 cur_idx = lppaca[dtl->cpu].dtl_idx;
173 last_idx = dtl->last_idx;
174
175 if (cur_idx - last_idx > dtl->buf_entries) {
176 pr_debug("%s: hv buffer overflow for cpu %d, samples lost\n",
177 __func__, dtl->cpu);
178 }
179
180 cur_idx %= dtl->buf_entries;
181 last_idx %= dtl->buf_entries;
182
183 /* read the tail of the buffer if we've wrapped */
184 if (last_idx > cur_idx) {
185 read_size = min(n_req, dtl->buf_entries - last_idx);
186
187 rc = copy_to_user(buf, &dtl->buf[last_idx],
188 read_size * sizeof(struct dtl_entry));
189 if (rc)
190 return -EFAULT;
191
192 last_idx = 0;
193 n_req -= read_size;
194 n_read += read_size;
195 buf += read_size * sizeof(struct dtl_entry);
196 }
197
198 /* .. and now the head */
199 read_size = min(n_req, cur_idx - last_idx);
200 rc = copy_to_user(buf, &dtl->buf[last_idx],
201 read_size * sizeof(struct dtl_entry));
202 if (rc)
203 return -EFAULT;
204
205 n_read += read_size;
206 dtl->last_idx += n_read;
207
208 return n_read * sizeof(struct dtl_entry);
209}
210
211static struct file_operations dtl_fops = {
212 .open = dtl_file_open,
213 .release = dtl_file_release,
214 .read = dtl_file_read,
215 .llseek = no_llseek,
216};
217
218static struct dentry *dtl_dir;
219
220static int dtl_setup_file(struct dtl *dtl)
221{
222 char name[10];
223
224 sprintf(name, "cpu-%d", dtl->cpu);
225
226 dtl->file = debugfs_create_file(name, 0400, dtl_dir, dtl, &dtl_fops);
227 if (!dtl->file)
228 return -ENOMEM;
229
230 return 0;
231}
232
233static int dtl_init(void)
234{
235 struct dentry *event_mask_file, *buf_entries_file;
236 int rc, i;
237
238 if (!firmware_has_feature(FW_FEATURE_SPLPAR))
239 return -ENODEV;
240
241 /* set up common debugfs structure */
242
243 rc = -ENOMEM;
244 dtl_dir = debugfs_create_dir("dtl", powerpc_debugfs_root);
245 if (!dtl_dir) {
246 printk(KERN_WARNING "%s: can't create dtl root dir\n",
247 __func__);
248 goto err;
249 }
250
251 event_mask_file = debugfs_create_x8("dtl_event_mask", 0600,
252 dtl_dir, &dtl_event_mask);
253 buf_entries_file = debugfs_create_u32("dtl_buf_entries", 0600,
254 dtl_dir, &dtl_buf_entries);
255
256 if (!event_mask_file || !buf_entries_file) {
257 printk(KERN_WARNING "%s: can't create dtl files\n", __func__);
258 goto err_remove_dir;
259 }
260
261 /* set up the per-cpu log structures */
262 for_each_possible_cpu(i) {
263 struct dtl *dtl = &per_cpu(dtl, i);
264 dtl->cpu = i;
265
266 rc = dtl_setup_file(dtl);
267 if (rc)
268 goto err_remove_dir;
269 }
270
271 return 0;
272
273err_remove_dir:
274 debugfs_remove_recursive(dtl_dir);
275err:
276 return rc;
277}
278arch_initcall(dtl_init);
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 0ad56ff7b4a0..380420f8c400 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -79,6 +79,40 @@ static int irq_in_use(unsigned int irq)
79 return rc; 79 return rc;
80} 80}
81 81
82/**
83 * eeh_disable_irq - disable interrupt for the recovering device
84 */
85static void eeh_disable_irq(struct pci_dev *dev)
86{
87 struct device_node *dn = pci_device_to_OF_node(dev);
88
89 /* Don't disable MSI and MSI-X interrupts. They are
90 * effectively disabled by the DMA Stopped state
91 * when an EEH error occurs.
92 */
93 if (dev->msi_enabled || dev->msix_enabled)
94 return;
95
96 if (!irq_in_use(dev->irq))
97 return;
98
99 PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
100 disable_irq_nosync(dev->irq);
101}
102
103/**
104 * eeh_enable_irq - enable interrupt for the recovering device
105 */
106static void eeh_enable_irq(struct pci_dev *dev)
107{
108 struct device_node *dn = pci_device_to_OF_node(dev);
109
110 if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
111 PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
112 enable_irq(dev->irq);
113 }
114}
115
82/* ------------------------------------------------------- */ 116/* ------------------------------------------------------- */
83/** 117/**
84 * eeh_report_error - report pci error to each device driver 118 * eeh_report_error - report pci error to each device driver
@@ -98,11 +132,8 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata)
98 if (!driver) 132 if (!driver)
99 return; 133 return;
100 134
101 if (irq_in_use (dev->irq)) { 135 eeh_disable_irq(dev);
102 struct device_node *dn = pci_device_to_OF_node(dev); 136
103 PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
104 disable_irq_nosync(dev->irq);
105 }
106 if (!driver->err_handler || 137 if (!driver->err_handler ||
107 !driver->err_handler->error_detected) 138 !driver->err_handler->error_detected)
108 return; 139 return;
@@ -147,15 +178,12 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)
147{ 178{
148 enum pci_ers_result rc, *res = userdata; 179 enum pci_ers_result rc, *res = userdata;
149 struct pci_driver *driver = dev->driver; 180 struct pci_driver *driver = dev->driver;
150 struct device_node *dn = pci_device_to_OF_node(dev);
151 181
152 if (!driver) 182 if (!driver)
153 return; 183 return;
154 184
155 if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) { 185 eeh_enable_irq(dev);
156 PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED; 186
157 enable_irq(dev->irq);
158 }
159 if (!driver->err_handler || 187 if (!driver->err_handler ||
160 !driver->err_handler->slot_reset) 188 !driver->err_handler->slot_reset)
161 return; 189 return;
@@ -174,17 +202,14 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata)
174static void eeh_report_resume(struct pci_dev *dev, void *userdata) 202static void eeh_report_resume(struct pci_dev *dev, void *userdata)
175{ 203{
176 struct pci_driver *driver = dev->driver; 204 struct pci_driver *driver = dev->driver;
177 struct device_node *dn = pci_device_to_OF_node(dev);
178 205
179 dev->error_state = pci_channel_io_normal; 206 dev->error_state = pci_channel_io_normal;
180 207
181 if (!driver) 208 if (!driver)
182 return; 209 return;
183 210
184 if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) { 211 eeh_enable_irq(dev);
185 PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED; 212
186 enable_irq(dev->irq);
187 }
188 if (!driver->err_handler || 213 if (!driver->err_handler ||
189 !driver->err_handler->resume) 214 !driver->err_handler->resume)
190 return; 215 return;
@@ -208,15 +233,12 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata)
208 if (!driver) 233 if (!driver)
209 return; 234 return;
210 235
211 if (irq_in_use (dev->irq)) { 236 eeh_disable_irq(dev);
212 struct device_node *dn = pci_device_to_OF_node(dev); 237
213 PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; 238 if (!driver->err_handler ||
214 disable_irq_nosync(dev->irq); 239 !driver->err_handler->error_detected)
215 }
216 if (!driver->err_handler)
217 return;
218 if (!driver->err_handler->error_detected)
219 return; 240 return;
241
220 driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); 242 driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
221} 243}
222 244
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index f15222bbe136..bf2e1ac41308 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -71,11 +71,13 @@ static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs)
71 } while (rtas_busy_delay(rc)); 71 } while (rtas_busy_delay(rc));
72 72
73 /* 73 /*
74 * If the RTAS call succeeded, check the number of irqs is actually 74 * If the RTAS call succeeded, return the number of irqs allocated.
75 * what we asked for. If not, return an error. 75 * If not, make sure we return a negative error code.
76 */ 76 */
77 if (rc == 0 && rtas_ret[0] != num_irqs) 77 if (rc == 0)
78 rc = -ENOSPC; 78 rc = rtas_ret[0];
79 else if (rc > 0)
80 rc = -rc;
79 81
80 pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d), got %d rc = %d\n", 82 pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d), got %d rc = %d\n",
81 func, num_irqs, rtas_ret[0], rc); 83 func, num_irqs, rtas_ret[0], rc);
@@ -91,7 +93,7 @@ static void rtas_disable_msi(struct pci_dev *pdev)
91 if (!pdn) 93 if (!pdn)
92 return; 94 return;
93 95
94 if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0)) 96 if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0)
95 pr_debug("rtas_msi: Setting MSIs to 0 failed!\n"); 97 pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
96} 98}
97 99
@@ -132,7 +134,7 @@ static void rtas_teardown_msi_irqs(struct pci_dev *pdev)
132 rtas_disable_msi(pdev); 134 rtas_disable_msi(pdev);
133} 135}
134 136
135static int check_req_msi(struct pci_dev *pdev, int nvec) 137static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
136{ 138{
137 struct device_node *dn; 139 struct device_node *dn;
138 struct pci_dn *pdn; 140 struct pci_dn *pdn;
@@ -144,26 +146,235 @@ static int check_req_msi(struct pci_dev *pdev, int nvec)
144 146
145 dn = pdn->node; 147 dn = pdn->node;
146 148
147 req_msi = of_get_property(dn, "ibm,req#msi", NULL); 149 req_msi = of_get_property(dn, prop_name, NULL);
148 if (!req_msi) { 150 if (!req_msi) {
149 pr_debug("rtas_msi: No ibm,req#msi on %s\n", dn->full_name); 151 pr_debug("rtas_msi: No %s on %s\n", prop_name, dn->full_name);
150 return -ENOENT; 152 return -ENOENT;
151 } 153 }
152 154
153 if (*req_msi < nvec) { 155 if (*req_msi < nvec) {
154 pr_debug("rtas_msi: ibm,req#msi requests < %d MSIs\n", nvec); 156 pr_debug("rtas_msi: %s requests < %d MSIs\n", prop_name, nvec);
155 return -ENOSPC; 157
158 if (*req_msi == 0) /* Be paranoid */
159 return -ENOSPC;
160
161 return *req_msi;
156 } 162 }
157 163
158 return 0; 164 return 0;
159} 165}
160 166
167static int check_req_msi(struct pci_dev *pdev, int nvec)
168{
169 return check_req(pdev, nvec, "ibm,req#msi");
170}
171
172static int check_req_msix(struct pci_dev *pdev, int nvec)
173{
174 return check_req(pdev, nvec, "ibm,req#msi-x");
175}
176
177/* Quota calculation */
178
179static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
180{
181 struct device_node *dn;
182 const u32 *p;
183
184 dn = of_node_get(pci_device_to_OF_node(dev));
185 while (dn) {
186 p = of_get_property(dn, "ibm,pe-total-#msi", NULL);
187 if (p) {
188 pr_debug("rtas_msi: found prop on dn %s\n",
189 dn->full_name);
190 *total = *p;
191 return dn;
192 }
193
194 dn = of_get_next_parent(dn);
195 }
196
197 return NULL;
198}
199
200static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
201{
202 struct device_node *dn;
203
204 /* Found our PE and assume 8 at that point. */
205
206 dn = pci_device_to_OF_node(dev);
207 if (!dn)
208 return NULL;
209
210 dn = find_device_pe(dn);
211 if (!dn)
212 return NULL;
213
214 /* We actually want the parent */
215 dn = of_get_parent(dn);
216 if (!dn)
217 return NULL;
218
219 /* Hardcode of 8 for old firmwares */
220 *total = 8;
221 pr_debug("rtas_msi: using PE dn %s\n", dn->full_name);
222
223 return dn;
224}
225
226struct msi_counts {
227 struct device_node *requestor;
228 int num_devices;
229 int request;
230 int quota;
231 int spare;
232 int over_quota;
233};
234
235static void *count_non_bridge_devices(struct device_node *dn, void *data)
236{
237 struct msi_counts *counts = data;
238 const u32 *p;
239 u32 class;
240
241 pr_debug("rtas_msi: counting %s\n", dn->full_name);
242
243 p = of_get_property(dn, "class-code", NULL);
244 class = p ? *p : 0;
245
246 if ((class >> 8) != PCI_CLASS_BRIDGE_PCI)
247 counts->num_devices++;
248
249 return NULL;
250}
251
252static void *count_spare_msis(struct device_node *dn, void *data)
253{
254 struct msi_counts *counts = data;
255 const u32 *p;
256 int req;
257
258 if (dn == counts->requestor)
259 req = counts->request;
260 else {
261 /* We don't know if a driver will try to use MSI or MSI-X,
262 * so we just have to punt and use the larger of the two. */
263 req = 0;
264 p = of_get_property(dn, "ibm,req#msi", NULL);
265 if (p)
266 req = *p;
267
268 p = of_get_property(dn, "ibm,req#msi-x", NULL);
269 if (p)
270 req = max(req, (int)*p);
271 }
272
273 if (req < counts->quota)
274 counts->spare += counts->quota - req;
275 else if (req > counts->quota)
276 counts->over_quota++;
277
278 return NULL;
279}
280
281static int msi_quota_for_device(struct pci_dev *dev, int request)
282{
283 struct device_node *pe_dn;
284 struct msi_counts counts;
285 int total;
286
287 pr_debug("rtas_msi: calc quota for %s, request %d\n", pci_name(dev),
288 request);
289
290 pe_dn = find_pe_total_msi(dev, &total);
291 if (!pe_dn)
292 pe_dn = find_pe_dn(dev, &total);
293
294 if (!pe_dn) {
295 pr_err("rtas_msi: couldn't find PE for %s\n", pci_name(dev));
296 goto out;
297 }
298
299 pr_debug("rtas_msi: found PE %s\n", pe_dn->full_name);
300
301 memset(&counts, 0, sizeof(struct msi_counts));
302
303 /* Work out how many devices we have below this PE */
304 traverse_pci_devices(pe_dn, count_non_bridge_devices, &counts);
305
306 if (counts.num_devices == 0) {
307 pr_err("rtas_msi: found 0 devices under PE for %s\n",
308 pci_name(dev));
309 goto out;
310 }
311
312 counts.quota = total / counts.num_devices;
313 if (request <= counts.quota)
314 goto out;
315
316 /* else, we have some more calculating to do */
317 counts.requestor = pci_device_to_OF_node(dev);
318 counts.request = request;
319 traverse_pci_devices(pe_dn, count_spare_msis, &counts);
320
321 /* If the quota isn't an integer multiple of the total, we can
322 * use the remainder as spare MSIs for anyone that wants them. */
323 counts.spare += total % counts.num_devices;
324
325 /* Divide any spare by the number of over-quota requestors */
326 if (counts.over_quota)
327 counts.quota += counts.spare / counts.over_quota;
328
329 /* And finally clamp the request to the possibly adjusted quota */
330 request = min(counts.quota, request);
331
332 pr_debug("rtas_msi: request clamped to quota %d\n", request);
333out:
334 of_node_put(pe_dn);
335
336 return request;
337}
338
161static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type) 339static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type)
162{ 340{
341 int quota, rc;
342
163 if (type == PCI_CAP_ID_MSIX) 343 if (type == PCI_CAP_ID_MSIX)
164 pr_debug("rtas_msi: MSI-X untested, trying anyway.\n"); 344 rc = check_req_msix(pdev, nvec);
345 else
346 rc = check_req_msi(pdev, nvec);
347
348 if (rc)
349 return rc;
350
351 quota = msi_quota_for_device(pdev, nvec);
165 352
166 return check_req_msi(pdev, nvec); 353 if (quota && quota < nvec)
354 return quota;
355
356 return 0;
357}
358
359static int check_msix_entries(struct pci_dev *pdev)
360{
361 struct msi_desc *entry;
362 int expected;
363
364 /* There's no way for us to express to firmware that we want
365 * a discontiguous, or non-zero based, range of MSI-X entries.
366 * So we must reject such requests. */
367
368 expected = 0;
369 list_for_each_entry(entry, &pdev->msi_list, list) {
370 if (entry->msi_attrib.entry_nr != expected) {
371 pr_debug("rtas_msi: bad MSI-X entries.\n");
372 return -EINVAL;
373 }
374 expected++;
375 }
376
377 return 0;
167} 378}
168 379
169static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 380static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
@@ -177,6 +388,9 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
177 if (!pdn) 388 if (!pdn)
178 return -ENODEV; 389 return -ENODEV;
179 390
391 if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev))
392 return -EINVAL;
393
180 /* 394 /*
181 * Try the new more explicit firmware interface, if that fails fall 395 * Try the new more explicit firmware interface, if that fails fall
182 * back to the old interface. The old interface is known to never 396 * back to the old interface. The old interface is known to never
@@ -185,21 +399,21 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
185 if (type == PCI_CAP_ID_MSI) { 399 if (type == PCI_CAP_ID_MSI) {
186 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); 400 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
187 401
188 if (rc) { 402 if (rc < 0) {
189 pr_debug("rtas_msi: trying the old firmware call.\n"); 403 pr_debug("rtas_msi: trying the old firmware call.\n");
190 rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); 404 rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
191 } 405 }
192 } else 406 } else
193 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec); 407 rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
194 408
195 if (rc) { 409 if (rc != nvec) {
196 pr_debug("rtas_msi: rtas_change_msi() failed\n"); 410 pr_debug("rtas_msi: rtas_change_msi() failed\n");
197 return rc; 411 return rc;
198 } 412 }
199 413
200 i = 0; 414 i = 0;
201 list_for_each_entry(entry, &pdev->msi_list, list) { 415 list_for_each_entry(entry, &pdev->msi_list, list) {
202 hwirq = rtas_query_irq_number(pdn, i); 416 hwirq = rtas_query_irq_number(pdn, i++);
203 if (hwirq < 0) { 417 if (hwirq < 0) {
204 pr_debug("rtas_msi: error (%d) getting hwirq\n", rc); 418 pr_debug("rtas_msi: error (%d) getting hwirq\n", rc);
205 return hwirq; 419 return hwirq;
@@ -234,8 +448,8 @@ static void rtas_msi_pci_irq_fixup(struct pci_dev *pdev)
234 } 448 }
235 449
236 /* No MSI -> MSIs can't have been assigned by fw, leave LSI */ 450 /* No MSI -> MSIs can't have been assigned by fw, leave LSI */
237 if (check_req_msi(pdev, 1)) { 451 if (check_req_msi(pdev, 1) && check_req_msix(pdev, 1)) {
238 dev_dbg(&pdev->dev, "rtas_msi: no req#msi, nothing to do.\n"); 452 dev_dbg(&pdev->dev, "rtas_msi: no req#msi/x, nothing to do.\n");
239 return; 453 return;
240 } 454 }
241 455
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 5e1ed3d60ee5..ad152a0e3946 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -137,11 +137,9 @@ EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
137struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) 137struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
138{ 138{
139 struct pci_controller *phb; 139 struct pci_controller *phb;
140 int primary;
141 140
142 pr_debug("PCI: Initializing new hotplug PHB %s\n", dn->full_name); 141 pr_debug("PCI: Initializing new hotplug PHB %s\n", dn->full_name);
143 142
144 primary = list_empty(&hose_list);
145 phb = pcibios_alloc_controller(dn); 143 phb = pcibios_alloc_controller(dn);
146 if (!phb) 144 if (!phb)
147 return NULL; 145 return NULL;
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index d967c1893ab5..a24a6b2333b2 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -43,6 +43,16 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)
43 return vpa_call(0x3, cpu, vpa); 43 return vpa_call(0x3, cpu, vpa);
44} 44}
45 45
46static inline long unregister_dtl(unsigned long cpu, unsigned long vpa)
47{
48 return vpa_call(0x6, cpu, vpa);
49}
50
51static inline long register_dtl(unsigned long cpu, unsigned long vpa)
52{
53 return vpa_call(0x2, cpu, vpa);
54}
55
46static inline long plpar_page_set_loaned(unsigned long vpa) 56static inline long plpar_page_set_loaned(unsigned long vpa)
47{ 57{
48 unsigned long cmo_page_sz = cmo_get_page_size(); 58 unsigned long cmo_page_sz = cmo_get_page_size();
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index c591a25b0b0d..b6f1b137d427 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -468,9 +468,13 @@ static int do_update_property(char *buf, size_t bufsize)
468 468
469 rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, 469 rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
470 action, value); 470 action, value);
471 if (rc == NOTIFY_BAD) {
472 rc = prom_update_property(np, oldprop, newprop);
473 return -ENOMEM;
474 }
471 } 475 }
472 476
473 return rc; 477 return 0;
474} 478}
475 479
476/** 480/**