diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-07-18 13:53:16 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-18 13:53:16 -0400 |
commit | 9b610fda0df5d0f0b0c64242e37441ad1b384aac (patch) | |
tree | 0ea14b15f2e6546f37fe18d8ac3dc83077ec0e55 /arch/powerpc/platforms | |
parent | b8f8c3cf0a4ac0632ec3f0e15e9dc0c29de917af (diff) | |
parent | 5b664cb235e97afbf34db9c4d77f08ebd725335e (diff) |
Merge branch 'linus' into timers/nohz
Diffstat (limited to 'arch/powerpc/platforms')
84 files changed, 2888 insertions, 560 deletions
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 6abe91357eee..249ba01c6674 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig | |||
@@ -17,6 +17,15 @@ config EBONY | |||
17 | help | 17 | help |
18 | This option enables support for the IBM PPC440GP evaluation board. | 18 | This option enables support for the IBM PPC440GP evaluation board. |
19 | 19 | ||
20 | config SAM440EP | ||
21 | bool "Sam440ep" | ||
22 | depends on 44x | ||
23 | default n | ||
24 | select 440EP | ||
25 | select PCI | ||
26 | help | ||
27 | This option enables support for the ACube Sam440ep board. | ||
28 | |||
20 | config SEQUOIA | 29 | config SEQUOIA |
21 | bool "Sequoia" | 30 | bool "Sequoia" |
22 | depends on 44x | 31 | depends on 44x |
@@ -102,6 +111,22 @@ config YOSEMITE | |||
102 | # help | 111 | # help |
103 | # This option enables support for the IBM PPC440GX evaluation board. | 112 | # This option enables support for the IBM PPC440GX evaluation board. |
104 | 113 | ||
114 | config XILINX_VIRTEX440_GENERIC_BOARD | ||
115 | bool "Generic Xilinx Virtex 440 board" | ||
116 | depends on 44x | ||
117 | default n | ||
118 | select XILINX_VIRTEX_5_FXT | ||
119 | help | ||
120 | This option enables generic support for Xilinx Virtex based boards | ||
121 | that use a 440 based processor in the Virtex 5 FXT FPGA architecture. | ||
122 | |||
123 | The generic virtex board support matches any device tree which | ||
124 | specifies 'xlnx,virtex440' in its compatible field. This includes | ||
125 | the Xilinx ML5xx reference designs using the powerpc core. | ||
126 | |||
127 | Most Virtex 5 designs should use this unless it needs to do some | ||
128 | special configuration at board probe time. | ||
129 | |||
105 | # 44x specific CPU modules, selected based on the board above. | 130 | # 44x specific CPU modules, selected based on the board above. |
106 | config 440EP | 131 | config 440EP |
107 | bool | 132 | bool |
@@ -152,3 +177,13 @@ config 460EX | |||
152 | # 44x errata/workaround config symbols, selected by the CPU models above | 177 | # 44x errata/workaround config symbols, selected by the CPU models above |
153 | config IBM440EP_ERR42 | 178 | config IBM440EP_ERR42 |
154 | bool | 179 | bool |
180 | |||
181 | # Xilinx specific config options. | ||
182 | config XILINX_VIRTEX | ||
183 | bool | ||
184 | |||
185 | # Xilinx Virtex 5 FXT FPGA architecture, selected by a Xilinx board above | ||
186 | config XILINX_VIRTEX_5_FXT | ||
187 | bool | ||
188 | select XILINX_VIRTEX | ||
189 | |||
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile index 774165f9acdd..8d0b1a192d62 100644 --- a/arch/powerpc/platforms/44x/Makefile +++ b/arch/powerpc/platforms/44x/Makefile | |||
@@ -3,9 +3,11 @@ obj-$(CONFIG_EBONY) += ebony.o | |||
3 | obj-$(CONFIG_TAISHAN) += taishan.o | 3 | obj-$(CONFIG_TAISHAN) += taishan.o |
4 | obj-$(CONFIG_BAMBOO) += bamboo.o | 4 | obj-$(CONFIG_BAMBOO) += bamboo.o |
5 | obj-$(CONFIG_YOSEMITE) += bamboo.o | 5 | obj-$(CONFIG_YOSEMITE) += bamboo.o |
6 | obj-$(CONFIG_SAM440EP) += sam440ep.o | ||
6 | obj-$(CONFIG_SEQUOIA) += sequoia.o | 7 | obj-$(CONFIG_SEQUOIA) += sequoia.o |
7 | obj-$(CONFIG_KATMAI) += katmai.o | 8 | obj-$(CONFIG_KATMAI) += katmai.o |
8 | obj-$(CONFIG_RAINIER) += rainier.o | 9 | obj-$(CONFIG_RAINIER) += rainier.o |
9 | obj-$(CONFIG_WARP) += warp.o | 10 | obj-$(CONFIG_WARP) += warp.o |
10 | obj-$(CONFIG_WARP) += warp-nand.o | 11 | obj-$(CONFIG_WARP) += warp-nand.o |
11 | obj-$(CONFIG_CANYONLANDS) += canyonlands.o | 12 | obj-$(CONFIG_CANYONLANDS) += canyonlands.o |
13 | obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o | ||
diff --git a/arch/powerpc/platforms/44x/sam440ep.c b/arch/powerpc/platforms/44x/sam440ep.c new file mode 100644 index 000000000000..47f10e647735 --- /dev/null +++ b/arch/powerpc/platforms/44x/sam440ep.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * Sam440ep board specific routines based off bamboo.c code | ||
3 | * original copyrights below | ||
4 | * | ||
5 | * Wade Farnsworth <wfarnsworth@mvista.com> | ||
6 | * Copyright 2004 MontaVista Software Inc. | ||
7 | * | ||
8 | * Rewritten and ported to the merged powerpc tree: | ||
9 | * Josh Boyer <jwboyer@linux.vnet.ibm.com> | ||
10 | * Copyright 2007 IBM Corporation | ||
11 | * | ||
12 | * Modified from bamboo.c for sam440ep: | ||
13 | * Copyright 2008 Giuseppe Coviello <gicoviello@gmail.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2 of the License, or (at your | ||
18 | * option) any later version. | ||
19 | */ | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/of_platform.h> | ||
22 | |||
23 | #include <asm/machdep.h> | ||
24 | #include <asm/prom.h> | ||
25 | #include <asm/udbg.h> | ||
26 | #include <asm/time.h> | ||
27 | #include <asm/uic.h> | ||
28 | #include <asm/pci-bridge.h> | ||
29 | #include <asm/ppc4xx.h> | ||
30 | #include <linux/i2c.h> | ||
31 | |||
32 | static __initdata struct of_device_id sam440ep_of_bus[] = { | ||
33 | { .compatible = "ibm,plb4", }, | ||
34 | { .compatible = "ibm,opb", }, | ||
35 | { .compatible = "ibm,ebc", }, | ||
36 | {}, | ||
37 | }; | ||
38 | |||
39 | static int __init sam440ep_device_probe(void) | ||
40 | { | ||
41 | of_platform_bus_probe(NULL, sam440ep_of_bus, NULL); | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | machine_device_initcall(sam440ep, sam440ep_device_probe); | ||
46 | |||
47 | static int __init sam440ep_probe(void) | ||
48 | { | ||
49 | unsigned long root = of_get_flat_dt_root(); | ||
50 | |||
51 | if (!of_flat_dt_is_compatible(root, "acube,sam440ep")) | ||
52 | return 0; | ||
53 | |||
54 | ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC; | ||
55 | |||
56 | return 1; | ||
57 | } | ||
58 | |||
59 | define_machine(sam440ep) { | ||
60 | .name = "Sam440ep", | ||
61 | .probe = sam440ep_probe, | ||
62 | .progress = udbg_progress, | ||
63 | .init_IRQ = uic_init_tree, | ||
64 | .get_irq = uic_get_irq, | ||
65 | .restart = ppc4xx_reset_system, | ||
66 | .calibrate_decr = generic_calibrate_decr, | ||
67 | }; | ||
68 | |||
69 | static struct i2c_board_info sam440ep_rtc_info = { | ||
70 | .type = "m41st85", | ||
71 | .addr = 0x68, | ||
72 | .irq = -1, | ||
73 | }; | ||
74 | |||
75 | static int sam440ep_setup_rtc(void) | ||
76 | { | ||
77 | return i2c_register_board_info(0, &sam440ep_rtc_info, 1); | ||
78 | } | ||
79 | machine_device_initcall(sam440ep, sam440ep_setup_rtc); | ||
diff --git a/arch/powerpc/platforms/44x/virtex.c b/arch/powerpc/platforms/44x/virtex.c new file mode 100644 index 000000000000..68637faf70ae --- /dev/null +++ b/arch/powerpc/platforms/44x/virtex.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Xilinx Virtex 5FXT based board support, derived from | ||
3 | * the Xilinx Virtex (IIpro & 4FX) based board support | ||
4 | * | ||
5 | * Copyright 2007 Secret Lab Technologies Ltd. | ||
6 | * Copyright 2008 Xilinx, Inc. | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/of_platform.h> | ||
15 | #include <asm/machdep.h> | ||
16 | #include <asm/prom.h> | ||
17 | #include <asm/time.h> | ||
18 | #include <asm/xilinx_intc.h> | ||
19 | #include <asm/reg.h> | ||
20 | #include <asm/ppc4xx.h> | ||
21 | #include "44x.h" | ||
22 | |||
23 | static struct of_device_id xilinx_of_bus_ids[] __initdata = { | ||
24 | { .compatible = "simple-bus", }, | ||
25 | { .compatible = "xlnx,plb-v46-1.00.a", }, | ||
26 | { .compatible = "xlnx,plb-v46-1.02.a", }, | ||
27 | { .compatible = "xlnx,plb-v34-1.01.a", }, | ||
28 | { .compatible = "xlnx,plb-v34-1.02.a", }, | ||
29 | { .compatible = "xlnx,opb-v20-1.10.c", }, | ||
30 | { .compatible = "xlnx,dcr-v29-1.00.a", }, | ||
31 | { .compatible = "xlnx,compound", }, | ||
32 | {} | ||
33 | }; | ||
34 | |||
35 | static int __init virtex_device_probe(void) | ||
36 | { | ||
37 | of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | machine_device_initcall(virtex, virtex_device_probe); | ||
42 | |||
43 | static int __init virtex_probe(void) | ||
44 | { | ||
45 | unsigned long root = of_get_flat_dt_root(); | ||
46 | |||
47 | if (!of_flat_dt_is_compatible(root, "xlnx,virtex440")) | ||
48 | return 0; | ||
49 | |||
50 | return 1; | ||
51 | } | ||
52 | |||
53 | define_machine(virtex) { | ||
54 | .name = "Xilinx Virtex440", | ||
55 | .probe = virtex_probe, | ||
56 | .init_IRQ = xilinx_intc_init_tree, | ||
57 | .get_irq = xilinx_intc_get_irq, | ||
58 | .calibrate_decr = generic_calibrate_decr, | ||
59 | .restart = ppc4xx_reset_system, | ||
60 | }; | ||
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c index 9150318cfc56..e55746b824b4 100644 --- a/arch/powerpc/platforms/44x/warp-nand.c +++ b/arch/powerpc/platforms/44x/warp-nand.c | |||
@@ -11,8 +11,10 @@ | |||
11 | #include <linux/mtd/partitions.h> | 11 | #include <linux/mtd/partitions.h> |
12 | #include <linux/mtd/nand.h> | 12 | #include <linux/mtd/nand.h> |
13 | #include <linux/mtd/ndfc.h> | 13 | #include <linux/mtd/ndfc.h> |
14 | #include <linux/of.h> | ||
14 | #include <asm/machdep.h> | 15 | #include <asm/machdep.h> |
15 | 16 | ||
17 | |||
16 | #ifdef CONFIG_MTD_NAND_NDFC | 18 | #ifdef CONFIG_MTD_NAND_NDFC |
17 | 19 | ||
18 | #define CS_NAND_0 1 /* use chip select 1 for NAND device 0 */ | 20 | #define CS_NAND_0 1 /* use chip select 1 for NAND device 0 */ |
@@ -35,13 +37,23 @@ static struct mtd_partition nand_parts[] = { | |||
35 | { | 37 | { |
36 | .name = "root", | 38 | .name = "root", |
37 | .offset = 0x0200000, | 39 | .offset = 0x0200000, |
38 | .size = 0x3400000 | 40 | .size = 0x3E00000 |
41 | }, | ||
42 | { | ||
43 | .name = "persistent", | ||
44 | .offset = 0x4000000, | ||
45 | .size = 0x4000000 | ||
39 | }, | 46 | }, |
40 | { | 47 | { |
41 | .name = "user", | 48 | .name = "persistent1", |
42 | .offset = 0x3600000, | 49 | .offset = 0x8000000, |
43 | .size = 0x0A00000 | 50 | .size = 0x4000000 |
44 | }, | 51 | }, |
52 | { | ||
53 | .name = "persistent2", | ||
54 | .offset = 0xC000000, | ||
55 | .size = 0x4000000 | ||
56 | } | ||
45 | }; | 57 | }; |
46 | 58 | ||
47 | struct ndfc_controller_settings warp_ndfc_settings = { | 59 | struct ndfc_controller_settings warp_ndfc_settings = { |
@@ -67,27 +79,22 @@ static struct platform_device warp_ndfc_device = { | |||
67 | .resource = &warp_ndfc, | 79 | .resource = &warp_ndfc, |
68 | }; | 80 | }; |
69 | 81 | ||
70 | static struct nand_ecclayout nand_oob_16 = { | 82 | /* Do NOT set the ecclayout: let it default so it is correct for both |
71 | .eccbytes = 3, | 83 | * 64M and 256M flash chips. |
72 | .eccpos = { 0, 1, 2, 3, 6, 7 }, | 84 | */ |
73 | .oobfree = { {.offset = 8, .length = 16} } | ||
74 | }; | ||
75 | |||
76 | static struct platform_nand_chip warp_nand_chip0 = { | 85 | static struct platform_nand_chip warp_nand_chip0 = { |
77 | .nr_chips = 1, | 86 | .nr_chips = 1, |
78 | .chip_offset = CS_NAND_0, | 87 | .chip_offset = CS_NAND_0, |
79 | .nr_partitions = ARRAY_SIZE(nand_parts), | 88 | .nr_partitions = ARRAY_SIZE(nand_parts), |
80 | .partitions = nand_parts, | 89 | .partitions = nand_parts, |
81 | .chip_delay = 50, | 90 | .chip_delay = 20, |
82 | .ecclayout = &nand_oob_16, | ||
83 | .priv = &warp_chip0_settings, | 91 | .priv = &warp_chip0_settings, |
84 | }; | 92 | }; |
85 | 93 | ||
86 | static struct platform_device warp_nand_device = { | 94 | static struct platform_device warp_nand_device = { |
87 | .name = "ndfc-chip", | 95 | .name = "ndfc-chip", |
88 | .id = 0, | 96 | .id = 0, |
89 | .num_resources = 1, | 97 | .num_resources = 0, |
90 | .resource = &warp_ndfc, | ||
91 | .dev = { | 98 | .dev = { |
92 | .platform_data = &warp_nand_chip0, | 99 | .platform_data = &warp_nand_chip0, |
93 | .parent = &warp_ndfc_device.dev, | 100 | .parent = &warp_ndfc_device.dev, |
@@ -96,6 +103,28 @@ static struct platform_device warp_nand_device = { | |||
96 | 103 | ||
97 | static int warp_setup_nand_flash(void) | 104 | static int warp_setup_nand_flash(void) |
98 | { | 105 | { |
106 | struct device_node *np; | ||
107 | |||
108 | /* Try to detect a rev A based on NOR size. */ | ||
109 | np = of_find_compatible_node(NULL, NULL, "cfi-flash"); | ||
110 | if (np) { | ||
111 | struct property *pp; | ||
112 | |||
113 | pp = of_find_property(np, "reg", NULL); | ||
114 | if (pp && (pp->length == 12)) { | ||
115 | u32 *v = pp->value; | ||
116 | if (v[2] == 0x4000000) { | ||
117 | /* Rev A = 64M NAND */ | ||
118 | warp_nand_chip0.nr_partitions = 3; | ||
119 | |||
120 | nand_parts[1].size = 0x3000000; | ||
121 | nand_parts[2].offset = 0x3200000; | ||
122 | nand_parts[2].size = 0x0e00000; | ||
123 | } | ||
124 | } | ||
125 | of_node_put(np); | ||
126 | } | ||
127 | |||
99 | platform_device_register(&warp_ndfc_device); | 128 | platform_device_register(&warp_ndfc_device); |
100 | platform_device_register(&warp_nand_device); | 129 | platform_device_register(&warp_nand_device); |
101 | 130 | ||
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 39cf6150a72b..9565995cba7f 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c | |||
@@ -12,6 +12,9 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/of_platform.h> | 13 | #include <linux/of_platform.h> |
14 | #include <linux/kthread.h> | 14 | #include <linux/kthread.h> |
15 | #include <linux/i2c.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/delay.h> | ||
15 | 18 | ||
16 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
17 | #include <asm/prom.h> | 20 | #include <asm/prom.h> |
@@ -27,6 +30,18 @@ static __initdata struct of_device_id warp_of_bus[] = { | |||
27 | {}, | 30 | {}, |
28 | }; | 31 | }; |
29 | 32 | ||
33 | static __initdata struct i2c_board_info warp_i2c_info[] = { | ||
34 | { I2C_BOARD_INFO("ad7414", 0x4a) } | ||
35 | }; | ||
36 | |||
37 | static int __init warp_arch_init(void) | ||
38 | { | ||
39 | /* This should go away once support is moved to the dts. */ | ||
40 | i2c_register_board_info(0, warp_i2c_info, ARRAY_SIZE(warp_i2c_info)); | ||
41 | return 0; | ||
42 | } | ||
43 | machine_arch_initcall(warp, warp_arch_init); | ||
44 | |||
30 | static int __init warp_device_probe(void) | 45 | static int __init warp_device_probe(void) |
31 | { | 46 | { |
32 | of_platform_bus_probe(NULL, warp_of_bus, NULL); | 47 | of_platform_bus_probe(NULL, warp_of_bus, NULL); |
@@ -52,61 +67,232 @@ define_machine(warp) { | |||
52 | }; | 67 | }; |
53 | 68 | ||
54 | 69 | ||
55 | #define LED_GREEN (0x80000000 >> 0) | 70 | /* I am not sure this is the best place for this... */ |
56 | #define LED_RED (0x80000000 >> 1) | 71 | static int __init warp_post_info(void) |
72 | { | ||
73 | struct device_node *np; | ||
74 | void __iomem *fpga; | ||
75 | u32 post1, post2; | ||
76 | |||
77 | /* Sighhhh... POST information is in the sd area. */ | ||
78 | np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd"); | ||
79 | if (np == NULL) | ||
80 | return -ENOENT; | ||
81 | |||
82 | fpga = of_iomap(np, 0); | ||
83 | of_node_put(np); | ||
84 | if (fpga == NULL) | ||
85 | return -ENOENT; | ||
86 | |||
87 | post1 = in_be32(fpga + 0x40); | ||
88 | post2 = in_be32(fpga + 0x44); | ||
89 | |||
90 | iounmap(fpga); | ||
91 | |||
92 | if (post1 || post2) | ||
93 | printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2); | ||
94 | else | ||
95 | printk(KERN_INFO "Warp POST OK\n"); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | machine_late_initcall(warp, warp_post_info); | ||
100 | |||
101 | |||
102 | #ifdef CONFIG_SENSORS_AD7414 | ||
103 | |||
104 | static LIST_HEAD(dtm_shutdown_list); | ||
105 | static void __iomem *dtm_fpga; | ||
106 | static void __iomem *gpio_base; | ||
107 | |||
108 | |||
109 | struct dtm_shutdown { | ||
110 | struct list_head list; | ||
111 | void (*func)(void *arg); | ||
112 | void *arg; | ||
113 | }; | ||
57 | 114 | ||
58 | 115 | ||
59 | /* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */ | 116 | int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg) |
60 | void warp_set_power_leds(int green, int red) | ||
61 | { | 117 | { |
62 | static void __iomem *gpio_base = NULL; | 118 | struct dtm_shutdown *shutdown; |
63 | unsigned leds; | 119 | |
64 | 120 | shutdown = kmalloc(sizeof(struct dtm_shutdown), GFP_KERNEL); | |
65 | if (gpio_base == NULL) { | 121 | if (shutdown == NULL) |
66 | struct device_node *np; | 122 | return -ENOMEM; |
67 | 123 | ||
68 | /* Power LEDS are on the second GPIO controller */ | 124 | shutdown->func = func; |
69 | np = of_find_compatible_node(NULL, NULL, "ibm,gpio-440EP"); | 125 | shutdown->arg = arg; |
70 | if (np) | 126 | |
71 | np = of_find_compatible_node(np, NULL, "ibm,gpio-440EP"); | 127 | list_add(&shutdown->list, &dtm_shutdown_list); |
72 | if (np == NULL) { | 128 | |
73 | printk(KERN_ERR __FILE__ ": Unable to find gpio\n"); | 129 | return 0; |
74 | return; | 130 | } |
131 | |||
132 | int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg) | ||
133 | { | ||
134 | struct dtm_shutdown *shutdown; | ||
135 | |||
136 | list_for_each_entry(shutdown, &dtm_shutdown_list, list) | ||
137 | if (shutdown->func == func && shutdown->arg == arg) { | ||
138 | list_del(&shutdown->list); | ||
139 | kfree(shutdown); | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | return -EINVAL; | ||
144 | } | ||
145 | |||
146 | static irqreturn_t temp_isr(int irq, void *context) | ||
147 | { | ||
148 | struct dtm_shutdown *shutdown; | ||
149 | |||
150 | local_irq_disable(); | ||
151 | |||
152 | /* Run through the shutdown list. */ | ||
153 | list_for_each_entry(shutdown, &dtm_shutdown_list, list) | ||
154 | shutdown->func(shutdown->arg); | ||
155 | |||
156 | printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n"); | ||
157 | |||
158 | while (1) { | ||
159 | if (dtm_fpga) { | ||
160 | unsigned reset = in_be32(dtm_fpga + 0x14); | ||
161 | out_be32(dtm_fpga + 0x14, reset); | ||
75 | } | 162 | } |
76 | 163 | ||
77 | gpio_base = of_iomap(np, 0); | 164 | if (gpio_base) { |
78 | of_node_put(np); | 165 | unsigned leds = in_be32(gpio_base); |
79 | if (gpio_base == NULL) { | 166 | |
80 | printk(KERN_ERR __FILE__ ": Unable to map gpio"); | 167 | /* green off, red toggle */ |
81 | return; | 168 | leds &= ~0x80000000; |
169 | leds ^= 0x40000000; | ||
170 | |||
171 | out_be32(gpio_base, leds); | ||
82 | } | 172 | } |
173 | |||
174 | mdelay(500); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | static int pika_setup_leds(void) | ||
179 | { | ||
180 | struct device_node *np; | ||
181 | const u32 *gpios; | ||
182 | int len; | ||
183 | |||
184 | np = of_find_compatible_node(NULL, NULL, "linux,gpio-led"); | ||
185 | if (!np) { | ||
186 | printk(KERN_ERR __FILE__ ": Unable to find gpio-led\n"); | ||
187 | return -ENOENT; | ||
83 | } | 188 | } |
84 | 189 | ||
85 | leds = in_be32(gpio_base); | 190 | gpios = of_get_property(np, "gpios", &len); |
191 | of_node_put(np); | ||
192 | if (!gpios || len < 4) { | ||
193 | printk(KERN_ERR __FILE__ | ||
194 | ": Unable to get gpios property (%d)\n", len); | ||
195 | return -ENOENT; | ||
196 | } | ||
86 | 197 | ||
87 | switch (green) { | 198 | np = of_find_node_by_phandle(gpios[0]); |
88 | case 0: leds &= ~LED_GREEN; break; | 199 | if (!np) { |
89 | case 1: leds |= LED_GREEN; break; | 200 | printk(KERN_ERR __FILE__ ": Unable to find gpio\n"); |
201 | return -ENOENT; | ||
90 | } | 202 | } |
91 | switch (red) { | 203 | |
92 | case 0: leds &= ~LED_RED; break; | 204 | gpio_base = of_iomap(np, 0); |
93 | case 1: leds |= LED_RED; break; | 205 | of_node_put(np); |
206 | if (!gpio_base) { | ||
207 | printk(KERN_ERR __FILE__ ": Unable to map gpio"); | ||
208 | return -ENOMEM; | ||
94 | } | 209 | } |
95 | 210 | ||
96 | out_be32(gpio_base, leds); | 211 | return 0; |
97 | } | 212 | } |
98 | EXPORT_SYMBOL(warp_set_power_leds); | ||
99 | 213 | ||
214 | static void pika_setup_critical_temp(struct i2c_client *client) | ||
215 | { | ||
216 | struct device_node *np; | ||
217 | int irq, rc; | ||
218 | |||
219 | /* Do this before enabling critical temp interrupt since we | ||
220 | * may immediately interrupt. | ||
221 | */ | ||
222 | pika_setup_leds(); | ||
223 | |||
224 | /* These registers are in 1 degree increments. */ | ||
225 | i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */ | ||
226 | i2c_smbus_write_byte_data(client, 3, 55); /* Tlow */ | ||
227 | |||
228 | np = of_find_compatible_node(NULL, NULL, "adi,ad7414"); | ||
229 | if (np == NULL) { | ||
230 | printk(KERN_ERR __FILE__ ": Unable to find ad7414\n"); | ||
231 | return; | ||
232 | } | ||
233 | |||
234 | irq = irq_of_parse_and_map(np, 0); | ||
235 | of_node_put(np); | ||
236 | if (irq == NO_IRQ) { | ||
237 | printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n"); | ||
238 | return; | ||
239 | } | ||
240 | |||
241 | rc = request_irq(irq, temp_isr, 0, "ad7414", NULL); | ||
242 | if (rc) { | ||
243 | printk(KERN_ERR __FILE__ | ||
244 | ": Unable to request ad7414 irq %d = %d\n", irq, rc); | ||
245 | return; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | static inline void pika_dtm_check_fan(void __iomem *fpga) | ||
250 | { | ||
251 | static int fan_state; | ||
252 | u32 fan = in_be32(fpga + 0x34) & (1 << 14); | ||
253 | |||
254 | if (fan_state != fan) { | ||
255 | fan_state = fan; | ||
256 | if (fan) | ||
257 | printk(KERN_WARNING "Fan rotation error detected." | ||
258 | " Please check hardware.\n"); | ||
259 | } | ||
260 | } | ||
100 | 261 | ||
101 | #ifdef CONFIG_SENSORS_AD7414 | ||
102 | static int pika_dtm_thread(void __iomem *fpga) | 262 | static int pika_dtm_thread(void __iomem *fpga) |
103 | { | 263 | { |
104 | extern int ad7414_get_temp(int index); | 264 | struct i2c_adapter *adap; |
265 | struct i2c_client *client; | ||
266 | |||
267 | /* We loop in case either driver was compiled as a module and | ||
268 | * has not been insmoded yet. | ||
269 | */ | ||
270 | while (!(adap = i2c_get_adapter(0))) { | ||
271 | set_current_state(TASK_INTERRUPTIBLE); | ||
272 | schedule_timeout(HZ); | ||
273 | } | ||
274 | |||
275 | while (1) { | ||
276 | list_for_each_entry(client, &adap->clients, list) | ||
277 | if (client->addr == 0x4a) | ||
278 | goto found_it; | ||
279 | |||
280 | set_current_state(TASK_INTERRUPTIBLE); | ||
281 | schedule_timeout(HZ); | ||
282 | } | ||
283 | |||
284 | found_it: | ||
285 | i2c_put_adapter(adap); | ||
286 | |||
287 | pika_setup_critical_temp(client); | ||
288 | |||
289 | printk(KERN_INFO "PIKA DTM thread running.\n"); | ||
105 | 290 | ||
106 | while (!kthread_should_stop()) { | 291 | while (!kthread_should_stop()) { |
107 | int temp = ad7414_get_temp(0); | 292 | u16 temp = swab16(i2c_smbus_read_word_data(client, 0)); |
293 | out_be32(fpga + 0x20, temp); | ||
108 | 294 | ||
109 | out_be32(fpga, temp); | 295 | pika_dtm_check_fan(fpga); |
110 | 296 | ||
111 | set_current_state(TASK_INTERRUPTIBLE); | 297 | set_current_state(TASK_INTERRUPTIBLE); |
112 | schedule_timeout(HZ); | 298 | schedule_timeout(HZ); |
@@ -115,37 +301,44 @@ static int pika_dtm_thread(void __iomem *fpga) | |||
115 | return 0; | 301 | return 0; |
116 | } | 302 | } |
117 | 303 | ||
304 | |||
118 | static int __init pika_dtm_start(void) | 305 | static int __init pika_dtm_start(void) |
119 | { | 306 | { |
120 | struct task_struct *dtm_thread; | 307 | struct task_struct *dtm_thread; |
121 | struct device_node *np; | 308 | struct device_node *np; |
122 | struct resource res; | ||
123 | void __iomem *fpga; | ||
124 | 309 | ||
125 | np = of_find_compatible_node(NULL, NULL, "pika,fpga"); | 310 | np = of_find_compatible_node(NULL, NULL, "pika,fpga"); |
126 | if (np == NULL) | 311 | if (np == NULL) |
127 | return -ENOENT; | 312 | return -ENOENT; |
128 | 313 | ||
129 | /* We do not call of_iomap here since it would map in the entire | 314 | dtm_fpga = of_iomap(np, 0); |
130 | * fpga space, which is over 8k. | ||
131 | */ | ||
132 | if (of_address_to_resource(np, 0, &res)) { | ||
133 | of_node_put(np); | ||
134 | return -ENOENT; | ||
135 | } | ||
136 | of_node_put(np); | 315 | of_node_put(np); |
137 | 316 | if (dtm_fpga == NULL) | |
138 | fpga = ioremap(res.start, 0x24); | ||
139 | if (fpga == NULL) | ||
140 | return -ENOENT; | 317 | return -ENOENT; |
141 | 318 | ||
142 | dtm_thread = kthread_run(pika_dtm_thread, fpga + 0x20, "pika-dtm"); | 319 | dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm"); |
143 | if (IS_ERR(dtm_thread)) { | 320 | if (IS_ERR(dtm_thread)) { |
144 | iounmap(fpga); | 321 | iounmap(dtm_fpga); |
145 | return PTR_ERR(dtm_thread); | 322 | return PTR_ERR(dtm_thread); |
146 | } | 323 | } |
147 | 324 | ||
148 | return 0; | 325 | return 0; |
149 | } | 326 | } |
150 | device_initcall(pika_dtm_start); | 327 | machine_late_initcall(warp, pika_dtm_start); |
328 | |||
329 | #else /* !CONFIG_SENSORS_AD7414 */ | ||
330 | |||
331 | int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg) | ||
332 | { | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg) | ||
337 | { | ||
338 | return 0; | ||
339 | } | ||
340 | |||
151 | #endif | 341 | #endif |
342 | |||
343 | EXPORT_SYMBOL(pika_dtm_register_shutdown); | ||
344 | EXPORT_SYMBOL(pika_dtm_unregister_shutdown); | ||
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig index 4c0da0c079e9..c62f893ede19 100644 --- a/arch/powerpc/platforms/512x/Kconfig +++ b/arch/powerpc/platforms/512x/Kconfig | |||
@@ -2,18 +2,29 @@ config PPC_MPC512x | |||
2 | bool | 2 | bool |
3 | select FSL_SOC | 3 | select FSL_SOC |
4 | select IPIC | 4 | select IPIC |
5 | default n | 5 | select PPC_CLOCK |
6 | 6 | ||
7 | config PPC_MPC5121 | 7 | config PPC_MPC5121 |
8 | bool | 8 | bool |
9 | select PPC_MPC512x | 9 | select PPC_MPC512x |
10 | default n | ||
11 | 10 | ||
12 | config MPC5121_ADS | 11 | config MPC5121_ADS |
13 | bool "Freescale MPC5121E ADS" | 12 | bool "Freescale MPC5121E ADS" |
14 | depends on PPC_MULTIPLATFORM && PPC32 | 13 | depends on PPC_MULTIPLATFORM && PPC32 |
15 | select DEFAULT_UIMAGE | 14 | select DEFAULT_UIMAGE |
16 | select PPC_MPC5121 | 15 | select PPC_MPC5121 |
16 | select MPC5121_ADS_CPLD | ||
17 | help | 17 | help |
18 | This option enables support for the MPC5121E ADS board. | 18 | This option enables support for the MPC5121E ADS board. |
19 | default n | 19 | |
20 | config MPC5121_GENERIC | ||
21 | bool "Generic support for simple MPC5121 based boards" | ||
22 | depends on PPC_MULTIPLATFORM && PPC32 | ||
23 | select DEFAULT_UIMAGE | ||
24 | select PPC_MPC5121 | ||
25 | help | ||
26 | This option enables support for simple MPC5121 based boards | ||
27 | which do not need custom platform specific setup. | ||
28 | |||
29 | Compatible boards include: Protonic LVT base boards (ZANMCU | ||
30 | and VICVT2). | ||
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile index 232c89f2039a..90be2f5717e6 100644 --- a/arch/powerpc/platforms/512x/Makefile +++ b/arch/powerpc/platforms/512x/Makefile | |||
@@ -1,4 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the Freescale PowerPC 512x linux kernel. | 2 | # Makefile for the Freescale PowerPC 512x linux kernel. |
3 | # | 3 | # |
4 | obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o | 4 | obj-y += clock.o mpc512x_shared.o |
5 | obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o | ||
6 | obj-$(CONFIG_MPC5121_GENERIC) += mpc5121_generic.o | ||
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c new file mode 100644 index 000000000000..f416014ee727 --- /dev/null +++ b/arch/powerpc/platforms/512x/clock.c | |||
@@ -0,0 +1,729 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby <jrigby@freescale.com> | ||
5 | * | ||
6 | * Implements the clk api defined in include/linux/clk.h | ||
7 | * | ||
8 | * Original based on linux/arch/arm/mach-integrator/clock.c | ||
9 | * | ||
10 | * Copyright (C) 2004 ARM Limited. | ||
11 | * Written by Deep Blue Solutions Limited. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/list.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/io.h> | ||
25 | |||
26 | #include <linux/of_platform.h> | ||
27 | #include <asm/mpc512x.h> | ||
28 | #include <asm/clk_interface.h> | ||
29 | |||
30 | #undef CLK_DEBUG | ||
31 | |||
32 | static int clocks_initialized; | ||
33 | |||
34 | #define CLK_HAS_RATE 0x1 /* has rate in MHz */ | ||
35 | #define CLK_HAS_CTRL 0x2 /* has control reg and bit */ | ||
36 | |||
37 | struct clk { | ||
38 | struct list_head node; | ||
39 | char name[32]; | ||
40 | int flags; | ||
41 | struct device *dev; | ||
42 | unsigned long rate; | ||
43 | struct module *owner; | ||
44 | void (*calc) (struct clk *); | ||
45 | struct clk *parent; | ||
46 | int reg, bit; /* CLK_HAS_CTRL */ | ||
47 | int div_shift; /* only used by generic_div_clk_calc */ | ||
48 | }; | ||
49 | |||
50 | static LIST_HEAD(clocks); | ||
51 | static DEFINE_MUTEX(clocks_mutex); | ||
52 | |||
53 | static struct clk *mpc5121_clk_get(struct device *dev, const char *id) | ||
54 | { | ||
55 | struct clk *p, *clk = ERR_PTR(-ENOENT); | ||
56 | int dev_match = 0; | ||
57 | int id_match = 0; | ||
58 | |||
59 | if (dev == NULL && id == NULL) | ||
60 | return NULL; | ||
61 | |||
62 | mutex_lock(&clocks_mutex); | ||
63 | list_for_each_entry(p, &clocks, node) { | ||
64 | if (dev && dev == p->dev) | ||
65 | dev_match++; | ||
66 | if (strcmp(id, p->name) == 0) | ||
67 | id_match++; | ||
68 | if ((dev_match || id_match) && try_module_get(p->owner)) { | ||
69 | clk = p; | ||
70 | break; | ||
71 | } | ||
72 | } | ||
73 | mutex_unlock(&clocks_mutex); | ||
74 | |||
75 | return clk; | ||
76 | } | ||
77 | |||
78 | #ifdef CLK_DEBUG | ||
79 | static void dump_clocks(void) | ||
80 | { | ||
81 | struct clk *p; | ||
82 | |||
83 | mutex_lock(&clocks_mutex); | ||
84 | printk(KERN_INFO "CLOCKS:\n"); | ||
85 | list_for_each_entry(p, &clocks, node) { | ||
86 | printk(KERN_INFO " %s %ld", p->name, p->rate); | ||
87 | if (p->parent) | ||
88 | printk(KERN_INFO " %s %ld", p->parent->name, | ||
89 | p->parent->rate); | ||
90 | if (p->flags & CLK_HAS_CTRL) | ||
91 | printk(KERN_INFO " reg/bit %d/%d", p->reg, p->bit); | ||
92 | printk("\n"); | ||
93 | } | ||
94 | mutex_unlock(&clocks_mutex); | ||
95 | } | ||
96 | #define DEBUG_CLK_DUMP() dump_clocks() | ||
97 | #else | ||
98 | #define DEBUG_CLK_DUMP() | ||
99 | #endif | ||
100 | |||
101 | |||
102 | static void mpc5121_clk_put(struct clk *clk) | ||
103 | { | ||
104 | module_put(clk->owner); | ||
105 | } | ||
106 | |||
107 | #define NRPSC 12 | ||
108 | |||
109 | struct mpc512x_clockctl { | ||
110 | u32 spmr; /* System PLL Mode Reg */ | ||
111 | u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */ | ||
112 | u32 scfr1; /* System Clk Freq Reg 1 */ | ||
113 | u32 scfr2; /* System Clk Freq Reg 2 */ | ||
114 | u32 reserved; | ||
115 | u32 bcr; /* Bread Crumb Reg */ | ||
116 | u32 pccr[NRPSC]; /* PSC Clk Ctrl Reg 0-11 */ | ||
117 | u32 spccr; /* SPDIF Clk Ctrl Reg */ | ||
118 | u32 cccr; /* CFM Clk Ctrl Reg */ | ||
119 | u32 dccr; /* DIU Clk Cnfg Reg */ | ||
120 | }; | ||
121 | |||
122 | struct mpc512x_clockctl __iomem *clockctl; | ||
123 | |||
124 | static int mpc5121_clk_enable(struct clk *clk) | ||
125 | { | ||
126 | unsigned int mask; | ||
127 | |||
128 | if (clk->flags & CLK_HAS_CTRL) { | ||
129 | mask = in_be32(&clockctl->sccr[clk->reg]); | ||
130 | mask |= 1 << clk->bit; | ||
131 | out_be32(&clockctl->sccr[clk->reg], mask); | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static void mpc5121_clk_disable(struct clk *clk) | ||
137 | { | ||
138 | unsigned int mask; | ||
139 | |||
140 | if (clk->flags & CLK_HAS_CTRL) { | ||
141 | mask = in_be32(&clockctl->sccr[clk->reg]); | ||
142 | mask &= ~(1 << clk->bit); | ||
143 | out_be32(&clockctl->sccr[clk->reg], mask); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static unsigned long mpc5121_clk_get_rate(struct clk *clk) | ||
148 | { | ||
149 | if (clk->flags & CLK_HAS_RATE) | ||
150 | return clk->rate; | ||
151 | else | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate) | ||
156 | { | ||
157 | return rate; | ||
158 | } | ||
159 | |||
160 | static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate) | ||
161 | { | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int clk_register(struct clk *clk) | ||
166 | { | ||
167 | mutex_lock(&clocks_mutex); | ||
168 | list_add(&clk->node, &clocks); | ||
169 | mutex_unlock(&clocks_mutex); | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static unsigned long spmf_mult(void) | ||
174 | { | ||
175 | /* | ||
176 | * Convert spmf to multiplier | ||
177 | */ | ||
178 | static int spmf_to_mult[] = { | ||
179 | 68, 1, 12, 16, | ||
180 | 20, 24, 28, 32, | ||
181 | 36, 40, 44, 48, | ||
182 | 52, 56, 60, 64 | ||
183 | }; | ||
184 | int spmf = (clockctl->spmr >> 24) & 0xf; | ||
185 | return spmf_to_mult[spmf]; | ||
186 | } | ||
187 | |||
188 | static unsigned long sysdiv_div_x_2(void) | ||
189 | { | ||
190 | /* | ||
191 | * Convert sysdiv to divisor x 2 | ||
192 | * Some divisors have fractional parts so | ||
193 | * multiply by 2 then divide by this value | ||
194 | */ | ||
195 | static int sysdiv_to_div_x_2[] = { | ||
196 | 4, 5, 6, 7, | ||
197 | 8, 9, 10, 14, | ||
198 | 12, 16, 18, 22, | ||
199 | 20, 24, 26, 30, | ||
200 | 28, 32, 34, 38, | ||
201 | 36, 40, 42, 46, | ||
202 | 44, 48, 50, 54, | ||
203 | 52, 56, 58, 62, | ||
204 | 60, 64, 66, | ||
205 | }; | ||
206 | int sysdiv = (clockctl->scfr2 >> 26) & 0x3f; | ||
207 | return sysdiv_to_div_x_2[sysdiv]; | ||
208 | } | ||
209 | |||
210 | static unsigned long ref_to_sys(unsigned long rate) | ||
211 | { | ||
212 | rate *= spmf_mult(); | ||
213 | rate *= 2; | ||
214 | rate /= sysdiv_div_x_2(); | ||
215 | |||
216 | return rate; | ||
217 | } | ||
218 | |||
219 | static unsigned long sys_to_ref(unsigned long rate) | ||
220 | { | ||
221 | rate *= sysdiv_div_x_2(); | ||
222 | rate /= 2; | ||
223 | rate /= spmf_mult(); | ||
224 | |||
225 | return rate; | ||
226 | } | ||
227 | |||
228 | static long ips_to_ref(unsigned long rate) | ||
229 | { | ||
230 | int ips_div = (clockctl->scfr1 >> 23) & 0x7; | ||
231 | |||
232 | rate *= ips_div; /* csb_clk = ips_clk * ips_div */ | ||
233 | rate *= 2; /* sys_clk = csb_clk * 2 */ | ||
234 | return sys_to_ref(rate); | ||
235 | } | ||
236 | |||
237 | static unsigned long devtree_getfreq(char *clockname) | ||
238 | { | ||
239 | struct device_node *np; | ||
240 | const unsigned int *prop; | ||
241 | unsigned int val = 0; | ||
242 | |||
243 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr"); | ||
244 | if (np) { | ||
245 | prop = of_get_property(np, clockname, NULL); | ||
246 | if (prop) | ||
247 | val = *prop; | ||
248 | of_node_put(np); | ||
249 | } | ||
250 | return val; | ||
251 | } | ||
252 | |||
253 | static void ref_clk_calc(struct clk *clk) | ||
254 | { | ||
255 | unsigned long rate; | ||
256 | |||
257 | rate = devtree_getfreq("bus-frequency"); | ||
258 | if (rate == 0) { | ||
259 | printk(KERN_ERR "No bus-frequency in dev tree\n"); | ||
260 | clk->rate = 0; | ||
261 | return; | ||
262 | } | ||
263 | clk->rate = ips_to_ref(rate); | ||
264 | } | ||
265 | |||
266 | static struct clk ref_clk = { | ||
267 | .name = "ref_clk", | ||
268 | .calc = ref_clk_calc, | ||
269 | }; | ||
270 | |||
271 | |||
272 | static void sys_clk_calc(struct clk *clk) | ||
273 | { | ||
274 | clk->rate = ref_to_sys(ref_clk.rate); | ||
275 | } | ||
276 | |||
277 | static struct clk sys_clk = { | ||
278 | .name = "sys_clk", | ||
279 | .calc = sys_clk_calc, | ||
280 | }; | ||
281 | |||
282 | static void diu_clk_calc(struct clk *clk) | ||
283 | { | ||
284 | int diudiv_x_2 = clockctl->scfr1 & 0xff; | ||
285 | unsigned long rate; | ||
286 | |||
287 | rate = sys_clk.rate; | ||
288 | |||
289 | rate *= 2; | ||
290 | rate /= diudiv_x_2; | ||
291 | |||
292 | clk->rate = rate; | ||
293 | } | ||
294 | |||
295 | static void half_clk_calc(struct clk *clk) | ||
296 | { | ||
297 | clk->rate = clk->parent->rate / 2; | ||
298 | } | ||
299 | |||
300 | static void generic_div_clk_calc(struct clk *clk) | ||
301 | { | ||
302 | int div = (clockctl->scfr1 >> clk->div_shift) & 0x7; | ||
303 | |||
304 | clk->rate = clk->parent->rate / div; | ||
305 | } | ||
306 | |||
307 | static void unity_clk_calc(struct clk *clk) | ||
308 | { | ||
309 | clk->rate = clk->parent->rate; | ||
310 | } | ||
311 | |||
312 | static struct clk csb_clk = { | ||
313 | .name = "csb_clk", | ||
314 | .calc = half_clk_calc, | ||
315 | .parent = &sys_clk, | ||
316 | }; | ||
317 | |||
318 | static void e300_clk_calc(struct clk *clk) | ||
319 | { | ||
320 | int spmf = (clockctl->spmr >> 16) & 0xf; | ||
321 | int ratex2 = clk->parent->rate * spmf; | ||
322 | |||
323 | clk->rate = ratex2 / 2; | ||
324 | } | ||
325 | |||
326 | static struct clk e300_clk = { | ||
327 | .name = "e300_clk", | ||
328 | .calc = e300_clk_calc, | ||
329 | .parent = &csb_clk, | ||
330 | }; | ||
331 | |||
332 | static struct clk ips_clk = { | ||
333 | .name = "ips_clk", | ||
334 | .calc = generic_div_clk_calc, | ||
335 | .parent = &csb_clk, | ||
336 | .div_shift = 23, | ||
337 | }; | ||
338 | |||
339 | /* | ||
340 | * Clocks controlled by SCCR1 (.reg = 0) | ||
341 | */ | ||
342 | static struct clk lpc_clk = { | ||
343 | .name = "lpc_clk", | ||
344 | .flags = CLK_HAS_CTRL, | ||
345 | .reg = 0, | ||
346 | .bit = 30, | ||
347 | .calc = generic_div_clk_calc, | ||
348 | .parent = &ips_clk, | ||
349 | .div_shift = 11, | ||
350 | }; | ||
351 | |||
352 | static struct clk nfc_clk = { | ||
353 | .name = "nfc_clk", | ||
354 | .flags = CLK_HAS_CTRL, | ||
355 | .reg = 0, | ||
356 | .bit = 29, | ||
357 | .calc = generic_div_clk_calc, | ||
358 | .parent = &ips_clk, | ||
359 | .div_shift = 8, | ||
360 | }; | ||
361 | |||
362 | static struct clk pata_clk = { | ||
363 | .name = "pata_clk", | ||
364 | .flags = CLK_HAS_CTRL, | ||
365 | .reg = 0, | ||
366 | .bit = 28, | ||
367 | .calc = unity_clk_calc, | ||
368 | .parent = &ips_clk, | ||
369 | }; | ||
370 | |||
371 | /* | ||
372 | * PSC clocks (bits 27 - 16) | ||
373 | * are setup elsewhere | ||
374 | */ | ||
375 | |||
376 | static struct clk sata_clk = { | ||
377 | .name = "sata_clk", | ||
378 | .flags = CLK_HAS_CTRL, | ||
379 | .reg = 0, | ||
380 | .bit = 14, | ||
381 | .calc = unity_clk_calc, | ||
382 | .parent = &ips_clk, | ||
383 | }; | ||
384 | |||
385 | static struct clk fec_clk = { | ||
386 | .name = "fec_clk", | ||
387 | .flags = CLK_HAS_CTRL, | ||
388 | .reg = 0, | ||
389 | .bit = 13, | ||
390 | .calc = unity_clk_calc, | ||
391 | .parent = &ips_clk, | ||
392 | }; | ||
393 | |||
394 | static struct clk pci_clk = { | ||
395 | .name = "pci_clk", | ||
396 | .flags = CLK_HAS_CTRL, | ||
397 | .reg = 0, | ||
398 | .bit = 11, | ||
399 | .calc = generic_div_clk_calc, | ||
400 | .parent = &csb_clk, | ||
401 | .div_shift = 20, | ||
402 | }; | ||
403 | |||
404 | /* | ||
405 | * Clocks controlled by SCCR2 (.reg = 1) | ||
406 | */ | ||
407 | static struct clk diu_clk = { | ||
408 | .name = "diu_clk", | ||
409 | .flags = CLK_HAS_CTRL, | ||
410 | .reg = 1, | ||
411 | .bit = 31, | ||
412 | .calc = diu_clk_calc, | ||
413 | }; | ||
414 | |||
415 | static struct clk axe_clk = { | ||
416 | .name = "axe_clk", | ||
417 | .flags = CLK_HAS_CTRL, | ||
418 | .reg = 1, | ||
419 | .bit = 30, | ||
420 | .calc = unity_clk_calc, | ||
421 | .parent = &csb_clk, | ||
422 | }; | ||
423 | |||
424 | static struct clk usb1_clk = { | ||
425 | .name = "usb1_clk", | ||
426 | .flags = CLK_HAS_CTRL, | ||
427 | .reg = 1, | ||
428 | .bit = 28, | ||
429 | .calc = unity_clk_calc, | ||
430 | .parent = &csb_clk, | ||
431 | }; | ||
432 | |||
433 | static struct clk usb2_clk = { | ||
434 | .name = "usb2_clk", | ||
435 | .flags = CLK_HAS_CTRL, | ||
436 | .reg = 1, | ||
437 | .bit = 27, | ||
438 | .calc = unity_clk_calc, | ||
439 | .parent = &csb_clk, | ||
440 | }; | ||
441 | |||
442 | static struct clk i2c_clk = { | ||
443 | .name = "i2c_clk", | ||
444 | .flags = CLK_HAS_CTRL, | ||
445 | .reg = 1, | ||
446 | .bit = 26, | ||
447 | .calc = unity_clk_calc, | ||
448 | .parent = &ips_clk, | ||
449 | }; | ||
450 | |||
451 | static struct clk mscan_clk = { | ||
452 | .name = "mscan_clk", | ||
453 | .flags = CLK_HAS_CTRL, | ||
454 | .reg = 1, | ||
455 | .bit = 25, | ||
456 | .calc = unity_clk_calc, | ||
457 | .parent = &ips_clk, | ||
458 | }; | ||
459 | |||
460 | static struct clk sdhc_clk = { | ||
461 | .name = "sdhc_clk", | ||
462 | .flags = CLK_HAS_CTRL, | ||
463 | .reg = 1, | ||
464 | .bit = 24, | ||
465 | .calc = unity_clk_calc, | ||
466 | .parent = &ips_clk, | ||
467 | }; | ||
468 | |||
469 | static struct clk mbx_bus_clk = { | ||
470 | .name = "mbx_bus_clk", | ||
471 | .flags = CLK_HAS_CTRL, | ||
472 | .reg = 1, | ||
473 | .bit = 22, | ||
474 | .calc = half_clk_calc, | ||
475 | .parent = &csb_clk, | ||
476 | }; | ||
477 | |||
478 | static struct clk mbx_clk = { | ||
479 | .name = "mbx_clk", | ||
480 | .flags = CLK_HAS_CTRL, | ||
481 | .reg = 1, | ||
482 | .bit = 21, | ||
483 | .calc = unity_clk_calc, | ||
484 | .parent = &csb_clk, | ||
485 | }; | ||
486 | |||
487 | static struct clk mbx_3d_clk = { | ||
488 | .name = "mbx_3d_clk", | ||
489 | .flags = CLK_HAS_CTRL, | ||
490 | .reg = 1, | ||
491 | .bit = 20, | ||
492 | .calc = generic_div_clk_calc, | ||
493 | .parent = &mbx_bus_clk, | ||
494 | .div_shift = 14, | ||
495 | }; | ||
496 | |||
497 | static void psc_mclk_in_calc(struct clk *clk) | ||
498 | { | ||
499 | clk->rate = devtree_getfreq("psc_mclk_in"); | ||
500 | if (!clk->rate) | ||
501 | clk->rate = 25000000; | ||
502 | } | ||
503 | |||
504 | static struct clk psc_mclk_in = { | ||
505 | .name = "psc_mclk_in", | ||
506 | .calc = psc_mclk_in_calc, | ||
507 | }; | ||
508 | |||
509 | static struct clk spdif_txclk = { | ||
510 | .name = "spdif_txclk", | ||
511 | .flags = CLK_HAS_CTRL, | ||
512 | .reg = 1, | ||
513 | .bit = 23, | ||
514 | }; | ||
515 | |||
516 | static struct clk spdif_rxclk = { | ||
517 | .name = "spdif_rxclk", | ||
518 | .flags = CLK_HAS_CTRL, | ||
519 | .reg = 1, | ||
520 | .bit = 23, | ||
521 | }; | ||
522 | |||
523 | static void ac97_clk_calc(struct clk *clk) | ||
524 | { | ||
525 | /* ac97 bit clock is always 24.567 MHz */ | ||
526 | clk->rate = 24567000; | ||
527 | } | ||
528 | |||
529 | static struct clk ac97_clk = { | ||
530 | .name = "ac97_clk_in", | ||
531 | .calc = ac97_clk_calc, | ||
532 | }; | ||
533 | |||
534 | struct clk *rate_clks[] = { | ||
535 | &ref_clk, | ||
536 | &sys_clk, | ||
537 | &diu_clk, | ||
538 | &csb_clk, | ||
539 | &e300_clk, | ||
540 | &ips_clk, | ||
541 | &fec_clk, | ||
542 | &sata_clk, | ||
543 | &pata_clk, | ||
544 | &nfc_clk, | ||
545 | &lpc_clk, | ||
546 | &mbx_bus_clk, | ||
547 | &mbx_clk, | ||
548 | &mbx_3d_clk, | ||
549 | &axe_clk, | ||
550 | &usb1_clk, | ||
551 | &usb2_clk, | ||
552 | &i2c_clk, | ||
553 | &mscan_clk, | ||
554 | &sdhc_clk, | ||
555 | &pci_clk, | ||
556 | &psc_mclk_in, | ||
557 | &spdif_txclk, | ||
558 | &spdif_rxclk, | ||
559 | &ac97_clk, | ||
560 | NULL | ||
561 | }; | ||
562 | |||
563 | static void rate_clk_init(struct clk *clk) | ||
564 | { | ||
565 | if (clk->calc) { | ||
566 | clk->calc(clk); | ||
567 | clk->flags |= CLK_HAS_RATE; | ||
568 | clk_register(clk); | ||
569 | } else { | ||
570 | printk(KERN_WARNING | ||
571 | "Could not initialize clk %s without a calc routine\n", | ||
572 | clk->name); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | static void rate_clks_init(void) | ||
577 | { | ||
578 | struct clk **cpp, *clk; | ||
579 | |||
580 | cpp = rate_clks; | ||
581 | while ((clk = *cpp++)) | ||
582 | rate_clk_init(clk); | ||
583 | } | ||
584 | |||
585 | /* | ||
586 | * There are two clk enable registers with 32 enable bits each | ||
587 | * psc clocks and device clocks are all stored in dev_clks | ||
588 | */ | ||
589 | struct clk dev_clks[2][32]; | ||
590 | |||
591 | /* | ||
592 | * Given a psc number return the dev_clk | ||
593 | * associated with it | ||
594 | */ | ||
595 | static struct clk *psc_dev_clk(int pscnum) | ||
596 | { | ||
597 | int reg, bit; | ||
598 | struct clk *clk; | ||
599 | |||
600 | reg = 0; | ||
601 | bit = 27 - pscnum; | ||
602 | |||
603 | clk = &dev_clks[reg][bit]; | ||
604 | clk->reg = 0; | ||
605 | clk->bit = bit; | ||
606 | return clk; | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * PSC clock rate calculation | ||
611 | */ | ||
612 | static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np) | ||
613 | { | ||
614 | unsigned long mclk_src = sys_clk.rate; | ||
615 | unsigned long mclk_div; | ||
616 | |||
617 | /* | ||
618 | * Can only change value of mclk divider | ||
619 | * when the divider is disabled. | ||
620 | * | ||
621 | * Zero is not a valid divider so minimum | ||
622 | * divider is 1 | ||
623 | * | ||
624 | * disable/set divider/enable | ||
625 | */ | ||
626 | out_be32(&clockctl->pccr[pscnum], 0); | ||
627 | out_be32(&clockctl->pccr[pscnum], 0x00020000); | ||
628 | out_be32(&clockctl->pccr[pscnum], 0x00030000); | ||
629 | |||
630 | if (clockctl->pccr[pscnum] & 0x80) { | ||
631 | clk->rate = spdif_rxclk.rate; | ||
632 | return; | ||
633 | } | ||
634 | |||
635 | switch ((clockctl->pccr[pscnum] >> 14) & 0x3) { | ||
636 | case 0: | ||
637 | mclk_src = sys_clk.rate; | ||
638 | break; | ||
639 | case 1: | ||
640 | mclk_src = ref_clk.rate; | ||
641 | break; | ||
642 | case 2: | ||
643 | mclk_src = psc_mclk_in.rate; | ||
644 | break; | ||
645 | case 3: | ||
646 | mclk_src = spdif_txclk.rate; | ||
647 | break; | ||
648 | } | ||
649 | |||
650 | mclk_div = ((clockctl->pccr[pscnum] >> 17) & 0x7fff) + 1; | ||
651 | clk->rate = mclk_src / mclk_div; | ||
652 | } | ||
653 | |||
654 | /* | ||
655 | * Find all psc nodes in device tree and assign a clock | ||
656 | * with name "psc%d_mclk" and dev pointing at the device | ||
657 | * returned from of_find_device_by_node | ||
658 | */ | ||
659 | static void psc_clks_init(void) | ||
660 | { | ||
661 | struct device_node *np; | ||
662 | const u32 *cell_index; | ||
663 | struct of_device *ofdev; | ||
664 | |||
665 | for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") { | ||
666 | cell_index = of_get_property(np, "cell-index", NULL); | ||
667 | if (cell_index) { | ||
668 | int pscnum = *cell_index; | ||
669 | struct clk *clk = psc_dev_clk(pscnum); | ||
670 | |||
671 | clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL; | ||
672 | ofdev = of_find_device_by_node(np); | ||
673 | clk->dev = &ofdev->dev; | ||
674 | /* | ||
675 | * AC97 is special rate clock does | ||
676 | * not go through normal path | ||
677 | */ | ||
678 | if (strcmp("ac97", np->name) == 0) | ||
679 | clk->rate = ac97_clk.rate; | ||
680 | else | ||
681 | psc_calc_rate(clk, pscnum, np); | ||
682 | sprintf(clk->name, "psc%d_mclk", pscnum); | ||
683 | clk_register(clk); | ||
684 | clk_enable(clk); | ||
685 | } | ||
686 | } | ||
687 | } | ||
688 | |||
689 | static struct clk_interface mpc5121_clk_functions = { | ||
690 | .clk_get = mpc5121_clk_get, | ||
691 | .clk_enable = mpc5121_clk_enable, | ||
692 | .clk_disable = mpc5121_clk_disable, | ||
693 | .clk_get_rate = mpc5121_clk_get_rate, | ||
694 | .clk_put = mpc5121_clk_put, | ||
695 | .clk_round_rate = mpc5121_clk_round_rate, | ||
696 | .clk_set_rate = mpc5121_clk_set_rate, | ||
697 | .clk_set_parent = NULL, | ||
698 | .clk_get_parent = NULL, | ||
699 | }; | ||
700 | |||
701 | static int | ||
702 | mpc5121_clk_init(void) | ||
703 | { | ||
704 | struct device_node *np; | ||
705 | |||
706 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock"); | ||
707 | if (np) { | ||
708 | clockctl = of_iomap(np, 0); | ||
709 | of_node_put(np); | ||
710 | } | ||
711 | |||
712 | if (!clockctl) { | ||
713 | printk(KERN_ERR "Could not map clock control registers\n"); | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | rate_clks_init(); | ||
718 | psc_clks_init(); | ||
719 | |||
720 | /* leave clockctl mapped forever */ | ||
721 | /*iounmap(clockctl); */ | ||
722 | DEBUG_CLK_DUMP(); | ||
723 | clocks_initialized++; | ||
724 | clk_functions = mpc5121_clk_functions; | ||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | |||
729 | arch_initcall(mpc5121_clk_init); | ||
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c index 50bd3a319022..5ebf6939a697 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. | 2 | * Copyright (C) 2007, 2008 Freescale Semiconductor, Inc. All rights reserved. |
3 | * | 3 | * |
4 | * Author: John Rigby, <jrigby@freescale.com>, Thur Mar 29 2007 | 4 | * Author: John Rigby, <jrigby@freescale.com>, Thur Mar 29 2007 |
5 | * | 5 | * |
@@ -15,7 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/irq.h> | ||
19 | #include <linux/of_platform.h> | 18 | #include <linux/of_platform.h> |
20 | 19 | ||
21 | #include <asm/machdep.h> | 20 | #include <asm/machdep.h> |
@@ -23,65 +22,22 @@ | |||
23 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
24 | #include <asm/time.h> | 23 | #include <asm/time.h> |
25 | 24 | ||
26 | /** | 25 | #include "mpc512x.h" |
27 | * mpc512x_find_ips_freq - Find the IPS bus frequency for a device | 26 | #include "mpc5121_ads.h" |
28 | * @node: device node | ||
29 | * | ||
30 | * Returns IPS bus frequency, or 0 if the bus frequency cannot be found. | ||
31 | */ | ||
32 | unsigned long | ||
33 | mpc512x_find_ips_freq(struct device_node *node) | ||
34 | { | ||
35 | struct device_node *np; | ||
36 | const unsigned int *p_ips_freq = NULL; | ||
37 | |||
38 | of_node_get(node); | ||
39 | while (node) { | ||
40 | p_ips_freq = of_get_property(node, "bus-frequency", NULL); | ||
41 | if (p_ips_freq) | ||
42 | break; | ||
43 | |||
44 | np = of_get_parent(node); | ||
45 | of_node_put(node); | ||
46 | node = np; | ||
47 | } | ||
48 | if (node) | ||
49 | of_node_put(node); | ||
50 | |||
51 | return p_ips_freq ? *p_ips_freq : 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL(mpc512x_find_ips_freq); | ||
54 | |||
55 | static struct of_device_id __initdata of_bus_ids[] = { | ||
56 | { .name = "soc", }, | ||
57 | { .name = "localbus", }, | ||
58 | {}, | ||
59 | }; | ||
60 | 27 | ||
61 | static void __init mpc5121_ads_declare_of_platform_devices(void) | 28 | static void __init mpc5121_ads_setup_arch(void) |
62 | { | 29 | { |
63 | /* Find every child of the SOC node and add it to of_platform */ | 30 | printk(KERN_INFO "MPC5121 ADS board from Freescale Semiconductor\n"); |
64 | if (of_platform_bus_probe(NULL, of_bus_ids, NULL)) | 31 | /* |
65 | printk(KERN_ERR __FILE__ ": " | 32 | * cpld regs are needed early |
66 | "Error while probing of_platform bus\n"); | 33 | */ |
34 | mpc5121_ads_cpld_map(); | ||
67 | } | 35 | } |
68 | 36 | ||
69 | static void __init mpc5121_ads_init_IRQ(void) | 37 | static void __init mpc5121_ads_init_IRQ(void) |
70 | { | 38 | { |
71 | struct device_node *np; | 39 | mpc512x_init_IRQ(); |
72 | 40 | mpc5121_ads_cpld_pic_init(); | |
73 | np = of_find_compatible_node(NULL, NULL, "fsl,ipic"); | ||
74 | if (!np) | ||
75 | return; | ||
76 | |||
77 | ipic_init(np, 0); | ||
78 | of_node_put(np); | ||
79 | |||
80 | /* | ||
81 | * Initialize the default interrupt mapping priorities, | ||
82 | * in case the boot rom changed something on us. | ||
83 | */ | ||
84 | ipic_set_default_priority(); | ||
85 | } | 41 | } |
86 | 42 | ||
87 | /* | 43 | /* |
@@ -97,7 +53,8 @@ static int __init mpc5121_ads_probe(void) | |||
97 | define_machine(mpc5121_ads) { | 53 | define_machine(mpc5121_ads) { |
98 | .name = "MPC5121 ADS", | 54 | .name = "MPC5121 ADS", |
99 | .probe = mpc5121_ads_probe, | 55 | .probe = mpc5121_ads_probe, |
100 | .init = mpc5121_ads_declare_of_platform_devices, | 56 | .setup_arch = mpc5121_ads_setup_arch, |
57 | .init = mpc512x_declare_of_platform_devices, | ||
101 | .init_IRQ = mpc5121_ads_init_IRQ, | 58 | .init_IRQ = mpc5121_ads_init_IRQ, |
102 | .get_irq = ipic_get_irq, | 59 | .get_irq = ipic_get_irq, |
103 | .calibrate_decr = generic_calibrate_decr, | 60 | .calibrate_decr = generic_calibrate_decr, |
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.h b/arch/powerpc/platforms/512x/mpc5121_ads.h new file mode 100644 index 000000000000..662076cfee2f --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc5121_ads.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * Prototypes for ADS5121 specific code | ||
10 | */ | ||
11 | |||
12 | #ifndef __MPC512ADS_H__ | ||
13 | #define __MPC512ADS_H__ | ||
14 | extern void __init mpc5121_ads_cpld_map(void); | ||
15 | extern void __init mpc5121_ads_cpld_pic_init(void); | ||
16 | #endif /* __MPC512ADS_H__ */ | ||
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c new file mode 100644 index 000000000000..a6ce80566625 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby, <jrigby@freescale.com> | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC5121ADS CPLD irq handling | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #undef DEBUG | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <asm/prom.h> | ||
22 | |||
23 | static struct device_node *cpld_pic_node; | ||
24 | static struct irq_host *cpld_pic_host; | ||
25 | |||
26 | /* | ||
27 | * Bits to ignore in the misc_status register | ||
28 | * 0x10 touch screen pendown is hard routed to irq1 | ||
29 | * 0x02 pci status is read from pci status register | ||
30 | */ | ||
31 | #define MISC_IGNORE 0x12 | ||
32 | |||
33 | /* | ||
34 | * Nothing to ignore in pci status register | ||
35 | */ | ||
36 | #define PCI_IGNORE 0x00 | ||
37 | |||
38 | struct cpld_pic { | ||
39 | u8 pci_mask; | ||
40 | u8 pci_status; | ||
41 | u8 route; | ||
42 | u8 misc_mask; | ||
43 | u8 misc_status; | ||
44 | u8 misc_control; | ||
45 | }; | ||
46 | |||
47 | static struct cpld_pic __iomem *cpld_regs; | ||
48 | |||
49 | static void __iomem * | ||
50 | irq_to_pic_mask(unsigned int irq) | ||
51 | { | ||
52 | return irq <= 7 ? &cpld_regs->pci_mask : &cpld_regs->misc_mask; | ||
53 | } | ||
54 | |||
55 | static unsigned int | ||
56 | irq_to_pic_bit(unsigned int irq) | ||
57 | { | ||
58 | return 1 << (irq & 0x7); | ||
59 | } | ||
60 | |||
61 | static void | ||
62 | cpld_mask_irq(unsigned int irq) | ||
63 | { | ||
64 | unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq; | ||
65 | void __iomem *pic_mask = irq_to_pic_mask(cpld_irq); | ||
66 | |||
67 | out_8(pic_mask, | ||
68 | in_8(pic_mask) | irq_to_pic_bit(cpld_irq)); | ||
69 | } | ||
70 | |||
71 | static void | ||
72 | cpld_unmask_irq(unsigned int irq) | ||
73 | { | ||
74 | unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq; | ||
75 | void __iomem *pic_mask = irq_to_pic_mask(cpld_irq); | ||
76 | |||
77 | out_8(pic_mask, | ||
78 | in_8(pic_mask) & ~irq_to_pic_bit(cpld_irq)); | ||
79 | } | ||
80 | |||
81 | static struct irq_chip cpld_pic = { | ||
82 | .typename = " CPLD PIC ", | ||
83 | .mask = cpld_mask_irq, | ||
84 | .ack = cpld_mask_irq, | ||
85 | .unmask = cpld_unmask_irq, | ||
86 | }; | ||
87 | |||
88 | static int | ||
89 | cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp, | ||
90 | u8 __iomem *maskp) | ||
91 | { | ||
92 | int cpld_irq; | ||
93 | u8 status = in_8(statusp); | ||
94 | u8 mask = in_8(maskp); | ||
95 | |||
96 | /* ignore don't cares and masked irqs */ | ||
97 | status |= (ignore | mask); | ||
98 | |||
99 | if (status == 0xff) | ||
100 | return NO_IRQ_IGNORE; | ||
101 | |||
102 | cpld_irq = ffz(status) + offset; | ||
103 | |||
104 | return irq_linear_revmap(cpld_pic_host, cpld_irq); | ||
105 | } | ||
106 | |||
107 | static void | ||
108 | cpld_pic_cascade(unsigned int irq, struct irq_desc *desc) | ||
109 | { | ||
110 | irq = cpld_pic_get_irq(0, PCI_IGNORE, &cpld_regs->pci_status, | ||
111 | &cpld_regs->pci_mask); | ||
112 | if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) { | ||
113 | generic_handle_irq(irq); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | irq = cpld_pic_get_irq(8, MISC_IGNORE, &cpld_regs->misc_status, | ||
118 | &cpld_regs->misc_mask); | ||
119 | if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) { | ||
120 | generic_handle_irq(irq); | ||
121 | return; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | static int | ||
126 | cpld_pic_host_match(struct irq_host *h, struct device_node *node) | ||
127 | { | ||
128 | return cpld_pic_node == node; | ||
129 | } | ||
130 | |||
131 | static int | ||
132 | cpld_pic_host_map(struct irq_host *h, unsigned int virq, | ||
133 | irq_hw_number_t hw) | ||
134 | { | ||
135 | get_irq_desc(virq)->status |= IRQ_LEVEL; | ||
136 | set_irq_chip_and_handler(virq, &cpld_pic, handle_level_irq); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static struct | ||
141 | irq_host_ops cpld_pic_host_ops = { | ||
142 | .match = cpld_pic_host_match, | ||
143 | .map = cpld_pic_host_map, | ||
144 | }; | ||
145 | |||
146 | void __init | ||
147 | mpc5121_ads_cpld_map(void) | ||
148 | { | ||
149 | struct device_node *np = NULL; | ||
150 | |||
151 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121ads-cpld-pic"); | ||
152 | if (!np) { | ||
153 | printk(KERN_ERR "CPLD PIC init: can not find cpld-pic node\n"); | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | cpld_regs = of_iomap(np, 0); | ||
158 | of_node_put(np); | ||
159 | } | ||
160 | |||
161 | void __init | ||
162 | mpc5121_ads_cpld_pic_init(void) | ||
163 | { | ||
164 | unsigned int cascade_irq; | ||
165 | struct device_node *np = NULL; | ||
166 | |||
167 | pr_debug("cpld_ic_init\n"); | ||
168 | |||
169 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121ads-cpld-pic"); | ||
170 | if (!np) { | ||
171 | printk(KERN_ERR "CPLD PIC init: can not find cpld-pic node\n"); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | if (!cpld_regs) | ||
176 | goto end; | ||
177 | |||
178 | cascade_irq = irq_of_parse_and_map(np, 0); | ||
179 | if (cascade_irq == NO_IRQ) | ||
180 | goto end; | ||
181 | |||
182 | /* | ||
183 | * statically route touch screen pendown through 1 | ||
184 | * and ignore it here | ||
185 | * route all others through our cascade irq | ||
186 | */ | ||
187 | out_8(&cpld_regs->route, 0xfd); | ||
188 | out_8(&cpld_regs->pci_mask, 0xff); | ||
189 | /* unmask pci ints in misc mask */ | ||
190 | out_8(&cpld_regs->misc_mask, ~(MISC_IGNORE)); | ||
191 | |||
192 | cpld_pic_node = of_node_get(np); | ||
193 | |||
194 | cpld_pic_host = | ||
195 | irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, 16, &cpld_pic_host_ops, 16); | ||
196 | if (!cpld_pic_host) { | ||
197 | printk(KERN_ERR "CPLD PIC: failed to allocate irq host!\n"); | ||
198 | goto end; | ||
199 | } | ||
200 | |||
201 | set_irq_chained_handler(cascade_irq, cpld_pic_cascade); | ||
202 | end: | ||
203 | of_node_put(np); | ||
204 | } | ||
diff --git a/arch/powerpc/platforms/512x/mpc5121_generic.c b/arch/powerpc/platforms/512x/mpc5121_generic.c new file mode 100644 index 000000000000..2479de9e2d12 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc5121_generic.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby, <jrigby@freescale.com> | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC5121 SoC setup | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/of_platform.h> | ||
18 | |||
19 | #include <asm/machdep.h> | ||
20 | #include <asm/ipic.h> | ||
21 | #include <asm/prom.h> | ||
22 | #include <asm/time.h> | ||
23 | |||
24 | #include "mpc512x.h" | ||
25 | |||
26 | /* | ||
27 | * list of supported boards | ||
28 | */ | ||
29 | static char *board[] __initdata = { | ||
30 | "prt,prtlvt", | ||
31 | NULL | ||
32 | }; | ||
33 | |||
34 | /* | ||
35 | * Called very early, MMU is off, device-tree isn't unflattened | ||
36 | */ | ||
37 | static int __init mpc5121_generic_probe(void) | ||
38 | { | ||
39 | unsigned long node = of_get_flat_dt_root(); | ||
40 | int i = 0; | ||
41 | |||
42 | while (board[i]) { | ||
43 | if (of_flat_dt_is_compatible(node, board[i])) | ||
44 | break; | ||
45 | i++; | ||
46 | } | ||
47 | |||
48 | return board[i] != NULL; | ||
49 | } | ||
50 | |||
51 | define_machine(mpc5121_generic) { | ||
52 | .name = "MPC5121 generic", | ||
53 | .probe = mpc5121_generic_probe, | ||
54 | .init = mpc512x_declare_of_platform_devices, | ||
55 | .init_IRQ = mpc512x_init_IRQ, | ||
56 | .get_irq = ipic_get_irq, | ||
57 | .calibrate_decr = generic_calibrate_decr, | ||
58 | }; | ||
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h new file mode 100644 index 000000000000..9c03693cb009 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc512x.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * Prototypes for MPC512x shared code | ||
10 | */ | ||
11 | |||
12 | #ifndef __MPC512X_H__ | ||
13 | #define __MPC512X_H__ | ||
14 | extern unsigned long mpc512x_find_ips_freq(struct device_node *node); | ||
15 | extern void __init mpc512x_init_IRQ(void); | ||
16 | void __init mpc512x_declare_of_platform_devices(void); | ||
17 | #endif /* __MPC512X_H__ */ | ||
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c new file mode 100644 index 000000000000..d8cd579f3191 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby <jrigby@freescale.com> | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC512x Shared code | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | |||
20 | #include <asm/machdep.h> | ||
21 | #include <asm/ipic.h> | ||
22 | #include <asm/prom.h> | ||
23 | #include <asm/time.h> | ||
24 | |||
25 | #include "mpc512x.h" | ||
26 | |||
27 | unsigned long | ||
28 | mpc512x_find_ips_freq(struct device_node *node) | ||
29 | { | ||
30 | struct device_node *np; | ||
31 | const unsigned int *p_ips_freq = NULL; | ||
32 | |||
33 | of_node_get(node); | ||
34 | while (node) { | ||
35 | p_ips_freq = of_get_property(node, "bus-frequency", NULL); | ||
36 | if (p_ips_freq) | ||
37 | break; | ||
38 | |||
39 | np = of_get_parent(node); | ||
40 | of_node_put(node); | ||
41 | node = np; | ||
42 | } | ||
43 | if (node) | ||
44 | of_node_put(node); | ||
45 | |||
46 | return p_ips_freq ? *p_ips_freq : 0; | ||
47 | } | ||
48 | EXPORT_SYMBOL(mpc512x_find_ips_freq); | ||
49 | |||
50 | void __init mpc512x_init_IRQ(void) | ||
51 | { | ||
52 | struct device_node *np; | ||
53 | |||
54 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-ipic"); | ||
55 | if (!np) | ||
56 | return; | ||
57 | |||
58 | ipic_init(np, 0); | ||
59 | of_node_put(np); | ||
60 | |||
61 | /* | ||
62 | * Initialize the default interrupt mapping priorities, | ||
63 | * in case the boot rom changed something on us. | ||
64 | */ | ||
65 | ipic_set_default_priority(); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Nodes to do bus probe on, soc and localbus | ||
70 | */ | ||
71 | static struct of_device_id __initdata of_bus_ids[] = { | ||
72 | { .compatible = "fsl,mpc5121-immr", }, | ||
73 | { .compatible = "fsl,mpc5121-localbus", }, | ||
74 | {}, | ||
75 | }; | ||
76 | |||
77 | void __init mpc512x_declare_of_platform_devices(void) | ||
78 | { | ||
79 | if (of_platform_bus_probe(NULL, of_bus_ids, NULL)) | ||
80 | printk(KERN_ERR __FILE__ ": " | ||
81 | "Error while probing of_platform bus\n"); | ||
82 | } | ||
83 | |||
diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c index 41c7fd91e99e..fe92e65103ed 100644 --- a/arch/powerpc/platforms/52xx/lite5200_pm.c +++ b/arch/powerpc/platforms/52xx/lite5200_pm.c | |||
@@ -14,6 +14,7 @@ static struct mpc52xx_sdma __iomem *bes; | |||
14 | static struct mpc52xx_xlb __iomem *xlb; | 14 | static struct mpc52xx_xlb __iomem *xlb; |
15 | static struct mpc52xx_gpio __iomem *gps; | 15 | static struct mpc52xx_gpio __iomem *gps; |
16 | static struct mpc52xx_gpio_wkup __iomem *gpw; | 16 | static struct mpc52xx_gpio_wkup __iomem *gpw; |
17 | static void __iomem *pci; | ||
17 | static void __iomem *sram; | 18 | static void __iomem *sram; |
18 | static const int sram_size = 0x4000; /* 16 kBytes */ | 19 | static const int sram_size = 0x4000; /* 16 kBytes */ |
19 | static void __iomem *mbar; | 20 | static void __iomem *mbar; |
@@ -50,6 +51,8 @@ static int lite5200_pm_prepare(void) | |||
50 | { .type = "builtin", .compatible = "mpc5200", }, /* efika */ | 51 | { .type = "builtin", .compatible = "mpc5200", }, /* efika */ |
51 | {} | 52 | {} |
52 | }; | 53 | }; |
54 | u64 regaddr64 = 0; | ||
55 | const u32 *regaddr_p; | ||
53 | 56 | ||
54 | /* deep sleep? let mpc52xx code handle that */ | 57 | /* deep sleep? let mpc52xx code handle that */ |
55 | if (lite5200_pm_target_state == PM_SUSPEND_STANDBY) | 58 | if (lite5200_pm_target_state == PM_SUSPEND_STANDBY) |
@@ -60,8 +63,12 @@ static int lite5200_pm_prepare(void) | |||
60 | 63 | ||
61 | /* map registers */ | 64 | /* map registers */ |
62 | np = of_find_matching_node(NULL, immr_ids); | 65 | np = of_find_matching_node(NULL, immr_ids); |
63 | mbar = of_iomap(np, 0); | 66 | regaddr_p = of_get_address(np, 0, NULL, NULL); |
67 | if (regaddr_p) | ||
68 | regaddr64 = of_translate_address(np, regaddr_p); | ||
64 | of_node_put(np); | 69 | of_node_put(np); |
70 | |||
71 | mbar = ioremap((u32) regaddr64, 0xC000); | ||
65 | if (!mbar) { | 72 | if (!mbar) { |
66 | printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__); | 73 | printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__); |
67 | return -ENOSYS; | 74 | return -ENOSYS; |
@@ -71,6 +78,7 @@ static int lite5200_pm_prepare(void) | |||
71 | pic = mbar + 0x500; | 78 | pic = mbar + 0x500; |
72 | gps = mbar + 0xb00; | 79 | gps = mbar + 0xb00; |
73 | gpw = mbar + 0xc00; | 80 | gpw = mbar + 0xc00; |
81 | pci = mbar + 0xd00; | ||
74 | bes = mbar + 0x1200; | 82 | bes = mbar + 0x1200; |
75 | xlb = mbar + 0x1f00; | 83 | xlb = mbar + 0x1f00; |
76 | sram = mbar + 0x8000; | 84 | sram = mbar + 0x8000; |
@@ -85,6 +93,7 @@ static struct mpc52xx_sdma sbes; | |||
85 | static struct mpc52xx_xlb sxlb; | 93 | static struct mpc52xx_xlb sxlb; |
86 | static struct mpc52xx_gpio sgps; | 94 | static struct mpc52xx_gpio sgps; |
87 | static struct mpc52xx_gpio_wkup sgpw; | 95 | static struct mpc52xx_gpio_wkup sgpw; |
96 | static char spci[0x200]; | ||
88 | 97 | ||
89 | static void lite5200_save_regs(void) | 98 | static void lite5200_save_regs(void) |
90 | { | 99 | { |
@@ -94,6 +103,7 @@ static void lite5200_save_regs(void) | |||
94 | _memcpy_fromio(&sxlb, xlb, sizeof(*xlb)); | 103 | _memcpy_fromio(&sxlb, xlb, sizeof(*xlb)); |
95 | _memcpy_fromio(&sgps, gps, sizeof(*gps)); | 104 | _memcpy_fromio(&sgps, gps, sizeof(*gps)); |
96 | _memcpy_fromio(&sgpw, gpw, sizeof(*gpw)); | 105 | _memcpy_fromio(&sgpw, gpw, sizeof(*gpw)); |
106 | _memcpy_fromio(spci, pci, 0x200); | ||
97 | 107 | ||
98 | _memcpy_fromio(saved_sram, sram, sram_size); | 108 | _memcpy_fromio(saved_sram, sram, sram_size); |
99 | } | 109 | } |
@@ -103,6 +113,8 @@ static void lite5200_restore_regs(void) | |||
103 | int i; | 113 | int i; |
104 | _memcpy_toio(sram, saved_sram, sram_size); | 114 | _memcpy_toio(sram, saved_sram, sram_size); |
105 | 115 | ||
116 | /* PCI Configuration */ | ||
117 | _memcpy_toio(pci, spci, 0x200); | ||
106 | 118 | ||
107 | /* | 119 | /* |
108 | * GPIOs. Interrupt Master Enable has higher address then other | 120 | * GPIOs. Interrupt Master Enable has higher address then other |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c index 48da5dfe4856..8a455ebce98d 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c | |||
@@ -100,7 +100,7 @@ static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | |||
100 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 100 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
101 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | 101 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
102 | struct mpc52xx_gpiochip, mmchip); | 102 | struct mpc52xx_gpiochip, mmchip); |
103 | struct mpc52xx_gpio_wkup *regs = mm_gc->regs; | 103 | struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; |
104 | unsigned long flags; | 104 | unsigned long flags; |
105 | 105 | ||
106 | spin_lock_irqsave(&gpio_lock, flags); | 106 | spin_lock_irqsave(&gpio_lock, flags); |
@@ -122,7 +122,7 @@ static int | |||
122 | mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | 122 | mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
123 | { | 123 | { |
124 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 124 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
125 | struct mpc52xx_gpio_wkup *regs = mm_gc->regs; | 125 | struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs; |
126 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | 126 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
127 | struct mpc52xx_gpiochip, mmchip); | 127 | struct mpc52xx_gpiochip, mmchip); |
128 | unsigned long flags; | 128 | unsigned long flags; |
@@ -150,7 +150,7 @@ static int __devinit mpc52xx_wkup_gpiochip_probe(struct of_device *ofdev, | |||
150 | const struct of_device_id *match) | 150 | const struct of_device_id *match) |
151 | { | 151 | { |
152 | struct mpc52xx_gpiochip *chip; | 152 | struct mpc52xx_gpiochip *chip; |
153 | struct mpc52xx_gpio_wkup *regs; | 153 | struct mpc52xx_gpio_wkup __iomem *regs; |
154 | struct of_gpio_chip *ofchip; | 154 | struct of_gpio_chip *ofchip; |
155 | int ret; | 155 | int ret; |
156 | 156 | ||
@@ -260,7 +260,7 @@ static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | |||
260 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 260 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
261 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | 261 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
262 | struct mpc52xx_gpiochip, mmchip); | 262 | struct mpc52xx_gpiochip, mmchip); |
263 | struct mpc52xx_gpio *regs = mm_gc->regs; | 263 | struct mpc52xx_gpio __iomem *regs = mm_gc->regs; |
264 | unsigned long flags; | 264 | unsigned long flags; |
265 | 265 | ||
266 | spin_lock_irqsave(&gpio_lock, flags); | 266 | spin_lock_irqsave(&gpio_lock, flags); |
@@ -284,7 +284,7 @@ mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | |||
284 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 284 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
285 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, | 285 | struct mpc52xx_gpiochip *chip = container_of(mm_gc, |
286 | struct mpc52xx_gpiochip, mmchip); | 286 | struct mpc52xx_gpiochip, mmchip); |
287 | struct mpc52xx_gpio *regs = mm_gc->regs; | 287 | struct mpc52xx_gpio __iomem *regs = mm_gc->regs; |
288 | unsigned long flags; | 288 | unsigned long flags; |
289 | 289 | ||
290 | spin_lock_irqsave(&gpio_lock, flags); | 290 | spin_lock_irqsave(&gpio_lock, flags); |
@@ -312,7 +312,7 @@ static int __devinit mpc52xx_simple_gpiochip_probe(struct of_device *ofdev, | |||
312 | { | 312 | { |
313 | struct mpc52xx_gpiochip *chip; | 313 | struct mpc52xx_gpiochip *chip; |
314 | struct of_gpio_chip *ofchip; | 314 | struct of_gpio_chip *ofchip; |
315 | struct mpc52xx_gpio *regs; | 315 | struct mpc52xx_gpio __iomem *regs; |
316 | int ret; | 316 | int ret; |
317 | 317 | ||
318 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 318 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
@@ -387,7 +387,7 @@ mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | |||
387 | static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | 387 | static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) |
388 | { | 388 | { |
389 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 389 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
390 | struct mpc52xx_gpt *regs = mm_gc->regs; | 390 | struct mpc52xx_gpt __iomem *regs = mm_gc->regs; |
391 | 391 | ||
392 | out_be32(®s->mode, 0x04); | 392 | out_be32(®s->mode, 0x04); |
393 | 393 | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index e3428ddd9040..5a382bb15f62 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c | |||
@@ -63,6 +63,7 @@ | |||
63 | 63 | ||
64 | #define MPC52xx_PCI_TCR_P 0x01000000 | 64 | #define MPC52xx_PCI_TCR_P 0x01000000 |
65 | #define MPC52xx_PCI_TCR_LD 0x00010000 | 65 | #define MPC52xx_PCI_TCR_LD 0x00010000 |
66 | #define MPC52xx_PCI_TCR_WCT8 0x00000008 | ||
66 | 67 | ||
67 | #define MPC52xx_PCI_TBATR_DISABLE 0x0 | 68 | #define MPC52xx_PCI_TBATR_DISABLE 0x0 |
68 | #define MPC52xx_PCI_TBATR_ENABLE 0x1 | 69 | #define MPC52xx_PCI_TBATR_ENABLE 0x1 |
@@ -313,7 +314,7 @@ mpc52xx_pci_setup(struct pci_controller *hose, | |||
313 | out_be32(&pci_regs->tbatr1, | 314 | out_be32(&pci_regs->tbatr1, |
314 | MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM ); | 315 | MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM ); |
315 | 316 | ||
316 | out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD); | 317 | out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD | MPC52xx_PCI_TCR_WCT8); |
317 | 318 | ||
318 | tmp = in_be32(&pci_regs->gscr); | 319 | tmp = in_be32(&pci_regs->gscr); |
319 | #if 0 | 320 | #if 0 |
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig index 917ac8891555..1c8034bfa796 100644 --- a/arch/powerpc/platforms/82xx/Kconfig +++ b/arch/powerpc/platforms/82xx/Kconfig | |||
@@ -1,7 +1,8 @@ | |||
1 | choice | 1 | menuconfig PPC_82xx |
2 | prompt "82xx Board Type" | 2 | bool "82xx-based boards (PQ II)" |
3 | depends on PPC_82xx | 3 | depends on 6xx && PPC_MULTIPLATFORM |
4 | default MPC8272_ADS | 4 | |
5 | if PPC_82xx | ||
5 | 6 | ||
6 | config MPC8272_ADS | 7 | config MPC8272_ADS |
7 | bool "Freescale MPC8272 ADS" | 8 | bool "Freescale MPC8272 ADS" |
@@ -36,7 +37,7 @@ config EP8248E | |||
36 | This board is also resold by Freescale as the QUICCStart | 37 | This board is also resold by Freescale as the QUICCStart |
37 | MPC8248 Evaluation System and/or the CWH-PPC-8248N-VE. | 38 | MPC8248 Evaluation System and/or the CWH-PPC-8248N-VE. |
38 | 39 | ||
39 | endchoice | 40 | endif |
40 | 41 | ||
41 | config PQ2ADS | 42 | config PQ2ADS |
42 | bool | 43 | bool |
diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c index d5770fdf7f09..373e993a5ed5 100644 --- a/arch/powerpc/platforms/82xx/ep8248e.c +++ b/arch/powerpc/platforms/82xx/ep8248e.c | |||
@@ -59,6 +59,7 @@ static void __init ep8248e_pic_init(void) | |||
59 | of_node_put(np); | 59 | of_node_put(np); |
60 | } | 60 | } |
61 | 61 | ||
62 | #ifdef CONFIG_FS_ENET_MDIO_FCC | ||
62 | static void ep8248e_set_mdc(struct mdiobb_ctrl *ctrl, int level) | 63 | static void ep8248e_set_mdc(struct mdiobb_ctrl *ctrl, int level) |
63 | { | 64 | { |
64 | if (level) | 65 | if (level) |
@@ -164,6 +165,7 @@ static struct of_platform_driver ep8248e_mdio_driver = { | |||
164 | .probe = ep8248e_mdio_probe, | 165 | .probe = ep8248e_mdio_probe, |
165 | .remove = ep8248e_mdio_remove, | 166 | .remove = ep8248e_mdio_remove, |
166 | }; | 167 | }; |
168 | #endif | ||
167 | 169 | ||
168 | struct cpm_pin { | 170 | struct cpm_pin { |
169 | int port, pin, flags; | 171 | int port, pin, flags; |
@@ -296,7 +298,9 @@ static __initdata struct of_device_id of_bus_ids[] = { | |||
296 | static int __init declare_of_platform_devices(void) | 298 | static int __init declare_of_platform_devices(void) |
297 | { | 299 | { |
298 | of_platform_bus_probe(NULL, of_bus_ids, NULL); | 300 | of_platform_bus_probe(NULL, of_bus_ids, NULL); |
301 | #ifdef CONFIG_FS_ENET_MDIO_FCC | ||
299 | of_register_platform_driver(&ep8248e_mdio_driver); | 302 | of_register_platform_driver(&ep8248e_mdio_driver); |
303 | #endif | ||
300 | 304 | ||
301 | return 0; | 305 | return 0; |
302 | } | 306 | } |
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c index 7d3018751988..8054c685d323 100644 --- a/arch/powerpc/platforms/82xx/mpc8272_ads.c +++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c | |||
@@ -96,6 +96,10 @@ static struct cpm_pin mpc8272_ads_pins[] = { | |||
96 | {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | 96 | {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, |
97 | {2, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | 97 | {2, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, |
98 | {2, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | 98 | {2, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, |
99 | |||
100 | /* I2C */ | ||
101 | {3, 14, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN}, | ||
102 | {3, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN}, | ||
99 | }; | 103 | }; |
100 | 104 | ||
101 | static void __init init_ioports(void) | 105 | static void __init init_ioports(void) |
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c index a8013816125c..9876d7e072f4 100644 --- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c +++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c | |||
@@ -109,7 +109,7 @@ static int pci_pic_host_map(struct irq_host *h, unsigned int virq, | |||
109 | { | 109 | { |
110 | get_irq_desc(virq)->status |= IRQ_LEVEL; | 110 | get_irq_desc(virq)->status |= IRQ_LEVEL; |
111 | set_irq_chip_data(virq, h->host_data); | 111 | set_irq_chip_data(virq, h->host_data); |
112 | set_irq_chip(virq, &pq2ads_pci_ic); | 112 | set_irq_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq); |
113 | return 0; | 113 | return 0; |
114 | } | 114 | } |
115 | 115 | ||
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 13587e2e8680..27d9bf86de01 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig | |||
@@ -1,10 +1,12 @@ | |||
1 | menuconfig MPC83xx | 1 | menuconfig PPC_83xx |
2 | bool "83xx Board Type" | 2 | bool "83xx-based boards" |
3 | depends on PPC_83xx | 3 | depends on 6xx && PPC_MULTIPLATFORM |
4 | select PPC_UDBG_16550 | 4 | select PPC_UDBG_16550 |
5 | select PPC_INDIRECT_PCI | 5 | select PPC_INDIRECT_PCI |
6 | select FSL_SOC | ||
7 | select IPIC | ||
6 | 8 | ||
7 | if MPC83xx | 9 | if PPC_83xx |
8 | 10 | ||
9 | config MPC831x_RDB | 11 | config MPC831x_RDB |
10 | bool "Freescale MPC831x RDB" | 12 | bool "Freescale MPC831x RDB" |
@@ -58,6 +60,17 @@ config MPC836x_MDS | |||
58 | help | 60 | help |
59 | This option enables support for the MPC836x MDS Processor Board. | 61 | This option enables support for the MPC836x MDS Processor Board. |
60 | 62 | ||
63 | config MPC836x_RDK | ||
64 | bool "Freescale/Logic MPC836x RDK" | ||
65 | select DEFAULT_UIMAGE | ||
66 | select QUICC_ENGINE | ||
67 | select QE_GPIO | ||
68 | select FSL_GTM | ||
69 | select FSL_LBC | ||
70 | help | ||
71 | This option enables support for the MPC836x RDK Processor Board, | ||
72 | also known as ZOOM PowerQUICC Kit. | ||
73 | |||
61 | config MPC837x_MDS | 74 | config MPC837x_MDS |
62 | bool "Freescale MPC837x MDS" | 75 | bool "Freescale MPC837x MDS" |
63 | select DEFAULT_UIMAGE | 76 | select DEFAULT_UIMAGE |
@@ -79,6 +92,15 @@ config SBC834x | |||
79 | help | 92 | help |
80 | This option enables support for the Wind River SBC834x board. | 93 | This option enables support for the Wind River SBC834x board. |
81 | 94 | ||
95 | config ASP834x | ||
96 | bool "Analogue & Micro ASP 834x" | ||
97 | select PPC_MPC834x | ||
98 | select REDBOOT | ||
99 | help | ||
100 | This enables support for the Analogue & Micro ASP 83xx | ||
101 | board. | ||
102 | |||
103 | |||
82 | endif | 104 | endif |
83 | 105 | ||
84 | # used for usb | 106 | # used for usb |
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index 7e6dd3e259d8..f331fd7dd836 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile | |||
@@ -8,7 +8,9 @@ obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o | |||
8 | obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o | 8 | obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o |
9 | obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o | 9 | obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o |
10 | obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o | 10 | obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o |
11 | obj-$(CONFIG_MPC836x_RDK) += mpc836x_rdk.o | ||
11 | obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o | 12 | obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o |
12 | obj-$(CONFIG_MPC837x_MDS) += mpc837x_mds.o | 13 | obj-$(CONFIG_MPC837x_MDS) += mpc837x_mds.o |
13 | obj-$(CONFIG_SBC834x) += sbc834x.o | 14 | obj-$(CONFIG_SBC834x) += sbc834x.o |
14 | obj-$(CONFIG_MPC837x_RDB) += mpc837x_rdb.o | 15 | obj-$(CONFIG_MPC837x_RDB) += mpc837x_rdb.o |
16 | obj-$(CONFIG_ASP834x) += asp834x.o | ||
diff --git a/arch/powerpc/platforms/83xx/asp834x.c b/arch/powerpc/platforms/83xx/asp834x.c new file mode 100644 index 000000000000..bb30d67ad0a2 --- /dev/null +++ b/arch/powerpc/platforms/83xx/asp834x.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * arch/powerpc/platforms/83xx/asp834x.c | ||
3 | * | ||
4 | * Analogue & Micro ASP8347 board specific routines | ||
5 | * clone of mpc834x_itx | ||
6 | * | ||
7 | * Copyright 2008 Codehermit | ||
8 | * | ||
9 | * Maintainer: Bryan O'Donoghue <bodonoghue@codhermit.ie> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/pci.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | |||
20 | #include <asm/time.h> | ||
21 | #include <asm/ipic.h> | ||
22 | #include <asm/udbg.h> | ||
23 | |||
24 | #include "mpc83xx.h" | ||
25 | |||
26 | /* ************************************************************************ | ||
27 | * | ||
28 | * Setup the architecture | ||
29 | * | ||
30 | */ | ||
31 | static void __init asp834x_setup_arch(void) | ||
32 | { | ||
33 | if (ppc_md.progress) | ||
34 | ppc_md.progress("asp834x_setup_arch()", 0); | ||
35 | |||
36 | mpc834x_usb_cfg(); | ||
37 | } | ||
38 | |||
39 | static void __init asp834x_init_IRQ(void) | ||
40 | { | ||
41 | struct device_node *np; | ||
42 | |||
43 | np = of_find_node_by_type(NULL, "ipic"); | ||
44 | if (!np) | ||
45 | return; | ||
46 | |||
47 | ipic_init(np, 0); | ||
48 | |||
49 | of_node_put(np); | ||
50 | |||
51 | /* Initialize the default interrupt mapping priorities, | ||
52 | * in case the boot rom changed something on us. | ||
53 | */ | ||
54 | ipic_set_default_priority(); | ||
55 | } | ||
56 | |||
57 | static struct __initdata of_device_id asp8347_ids[] = { | ||
58 | { .type = "soc", }, | ||
59 | { .compatible = "soc", }, | ||
60 | { .compatible = "simple-bus", }, | ||
61 | {}, | ||
62 | }; | ||
63 | |||
64 | static int __init asp8347_declare_of_platform_devices(void) | ||
65 | { | ||
66 | of_platform_bus_probe(NULL, asp8347_ids, NULL); | ||
67 | return 0; | ||
68 | } | ||
69 | machine_device_initcall(asp834x, asp8347_declare_of_platform_devices); | ||
70 | |||
71 | /* | ||
72 | * Called very early, MMU is off, device-tree isn't unflattened | ||
73 | */ | ||
74 | static int __init asp834x_probe(void) | ||
75 | { | ||
76 | unsigned long root = of_get_flat_dt_root(); | ||
77 | return of_flat_dt_is_compatible(root, "analogue-and-micro,asp8347e"); | ||
78 | } | ||
79 | |||
80 | define_machine(asp834x) { | ||
81 | .name = "ASP8347E", | ||
82 | .probe = asp834x_probe, | ||
83 | .setup_arch = asp834x_setup_arch, | ||
84 | .init_IRQ = asp834x_init_IRQ, | ||
85 | .get_irq = ipic_get_irq, | ||
86 | .restart = mpc83xx_restart, | ||
87 | .time_init = mpc83xx_time_init, | ||
88 | .calibrate_decr = generic_calibrate_decr, | ||
89 | .progress = udbg_progress, | ||
90 | }; | ||
diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c new file mode 100644 index 000000000000..c10dec4bf178 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * MPC8360E-RDK board file. | ||
3 | * | ||
4 | * Copyright (c) 2006 Freescale Semicondutor, Inc. | ||
5 | * Copyright (c) 2007-2008 MontaVista Software, Inc. | ||
6 | * | ||
7 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | ||
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/pci.h> | ||
17 | #include <linux/of_platform.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <asm/prom.h> | ||
20 | #include <asm/time.h> | ||
21 | #include <asm/ipic.h> | ||
22 | #include <asm/udbg.h> | ||
23 | #include <asm/qe.h> | ||
24 | #include <asm/qe_ic.h> | ||
25 | #include <sysdev/fsl_soc.h> | ||
26 | |||
27 | #include "mpc83xx.h" | ||
28 | |||
29 | static struct of_device_id __initdata mpc836x_rdk_ids[] = { | ||
30 | { .compatible = "simple-bus", }, | ||
31 | {}, | ||
32 | }; | ||
33 | |||
34 | static int __init mpc836x_rdk_declare_of_platform_devices(void) | ||
35 | { | ||
36 | return of_platform_bus_probe(NULL, mpc836x_rdk_ids, NULL); | ||
37 | } | ||
38 | machine_device_initcall(mpc836x_rdk, mpc836x_rdk_declare_of_platform_devices); | ||
39 | |||
40 | static void __init mpc836x_rdk_setup_arch(void) | ||
41 | { | ||
42 | #ifdef CONFIG_PCI | ||
43 | struct device_node *np; | ||
44 | #endif | ||
45 | |||
46 | if (ppc_md.progress) | ||
47 | ppc_md.progress("mpc836x_rdk_setup_arch()", 0); | ||
48 | |||
49 | #ifdef CONFIG_PCI | ||
50 | for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") | ||
51 | mpc83xx_add_bridge(np); | ||
52 | #endif | ||
53 | |||
54 | qe_reset(); | ||
55 | } | ||
56 | |||
57 | static void __init mpc836x_rdk_init_IRQ(void) | ||
58 | { | ||
59 | struct device_node *np; | ||
60 | |||
61 | np = of_find_compatible_node(NULL, NULL, "fsl,ipic"); | ||
62 | if (!np) | ||
63 | return; | ||
64 | |||
65 | ipic_init(np, 0); | ||
66 | |||
67 | /* | ||
68 | * Initialize the default interrupt mapping priorities, | ||
69 | * in case the boot rom changed something on us. | ||
70 | */ | ||
71 | ipic_set_default_priority(); | ||
72 | of_node_put(np); | ||
73 | |||
74 | np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic"); | ||
75 | if (!np) | ||
76 | return; | ||
77 | |||
78 | qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic); | ||
79 | of_node_put(np); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Called very early, MMU is off, device-tree isn't unflattened. | ||
84 | */ | ||
85 | static int __init mpc836x_rdk_probe(void) | ||
86 | { | ||
87 | unsigned long root = of_get_flat_dt_root(); | ||
88 | |||
89 | return of_flat_dt_is_compatible(root, "fsl,mpc8360rdk"); | ||
90 | } | ||
91 | |||
92 | define_machine(mpc836x_rdk) { | ||
93 | .name = "MPC836x RDK", | ||
94 | .probe = mpc836x_rdk_probe, | ||
95 | .setup_arch = mpc836x_rdk_setup_arch, | ||
96 | .init_IRQ = mpc836x_rdk_init_IRQ, | ||
97 | .get_irq = ipic_get_irq, | ||
98 | .restart = mpc83xx_restart, | ||
99 | .time_init = mpc83xx_time_init, | ||
100 | .calibrate_decr = generic_calibrate_decr, | ||
101 | .progress = udbg_progress, | ||
102 | }; | ||
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 7ff29d53dc2d..cebea5cadbc1 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
@@ -34,9 +34,16 @@ config MPC85xx_MDS | |||
34 | bool "Freescale MPC85xx MDS" | 34 | bool "Freescale MPC85xx MDS" |
35 | select DEFAULT_UIMAGE | 35 | select DEFAULT_UIMAGE |
36 | select QUICC_ENGINE | 36 | select QUICC_ENGINE |
37 | select PHYLIB | ||
37 | help | 38 | help |
38 | This option enables support for the MPC85xx MDS board | 39 | This option enables support for the MPC85xx MDS board |
39 | 40 | ||
41 | config MPC8536_DS | ||
42 | bool "Freescale MPC8536 DS" | ||
43 | select DEFAULT_UIMAGE | ||
44 | help | ||
45 | This option enables support for the MPC8536 DS board | ||
46 | |||
40 | config MPC85xx_DS | 47 | config MPC85xx_DS |
41 | bool "Freescale MPC85xx DS" | 48 | bool "Freescale MPC85xx DS" |
42 | select PPC_I8259 | 49 | select PPC_I8259 |
@@ -74,6 +81,14 @@ config TQM8541 | |||
74 | select TQM85xx | 81 | select TQM85xx |
75 | select CPM2 | 82 | select CPM2 |
76 | 83 | ||
84 | config TQM8548 | ||
85 | bool "TQ Components TQM8548" | ||
86 | help | ||
87 | This option enables support for the TQ Components TQM8548 board. | ||
88 | select DEFAULT_UIMAGE | ||
89 | select PPC_CPM_NEW_BINDING | ||
90 | select TQM85xx | ||
91 | |||
77 | config TQM8555 | 92 | config TQM8555 |
78 | bool "TQ Components TQM8555" | 93 | bool "TQ Components TQM8555" |
79 | help | 94 | help |
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 6cea185f62b2..cb3054e1001d 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o | 4 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o |
5 | obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o | 5 | obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o |
6 | obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o | 6 | obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o |
7 | obj-$(CONFIG_MPC8536_DS) += mpc8536_ds.o | ||
7 | obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o | 8 | obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o |
8 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o | 9 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o |
9 | obj-$(CONFIG_STX_GP3) += stx_gp3.o | 10 | obj-$(CONFIG_STX_GP3) += stx_gp3.o |
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c new file mode 100644 index 000000000000..6b846aa1ced9 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * MPC8536 DS Board Setup | ||
3 | * | ||
4 | * Copyright 2008 Freescale Semiconductor, Inc. | ||
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 | |||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/kdev_t.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/seq_file.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | |||
21 | #include <asm/system.h> | ||
22 | #include <asm/time.h> | ||
23 | #include <asm/machdep.h> | ||
24 | #include <asm/pci-bridge.h> | ||
25 | #include <mm/mmu_decl.h> | ||
26 | #include <asm/prom.h> | ||
27 | #include <asm/udbg.h> | ||
28 | #include <asm/mpic.h> | ||
29 | |||
30 | #include <sysdev/fsl_soc.h> | ||
31 | #include <sysdev/fsl_pci.h> | ||
32 | |||
33 | void __init mpc8536_ds_pic_init(void) | ||
34 | { | ||
35 | struct mpic *mpic; | ||
36 | struct resource r; | ||
37 | struct device_node *np; | ||
38 | |||
39 | np = of_find_node_by_type(NULL, "open-pic"); | ||
40 | if (np == NULL) { | ||
41 | printk(KERN_ERR "Could not find open-pic node\n"); | ||
42 | return; | ||
43 | } | ||
44 | |||
45 | if (of_address_to_resource(np, 0, &r)) { | ||
46 | printk(KERN_ERR "Failed to map mpic register space\n"); | ||
47 | of_node_put(np); | ||
48 | return; | ||
49 | } | ||
50 | |||
51 | mpic = mpic_alloc(np, r.start, | ||
52 | MPIC_PRIMARY | MPIC_WANTS_RESET | | ||
53 | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, | ||
54 | 0, 256, " OpenPIC "); | ||
55 | BUG_ON(mpic == NULL); | ||
56 | of_node_put(np); | ||
57 | |||
58 | mpic_init(mpic); | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Setup the architecture | ||
63 | */ | ||
64 | static void __init mpc8536_ds_setup_arch(void) | ||
65 | { | ||
66 | #ifdef CONFIG_PCI | ||
67 | struct device_node *np; | ||
68 | #endif | ||
69 | |||
70 | if (ppc_md.progress) | ||
71 | ppc_md.progress("mpc8536_ds_setup_arch()", 0); | ||
72 | |||
73 | #ifdef CONFIG_PCI | ||
74 | for_each_node_by_type(np, "pci") { | ||
75 | if (of_device_is_compatible(np, "fsl,mpc8540-pci") || | ||
76 | of_device_is_compatible(np, "fsl,mpc8548-pcie")) { | ||
77 | struct resource rsrc; | ||
78 | of_address_to_resource(np, 0, &rsrc); | ||
79 | if ((rsrc.start & 0xfffff) == 0x8000) | ||
80 | fsl_add_bridge(np, 1); | ||
81 | else | ||
82 | fsl_add_bridge(np, 0); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | #endif | ||
87 | |||
88 | printk("MPC8536 DS board from Freescale Semiconductor\n"); | ||
89 | } | ||
90 | |||
91 | static struct of_device_id __initdata mpc8536_ds_ids[] = { | ||
92 | { .type = "soc", }, | ||
93 | { .compatible = "soc", }, | ||
94 | {}, | ||
95 | }; | ||
96 | |||
97 | static int __init mpc8536_ds_publish_devices(void) | ||
98 | { | ||
99 | return of_platform_bus_probe(NULL, mpc8536_ds_ids, NULL); | ||
100 | } | ||
101 | machine_device_initcall(mpc8536_ds, mpc8536_ds_publish_devices); | ||
102 | |||
103 | /* | ||
104 | * Called very early, device-tree isn't unflattened | ||
105 | */ | ||
106 | static int __init mpc8536_ds_probe(void) | ||
107 | { | ||
108 | unsigned long root = of_get_flat_dt_root(); | ||
109 | |||
110 | return of_flat_dt_is_compatible(root, "fsl,mpc8536ds"); | ||
111 | } | ||
112 | |||
113 | define_machine(mpc8536_ds) { | ||
114 | .name = "MPC8536 DS", | ||
115 | .probe = mpc8536_ds_probe, | ||
116 | .setup_arch = mpc8536_ds_setup_arch, | ||
117 | .init_IRQ = mpc8536_ds_pic_init, | ||
118 | #ifdef CONFIG_PCI | ||
119 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
120 | #endif | ||
121 | .get_irq = mpic_get_irq, | ||
122 | .restart = fsl_rstcr_restart, | ||
123 | .calibrate_decr = generic_calibrate_decr, | ||
124 | .progress = udbg_progress, | ||
125 | }; | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 3582c841844b..ba498d6f2d02 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c | |||
@@ -119,6 +119,8 @@ static const struct cpm_pin mpc8560_ads_pins[] = { | |||
119 | {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | 119 | {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, |
120 | 120 | ||
121 | /* SCC2 */ | 121 | /* SCC2 */ |
122 | {2, 12, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
123 | {2, 13, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | ||
122 | {3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | 124 | {3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, |
123 | {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | 125 | {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, |
124 | {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | 126 | {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, |
@@ -145,7 +147,6 @@ static const struct cpm_pin mpc8560_ads_pins[] = { | |||
145 | {1, 4, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | 147 | {1, 4, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, |
146 | {1, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | 148 | {1, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, |
147 | {1, 6, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | 149 | {1, 6, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, |
148 | {1, 7, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
149 | {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | 150 | {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, |
150 | {1, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | 151 | {1, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, |
151 | {1, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | 152 | {1, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, |
@@ -156,8 +157,9 @@ static const struct cpm_pin mpc8560_ads_pins[] = { | |||
156 | {1, 15, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | 157 | {1, 15, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, |
157 | {1, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | 158 | {1, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, |
158 | {1, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, | 159 | {1, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, |
159 | {2, 16, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK16 */ | 160 | {2, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK16 */ |
160 | {2, 17, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK15 */ | 161 | {2, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK15 */ |
162 | {2, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, | ||
161 | }; | 163 | }; |
162 | 164 | ||
163 | static void __init init_ioports(void) | 165 | static void __init init_ioports(void) |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 8b1de7884be6..50d7ea8f922b 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/fsl_devices.h> | 28 | #include <linux/fsl_devices.h> |
29 | #include <linux/of_platform.h> | ||
29 | 30 | ||
30 | #include <asm/system.h> | 31 | #include <asm/system.h> |
31 | #include <asm/pgtable.h> | 32 | #include <asm/pgtable.h> |
@@ -335,6 +336,19 @@ static int __init mpc85xx_cds_probe(void) | |||
335 | return of_flat_dt_is_compatible(root, "MPC85xxCDS"); | 336 | return of_flat_dt_is_compatible(root, "MPC85xxCDS"); |
336 | } | 337 | } |
337 | 338 | ||
339 | static struct of_device_id __initdata of_bus_ids[] = { | ||
340 | { .type = "soc", }, | ||
341 | { .compatible = "soc", }, | ||
342 | { .compatible = "simple-bus", }, | ||
343 | {}, | ||
344 | }; | ||
345 | |||
346 | static int __init declare_of_platform_devices(void) | ||
347 | { | ||
348 | return of_platform_bus_probe(NULL, of_bus_ids, NULL); | ||
349 | } | ||
350 | machine_device_initcall(mpc85xx_cds, declare_of_platform_devices); | ||
351 | |||
338 | define_machine(mpc85xx_cds) { | 352 | define_machine(mpc85xx_cds) { |
339 | .name = "MPC85xx CDS", | 353 | .name = "MPC85xx CDS", |
340 | .probe = mpc85xx_cds_probe, | 354 | .probe = mpc85xx_cds_probe, |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index dfd8b4ad9b28..25f41cd2d33a 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c | |||
@@ -58,14 +58,13 @@ void __init mpc85xx_ds_pic_init(void) | |||
58 | { | 58 | { |
59 | struct mpic *mpic; | 59 | struct mpic *mpic; |
60 | struct resource r; | 60 | struct resource r; |
61 | struct device_node *np = NULL; | 61 | struct device_node *np; |
62 | #ifdef CONFIG_PPC_I8259 | 62 | #ifdef CONFIG_PPC_I8259 |
63 | struct device_node *cascade_node = NULL; | 63 | struct device_node *cascade_node = NULL; |
64 | int cascade_irq; | 64 | int cascade_irq; |
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | np = of_find_node_by_type(np, "open-pic"); | 67 | np = of_find_node_by_type(NULL, "open-pic"); |
68 | |||
69 | if (np == NULL) { | 68 | if (np == NULL) { |
70 | printk(KERN_ERR "Could not find open-pic node\n"); | 69 | printk(KERN_ERR "Could not find open-pic node\n"); |
71 | return; | 70 | return; |
@@ -78,9 +77,11 @@ void __init mpc85xx_ds_pic_init(void) | |||
78 | } | 77 | } |
79 | 78 | ||
80 | mpic = mpic_alloc(np, r.start, | 79 | mpic = mpic_alloc(np, r.start, |
81 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 80 | MPIC_PRIMARY | MPIC_WANTS_RESET | |
81 | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, | ||
82 | 0, 256, " OpenPIC "); | 82 | 0, 256, " OpenPIC "); |
83 | BUG_ON(mpic == NULL); | 83 | BUG_ON(mpic == NULL); |
84 | of_node_put(np); | ||
84 | 85 | ||
85 | mpic_init(mpic); | 86 | mpic_init(mpic); |
86 | 87 | ||
@@ -184,7 +185,7 @@ static int __init mpc8544_ds_probe(void) | |||
184 | } | 185 | } |
185 | } | 186 | } |
186 | 187 | ||
187 | static struct of_device_id mpc85xxds_ids[] = { | 188 | static struct of_device_id __initdata mpc85xxds_ids[] = { |
188 | { .type = "soc", }, | 189 | { .type = "soc", }, |
189 | { .compatible = "soc", }, | 190 | { .compatible = "soc", }, |
190 | {}, | 191 | {}, |
@@ -195,6 +196,7 @@ static int __init mpc85xxds_publish_devices(void) | |||
195 | return of_platform_bus_probe(NULL, mpc85xxds_ids, NULL); | 196 | return of_platform_bus_probe(NULL, mpc85xxds_ids, NULL); |
196 | } | 197 | } |
197 | machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices); | 198 | machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices); |
199 | machine_device_initcall(mpc8572_ds, mpc85xxds_publish_devices); | ||
198 | 200 | ||
199 | /* | 201 | /* |
200 | * Called very early, device-tree isn't unflattened | 202 | * Called very early, device-tree isn't unflattened |
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c index 77681acf1bae..d850880d6964 100644 --- a/arch/powerpc/platforms/85xx/tqm85xx.c +++ b/arch/powerpc/platforms/85xx/tqm85xx.c | |||
@@ -120,8 +120,18 @@ static void __init tqm85xx_setup_arch(void) | |||
120 | #endif | 120 | #endif |
121 | 121 | ||
122 | #ifdef CONFIG_PCI | 122 | #ifdef CONFIG_PCI |
123 | for_each_compatible_node(np, "pci", "fsl,mpc8540-pci") | 123 | for_each_node_by_type(np, "pci") { |
124 | fsl_add_bridge(np, 1); | 124 | if (of_device_is_compatible(np, "fsl,mpc8540-pci") || |
125 | of_device_is_compatible(np, "fsl,mpc8548-pcie")) { | ||
126 | struct resource rsrc; | ||
127 | if (!of_address_to_resource(np, 0, &rsrc)) { | ||
128 | if ((rsrc.start & 0xfffff) == 0x8000) | ||
129 | fsl_add_bridge(np, 1); | ||
130 | else | ||
131 | fsl_add_bridge(np, 0); | ||
132 | } | ||
133 | } | ||
134 | } | ||
125 | #endif | 135 | #endif |
126 | } | 136 | } |
127 | 137 | ||
@@ -165,10 +175,11 @@ static int __init tqm85xx_probe(void) | |||
165 | { | 175 | { |
166 | unsigned long root = of_get_flat_dt_root(); | 176 | unsigned long root = of_get_flat_dt_root(); |
167 | 177 | ||
168 | if ((of_flat_dt_is_compatible(root, "tqm,8540")) || | 178 | if ((of_flat_dt_is_compatible(root, "tqc,tqm8540")) || |
169 | (of_flat_dt_is_compatible(root, "tqm,8541")) || | 179 | (of_flat_dt_is_compatible(root, "tqc,tqm8541")) || |
170 | (of_flat_dt_is_compatible(root, "tqm,8555")) || | 180 | (of_flat_dt_is_compatible(root, "tqc,tqm8548")) || |
171 | (of_flat_dt_is_compatible(root, "tqm,8560"))) | 181 | (of_flat_dt_is_compatible(root, "tqc,tqm8555")) || |
182 | (of_flat_dt_is_compatible(root, "tqc,tqm8560"))) | ||
172 | return 1; | 183 | return 1; |
173 | 184 | ||
174 | return 0; | 185 | return 0; |
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 053f49a1dcae..80a81e02bb55 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig | |||
@@ -1,7 +1,13 @@ | |||
1 | choice | 1 | config PPC_86xx |
2 | prompt "86xx Board Type" | 2 | menuconfig PPC_86xx |
3 | depends on PPC_86xx | 3 | bool "86xx-based boards" |
4 | default MPC8641_HPCN | 4 | depends on 6xx && PPC_MULTIPLATFORM |
5 | select FSL_SOC | ||
6 | select ALTIVEC | ||
7 | help | ||
8 | The Freescale E600 SoCs have 74xx cores. | ||
9 | |||
10 | if PPC_86xx | ||
5 | 11 | ||
6 | config MPC8641_HPCN | 12 | config MPC8641_HPCN |
7 | bool "Freescale MPC8641 HPCN" | 13 | bool "Freescale MPC8641 HPCN" |
@@ -24,7 +30,7 @@ config MPC8610_HPCD | |||
24 | help | 30 | help |
25 | This option enables support for the MPC8610 HPCD board. | 31 | This option enables support for the MPC8610 HPCD board. |
26 | 32 | ||
27 | endchoice | 33 | endif |
28 | 34 | ||
29 | config MPC8641 | 35 | config MPC8641 |
30 | bool | 36 | bool |
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile index 1b9b4a9b2525..8fee37dec795 100644 --- a/arch/powerpc/platforms/86xx/Makefile +++ b/arch/powerpc/platforms/86xx/Makefile | |||
@@ -2,6 +2,7 @@ | |||
2 | # Makefile for the PowerPC 86xx linux kernel. | 2 | # Makefile for the PowerPC 86xx linux kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := pic.o | ||
5 | obj-$(CONFIG_SMP) += mpc86xx_smp.o | 6 | obj-$(CONFIG_SMP) += mpc86xx_smp.o |
6 | obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o | 7 | obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o |
7 | obj-$(CONFIG_SBC8641D) += sbc8641d.o | 8 | obj-$(CONFIG_SBC8641D) += sbc8641d.o |
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index dea13208bf64..30725302884a 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c | |||
@@ -39,6 +39,8 @@ | |||
39 | #include <sysdev/fsl_pci.h> | 39 | #include <sysdev/fsl_pci.h> |
40 | #include <sysdev/fsl_soc.h> | 40 | #include <sysdev/fsl_soc.h> |
41 | 41 | ||
42 | #include "mpc86xx.h" | ||
43 | |||
42 | static unsigned char *pixis_bdcfg0, *pixis_arch; | 44 | static unsigned char *pixis_bdcfg0, *pixis_arch; |
43 | 45 | ||
44 | static struct of_device_id __initdata mpc8610_ids[] = { | 46 | static struct of_device_id __initdata mpc8610_ids[] = { |
@@ -56,27 +58,6 @@ static int __init mpc8610_declare_of_platform_devices(void) | |||
56 | } | 58 | } |
57 | machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices); | 59 | machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices); |
58 | 60 | ||
59 | static void __init mpc86xx_hpcd_init_irq(void) | ||
60 | { | ||
61 | struct mpic *mpic1; | ||
62 | struct device_node *np; | ||
63 | struct resource res; | ||
64 | |||
65 | /* Determine PIC address. */ | ||
66 | np = of_find_node_by_type(NULL, "open-pic"); | ||
67 | if (np == NULL) | ||
68 | return; | ||
69 | of_address_to_resource(np, 0, &res); | ||
70 | |||
71 | /* Alloc mpic structure and per isu has 16 INT entries. */ | ||
72 | mpic1 = mpic_alloc(np, res.start, | ||
73 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | ||
74 | 0, 256, " MPIC "); | ||
75 | BUG_ON(mpic1 == NULL); | ||
76 | |||
77 | mpic_init(mpic1); | ||
78 | } | ||
79 | |||
80 | #ifdef CONFIG_PCI | 61 | #ifdef CONFIG_PCI |
81 | static void __devinit quirk_uli1575(struct pci_dev *dev) | 62 | static void __devinit quirk_uli1575(struct pci_dev *dev) |
82 | { | 63 | { |
@@ -404,7 +385,7 @@ define_machine(mpc86xx_hpcd) { | |||
404 | .name = "MPC86xx HPCD", | 385 | .name = "MPC86xx HPCD", |
405 | .probe = mpc86xx_hpcd_probe, | 386 | .probe = mpc86xx_hpcd_probe, |
406 | .setup_arch = mpc86xx_hpcd_setup_arch, | 387 | .setup_arch = mpc86xx_hpcd_setup_arch, |
407 | .init_IRQ = mpc86xx_hpcd_init_irq, | 388 | .init_IRQ = mpc86xx_init_irq, |
408 | .get_irq = mpic_get_irq, | 389 | .get_irq = mpic_get_irq, |
409 | .restart = fsl_rstcr_restart, | 390 | .restart = fsl_rstcr_restart, |
410 | .time_init = mpc86xx_time_init, | 391 | .time_init = mpc86xx_time_init, |
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h index 525ffa1904f9..08efb57559d1 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx.h +++ b/arch/powerpc/platforms/86xx/mpc86xx.h | |||
@@ -15,6 +15,7 @@ | |||
15 | * mpc86xx_* files. Mostly for use by mpc86xx_setup(). | 15 | * mpc86xx_* files. Mostly for use by mpc86xx_setup(). |
16 | */ | 16 | */ |
17 | 17 | ||
18 | extern void __init mpc86xx_smp_init(void); | 18 | extern void mpc86xx_smp_init(void); |
19 | extern void mpc86xx_init_irq(void); | ||
19 | 20 | ||
20 | #endif /* __MPC86XX_H__ */ | 21 | #endif /* __MPC86XX_H__ */ |
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index f13704aabbea..7916599c9126 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
29 | #include <mm/mmu_decl.h> | 29 | #include <mm/mmu_decl.h> |
30 | #include <asm/udbg.h> | 30 | #include <asm/udbg.h> |
31 | #include <asm/i8259.h> | ||
32 | 31 | ||
33 | #include <asm/mpic.h> | 32 | #include <asm/mpic.h> |
34 | 33 | ||
@@ -46,67 +45,6 @@ | |||
46 | #endif | 45 | #endif |
47 | 46 | ||
48 | #ifdef CONFIG_PCI | 47 | #ifdef CONFIG_PCI |
49 | static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc) | ||
50 | { | ||
51 | unsigned int cascade_irq = i8259_irq(); | ||
52 | if (cascade_irq != NO_IRQ) | ||
53 | generic_handle_irq(cascade_irq); | ||
54 | desc->chip->eoi(irq); | ||
55 | } | ||
56 | #endif /* CONFIG_PCI */ | ||
57 | |||
58 | static void __init | ||
59 | mpc86xx_hpcn_init_irq(void) | ||
60 | { | ||
61 | struct mpic *mpic1; | ||
62 | struct device_node *np; | ||
63 | struct resource res; | ||
64 | #ifdef CONFIG_PCI | ||
65 | struct device_node *cascade_node = NULL; | ||
66 | int cascade_irq; | ||
67 | #endif | ||
68 | |||
69 | /* Determine PIC address. */ | ||
70 | np = of_find_node_by_type(NULL, "open-pic"); | ||
71 | if (np == NULL) | ||
72 | return; | ||
73 | of_address_to_resource(np, 0, &res); | ||
74 | |||
75 | /* Alloc mpic structure and per isu has 16 INT entries. */ | ||
76 | mpic1 = mpic_alloc(np, res.start, | ||
77 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | ||
78 | 0, 256, " MPIC "); | ||
79 | BUG_ON(mpic1 == NULL); | ||
80 | |||
81 | mpic_init(mpic1); | ||
82 | |||
83 | #ifdef CONFIG_PCI | ||
84 | /* Initialize i8259 controller */ | ||
85 | for_each_node_by_type(np, "interrupt-controller") | ||
86 | if (of_device_is_compatible(np, "chrp,iic")) { | ||
87 | cascade_node = np; | ||
88 | break; | ||
89 | } | ||
90 | if (cascade_node == NULL) { | ||
91 | printk(KERN_DEBUG "mpc86xxhpcn: no ISA interrupt controller\n"); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | cascade_irq = irq_of_parse_and_map(cascade_node, 0); | ||
96 | if (cascade_irq == NO_IRQ) { | ||
97 | printk(KERN_ERR "mpc86xxhpcn: failed to map cascade interrupt"); | ||
98 | return; | ||
99 | } | ||
100 | DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq); | ||
101 | |||
102 | i8259_init(cascade_node, 0); | ||
103 | of_node_put(cascade_node); | ||
104 | |||
105 | set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade); | ||
106 | #endif | ||
107 | } | ||
108 | |||
109 | #ifdef CONFIG_PCI | ||
110 | extern int uses_fsl_uli_m1575; | 48 | extern int uses_fsl_uli_m1575; |
111 | extern int uli_exclude_device(struct pci_controller *hose, | 49 | extern int uli_exclude_device(struct pci_controller *hose, |
112 | u_char bus, u_char devfn); | 50 | u_char bus, u_char devfn); |
@@ -237,7 +175,7 @@ define_machine(mpc86xx_hpcn) { | |||
237 | .name = "MPC86xx HPCN", | 175 | .name = "MPC86xx HPCN", |
238 | .probe = mpc86xx_hpcn_probe, | 176 | .probe = mpc86xx_hpcn_probe, |
239 | .setup_arch = mpc86xx_hpcn_setup_arch, | 177 | .setup_arch = mpc86xx_hpcn_setup_arch, |
240 | .init_IRQ = mpc86xx_hpcn_init_irq, | 178 | .init_IRQ = mpc86xx_init_irq, |
241 | .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, | 179 | .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, |
242 | .get_irq = mpic_get_irq, | 180 | .get_irq = mpic_get_irq, |
243 | .restart = fsl_rstcr_restart, | 181 | .restart = fsl_rstcr_restart, |
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c index ba55b0ff0f74..835f2dc24dc9 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | 17 | ||
18 | #include <asm/code-patching.h> | ||
18 | #include <asm/page.h> | 19 | #include <asm/page.h> |
19 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
20 | #include <asm/pci-bridge.h> | 21 | #include <asm/pci-bridge.h> |
@@ -56,8 +57,7 @@ smp_86xx_kick_cpu(int nr) | |||
56 | unsigned int save_vector; | 57 | unsigned int save_vector; |
57 | unsigned long target, flags; | 58 | unsigned long target, flags; |
58 | int n = 0; | 59 | int n = 0; |
59 | volatile unsigned int *vector | 60 | unsigned int *vector = (unsigned int *)(KERNELBASE + 0x100); |
60 | = (volatile unsigned int *)(KERNELBASE + 0x100); | ||
61 | 61 | ||
62 | if (nr < 0 || nr >= NR_CPUS) | 62 | if (nr < 0 || nr >= NR_CPUS) |
63 | return; | 63 | return; |
@@ -71,7 +71,7 @@ smp_86xx_kick_cpu(int nr) | |||
71 | 71 | ||
72 | /* Setup fake reset vector to call __secondary_start_mpc86xx. */ | 72 | /* Setup fake reset vector to call __secondary_start_mpc86xx. */ |
73 | target = (unsigned long) __secondary_start_mpc86xx; | 73 | target = (unsigned long) __secondary_start_mpc86xx; |
74 | create_branch((unsigned long)vector, target, BRANCH_SET_LINK); | 74 | patch_branch(vector, target, BRANCH_SET_LINK); |
75 | 75 | ||
76 | /* Kick that CPU */ | 76 | /* Kick that CPU */ |
77 | smp_86xx_release_core(nr); | 77 | smp_86xx_release_core(nr); |
diff --git a/arch/powerpc/platforms/86xx/pic.c b/arch/powerpc/platforms/86xx/pic.c new file mode 100644 index 000000000000..8881c5de500d --- /dev/null +++ b/arch/powerpc/platforms/86xx/pic.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * Copyright 2008 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/stddef.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/of_platform.h> | ||
14 | |||
15 | #include <asm/system.h> | ||
16 | #include <asm/mpic.h> | ||
17 | #include <asm/i8259.h> | ||
18 | |||
19 | #ifdef CONFIG_PPC_I8259 | ||
20 | static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc) | ||
21 | { | ||
22 | unsigned int cascade_irq = i8259_irq(); | ||
23 | if (cascade_irq != NO_IRQ) | ||
24 | generic_handle_irq(cascade_irq); | ||
25 | desc->chip->eoi(irq); | ||
26 | } | ||
27 | #endif /* CONFIG_PPC_I8259 */ | ||
28 | |||
29 | void __init mpc86xx_init_irq(void) | ||
30 | { | ||
31 | struct mpic *mpic; | ||
32 | struct device_node *np; | ||
33 | struct resource res; | ||
34 | #ifdef CONFIG_PPC_I8259 | ||
35 | struct device_node *cascade_node = NULL; | ||
36 | int cascade_irq; | ||
37 | #endif | ||
38 | |||
39 | /* Determine PIC address. */ | ||
40 | np = of_find_node_by_type(NULL, "open-pic"); | ||
41 | if (np == NULL) | ||
42 | return; | ||
43 | of_address_to_resource(np, 0, &res); | ||
44 | |||
45 | mpic = mpic_alloc(np, res.start, | ||
46 | MPIC_PRIMARY | MPIC_WANTS_RESET | | ||
47 | MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, | ||
48 | 0, 256, " MPIC "); | ||
49 | of_node_put(np); | ||
50 | BUG_ON(mpic == NULL); | ||
51 | |||
52 | mpic_init(mpic); | ||
53 | |||
54 | #ifdef CONFIG_PPC_I8259 | ||
55 | /* Initialize i8259 controller */ | ||
56 | for_each_node_by_type(np, "interrupt-controller") | ||
57 | if (of_device_is_compatible(np, "chrp,iic")) { | ||
58 | cascade_node = np; | ||
59 | break; | ||
60 | } | ||
61 | |||
62 | if (cascade_node == NULL) { | ||
63 | printk(KERN_DEBUG "Could not find i8259 PIC\n"); | ||
64 | return; | ||
65 | } | ||
66 | |||
67 | cascade_irq = irq_of_parse_and_map(cascade_node, 0); | ||
68 | if (cascade_irq == NO_IRQ) { | ||
69 | printk(KERN_ERR "Failed to map cascade interrupt\n"); | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | i8259_init(cascade_node, 0); | ||
74 | of_node_put(cascade_node); | ||
75 | |||
76 | set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade); | ||
77 | #endif | ||
78 | } | ||
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c index 510a06ef0b55..00e6fad3b3ca 100644 --- a/arch/powerpc/platforms/86xx/sbc8641d.c +++ b/arch/powerpc/platforms/86xx/sbc8641d.c | |||
@@ -38,29 +38,6 @@ | |||
38 | #include "mpc86xx.h" | 38 | #include "mpc86xx.h" |
39 | 39 | ||
40 | static void __init | 40 | static void __init |
41 | sbc8641_init_irq(void) | ||
42 | { | ||
43 | struct mpic *mpic1; | ||
44 | struct device_node *np; | ||
45 | struct resource res; | ||
46 | |||
47 | /* Determine PIC address. */ | ||
48 | np = of_find_node_by_type(NULL, "open-pic"); | ||
49 | if (np == NULL) | ||
50 | return; | ||
51 | of_address_to_resource(np, 0, &res); | ||
52 | |||
53 | /* Alloc mpic structure and per isu has 16 INT entries. */ | ||
54 | mpic1 = mpic_alloc(np, res.start, | ||
55 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | ||
56 | 0, 256, " MPIC "); | ||
57 | of_node_put(np); | ||
58 | BUG_ON(mpic1 == NULL); | ||
59 | |||
60 | mpic_init(mpic1); | ||
61 | } | ||
62 | |||
63 | static void __init | ||
64 | sbc8641_setup_arch(void) | 41 | sbc8641_setup_arch(void) |
65 | { | 42 | { |
66 | #ifdef CONFIG_PCI | 43 | #ifdef CONFIG_PCI |
@@ -151,7 +128,7 @@ define_machine(sbc8641) { | |||
151 | .name = "SBC8641D", | 128 | .name = "SBC8641D", |
152 | .probe = sbc8641_probe, | 129 | .probe = sbc8641_probe, |
153 | .setup_arch = sbc8641_setup_arch, | 130 | .setup_arch = sbc8641_setup_arch, |
154 | .init_IRQ = sbc8641_init_irq, | 131 | .init_IRQ = mpc86xx_init_irq, |
155 | .show_cpuinfo = sbc8641_show_cpuinfo, | 132 | .show_cpuinfo = sbc8641_show_cpuinfo, |
156 | .get_irq = mpic_get_irq, | 133 | .get_irq = mpic_get_irq, |
157 | .restart = fsl_rstcr_restart, | 134 | .restart = fsl_rstcr_restart, |
diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c index c028a5b71bbb..caaec29796b7 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c | |||
@@ -65,6 +65,10 @@ static struct cpm_pin mpc866ads_pins[] = { | |||
65 | {CPM_PORTD, 13, CPM_PIN_OUTPUT}, | 65 | {CPM_PORTD, 13, CPM_PIN_OUTPUT}, |
66 | {CPM_PORTD, 14, CPM_PIN_OUTPUT}, | 66 | {CPM_PORTD, 14, CPM_PIN_OUTPUT}, |
67 | {CPM_PORTD, 15, CPM_PIN_OUTPUT}, | 67 | {CPM_PORTD, 15, CPM_PIN_OUTPUT}, |
68 | |||
69 | /* I2C */ | ||
70 | {CPM_PORTB, 26, CPM_PIN_INPUT | CPM_PIN_OPENDRAIN}, | ||
71 | {CPM_PORTB, 27, CPM_PIN_INPUT | CPM_PIN_OPENDRAIN}, | ||
68 | }; | 72 | }; |
69 | 73 | ||
70 | static void __init init_ioports(void) | 74 | static void __init init_ioports(void) |
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index 6e7ded0233f6..45ed6cdc1310 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c | |||
@@ -158,6 +158,9 @@ static struct cpm_pin mpc885ads_pins[] = { | |||
158 | {CPM_PORTE, 28, CPM_PIN_OUTPUT}, | 158 | {CPM_PORTE, 28, CPM_PIN_OUTPUT}, |
159 | {CPM_PORTE, 29, CPM_PIN_OUTPUT}, | 159 | {CPM_PORTE, 29, CPM_PIN_OUTPUT}, |
160 | #endif | 160 | #endif |
161 | /* I2C */ | ||
162 | {CPM_PORTB, 26, CPM_PIN_INPUT | CPM_PIN_OPENDRAIN}, | ||
163 | {CPM_PORTB, 27, CPM_PIN_INPUT | CPM_PIN_OPENDRAIN}, | ||
161 | }; | 164 | }; |
162 | 165 | ||
163 | static void __init init_ioports(void) | 166 | static void __init init_ioports(void) |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 87454c526973..690c1f46e698 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -1,36 +1,9 @@ | |||
1 | menu "Platform support" | 1 | menu "Platform support" |
2 | 2 | ||
3 | choice | ||
4 | prompt "Machine type" | ||
5 | depends on PPC64 || 6xx | ||
6 | default PPC_MULTIPLATFORM | ||
7 | |||
8 | config PPC_MULTIPLATFORM | 3 | config PPC_MULTIPLATFORM |
9 | bool "Generic desktop/server/laptop" | 4 | bool |
10 | help | 5 | depends on PPC64 || 6xx |
11 | Select this option if configuring for an IBM pSeries or | 6 | default y |
12 | RS/6000 machine, an Apple machine, or a PReP, CHRP, | ||
13 | Maple or Cell-based machine. | ||
14 | |||
15 | config PPC_82xx | ||
16 | bool "Freescale 82xx" | ||
17 | depends on 6xx | ||
18 | |||
19 | config PPC_83xx | ||
20 | bool "Freescale 83xx" | ||
21 | depends on 6xx | ||
22 | select FSL_SOC | ||
23 | select MPC83xx | ||
24 | select IPIC | ||
25 | |||
26 | config PPC_86xx | ||
27 | bool "Freescale 86xx" | ||
28 | depends on 6xx | ||
29 | select FSL_SOC | ||
30 | select ALTIVEC | ||
31 | help | ||
32 | The Freescale E600 SoCs have 74xx cores. | ||
33 | endchoice | ||
34 | 7 | ||
35 | config CLASSIC32 | 8 | config CLASSIC32 |
36 | def_bool y | 9 | def_bool y |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index f7efaa925a13..5bc4b611ff88 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -95,6 +95,11 @@ config E500 | |||
95 | select FSL_EMB_PERFMON | 95 | select FSL_EMB_PERFMON |
96 | bool | 96 | bool |
97 | 97 | ||
98 | config PPC_E500MC | ||
99 | bool "e500mc Support" | ||
100 | select PPC_FPU | ||
101 | depends on E500 | ||
102 | |||
98 | config PPC_FPU | 103 | config PPC_FPU |
99 | bool | 104 | bool |
100 | default y if PPC64 | 105 | default y if PPC64 |
@@ -155,9 +160,25 @@ config ALTIVEC | |||
155 | 160 | ||
156 | If in doubt, say Y here. | 161 | If in doubt, say Y here. |
157 | 162 | ||
163 | config VSX | ||
164 | bool "VSX Support" | ||
165 | depends on POWER4 && ALTIVEC && PPC_FPU | ||
166 | ---help--- | ||
167 | |||
168 | This option enables kernel support for the Vector Scaler extensions | ||
169 | to the PowerPC processor. The kernel currently supports saving and | ||
170 | restoring VSX registers, and turning on the 'VSX enable' bit so user | ||
171 | processes can execute VSX instructions. | ||
172 | |||
173 | This option is only useful if you have a processor that supports | ||
174 | VSX (P7 and above), but does not have any affect on a non-VSX | ||
175 | CPUs (it does, however add code to the kernel). | ||
176 | |||
177 | If in doubt, say Y here. | ||
178 | |||
158 | config SPE | 179 | config SPE |
159 | bool "SPE Support" | 180 | bool "SPE Support" |
160 | depends on E200 || E500 | 181 | depends on E200 || (E500 && !PPC_E500MC) |
161 | default y | 182 | default y |
162 | ---help--- | 183 | ---help--- |
163 | This option enables kernel support for the Signal Processing | 184 | This option enables kernel support for the Signal Processing |
@@ -182,7 +203,7 @@ config PPC_STD_MMU_32 | |||
182 | 203 | ||
183 | config PPC_MM_SLICES | 204 | config PPC_MM_SLICES |
184 | bool | 205 | bool |
185 | default y if HUGETLB_PAGE | 206 | default y if HUGETLB_PAGE || PPC_64K_PAGES |
186 | default n | 207 | default n |
187 | 208 | ||
188 | config VIRT_CPU_ACCOUNTING | 209 | config VIRT_CPU_ACCOUNTING |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index c39f5c225f2e..896548ba1ca1 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/msi.h> | 15 | #include <linux/msi.h> |
16 | #include <linux/of_platform.h> | 16 | #include <linux/of_platform.h> |
17 | #include <linux/debugfs.h> | ||
17 | 18 | ||
18 | #include <asm/dcr.h> | 19 | #include <asm/dcr.h> |
19 | #include <asm/machdep.h> | 20 | #include <asm/machdep.h> |
@@ -69,8 +70,19 @@ struct axon_msic { | |||
69 | dma_addr_t fifo_phys; | 70 | dma_addr_t fifo_phys; |
70 | dcr_host_t dcr_host; | 71 | dcr_host_t dcr_host; |
71 | u32 read_offset; | 72 | u32 read_offset; |
73 | #ifdef DEBUG | ||
74 | u32 __iomem *trigger; | ||
75 | #endif | ||
72 | }; | 76 | }; |
73 | 77 | ||
78 | #ifdef DEBUG | ||
79 | void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic); | ||
80 | #else | ||
81 | static inline void axon_msi_debug_setup(struct device_node *dn, | ||
82 | struct axon_msic *msic) { } | ||
83 | #endif | ||
84 | |||
85 | |||
74 | static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) | 86 | static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) |
75 | { | 87 | { |
76 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); | 88 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); |
@@ -346,7 +358,14 @@ static int axon_msi_probe(struct of_device *device, | |||
346 | goto out_free_msic; | 358 | goto out_free_msic; |
347 | } | 359 | } |
348 | 360 | ||
349 | msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP, | 361 | virq = irq_of_parse_and_map(dn, 0); |
362 | if (virq == NO_IRQ) { | ||
363 | printk(KERN_ERR "axon_msi: irq parse and map failed for %s\n", | ||
364 | dn->full_name); | ||
365 | goto out_free_fifo; | ||
366 | } | ||
367 | |||
368 | msic->irq_host = irq_alloc_host(dn, IRQ_HOST_MAP_NOMAP, | ||
350 | NR_IRQS, &msic_host_ops, 0); | 369 | NR_IRQS, &msic_host_ops, 0); |
351 | if (!msic->irq_host) { | 370 | if (!msic->irq_host) { |
352 | printk(KERN_ERR "axon_msi: couldn't allocate irq_host for %s\n", | 371 | printk(KERN_ERR "axon_msi: couldn't allocate irq_host for %s\n", |
@@ -356,13 +375,6 @@ static int axon_msi_probe(struct of_device *device, | |||
356 | 375 | ||
357 | msic->irq_host->host_data = msic; | 376 | msic->irq_host->host_data = msic; |
358 | 377 | ||
359 | virq = irq_of_parse_and_map(dn, 0); | ||
360 | if (virq == NO_IRQ) { | ||
361 | printk(KERN_ERR "axon_msi: irq parse and map failed for %s\n", | ||
362 | dn->full_name); | ||
363 | goto out_free_host; | ||
364 | } | ||
365 | |||
366 | set_irq_data(virq, msic); | 378 | set_irq_data(virq, msic); |
367 | set_irq_chained_handler(virq, axon_msi_cascade); | 379 | set_irq_chained_handler(virq, axon_msi_cascade); |
368 | pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); | 380 | pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); |
@@ -381,12 +393,12 @@ static int axon_msi_probe(struct of_device *device, | |||
381 | ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs; | 393 | ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs; |
382 | ppc_md.msi_check_device = axon_msi_check_device; | 394 | ppc_md.msi_check_device = axon_msi_check_device; |
383 | 395 | ||
396 | axon_msi_debug_setup(dn, msic); | ||
397 | |||
384 | printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name); | 398 | printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name); |
385 | 399 | ||
386 | return 0; | 400 | return 0; |
387 | 401 | ||
388 | out_free_host: | ||
389 | kfree(msic->irq_host); | ||
390 | out_free_fifo: | 402 | out_free_fifo: |
391 | dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt, | 403 | dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt, |
392 | msic->fifo_phys); | 404 | msic->fifo_phys); |
@@ -418,3 +430,47 @@ static int __init axon_msi_init(void) | |||
418 | return of_register_platform_driver(&axon_msi_driver); | 430 | return of_register_platform_driver(&axon_msi_driver); |
419 | } | 431 | } |
420 | subsys_initcall(axon_msi_init); | 432 | subsys_initcall(axon_msi_init); |
433 | |||
434 | |||
435 | #ifdef DEBUG | ||
436 | static int msic_set(void *data, u64 val) | ||
437 | { | ||
438 | struct axon_msic *msic = data; | ||
439 | out_le32(msic->trigger, val); | ||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static int msic_get(void *data, u64 *val) | ||
444 | { | ||
445 | *val = 0; | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | DEFINE_SIMPLE_ATTRIBUTE(fops_msic, msic_get, msic_set, "%llu\n"); | ||
450 | |||
451 | void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic) | ||
452 | { | ||
453 | char name[8]; | ||
454 | u64 addr; | ||
455 | |||
456 | addr = of_translate_address(dn, of_get_property(dn, "reg", NULL)); | ||
457 | if (addr == OF_BAD_ADDR) { | ||
458 | pr_debug("axon_msi: couldn't translate reg property\n"); | ||
459 | return; | ||
460 | } | ||
461 | |||
462 | msic->trigger = ioremap(addr, 0x4); | ||
463 | if (!msic->trigger) { | ||
464 | pr_debug("axon_msi: ioremap failed\n"); | ||
465 | return; | ||
466 | } | ||
467 | |||
468 | snprintf(name, sizeof(name), "msic_%d", of_node_to_nid(dn)); | ||
469 | |||
470 | if (!debugfs_create_file(name, 0600, powerpc_debugfs_root, | ||
471 | msic, &fops_msic)) { | ||
472 | pr_debug("axon_msi: debugfs_create_file failed!\n"); | ||
473 | return; | ||
474 | } | ||
475 | } | ||
476 | #endif /* DEBUG */ | ||
diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c index 81467ff055c8..2e67bd840e01 100644 --- a/arch/powerpc/platforms/cell/beat_htab.c +++ b/arch/powerpc/platforms/cell/beat_htab.c | |||
@@ -112,7 +112,7 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group, | |||
112 | if (!(vflags & HPTE_V_BOLTED)) | 112 | if (!(vflags & HPTE_V_BOLTED)) |
113 | DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); | 113 | DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); |
114 | 114 | ||
115 | if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) | 115 | if (rflags & _PAGE_NO_CACHE) |
116 | hpte_r &= ~_PAGE_COHERENT; | 116 | hpte_r &= ~_PAGE_COHERENT; |
117 | 117 | ||
118 | spin_lock(&beat_htab_lock); | 118 | spin_lock(&beat_htab_lock); |
@@ -334,7 +334,7 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group, | |||
334 | if (!(vflags & HPTE_V_BOLTED)) | 334 | if (!(vflags & HPTE_V_BOLTED)) |
335 | DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); | 335 | DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); |
336 | 336 | ||
337 | if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) | 337 | if (rflags & _PAGE_NO_CACHE) |
338 | hpte_r &= ~_PAGE_COHERENT; | 338 | hpte_r &= ~_PAGE_COHERENT; |
339 | 339 | ||
340 | /* insert into not-volted entry */ | 340 | /* insert into not-volted entry */ |
diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c index 31da84c458d2..0e04f8fb152a 100644 --- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c +++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c | |||
@@ -217,7 +217,7 @@ static u##size scc_pciex_in##name(unsigned long port) \ | |||
217 | static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \ | 217 | static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \ |
218 | { \ | 218 | { \ |
219 | struct iowa_bus *bus = iowa_pio_find_bus(p); \ | 219 | struct iowa_bus *bus = iowa_pio_find_bus(p); \ |
220 | u##size *dst = b; \ | 220 | __le##size *dst = b; \ |
221 | for (; c != 0; c--, dst++) \ | 221 | for (; c != 0; c--, dst++) \ |
222 | *dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \ | 222 | *dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \ |
223 | scc_pciex_io_flush(bus); \ | 223 | scc_pciex_io_flush(bus); \ |
@@ -231,10 +231,11 @@ static void scc_pciex_outs##name(unsigned long p, const void *b, \ | |||
231 | unsigned long c) \ | 231 | unsigned long c) \ |
232 | { \ | 232 | { \ |
233 | struct iowa_bus *bus = iowa_pio_find_bus(p); \ | 233 | struct iowa_bus *bus = iowa_pio_find_bus(p); \ |
234 | const u##size *src = b; \ | 234 | const __le##size *src = b; \ |
235 | for (; c != 0; c--, src++) \ | 235 | for (; c != 0; c--, src++) \ |
236 | __scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \ | 236 | __scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \ |
237 | } | 237 | } |
238 | #define __le8 u8 | ||
238 | #define cpu_to_le8(x) (x) | 239 | #define cpu_to_le8(x) (x) |
239 | #define le8_to_cpu(x) (x) | 240 | #define le8_to_cpu(x) (x) |
240 | PCIEX_PIO_FUNC(8, b) | 241 | PCIEX_PIO_FUNC(8, b) |
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 5bf7df146022..2d5bb22d6c09 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c | |||
@@ -218,6 +218,7 @@ void iic_request_IPIs(void) | |||
218 | { | 218 | { |
219 | iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call"); | 219 | iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call"); |
220 | iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched"); | 220 | iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched"); |
221 | iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE, "IPI-call-single"); | ||
221 | #ifdef CONFIG_DEBUGGER | 222 | #ifdef CONFIG_DEBUGGER |
222 | iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); | 223 | iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); |
223 | #endif /* CONFIG_DEBUGGER */ | 224 | #endif /* CONFIG_DEBUGGER */ |
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 45646b2b4af4..eeacb3a52ca1 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -540,7 +540,7 @@ static unsigned long cell_dma_direct_offset; | |||
540 | static unsigned long dma_iommu_fixed_base; | 540 | static unsigned long dma_iommu_fixed_base; |
541 | struct dma_mapping_ops dma_iommu_fixed_ops; | 541 | struct dma_mapping_ops dma_iommu_fixed_ops; |
542 | 542 | ||
543 | static void cell_dma_dev_setup_iommu(struct device *dev) | 543 | static struct iommu_table *cell_get_iommu_table(struct device *dev) |
544 | { | 544 | { |
545 | struct iommu_window *window; | 545 | struct iommu_window *window; |
546 | struct cbe_iommu *iommu; | 546 | struct cbe_iommu *iommu; |
@@ -555,11 +555,11 @@ static void cell_dma_dev_setup_iommu(struct device *dev) | |||
555 | printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", | 555 | printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", |
556 | archdata->of_node ? archdata->of_node->full_name : "?", | 556 | archdata->of_node ? archdata->of_node->full_name : "?", |
557 | archdata->numa_node); | 557 | archdata->numa_node); |
558 | return; | 558 | return NULL; |
559 | } | 559 | } |
560 | window = list_entry(iommu->windows.next, struct iommu_window, list); | 560 | window = list_entry(iommu->windows.next, struct iommu_window, list); |
561 | 561 | ||
562 | archdata->dma_data = &window->table; | 562 | return &window->table; |
563 | } | 563 | } |
564 | 564 | ||
565 | static void cell_dma_dev_setup_fixed(struct device *dev); | 565 | static void cell_dma_dev_setup_fixed(struct device *dev); |
@@ -572,7 +572,7 @@ static void cell_dma_dev_setup(struct device *dev) | |||
572 | if (get_dma_ops(dev) == &dma_iommu_fixed_ops) | 572 | if (get_dma_ops(dev) == &dma_iommu_fixed_ops) |
573 | cell_dma_dev_setup_fixed(dev); | 573 | cell_dma_dev_setup_fixed(dev); |
574 | else if (get_pci_dma_ops() == &dma_iommu_ops) | 574 | else if (get_pci_dma_ops() == &dma_iommu_ops) |
575 | cell_dma_dev_setup_iommu(dev); | 575 | archdata->dma_data = cell_get_iommu_table(dev); |
576 | else if (get_pci_dma_ops() == &dma_direct_ops) | 576 | else if (get_pci_dma_ops() == &dma_direct_ops) |
577 | archdata->dma_data = (void *)cell_dma_direct_offset; | 577 | archdata->dma_data = (void *)cell_dma_direct_offset; |
578 | else | 578 | else |
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 655704ad03cf..505f9b9bdf0c 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/reg.h> | 17 | #include <asm/reg.h> |
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
20 | #include <asm/kexec.h> | ||
20 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
21 | #include <asm/rtas.h> | 22 | #include <asm/rtas.h> |
22 | #include <asm/cell-regs.h> | 23 | #include <asm/cell-regs.h> |
@@ -226,6 +227,11 @@ static int cbe_ptcal_notify_reboot(struct notifier_block *nb, | |||
226 | return cbe_ptcal_disable(); | 227 | return cbe_ptcal_disable(); |
227 | } | 228 | } |
228 | 229 | ||
230 | static void cbe_ptcal_crash_shutdown(void) | ||
231 | { | ||
232 | cbe_ptcal_disable(); | ||
233 | } | ||
234 | |||
229 | static struct notifier_block cbe_ptcal_reboot_notifier = { | 235 | static struct notifier_block cbe_ptcal_reboot_notifier = { |
230 | .notifier_call = cbe_ptcal_notify_reboot | 236 | .notifier_call = cbe_ptcal_notify_reboot |
231 | }; | 237 | }; |
@@ -241,12 +247,20 @@ int __init cbe_ptcal_init(void) | |||
241 | return -ENODEV; | 247 | return -ENODEV; |
242 | 248 | ||
243 | ret = register_reboot_notifier(&cbe_ptcal_reboot_notifier); | 249 | ret = register_reboot_notifier(&cbe_ptcal_reboot_notifier); |
244 | if (ret) { | 250 | if (ret) |
245 | printk(KERN_ERR "Can't disable PTCAL, so not enabling\n"); | 251 | goto out1; |
246 | return ret; | 252 | |
247 | } | 253 | ret = crash_shutdown_register(&cbe_ptcal_crash_shutdown); |
254 | if (ret) | ||
255 | goto out2; | ||
248 | 256 | ||
249 | return cbe_ptcal_enable(); | 257 | return cbe_ptcal_enable(); |
258 | |||
259 | out2: | ||
260 | unregister_reboot_notifier(&cbe_ptcal_reboot_notifier); | ||
261 | out1: | ||
262 | printk(KERN_ERR "Can't disable PTCAL, so not enabling\n"); | ||
263 | return ret; | ||
250 | } | 264 | } |
251 | 265 | ||
252 | arch_initcall(cbe_ptcal_init); | 266 | arch_initcall(cbe_ptcal_init); |
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 3f4b4aef756d..4e5655624ae8 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c | |||
@@ -300,7 +300,7 @@ static void __init spider_init_one(struct device_node *of_node, int chip, | |||
300 | panic("spider_pic: can't map registers !"); | 300 | panic("spider_pic: can't map registers !"); |
301 | 301 | ||
302 | /* Allocate a host */ | 302 | /* Allocate a host */ |
303 | pic->host = irq_alloc_host(of_node_get(of_node), IRQ_HOST_MAP_LINEAR, | 303 | pic->host = irq_alloc_host(of_node, IRQ_HOST_MAP_LINEAR, |
304 | SPIDER_SRC_COUNT, &spider_host_ops, | 304 | SPIDER_SRC_COUNT, &spider_host_ops, |
305 | SPIDER_IRQ_INVALID); | 305 | SPIDER_IRQ_INVALID); |
306 | if (pic->host == NULL) | 306 | if (pic->host == NULL) |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 70c660121ec4..78f905bc6a42 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -219,15 +219,25 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
219 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX | 219 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX |
220 | static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) | 220 | static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) |
221 | { | 221 | { |
222 | int ret; | ||
223 | |||
222 | pr_debug("%s, %lx, %lx\n", __func__, dsisr, ea); | 224 | pr_debug("%s, %lx, %lx\n", __func__, dsisr, ea); |
223 | 225 | ||
224 | /* Handle kernel space hash faults immediately. | 226 | /* |
225 | User hash faults need to be deferred to process context. */ | 227 | * Handle kernel space hash faults immediately. User hash |
226 | if ((dsisr & MFC_DSISR_PTE_NOT_FOUND) | 228 | * faults need to be deferred to process context. |
227 | && REGION_ID(ea) != USER_REGION_ID | 229 | */ |
228 | && hash_page(ea, _PAGE_PRESENT, 0x300) == 0) { | 230 | if ((dsisr & MFC_DSISR_PTE_NOT_FOUND) && |
229 | spu_restart_dma(spu); | 231 | (REGION_ID(ea) != USER_REGION_ID)) { |
230 | return 0; | 232 | |
233 | spin_unlock(&spu->register_lock); | ||
234 | ret = hash_page(ea, _PAGE_PRESENT, 0x300); | ||
235 | spin_lock(&spu->register_lock); | ||
236 | |||
237 | if (!ret) { | ||
238 | spu_restart_dma(spu); | ||
239 | return 0; | ||
240 | } | ||
231 | } | 241 | } |
232 | 242 | ||
233 | spu->class_1_dar = ea; | 243 | spu->class_1_dar = ea; |
@@ -324,17 +334,13 @@ spu_irq_class_0(int irq, void *data) | |||
324 | stat = spu_int_stat_get(spu, 0) & mask; | 334 | stat = spu_int_stat_get(spu, 0) & mask; |
325 | 335 | ||
326 | spu->class_0_pending |= stat; | 336 | spu->class_0_pending |= stat; |
327 | spu->class_0_dsisr = spu_mfc_dsisr_get(spu); | ||
328 | spu->class_0_dar = spu_mfc_dar_get(spu); | 337 | spu->class_0_dar = spu_mfc_dar_get(spu); |
329 | spin_unlock(&spu->register_lock); | ||
330 | |||
331 | spu->stop_callback(spu, 0); | 338 | spu->stop_callback(spu, 0); |
332 | |||
333 | spu->class_0_pending = 0; | 339 | spu->class_0_pending = 0; |
334 | spu->class_0_dsisr = 0; | ||
335 | spu->class_0_dar = 0; | 340 | spu->class_0_dar = 0; |
336 | 341 | ||
337 | spu_int_stat_clear(spu, 0, stat); | 342 | spu_int_stat_clear(spu, 0, stat); |
343 | spin_unlock(&spu->register_lock); | ||
338 | 344 | ||
339 | return IRQ_HANDLED; | 345 | return IRQ_HANDLED; |
340 | } | 346 | } |
@@ -357,13 +363,12 @@ spu_irq_class_1(int irq, void *data) | |||
357 | spu_mfc_dsisr_set(spu, 0ul); | 363 | spu_mfc_dsisr_set(spu, 0ul); |
358 | spu_int_stat_clear(spu, 1, stat); | 364 | spu_int_stat_clear(spu, 1, stat); |
359 | 365 | ||
360 | if (stat & CLASS1_SEGMENT_FAULT_INTR) | ||
361 | __spu_trap_data_seg(spu, dar); | ||
362 | |||
363 | spin_unlock(&spu->register_lock); | ||
364 | pr_debug("%s: %lx %lx %lx %lx\n", __func__, mask, stat, | 366 | pr_debug("%s: %lx %lx %lx %lx\n", __func__, mask, stat, |
365 | dar, dsisr); | 367 | dar, dsisr); |
366 | 368 | ||
369 | if (stat & CLASS1_SEGMENT_FAULT_INTR) | ||
370 | __spu_trap_data_seg(spu, dar); | ||
371 | |||
367 | if (stat & CLASS1_STORAGE_FAULT_INTR) | 372 | if (stat & CLASS1_STORAGE_FAULT_INTR) |
368 | __spu_trap_data_map(spu, dar, dsisr); | 373 | __spu_trap_data_map(spu, dar, dsisr); |
369 | 374 | ||
@@ -376,6 +381,8 @@ spu_irq_class_1(int irq, void *data) | |||
376 | spu->class_1_dsisr = 0; | 381 | spu->class_1_dsisr = 0; |
377 | spu->class_1_dar = 0; | 382 | spu->class_1_dar = 0; |
378 | 383 | ||
384 | spin_unlock(&spu->register_lock); | ||
385 | |||
379 | return stat ? IRQ_HANDLED : IRQ_NONE; | 386 | return stat ? IRQ_HANDLED : IRQ_NONE; |
380 | } | 387 | } |
381 | 388 | ||
@@ -394,14 +401,12 @@ spu_irq_class_2(int irq, void *data) | |||
394 | mask = spu_int_mask_get(spu, 2); | 401 | mask = spu_int_mask_get(spu, 2); |
395 | /* ignore interrupts we're not waiting for */ | 402 | /* ignore interrupts we're not waiting for */ |
396 | stat &= mask; | 403 | stat &= mask; |
397 | |||
398 | /* mailbox interrupts are level triggered. mask them now before | 404 | /* mailbox interrupts are level triggered. mask them now before |
399 | * acknowledging */ | 405 | * acknowledging */ |
400 | if (stat & mailbox_intrs) | 406 | if (stat & mailbox_intrs) |
401 | spu_int_mask_and(spu, 2, ~(stat & mailbox_intrs)); | 407 | spu_int_mask_and(spu, 2, ~(stat & mailbox_intrs)); |
402 | /* acknowledge all interrupts before the callbacks */ | 408 | /* acknowledge all interrupts before the callbacks */ |
403 | spu_int_stat_clear(spu, 2, stat); | 409 | spu_int_stat_clear(spu, 2, stat); |
404 | spin_unlock(&spu->register_lock); | ||
405 | 410 | ||
406 | pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask); | 411 | pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask); |
407 | 412 | ||
@@ -421,6 +426,9 @@ spu_irq_class_2(int irq, void *data) | |||
421 | spu->wbox_callback(spu); | 426 | spu->wbox_callback(spu); |
422 | 427 | ||
423 | spu->stats.class2_intr++; | 428 | spu->stats.class2_intr++; |
429 | |||
430 | spin_unlock(&spu->register_lock); | ||
431 | |||
424 | return stat ? IRQ_HANDLED : IRQ_NONE; | 432 | return stat ? IRQ_HANDLED : IRQ_NONE; |
425 | } | 433 | } |
426 | 434 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 177735f79317..6653ddbed048 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -130,17 +130,17 @@ void spu_unmap_mappings(struct spu_context *ctx) | |||
130 | if (ctx->local_store) | 130 | if (ctx->local_store) |
131 | unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); | 131 | unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); |
132 | if (ctx->mfc) | 132 | if (ctx->mfc) |
133 | unmap_mapping_range(ctx->mfc, 0, 0x1000, 1); | 133 | unmap_mapping_range(ctx->mfc, 0, SPUFS_MFC_MAP_SIZE, 1); |
134 | if (ctx->cntl) | 134 | if (ctx->cntl) |
135 | unmap_mapping_range(ctx->cntl, 0, 0x1000, 1); | 135 | unmap_mapping_range(ctx->cntl, 0, SPUFS_CNTL_MAP_SIZE, 1); |
136 | if (ctx->signal1) | 136 | if (ctx->signal1) |
137 | unmap_mapping_range(ctx->signal1, 0, PAGE_SIZE, 1); | 137 | unmap_mapping_range(ctx->signal1, 0, SPUFS_SIGNAL_MAP_SIZE, 1); |
138 | if (ctx->signal2) | 138 | if (ctx->signal2) |
139 | unmap_mapping_range(ctx->signal2, 0, PAGE_SIZE, 1); | 139 | unmap_mapping_range(ctx->signal2, 0, SPUFS_SIGNAL_MAP_SIZE, 1); |
140 | if (ctx->mss) | 140 | if (ctx->mss) |
141 | unmap_mapping_range(ctx->mss, 0, 0x1000, 1); | 141 | unmap_mapping_range(ctx->mss, 0, SPUFS_MSS_MAP_SIZE, 1); |
142 | if (ctx->psmap) | 142 | if (ctx->psmap) |
143 | unmap_mapping_range(ctx->psmap, 0, 0x20000, 1); | 143 | unmap_mapping_range(ctx->psmap, 0, SPUFS_PS_MAP_SIZE, 1); |
144 | mutex_unlock(&ctx->mapping_lock); | 144 | mutex_unlock(&ctx->mapping_lock); |
145 | } | 145 | } |
146 | 146 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index c81341ff75b5..99c73066b82f 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -238,11 +238,13 @@ spufs_mem_write(struct file *file, const char __user *buffer, | |||
238 | return size; | 238 | return size; |
239 | } | 239 | } |
240 | 240 | ||
241 | static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma, | 241 | static int |
242 | unsigned long address) | 242 | spufs_mem_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
243 | { | 243 | { |
244 | struct spu_context *ctx = vma->vm_file->private_data; | 244 | struct spu_context *ctx = vma->vm_file->private_data; |
245 | unsigned long pfn, offset, addr0 = address; | 245 | unsigned long address = (unsigned long)vmf->virtual_address; |
246 | unsigned long pfn, offset; | ||
247 | |||
246 | #ifdef CONFIG_SPU_FS_64K_LS | 248 | #ifdef CONFIG_SPU_FS_64K_LS |
247 | struct spu_state *csa = &ctx->csa; | 249 | struct spu_state *csa = &ctx->csa; |
248 | int psize; | 250 | int psize; |
@@ -260,15 +262,15 @@ static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma, | |||
260 | } | 262 | } |
261 | #endif /* CONFIG_SPU_FS_64K_LS */ | 263 | #endif /* CONFIG_SPU_FS_64K_LS */ |
262 | 264 | ||
263 | offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); | 265 | offset = vmf->pgoff << PAGE_SHIFT; |
264 | if (offset >= LS_SIZE) | 266 | if (offset >= LS_SIZE) |
265 | return NOPFN_SIGBUS; | 267 | return VM_FAULT_SIGBUS; |
266 | 268 | ||
267 | pr_debug("spufs_mem_mmap_nopfn address=0x%lx -> 0x%lx, offset=0x%lx\n", | 269 | pr_debug("spufs_mem_mmap_fault address=0x%lx, offset=0x%lx\n", |
268 | addr0, address, offset); | 270 | address, offset); |
269 | 271 | ||
270 | if (spu_acquire(ctx)) | 272 | if (spu_acquire(ctx)) |
271 | return NOPFN_REFAULT; | 273 | return VM_FAULT_NOPAGE; |
272 | 274 | ||
273 | if (ctx->state == SPU_STATE_SAVED) { | 275 | if (ctx->state == SPU_STATE_SAVED) { |
274 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 276 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
@@ -283,12 +285,12 @@ static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma, | |||
283 | 285 | ||
284 | spu_release(ctx); | 286 | spu_release(ctx); |
285 | 287 | ||
286 | return NOPFN_REFAULT; | 288 | return VM_FAULT_NOPAGE; |
287 | } | 289 | } |
288 | 290 | ||
289 | 291 | ||
290 | static struct vm_operations_struct spufs_mem_mmap_vmops = { | 292 | static struct vm_operations_struct spufs_mem_mmap_vmops = { |
291 | .nopfn = spufs_mem_mmap_nopfn, | 293 | .fault = spufs_mem_mmap_fault, |
292 | }; | 294 | }; |
293 | 295 | ||
294 | static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) | 296 | static int spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) |
@@ -351,20 +353,19 @@ static const struct file_operations spufs_mem_fops = { | |||
351 | #endif | 353 | #endif |
352 | }; | 354 | }; |
353 | 355 | ||
354 | static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | 356 | static int spufs_ps_fault(struct vm_area_struct *vma, |
355 | unsigned long address, | 357 | struct vm_fault *vmf, |
356 | unsigned long ps_offs, | 358 | unsigned long ps_offs, |
357 | unsigned long ps_size) | 359 | unsigned long ps_size) |
358 | { | 360 | { |
359 | struct spu_context *ctx = vma->vm_file->private_data; | 361 | struct spu_context *ctx = vma->vm_file->private_data; |
360 | unsigned long area, offset = address - vma->vm_start; | 362 | unsigned long area, offset = vmf->pgoff << PAGE_SHIFT; |
361 | int ret = 0; | 363 | int ret = 0; |
362 | 364 | ||
363 | spu_context_nospu_trace(spufs_ps_nopfn__enter, ctx); | 365 | spu_context_nospu_trace(spufs_ps_fault__enter, ctx); |
364 | 366 | ||
365 | offset += vma->vm_pgoff << PAGE_SHIFT; | ||
366 | if (offset >= ps_size) | 367 | if (offset >= ps_size) |
367 | return NOPFN_SIGBUS; | 368 | return VM_FAULT_SIGBUS; |
368 | 369 | ||
369 | /* | 370 | /* |
370 | * Because we release the mmap_sem, the context may be destroyed while | 371 | * Because we release the mmap_sem, the context may be destroyed while |
@@ -378,7 +379,7 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
378 | * pages to hand out to the user, but we don't want to wait | 379 | * pages to hand out to the user, but we don't want to wait |
379 | * with the mmap_sem held. | 380 | * with the mmap_sem held. |
380 | * It is possible to drop the mmap_sem here, but then we need | 381 | * It is possible to drop the mmap_sem here, but then we need |
381 | * to return NOPFN_REFAULT because the mappings may have | 382 | * to return VM_FAULT_NOPAGE because the mappings may have |
382 | * hanged. | 383 | * hanged. |
383 | */ | 384 | */ |
384 | if (spu_acquire(ctx)) | 385 | if (spu_acquire(ctx)) |
@@ -386,14 +387,15 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
386 | 387 | ||
387 | if (ctx->state == SPU_STATE_SAVED) { | 388 | if (ctx->state == SPU_STATE_SAVED) { |
388 | up_read(¤t->mm->mmap_sem); | 389 | up_read(¤t->mm->mmap_sem); |
389 | spu_context_nospu_trace(spufs_ps_nopfn__sleep, ctx); | 390 | spu_context_nospu_trace(spufs_ps_fault__sleep, ctx); |
390 | ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); | 391 | ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); |
391 | spu_context_trace(spufs_ps_nopfn__wake, ctx, ctx->spu); | 392 | spu_context_trace(spufs_ps_fault__wake, ctx, ctx->spu); |
392 | down_read(¤t->mm->mmap_sem); | 393 | down_read(¤t->mm->mmap_sem); |
393 | } else { | 394 | } else { |
394 | area = ctx->spu->problem_phys + ps_offs; | 395 | area = ctx->spu->problem_phys + ps_offs; |
395 | vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT); | 396 | vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, |
396 | spu_context_trace(spufs_ps_nopfn__insert, ctx, ctx->spu); | 397 | (area + offset) >> PAGE_SHIFT); |
398 | spu_context_trace(spufs_ps_fault__insert, ctx, ctx->spu); | ||
397 | } | 399 | } |
398 | 400 | ||
399 | if (!ret) | 401 | if (!ret) |
@@ -401,18 +403,18 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
401 | 403 | ||
402 | refault: | 404 | refault: |
403 | put_spu_context(ctx); | 405 | put_spu_context(ctx); |
404 | return NOPFN_REFAULT; | 406 | return VM_FAULT_NOPAGE; |
405 | } | 407 | } |
406 | 408 | ||
407 | #if SPUFS_MMAP_4K | 409 | #if SPUFS_MMAP_4K |
408 | static unsigned long spufs_cntl_mmap_nopfn(struct vm_area_struct *vma, | 410 | static int spufs_cntl_mmap_fault(struct vm_area_struct *vma, |
409 | unsigned long address) | 411 | struct vm_fault *vmf) |
410 | { | 412 | { |
411 | return spufs_ps_nopfn(vma, address, 0x4000, 0x1000); | 413 | return spufs_ps_fault(vma, vmf, 0x4000, SPUFS_CNTL_MAP_SIZE); |
412 | } | 414 | } |
413 | 415 | ||
414 | static struct vm_operations_struct spufs_cntl_mmap_vmops = { | 416 | static struct vm_operations_struct spufs_cntl_mmap_vmops = { |
415 | .nopfn = spufs_cntl_mmap_nopfn, | 417 | .fault = spufs_cntl_mmap_fault, |
416 | }; | 418 | }; |
417 | 419 | ||
418 | /* | 420 | /* |
@@ -1097,23 +1099,23 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, | |||
1097 | return 4; | 1099 | return 4; |
1098 | } | 1100 | } |
1099 | 1101 | ||
1100 | static unsigned long spufs_signal1_mmap_nopfn(struct vm_area_struct *vma, | 1102 | static int |
1101 | unsigned long address) | 1103 | spufs_signal1_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
1102 | { | 1104 | { |
1103 | #if PAGE_SIZE == 0x1000 | 1105 | #if SPUFS_SIGNAL_MAP_SIZE == 0x1000 |
1104 | return spufs_ps_nopfn(vma, address, 0x14000, 0x1000); | 1106 | return spufs_ps_fault(vma, vmf, 0x14000, SPUFS_SIGNAL_MAP_SIZE); |
1105 | #elif PAGE_SIZE == 0x10000 | 1107 | #elif SPUFS_SIGNAL_MAP_SIZE == 0x10000 |
1106 | /* For 64k pages, both signal1 and signal2 can be used to mmap the whole | 1108 | /* For 64k pages, both signal1 and signal2 can be used to mmap the whole |
1107 | * signal 1 and 2 area | 1109 | * signal 1 and 2 area |
1108 | */ | 1110 | */ |
1109 | return spufs_ps_nopfn(vma, address, 0x10000, 0x10000); | 1111 | return spufs_ps_fault(vma, vmf, 0x10000, SPUFS_SIGNAL_MAP_SIZE); |
1110 | #else | 1112 | #else |
1111 | #error unsupported page size | 1113 | #error unsupported page size |
1112 | #endif | 1114 | #endif |
1113 | } | 1115 | } |
1114 | 1116 | ||
1115 | static struct vm_operations_struct spufs_signal1_mmap_vmops = { | 1117 | static struct vm_operations_struct spufs_signal1_mmap_vmops = { |
1116 | .nopfn = spufs_signal1_mmap_nopfn, | 1118 | .fault = spufs_signal1_mmap_fault, |
1117 | }; | 1119 | }; |
1118 | 1120 | ||
1119 | static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma) | 1121 | static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma) |
@@ -1234,23 +1236,23 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, | |||
1234 | } | 1236 | } |
1235 | 1237 | ||
1236 | #if SPUFS_MMAP_4K | 1238 | #if SPUFS_MMAP_4K |
1237 | static unsigned long spufs_signal2_mmap_nopfn(struct vm_area_struct *vma, | 1239 | static int |
1238 | unsigned long address) | 1240 | spufs_signal2_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
1239 | { | 1241 | { |
1240 | #if PAGE_SIZE == 0x1000 | 1242 | #if SPUFS_SIGNAL_MAP_SIZE == 0x1000 |
1241 | return spufs_ps_nopfn(vma, address, 0x1c000, 0x1000); | 1243 | return spufs_ps_fault(vma, vmf, 0x1c000, SPUFS_SIGNAL_MAP_SIZE); |
1242 | #elif PAGE_SIZE == 0x10000 | 1244 | #elif SPUFS_SIGNAL_MAP_SIZE == 0x10000 |
1243 | /* For 64k pages, both signal1 and signal2 can be used to mmap the whole | 1245 | /* For 64k pages, both signal1 and signal2 can be used to mmap the whole |
1244 | * signal 1 and 2 area | 1246 | * signal 1 and 2 area |
1245 | */ | 1247 | */ |
1246 | return spufs_ps_nopfn(vma, address, 0x10000, 0x10000); | 1248 | return spufs_ps_fault(vma, vmf, 0x10000, SPUFS_SIGNAL_MAP_SIZE); |
1247 | #else | 1249 | #else |
1248 | #error unsupported page size | 1250 | #error unsupported page size |
1249 | #endif | 1251 | #endif |
1250 | } | 1252 | } |
1251 | 1253 | ||
1252 | static struct vm_operations_struct spufs_signal2_mmap_vmops = { | 1254 | static struct vm_operations_struct spufs_signal2_mmap_vmops = { |
1253 | .nopfn = spufs_signal2_mmap_nopfn, | 1255 | .fault = spufs_signal2_mmap_fault, |
1254 | }; | 1256 | }; |
1255 | 1257 | ||
1256 | static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma) | 1258 | static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma) |
@@ -1362,14 +1364,14 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, | |||
1362 | spufs_signal2_type_set, "%llu\n", SPU_ATTR_ACQUIRE); | 1364 | spufs_signal2_type_set, "%llu\n", SPU_ATTR_ACQUIRE); |
1363 | 1365 | ||
1364 | #if SPUFS_MMAP_4K | 1366 | #if SPUFS_MMAP_4K |
1365 | static unsigned long spufs_mss_mmap_nopfn(struct vm_area_struct *vma, | 1367 | static int |
1366 | unsigned long address) | 1368 | spufs_mss_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
1367 | { | 1369 | { |
1368 | return spufs_ps_nopfn(vma, address, 0x0000, 0x1000); | 1370 | return spufs_ps_fault(vma, vmf, 0x0000, SPUFS_MSS_MAP_SIZE); |
1369 | } | 1371 | } |
1370 | 1372 | ||
1371 | static struct vm_operations_struct spufs_mss_mmap_vmops = { | 1373 | static struct vm_operations_struct spufs_mss_mmap_vmops = { |
1372 | .nopfn = spufs_mss_mmap_nopfn, | 1374 | .fault = spufs_mss_mmap_fault, |
1373 | }; | 1375 | }; |
1374 | 1376 | ||
1375 | /* | 1377 | /* |
@@ -1424,14 +1426,14 @@ static const struct file_operations spufs_mss_fops = { | |||
1424 | .mmap = spufs_mss_mmap, | 1426 | .mmap = spufs_mss_mmap, |
1425 | }; | 1427 | }; |
1426 | 1428 | ||
1427 | static unsigned long spufs_psmap_mmap_nopfn(struct vm_area_struct *vma, | 1429 | static int |
1428 | unsigned long address) | 1430 | spufs_psmap_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
1429 | { | 1431 | { |
1430 | return spufs_ps_nopfn(vma, address, 0x0000, 0x20000); | 1432 | return spufs_ps_fault(vma, vmf, 0x0000, SPUFS_PS_MAP_SIZE); |
1431 | } | 1433 | } |
1432 | 1434 | ||
1433 | static struct vm_operations_struct spufs_psmap_mmap_vmops = { | 1435 | static struct vm_operations_struct spufs_psmap_mmap_vmops = { |
1434 | .nopfn = spufs_psmap_mmap_nopfn, | 1436 | .fault = spufs_psmap_mmap_fault, |
1435 | }; | 1437 | }; |
1436 | 1438 | ||
1437 | /* | 1439 | /* |
@@ -1484,14 +1486,14 @@ static const struct file_operations spufs_psmap_fops = { | |||
1484 | 1486 | ||
1485 | 1487 | ||
1486 | #if SPUFS_MMAP_4K | 1488 | #if SPUFS_MMAP_4K |
1487 | static unsigned long spufs_mfc_mmap_nopfn(struct vm_area_struct *vma, | 1489 | static int |
1488 | unsigned long address) | 1490 | spufs_mfc_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
1489 | { | 1491 | { |
1490 | return spufs_ps_nopfn(vma, address, 0x3000, 0x1000); | 1492 | return spufs_ps_fault(vma, vmf, 0x3000, SPUFS_MFC_MAP_SIZE); |
1491 | } | 1493 | } |
1492 | 1494 | ||
1493 | static struct vm_operations_struct spufs_mfc_mmap_vmops = { | 1495 | static struct vm_operations_struct spufs_mfc_mmap_vmops = { |
1494 | .nopfn = spufs_mfc_mmap_nopfn, | 1496 | .fault = spufs_mfc_mmap_fault, |
1495 | }; | 1497 | }; |
1496 | 1498 | ||
1497 | /* | 1499 | /* |
@@ -2553,22 +2555,74 @@ void spu_switch_log_notify(struct spu *spu, struct spu_context *ctx, | |||
2553 | wake_up(&ctx->switch_log->wait); | 2555 | wake_up(&ctx->switch_log->wait); |
2554 | } | 2556 | } |
2555 | 2557 | ||
2556 | struct tree_descr spufs_dir_contents[] = { | 2558 | static int spufs_show_ctx(struct seq_file *s, void *private) |
2559 | { | ||
2560 | struct spu_context *ctx = s->private; | ||
2561 | u64 mfc_control_RW; | ||
2562 | |||
2563 | mutex_lock(&ctx->state_mutex); | ||
2564 | if (ctx->spu) { | ||
2565 | struct spu *spu = ctx->spu; | ||
2566 | struct spu_priv2 __iomem *priv2 = spu->priv2; | ||
2567 | |||
2568 | spin_lock_irq(&spu->register_lock); | ||
2569 | mfc_control_RW = in_be64(&priv2->mfc_control_RW); | ||
2570 | spin_unlock_irq(&spu->register_lock); | ||
2571 | } else { | ||
2572 | struct spu_state *csa = &ctx->csa; | ||
2573 | |||
2574 | mfc_control_RW = csa->priv2.mfc_control_RW; | ||
2575 | } | ||
2576 | |||
2577 | seq_printf(s, "%c flgs(%lx) sflgs(%lx) pri(%d) ts(%d) spu(%02d)" | ||
2578 | " %c %lx %lx %lx %lx %x %x\n", | ||
2579 | ctx->state == SPU_STATE_SAVED ? 'S' : 'R', | ||
2580 | ctx->flags, | ||
2581 | ctx->sched_flags, | ||
2582 | ctx->prio, | ||
2583 | ctx->time_slice, | ||
2584 | ctx->spu ? ctx->spu->number : -1, | ||
2585 | !list_empty(&ctx->rq) ? 'q' : ' ', | ||
2586 | ctx->csa.class_0_pending, | ||
2587 | ctx->csa.class_0_dar, | ||
2588 | ctx->csa.class_1_dsisr, | ||
2589 | mfc_control_RW, | ||
2590 | ctx->ops->runcntl_read(ctx), | ||
2591 | ctx->ops->status_read(ctx)); | ||
2592 | |||
2593 | mutex_unlock(&ctx->state_mutex); | ||
2594 | |||
2595 | return 0; | ||
2596 | } | ||
2597 | |||
2598 | static int spufs_ctx_open(struct inode *inode, struct file *file) | ||
2599 | { | ||
2600 | return single_open(file, spufs_show_ctx, SPUFS_I(inode)->i_ctx); | ||
2601 | } | ||
2602 | |||
2603 | static const struct file_operations spufs_ctx_fops = { | ||
2604 | .open = spufs_ctx_open, | ||
2605 | .read = seq_read, | ||
2606 | .llseek = seq_lseek, | ||
2607 | .release = single_release, | ||
2608 | }; | ||
2609 | |||
2610 | struct spufs_tree_descr spufs_dir_contents[] = { | ||
2557 | { "capabilities", &spufs_caps_fops, 0444, }, | 2611 | { "capabilities", &spufs_caps_fops, 0444, }, |
2558 | { "mem", &spufs_mem_fops, 0666, }, | 2612 | { "mem", &spufs_mem_fops, 0666, LS_SIZE, }, |
2559 | { "regs", &spufs_regs_fops, 0666, }, | 2613 | { "regs", &spufs_regs_fops, 0666, sizeof(struct spu_reg128[128]), }, |
2560 | { "mbox", &spufs_mbox_fops, 0444, }, | 2614 | { "mbox", &spufs_mbox_fops, 0444, }, |
2561 | { "ibox", &spufs_ibox_fops, 0444, }, | 2615 | { "ibox", &spufs_ibox_fops, 0444, }, |
2562 | { "wbox", &spufs_wbox_fops, 0222, }, | 2616 | { "wbox", &spufs_wbox_fops, 0222, }, |
2563 | { "mbox_stat", &spufs_mbox_stat_fops, 0444, }, | 2617 | { "mbox_stat", &spufs_mbox_stat_fops, 0444, sizeof(u32), }, |
2564 | { "ibox_stat", &spufs_ibox_stat_fops, 0444, }, | 2618 | { "ibox_stat", &spufs_ibox_stat_fops, 0444, sizeof(u32), }, |
2565 | { "wbox_stat", &spufs_wbox_stat_fops, 0444, }, | 2619 | { "wbox_stat", &spufs_wbox_stat_fops, 0444, sizeof(u32), }, |
2566 | { "signal1", &spufs_signal1_fops, 0666, }, | 2620 | { "signal1", &spufs_signal1_fops, 0666, }, |
2567 | { "signal2", &spufs_signal2_fops, 0666, }, | 2621 | { "signal2", &spufs_signal2_fops, 0666, }, |
2568 | { "signal1_type", &spufs_signal1_type, 0666, }, | 2622 | { "signal1_type", &spufs_signal1_type, 0666, }, |
2569 | { "signal2_type", &spufs_signal2_type, 0666, }, | 2623 | { "signal2_type", &spufs_signal2_type, 0666, }, |
2570 | { "cntl", &spufs_cntl_fops, 0666, }, | 2624 | { "cntl", &spufs_cntl_fops, 0666, }, |
2571 | { "fpcr", &spufs_fpcr_fops, 0666, }, | 2625 | { "fpcr", &spufs_fpcr_fops, 0666, sizeof(struct spu_reg128), }, |
2572 | { "lslr", &spufs_lslr_ops, 0444, }, | 2626 | { "lslr", &spufs_lslr_ops, 0444, }, |
2573 | { "mfc", &spufs_mfc_fops, 0666, }, | 2627 | { "mfc", &spufs_mfc_fops, 0666, }, |
2574 | { "mss", &spufs_mss_fops, 0666, }, | 2628 | { "mss", &spufs_mss_fops, 0666, }, |
@@ -2578,29 +2632,31 @@ struct tree_descr spufs_dir_contents[] = { | |||
2578 | { "decr_status", &spufs_decr_status_ops, 0666, }, | 2632 | { "decr_status", &spufs_decr_status_ops, 0666, }, |
2579 | { "event_mask", &spufs_event_mask_ops, 0666, }, | 2633 | { "event_mask", &spufs_event_mask_ops, 0666, }, |
2580 | { "event_status", &spufs_event_status_ops, 0444, }, | 2634 | { "event_status", &spufs_event_status_ops, 0444, }, |
2581 | { "psmap", &spufs_psmap_fops, 0666, }, | 2635 | { "psmap", &spufs_psmap_fops, 0666, SPUFS_PS_MAP_SIZE, }, |
2582 | { "phys-id", &spufs_id_ops, 0666, }, | 2636 | { "phys-id", &spufs_id_ops, 0666, }, |
2583 | { "object-id", &spufs_object_id_ops, 0666, }, | 2637 | { "object-id", &spufs_object_id_ops, 0666, }, |
2584 | { "mbox_info", &spufs_mbox_info_fops, 0444, }, | 2638 | { "mbox_info", &spufs_mbox_info_fops, 0444, sizeof(u32), }, |
2585 | { "ibox_info", &spufs_ibox_info_fops, 0444, }, | 2639 | { "ibox_info", &spufs_ibox_info_fops, 0444, sizeof(u32), }, |
2586 | { "wbox_info", &spufs_wbox_info_fops, 0444, }, | 2640 | { "wbox_info", &spufs_wbox_info_fops, 0444, sizeof(u32), }, |
2587 | { "dma_info", &spufs_dma_info_fops, 0444, }, | 2641 | { "dma_info", &spufs_dma_info_fops, 0444, |
2588 | { "proxydma_info", &spufs_proxydma_info_fops, 0444, }, | 2642 | sizeof(struct spu_dma_info), }, |
2643 | { "proxydma_info", &spufs_proxydma_info_fops, 0444, | ||
2644 | sizeof(struct spu_proxydma_info)}, | ||
2589 | { "tid", &spufs_tid_fops, 0444, }, | 2645 | { "tid", &spufs_tid_fops, 0444, }, |
2590 | { "stat", &spufs_stat_fops, 0444, }, | 2646 | { "stat", &spufs_stat_fops, 0444, }, |
2591 | { "switch_log", &spufs_switch_log_fops, 0444 }, | 2647 | { "switch_log", &spufs_switch_log_fops, 0444 }, |
2592 | {}, | 2648 | {}, |
2593 | }; | 2649 | }; |
2594 | 2650 | ||
2595 | struct tree_descr spufs_dir_nosched_contents[] = { | 2651 | struct spufs_tree_descr spufs_dir_nosched_contents[] = { |
2596 | { "capabilities", &spufs_caps_fops, 0444, }, | 2652 | { "capabilities", &spufs_caps_fops, 0444, }, |
2597 | { "mem", &spufs_mem_fops, 0666, }, | 2653 | { "mem", &spufs_mem_fops, 0666, LS_SIZE, }, |
2598 | { "mbox", &spufs_mbox_fops, 0444, }, | 2654 | { "mbox", &spufs_mbox_fops, 0444, }, |
2599 | { "ibox", &spufs_ibox_fops, 0444, }, | 2655 | { "ibox", &spufs_ibox_fops, 0444, }, |
2600 | { "wbox", &spufs_wbox_fops, 0222, }, | 2656 | { "wbox", &spufs_wbox_fops, 0222, }, |
2601 | { "mbox_stat", &spufs_mbox_stat_fops, 0444, }, | 2657 | { "mbox_stat", &spufs_mbox_stat_fops, 0444, sizeof(u32), }, |
2602 | { "ibox_stat", &spufs_ibox_stat_fops, 0444, }, | 2658 | { "ibox_stat", &spufs_ibox_stat_fops, 0444, sizeof(u32), }, |
2603 | { "wbox_stat", &spufs_wbox_stat_fops, 0444, }, | 2659 | { "wbox_stat", &spufs_wbox_stat_fops, 0444, sizeof(u32), }, |
2604 | { "signal1", &spufs_signal1_nosched_fops, 0222, }, | 2660 | { "signal1", &spufs_signal1_nosched_fops, 0222, }, |
2605 | { "signal2", &spufs_signal2_nosched_fops, 0222, }, | 2661 | { "signal2", &spufs_signal2_nosched_fops, 0222, }, |
2606 | { "signal1_type", &spufs_signal1_type, 0666, }, | 2662 | { "signal1_type", &spufs_signal1_type, 0666, }, |
@@ -2609,7 +2665,7 @@ struct tree_descr spufs_dir_nosched_contents[] = { | |||
2609 | { "mfc", &spufs_mfc_fops, 0666, }, | 2665 | { "mfc", &spufs_mfc_fops, 0666, }, |
2610 | { "cntl", &spufs_cntl_fops, 0666, }, | 2666 | { "cntl", &spufs_cntl_fops, 0666, }, |
2611 | { "npc", &spufs_npc_ops, 0666, }, | 2667 | { "npc", &spufs_npc_ops, 0666, }, |
2612 | { "psmap", &spufs_psmap_fops, 0666, }, | 2668 | { "psmap", &spufs_psmap_fops, 0666, SPUFS_PS_MAP_SIZE, }, |
2613 | { "phys-id", &spufs_id_ops, 0666, }, | 2669 | { "phys-id", &spufs_id_ops, 0666, }, |
2614 | { "object-id", &spufs_object_id_ops, 0666, }, | 2670 | { "object-id", &spufs_object_id_ops, 0666, }, |
2615 | { "tid", &spufs_tid_fops, 0444, }, | 2671 | { "tid", &spufs_tid_fops, 0444, }, |
@@ -2617,6 +2673,11 @@ struct tree_descr spufs_dir_nosched_contents[] = { | |||
2617 | {}, | 2673 | {}, |
2618 | }; | 2674 | }; |
2619 | 2675 | ||
2676 | struct spufs_tree_descr spufs_dir_debug_contents[] = { | ||
2677 | { ".ctx", &spufs_ctx_fops, 0444, }, | ||
2678 | {}, | ||
2679 | }; | ||
2680 | |||
2620 | struct spufs_coredump_reader spufs_coredump_read[] = { | 2681 | struct spufs_coredump_reader spufs_coredump_read[] = { |
2621 | { "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])}, | 2682 | { "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])}, |
2622 | { "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) }, | 2683 | { "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) }, |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index f407b2471855..7123472801d9 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -42,10 +42,19 @@ | |||
42 | 42 | ||
43 | #include "spufs.h" | 43 | #include "spufs.h" |
44 | 44 | ||
45 | struct spufs_sb_info { | ||
46 | int debug; | ||
47 | }; | ||
48 | |||
45 | static struct kmem_cache *spufs_inode_cache; | 49 | static struct kmem_cache *spufs_inode_cache; |
46 | char *isolated_loader; | 50 | char *isolated_loader; |
47 | static int isolated_loader_size; | 51 | static int isolated_loader_size; |
48 | 52 | ||
53 | static struct spufs_sb_info *spufs_get_sb_info(struct super_block *sb) | ||
54 | { | ||
55 | return sb->s_fs_info; | ||
56 | } | ||
57 | |||
49 | static struct inode * | 58 | static struct inode * |
50 | spufs_alloc_inode(struct super_block *sb) | 59 | spufs_alloc_inode(struct super_block *sb) |
51 | { | 60 | { |
@@ -109,7 +118,7 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr) | |||
109 | static int | 118 | static int |
110 | spufs_new_file(struct super_block *sb, struct dentry *dentry, | 119 | spufs_new_file(struct super_block *sb, struct dentry *dentry, |
111 | const struct file_operations *fops, int mode, | 120 | const struct file_operations *fops, int mode, |
112 | struct spu_context *ctx) | 121 | size_t size, struct spu_context *ctx) |
113 | { | 122 | { |
114 | static struct inode_operations spufs_file_iops = { | 123 | static struct inode_operations spufs_file_iops = { |
115 | .setattr = spufs_setattr, | 124 | .setattr = spufs_setattr, |
@@ -125,6 +134,7 @@ spufs_new_file(struct super_block *sb, struct dentry *dentry, | |||
125 | ret = 0; | 134 | ret = 0; |
126 | inode->i_op = &spufs_file_iops; | 135 | inode->i_op = &spufs_file_iops; |
127 | inode->i_fop = fops; | 136 | inode->i_fop = fops; |
137 | inode->i_size = size; | ||
128 | inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx); | 138 | inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx); |
129 | d_add(dentry, inode); | 139 | d_add(dentry, inode); |
130 | out: | 140 | out: |
@@ -177,7 +187,7 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir) | |||
177 | return simple_rmdir(parent, dir); | 187 | return simple_rmdir(parent, dir); |
178 | } | 188 | } |
179 | 189 | ||
180 | static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, | 190 | static int spufs_fill_dir(struct dentry *dir, struct spufs_tree_descr *files, |
181 | int mode, struct spu_context *ctx) | 191 | int mode, struct spu_context *ctx) |
182 | { | 192 | { |
183 | struct dentry *dentry, *tmp; | 193 | struct dentry *dentry, *tmp; |
@@ -189,7 +199,7 @@ static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, | |||
189 | if (!dentry) | 199 | if (!dentry) |
190 | goto out; | 200 | goto out; |
191 | ret = spufs_new_file(dir->d_sb, dentry, files->ops, | 201 | ret = spufs_new_file(dir->d_sb, dentry, files->ops, |
192 | files->mode & mode, ctx); | 202 | files->mode & mode, files->size, ctx); |
193 | if (ret) | 203 | if (ret) |
194 | goto out; | 204 | goto out; |
195 | files++; | 205 | files++; |
@@ -279,6 +289,13 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, | |||
279 | if (ret) | 289 | if (ret) |
280 | goto out_free_ctx; | 290 | goto out_free_ctx; |
281 | 291 | ||
292 | if (spufs_get_sb_info(dir->i_sb)->debug) | ||
293 | ret = spufs_fill_dir(dentry, spufs_dir_debug_contents, | ||
294 | mode, ctx); | ||
295 | |||
296 | if (ret) | ||
297 | goto out_free_ctx; | ||
298 | |||
282 | d_instantiate(dentry, inode); | 299 | d_instantiate(dentry, inode); |
283 | dget(dentry); | 300 | dget(dentry); |
284 | dir->i_nlink++; | 301 | dir->i_nlink++; |
@@ -639,18 +656,19 @@ out: | |||
639 | 656 | ||
640 | /* File system initialization */ | 657 | /* File system initialization */ |
641 | enum { | 658 | enum { |
642 | Opt_uid, Opt_gid, Opt_mode, Opt_err, | 659 | Opt_uid, Opt_gid, Opt_mode, Opt_debug, Opt_err, |
643 | }; | 660 | }; |
644 | 661 | ||
645 | static match_table_t spufs_tokens = { | 662 | static match_table_t spufs_tokens = { |
646 | { Opt_uid, "uid=%d" }, | 663 | { Opt_uid, "uid=%d" }, |
647 | { Opt_gid, "gid=%d" }, | 664 | { Opt_gid, "gid=%d" }, |
648 | { Opt_mode, "mode=%o" }, | 665 | { Opt_mode, "mode=%o" }, |
649 | { Opt_err, NULL }, | 666 | { Opt_debug, "debug" }, |
667 | { Opt_err, NULL }, | ||
650 | }; | 668 | }; |
651 | 669 | ||
652 | static int | 670 | static int |
653 | spufs_parse_options(char *options, struct inode *root) | 671 | spufs_parse_options(struct super_block *sb, char *options, struct inode *root) |
654 | { | 672 | { |
655 | char *p; | 673 | char *p; |
656 | substring_t args[MAX_OPT_ARGS]; | 674 | substring_t args[MAX_OPT_ARGS]; |
@@ -678,6 +696,9 @@ spufs_parse_options(char *options, struct inode *root) | |||
678 | return 0; | 696 | return 0; |
679 | root->i_mode = option | S_IFDIR; | 697 | root->i_mode = option | S_IFDIR; |
680 | break; | 698 | break; |
699 | case Opt_debug: | ||
700 | spufs_get_sb_info(sb)->debug = 1; | ||
701 | break; | ||
681 | default: | 702 | default: |
682 | return 0; | 703 | return 0; |
683 | } | 704 | } |
@@ -736,7 +757,7 @@ spufs_create_root(struct super_block *sb, void *data) | |||
736 | SPUFS_I(inode)->i_ctx = NULL; | 757 | SPUFS_I(inode)->i_ctx = NULL; |
737 | 758 | ||
738 | ret = -EINVAL; | 759 | ret = -EINVAL; |
739 | if (!spufs_parse_options(data, inode)) | 760 | if (!spufs_parse_options(sb, data, inode)) |
740 | goto out_iput; | 761 | goto out_iput; |
741 | 762 | ||
742 | ret = -ENOMEM; | 763 | ret = -ENOMEM; |
@@ -754,6 +775,7 @@ out: | |||
754 | static int | 775 | static int |
755 | spufs_fill_super(struct super_block *sb, void *data, int silent) | 776 | spufs_fill_super(struct super_block *sb, void *data, int silent) |
756 | { | 777 | { |
778 | struct spufs_sb_info *info; | ||
757 | static struct super_operations s_ops = { | 779 | static struct super_operations s_ops = { |
758 | .alloc_inode = spufs_alloc_inode, | 780 | .alloc_inode = spufs_alloc_inode, |
759 | .destroy_inode = spufs_destroy_inode, | 781 | .destroy_inode = spufs_destroy_inode, |
@@ -765,11 +787,16 @@ spufs_fill_super(struct super_block *sb, void *data, int silent) | |||
765 | 787 | ||
766 | save_mount_options(sb, data); | 788 | save_mount_options(sb, data); |
767 | 789 | ||
790 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
791 | if (!info) | ||
792 | return -ENOMEM; | ||
793 | |||
768 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 794 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
769 | sb->s_blocksize = PAGE_CACHE_SIZE; | 795 | sb->s_blocksize = PAGE_CACHE_SIZE; |
770 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 796 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
771 | sb->s_magic = SPUFS_MAGIC; | 797 | sb->s_magic = SPUFS_MAGIC; |
772 | sb->s_op = &s_ops; | 798 | sb->s_op = &s_ops; |
799 | sb->s_fs_info = info; | ||
773 | 800 | ||
774 | return spufs_create_root(sb, data); | 801 | return spufs_create_root(sb, data); |
775 | } | 802 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index b7493b865812..f7edba6cb795 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -27,7 +27,6 @@ void spufs_stop_callback(struct spu *spu, int irq) | |||
27 | switch(irq) { | 27 | switch(irq) { |
28 | case 0 : | 28 | case 0 : |
29 | ctx->csa.class_0_pending = spu->class_0_pending; | 29 | ctx->csa.class_0_pending = spu->class_0_pending; |
30 | ctx->csa.class_0_dsisr = spu->class_0_dsisr; | ||
31 | ctx->csa.class_0_dar = spu->class_0_dar; | 30 | ctx->csa.class_0_dar = spu->class_0_dar; |
32 | break; | 31 | break; |
33 | case 1 : | 32 | case 1 : |
@@ -51,18 +50,22 @@ int spu_stopped(struct spu_context *ctx, u32 *stat) | |||
51 | u64 dsisr; | 50 | u64 dsisr; |
52 | u32 stopped; | 51 | u32 stopped; |
53 | 52 | ||
54 | *stat = ctx->ops->status_read(ctx); | ||
55 | |||
56 | if (test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags)) | ||
57 | return 1; | ||
58 | |||
59 | stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP | | 53 | stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP | |
60 | SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP; | 54 | SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP; |
61 | if (!(*stat & SPU_STATUS_RUNNING) && (*stat & stopped)) | 55 | |
56 | top: | ||
57 | *stat = ctx->ops->status_read(ctx); | ||
58 | if (*stat & stopped) { | ||
59 | /* | ||
60 | * If the spu hasn't finished stopping, we need to | ||
61 | * re-read the register to get the stopped value. | ||
62 | */ | ||
63 | if (*stat & SPU_STATUS_RUNNING) | ||
64 | goto top; | ||
62 | return 1; | 65 | return 1; |
66 | } | ||
63 | 67 | ||
64 | dsisr = ctx->csa.class_0_dsisr; | 68 | if (test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags)) |
65 | if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) | ||
66 | return 1; | 69 | return 1; |
67 | 70 | ||
68 | dsisr = ctx->csa.class_1_dsisr; | 71 | dsisr = ctx->csa.class_1_dsisr; |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 745dd51ec37f..34654743363d 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -230,19 +230,23 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | |||
230 | ctx->stats.slb_flt_base = spu->stats.slb_flt; | 230 | ctx->stats.slb_flt_base = spu->stats.slb_flt; |
231 | ctx->stats.class2_intr_base = spu->stats.class2_intr; | 231 | ctx->stats.class2_intr_base = spu->stats.class2_intr; |
232 | 232 | ||
233 | spu_associate_mm(spu, ctx->owner); | ||
234 | |||
235 | spin_lock_irq(&spu->register_lock); | ||
233 | spu->ctx = ctx; | 236 | spu->ctx = ctx; |
234 | spu->flags = 0; | 237 | spu->flags = 0; |
235 | ctx->spu = spu; | 238 | ctx->spu = spu; |
236 | ctx->ops = &spu_hw_ops; | 239 | ctx->ops = &spu_hw_ops; |
237 | spu->pid = current->pid; | 240 | spu->pid = current->pid; |
238 | spu->tgid = current->tgid; | 241 | spu->tgid = current->tgid; |
239 | spu_associate_mm(spu, ctx->owner); | ||
240 | spu->ibox_callback = spufs_ibox_callback; | 242 | spu->ibox_callback = spufs_ibox_callback; |
241 | spu->wbox_callback = spufs_wbox_callback; | 243 | spu->wbox_callback = spufs_wbox_callback; |
242 | spu->stop_callback = spufs_stop_callback; | 244 | spu->stop_callback = spufs_stop_callback; |
243 | spu->mfc_callback = spufs_mfc_callback; | 245 | spu->mfc_callback = spufs_mfc_callback; |
244 | mb(); | 246 | spin_unlock_irq(&spu->register_lock); |
247 | |||
245 | spu_unmap_mappings(ctx); | 248 | spu_unmap_mappings(ctx); |
249 | |||
246 | spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0); | 250 | spu_switch_log_notify(spu, ctx, SWITCH_LOG_START, 0); |
247 | spu_restore(&ctx->csa, spu); | 251 | spu_restore(&ctx->csa, spu); |
248 | spu->timestamp = jiffies; | 252 | spu->timestamp = jiffies; |
@@ -403,6 +407,8 @@ static int has_affinity(struct spu_context *ctx) | |||
403 | */ | 407 | */ |
404 | static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | 408 | static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) |
405 | { | 409 | { |
410 | u32 status; | ||
411 | |||
406 | spu_context_trace(spu_unbind_context__enter, ctx, spu); | 412 | spu_context_trace(spu_unbind_context__enter, ctx, spu); |
407 | 413 | ||
408 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); | 414 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); |
@@ -423,18 +429,22 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
423 | spu_unmap_mappings(ctx); | 429 | spu_unmap_mappings(ctx); |
424 | spu_save(&ctx->csa, spu); | 430 | spu_save(&ctx->csa, spu); |
425 | spu_switch_log_notify(spu, ctx, SWITCH_LOG_STOP, 0); | 431 | spu_switch_log_notify(spu, ctx, SWITCH_LOG_STOP, 0); |
432 | |||
433 | spin_lock_irq(&spu->register_lock); | ||
426 | spu->timestamp = jiffies; | 434 | spu->timestamp = jiffies; |
427 | ctx->state = SPU_STATE_SAVED; | 435 | ctx->state = SPU_STATE_SAVED; |
428 | spu->ibox_callback = NULL; | 436 | spu->ibox_callback = NULL; |
429 | spu->wbox_callback = NULL; | 437 | spu->wbox_callback = NULL; |
430 | spu->stop_callback = NULL; | 438 | spu->stop_callback = NULL; |
431 | spu->mfc_callback = NULL; | 439 | spu->mfc_callback = NULL; |
432 | spu_associate_mm(spu, NULL); | ||
433 | spu->pid = 0; | 440 | spu->pid = 0; |
434 | spu->tgid = 0; | 441 | spu->tgid = 0; |
435 | ctx->ops = &spu_backing_ops; | 442 | ctx->ops = &spu_backing_ops; |
436 | spu->flags = 0; | 443 | spu->flags = 0; |
437 | spu->ctx = NULL; | 444 | spu->ctx = NULL; |
445 | spin_unlock_irq(&spu->register_lock); | ||
446 | |||
447 | spu_associate_mm(spu, NULL); | ||
438 | 448 | ||
439 | ctx->stats.slb_flt += | 449 | ctx->stats.slb_flt += |
440 | (spu->stats.slb_flt - ctx->stats.slb_flt_base); | 450 | (spu->stats.slb_flt - ctx->stats.slb_flt_base); |
@@ -444,6 +454,9 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
444 | /* This maps the underlying spu state to idle */ | 454 | /* This maps the underlying spu state to idle */ |
445 | spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED); | 455 | spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED); |
446 | ctx->spu = NULL; | 456 | ctx->spu = NULL; |
457 | |||
458 | if (spu_stopped(ctx, &status)) | ||
459 | wake_up_all(&ctx->stop_wq); | ||
447 | } | 460 | } |
448 | 461 | ||
449 | /** | 462 | /** |
@@ -886,7 +899,8 @@ static noinline void spusched_tick(struct spu_context *ctx) | |||
886 | spu_add_to_rq(ctx); | 899 | spu_add_to_rq(ctx); |
887 | } else { | 900 | } else { |
888 | spu_context_nospu_trace(spusched_tick__newslice, ctx); | 901 | spu_context_nospu_trace(spusched_tick__newslice, ctx); |
889 | ctx->time_slice++; | 902 | if (!ctx->time_slice) |
903 | ctx->time_slice++; | ||
890 | } | 904 | } |
891 | out: | 905 | out: |
892 | spu_release(ctx); | 906 | spu_release(ctx); |
@@ -980,6 +994,7 @@ void spuctx_switch_state(struct spu_context *ctx, | |||
980 | struct timespec ts; | 994 | struct timespec ts; |
981 | struct spu *spu; | 995 | struct spu *spu; |
982 | enum spu_utilization_state old_state; | 996 | enum spu_utilization_state old_state; |
997 | int node; | ||
983 | 998 | ||
984 | ktime_get_ts(&ts); | 999 | ktime_get_ts(&ts); |
985 | curtime = timespec_to_ns(&ts); | 1000 | curtime = timespec_to_ns(&ts); |
@@ -1001,6 +1016,11 @@ void spuctx_switch_state(struct spu_context *ctx, | |||
1001 | spu->stats.times[old_state] += delta; | 1016 | spu->stats.times[old_state] += delta; |
1002 | spu->stats.util_state = new_state; | 1017 | spu->stats.util_state = new_state; |
1003 | spu->stats.tstamp = curtime; | 1018 | spu->stats.tstamp = curtime; |
1019 | node = spu->node; | ||
1020 | if (old_state == SPU_UTIL_USER) | ||
1021 | atomic_dec(&cbe_spu_info[node].busy_spus); | ||
1022 | if (new_state == SPU_UTIL_USER); | ||
1023 | atomic_inc(&cbe_spu_info[node].busy_spus); | ||
1004 | } | 1024 | } |
1005 | } | 1025 | } |
1006 | 1026 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 454c277c1457..8ae8ef9dfc22 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -32,6 +32,13 @@ | |||
32 | #include <asm/spu_csa.h> | 32 | #include <asm/spu_csa.h> |
33 | #include <asm/spu_info.h> | 33 | #include <asm/spu_info.h> |
34 | 34 | ||
35 | #define SPUFS_PS_MAP_SIZE 0x20000 | ||
36 | #define SPUFS_MFC_MAP_SIZE 0x1000 | ||
37 | #define SPUFS_CNTL_MAP_SIZE 0x1000 | ||
38 | #define SPUFS_CNTL_MAP_SIZE 0x1000 | ||
39 | #define SPUFS_SIGNAL_MAP_SIZE PAGE_SIZE | ||
40 | #define SPUFS_MSS_MAP_SIZE 0x1000 | ||
41 | |||
35 | /* The magic number for our file system */ | 42 | /* The magic number for our file system */ |
36 | enum { | 43 | enum { |
37 | SPUFS_MAGIC = 0x23c9b64e, | 44 | SPUFS_MAGIC = 0x23c9b64e, |
@@ -228,8 +235,16 @@ struct spufs_inode_info { | |||
228 | #define SPUFS_I(inode) \ | 235 | #define SPUFS_I(inode) \ |
229 | container_of(inode, struct spufs_inode_info, vfs_inode) | 236 | container_of(inode, struct spufs_inode_info, vfs_inode) |
230 | 237 | ||
231 | extern struct tree_descr spufs_dir_contents[]; | 238 | struct spufs_tree_descr { |
232 | extern struct tree_descr spufs_dir_nosched_contents[]; | 239 | const char *name; |
240 | const struct file_operations *ops; | ||
241 | int mode; | ||
242 | size_t size; | ||
243 | }; | ||
244 | |||
245 | extern struct spufs_tree_descr spufs_dir_contents[]; | ||
246 | extern struct spufs_tree_descr spufs_dir_nosched_contents[]; | ||
247 | extern struct spufs_tree_descr spufs_dir_debug_contents[]; | ||
233 | 248 | ||
234 | /* system call implementation */ | 249 | /* system call implementation */ |
235 | extern struct spufs_calls spufs_calls; | 250 | extern struct spufs_calls spufs_calls; |
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c index 53202422ba72..8c0e95766a62 100644 --- a/arch/powerpc/platforms/cell/spufs/sputrace.c +++ b/arch/powerpc/platforms/cell/spufs/sputrace.c | |||
@@ -182,10 +182,10 @@ struct spu_probe spu_probes[] = { | |||
182 | { "spu_yield__enter", "ctx %p", spu_context_nospu_event }, | 182 | { "spu_yield__enter", "ctx %p", spu_context_nospu_event }, |
183 | { "spu_deactivate__enter", "ctx %p", spu_context_nospu_event }, | 183 | { "spu_deactivate__enter", "ctx %p", spu_context_nospu_event }, |
184 | { "__spu_deactivate__unload", "ctx %p spu %p", spu_context_event }, | 184 | { "__spu_deactivate__unload", "ctx %p spu %p", spu_context_event }, |
185 | { "spufs_ps_nopfn__enter", "ctx %p", spu_context_nospu_event }, | 185 | { "spufs_ps_fault__enter", "ctx %p", spu_context_nospu_event }, |
186 | { "spufs_ps_nopfn__sleep", "ctx %p", spu_context_nospu_event }, | 186 | { "spufs_ps_fault__sleep", "ctx %p", spu_context_nospu_event }, |
187 | { "spufs_ps_nopfn__wake", "ctx %p spu %p", spu_context_event }, | 187 | { "spufs_ps_fault__wake", "ctx %p spu %p", spu_context_event }, |
188 | { "spufs_ps_nopfn__insert", "ctx %p spu %p", spu_context_event }, | 188 | { "spufs_ps_fault__insert", "ctx %p spu %p", spu_context_event }, |
189 | { "spu_acquire_saved__enter", "ctx %p", spu_context_nospu_event }, | 189 | { "spu_acquire_saved__enter", "ctx %p", spu_context_nospu_event }, |
190 | { "destroy_spu_context__enter", "ctx %p", spu_context_nospu_event }, | 190 | { "destroy_spu_context__enter", "ctx %p", spu_context_nospu_event }, |
191 | { "spufs_stop_callback__enter", "ctx %p spu %p", spu_context_event }, | 191 | { "spufs_stop_callback__enter", "ctx %p spu %p", spu_context_event }, |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 116babbaaf81..1ba7ce5aafae 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -63,13 +63,6 @@ static struct mpic *chrp_mpic; | |||
63 | DEFINE_PER_CPU(struct timer_list, heartbeat_timer); | 63 | DEFINE_PER_CPU(struct timer_list, heartbeat_timer); |
64 | unsigned long event_scan_interval; | 64 | unsigned long event_scan_interval; |
65 | 65 | ||
66 | /* | ||
67 | * XXX this should be in xmon.h, but putting it there means xmon.h | ||
68 | * has to include <linux/interrupt.h> (to get irqreturn_t), which | ||
69 | * causes all sorts of problems. -- paulus | ||
70 | */ | ||
71 | extern irqreturn_t xmon_irq(int, void *); | ||
72 | |||
73 | extern unsigned long loops_per_jiffy; | 66 | extern unsigned long loops_per_jiffy; |
74 | 67 | ||
75 | /* To be replaced by RTAS when available */ | 68 | /* To be replaced by RTAS when available */ |
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 429088967813..4f9f8184d164 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig | |||
@@ -59,6 +59,16 @@ config PPC_PRPMC2800 | |||
59 | help | 59 | help |
60 | This option enables support for the Motorola PrPMC2800 board | 60 | This option enables support for the Motorola PrPMC2800 board |
61 | 61 | ||
62 | config PPC_C2K | ||
63 | bool "SBS/GEFanuc C2K board" | ||
64 | depends on EMBEDDED6xx | ||
65 | select MV64X60 | ||
66 | select NOT_COHERENT_CACHE | ||
67 | select MTD_CFI_I4 | ||
68 | help | ||
69 | This option enables support for the GE Fanuc C2K board (formerly | ||
70 | an SBS board). | ||
71 | |||
62 | config TSI108_BRIDGE | 72 | config TSI108_BRIDGE |
63 | bool | 73 | bool |
64 | select PCI | 74 | select PCI |
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile index 06524d3ffd2e..0773c08bd444 100644 --- a/arch/powerpc/platforms/embedded6xx/Makefile +++ b/arch/powerpc/platforms/embedded6xx/Makefile | |||
@@ -6,3 +6,4 @@ obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o | |||
6 | obj-$(CONFIG_STORCENTER) += storcenter.o | 6 | obj-$(CONFIG_STORCENTER) += storcenter.o |
7 | obj-$(CONFIG_PPC_HOLLY) += holly.o | 7 | obj-$(CONFIG_PPC_HOLLY) += holly.o |
8 | obj-$(CONFIG_PPC_PRPMC2800) += prpmc2800.o | 8 | obj-$(CONFIG_PPC_PRPMC2800) += prpmc2800.o |
9 | obj-$(CONFIG_PPC_C2K) += c2k.o | ||
diff --git a/arch/powerpc/platforms/embedded6xx/c2k.c b/arch/powerpc/platforms/embedded6xx/c2k.c new file mode 100644 index 000000000000..d0b25b8c39d1 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/c2k.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Board setup routines for the GEFanuc C2K board | ||
3 | * | ||
4 | * Author: Remi Machet <rmachet@slac.stanford.edu> | ||
5 | * | ||
6 | * Originated from prpmc2800.c | ||
7 | * | ||
8 | * 2008 (c) Stanford University | ||
9 | * 2007 (c) MontaVista, Software, Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License version 2 as published | ||
13 | * by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/stddef.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/seq_file.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/kexec.h> | ||
24 | |||
25 | #include <asm/machdep.h> | ||
26 | #include <asm/prom.h> | ||
27 | #include <asm/system.h> | ||
28 | #include <asm/time.h> | ||
29 | |||
30 | #include <mm/mmu_decl.h> | ||
31 | |||
32 | #include <sysdev/mv64x60.h> | ||
33 | |||
34 | #define MV64x60_MPP_CNTL_0 0x0000 | ||
35 | #define MV64x60_MPP_CNTL_2 0x0008 | ||
36 | |||
37 | #define MV64x60_GPP_IO_CNTL 0x0000 | ||
38 | #define MV64x60_GPP_LEVEL_CNTL 0x0010 | ||
39 | #define MV64x60_GPP_VALUE_SET 0x0018 | ||
40 | |||
41 | static void __iomem *mv64x60_mpp_reg_base; | ||
42 | static void __iomem *mv64x60_gpp_reg_base; | ||
43 | |||
44 | static void __init c2k_setup_arch(void) | ||
45 | { | ||
46 | struct device_node *np; | ||
47 | phys_addr_t paddr; | ||
48 | const unsigned int *reg; | ||
49 | |||
50 | /* | ||
51 | * ioremap mpp and gpp registers in case they are later | ||
52 | * needed by c2k_reset_board(). | ||
53 | */ | ||
54 | np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-mpp"); | ||
55 | reg = of_get_property(np, "reg", NULL); | ||
56 | paddr = of_translate_address(np, reg); | ||
57 | of_node_put(np); | ||
58 | mv64x60_mpp_reg_base = ioremap(paddr, reg[1]); | ||
59 | |||
60 | np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-gpp"); | ||
61 | reg = of_get_property(np, "reg", NULL); | ||
62 | paddr = of_translate_address(np, reg); | ||
63 | of_node_put(np); | ||
64 | mv64x60_gpp_reg_base = ioremap(paddr, reg[1]); | ||
65 | |||
66 | #ifdef CONFIG_PCI | ||
67 | mv64x60_pci_init(); | ||
68 | #endif | ||
69 | } | ||
70 | |||
71 | static void c2k_reset_board(void) | ||
72 | { | ||
73 | u32 temp; | ||
74 | |||
75 | local_irq_disable(); | ||
76 | |||
77 | temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0); | ||
78 | temp &= 0xFFFF0FFF; | ||
79 | out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0, temp); | ||
80 | |||
81 | temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL); | ||
82 | temp |= 0x00000004; | ||
83 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp); | ||
84 | |||
85 | temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL); | ||
86 | temp |= 0x00000004; | ||
87 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp); | ||
88 | |||
89 | temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2); | ||
90 | temp &= 0xFFFF0FFF; | ||
91 | out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2, temp); | ||
92 | |||
93 | temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL); | ||
94 | temp |= 0x00080000; | ||
95 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp); | ||
96 | |||
97 | temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL); | ||
98 | temp |= 0x00080000; | ||
99 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp); | ||
100 | |||
101 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_VALUE_SET, 0x00080004); | ||
102 | } | ||
103 | |||
104 | static void c2k_restart(char *cmd) | ||
105 | { | ||
106 | c2k_reset_board(); | ||
107 | msleep(100); | ||
108 | panic("restart failed\n"); | ||
109 | } | ||
110 | |||
111 | #ifdef CONFIG_NOT_COHERENT_CACHE | ||
112 | #define COHERENCY_SETTING "off" | ||
113 | #else | ||
114 | #define COHERENCY_SETTING "on" | ||
115 | #endif | ||
116 | |||
117 | void c2k_show_cpuinfo(struct seq_file *m) | ||
118 | { | ||
119 | uint memsize = total_memory; | ||
120 | |||
121 | seq_printf(m, "Vendor\t\t: GEFanuc\n"); | ||
122 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | ||
123 | seq_printf(m, "coherency\t: %s\n", COHERENCY_SETTING); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Called very early, device-tree isn't unflattened | ||
128 | */ | ||
129 | static int __init c2k_probe(void) | ||
130 | { | ||
131 | unsigned long root = of_get_flat_dt_root(); | ||
132 | |||
133 | if (!of_flat_dt_is_compatible(root, "GEFanuc,C2K")) | ||
134 | return 0; | ||
135 | |||
136 | printk(KERN_INFO "Detected a GEFanuc C2K board\n"); | ||
137 | |||
138 | _set_L2CR(0); | ||
139 | _set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2I); | ||
140 | return 1; | ||
141 | } | ||
142 | |||
143 | define_machine(c2k) { | ||
144 | .name = "C2K", | ||
145 | .probe = c2k_probe, | ||
146 | .setup_arch = c2k_setup_arch, | ||
147 | .init_early = mv64x60_init_early, | ||
148 | .show_cpuinfo = c2k_show_cpuinfo, | ||
149 | .init_IRQ = mv64x60_init_irq, | ||
150 | .get_irq = mv64x60_get_irq, | ||
151 | .restart = c2k_restart, | ||
152 | .calibrate_decr = generic_calibrate_decr, | ||
153 | #ifdef CONFIG_KEXEC | ||
154 | .machine_kexec = default_machine_kexec, | ||
155 | .machine_kexec_prepare = default_machine_kexec_prepare, | ||
156 | .machine_crash_shutdown = default_machine_crash_shutdown, | ||
157 | #endif | ||
158 | }; | ||
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 11fa3c772ed5..ab5d8687c3cf 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c | |||
@@ -214,13 +214,13 @@ dma_addr_t iseries_hv_map(void *vaddr, size_t size, | |||
214 | enum dma_data_direction direction) | 214 | enum dma_data_direction direction) |
215 | { | 215 | { |
216 | return iommu_map_single(NULL, &vio_iommu_table, vaddr, size, | 216 | return iommu_map_single(NULL, &vio_iommu_table, vaddr, size, |
217 | DMA_32BIT_MASK, direction); | 217 | DMA_32BIT_MASK, direction, NULL); |
218 | } | 218 | } |
219 | 219 | ||
220 | void iseries_hv_unmap(dma_addr_t dma_handle, size_t size, | 220 | void iseries_hv_unmap(dma_addr_t dma_handle, size_t size, |
221 | enum dma_data_direction direction) | 221 | enum dma_data_direction direction) |
222 | { | 222 | { |
223 | iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction); | 223 | iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction, NULL); |
224 | } | 224 | } |
225 | 225 | ||
226 | void __init iommu_vio_init(void) | 226 | void __init iommu_vio_init(void) |
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 9f7579b38c72..53bca132fb48 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c | |||
@@ -41,8 +41,6 @@ | |||
41 | #define DBG(x...) | 41 | #define DBG(x...) |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | extern void GregorianDay(struct rtc_time * tm); | ||
45 | |||
46 | static int maple_rtc_addr; | 44 | static int maple_rtc_addr; |
47 | 45 | ||
48 | static int maple_clock_read(int addr) | 46 | static int maple_clock_read(int addr) |
diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index 4d72c8f72159..89774177b209 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile | |||
@@ -1,5 +1,10 @@ | |||
1 | CFLAGS_bootx_init.o += -fPIC | 1 | CFLAGS_bootx_init.o += -fPIC |
2 | 2 | ||
3 | ifdef CONFIG_FTRACE | ||
4 | # Do not trace early boot code | ||
5 | CFLAGS_REMOVE_bootx_init.o = -pg | ||
6 | endif | ||
7 | |||
3 | obj-y += pic.o setup.o time.o feature.o pci.o \ | 8 | obj-y += pic.o setup.o time.o feature.o pci.o \ |
4 | sleep.o low_i2c.o cache.o pfunc_core.o \ | 9 | sleep.o low_i2c.o cache.o pfunc_core.o \ |
5 | pfunc_base.o | 10 | pfunc_base.o |
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 829b8b02527b..6d149ae8ffa7 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
@@ -34,16 +34,10 @@ | |||
34 | #include <asm/time.h> | 34 | #include <asm/time.h> |
35 | #include <asm/pmac_feature.h> | 35 | #include <asm/pmac_feature.h> |
36 | #include <asm/mpic.h> | 36 | #include <asm/mpic.h> |
37 | #include <asm/xmon.h> | ||
37 | 38 | ||
38 | #include "pmac.h" | 39 | #include "pmac.h" |
39 | 40 | ||
40 | /* | ||
41 | * XXX this should be in xmon.h, but putting it there means xmon.h | ||
42 | * has to include <linux/interrupt.h> (to get irqreturn_t), which | ||
43 | * causes all sorts of problems. -- paulus | ||
44 | */ | ||
45 | extern irqreturn_t xmon_irq(int, void *); | ||
46 | |||
47 | #ifdef CONFIG_PPC32 | 41 | #ifdef CONFIG_PPC32 |
48 | struct pmac_irq_hw { | 42 | struct pmac_irq_hw { |
49 | unsigned int event; | 43 | unsigned int event; |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index cb2d894541c6..4ae3d00e0bdd 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -36,6 +36,7 @@ | |||
36 | 36 | ||
37 | #include <asm/ptrace.h> | 37 | #include <asm/ptrace.h> |
38 | #include <asm/atomic.h> | 38 | #include <asm/atomic.h> |
39 | #include <asm/code-patching.h> | ||
39 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
40 | #include <asm/page.h> | 41 | #include <asm/page.h> |
41 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
@@ -786,8 +787,7 @@ static void __devinit smp_core99_kick_cpu(int nr) | |||
786 | { | 787 | { |
787 | unsigned int save_vector; | 788 | unsigned int save_vector; |
788 | unsigned long target, flags; | 789 | unsigned long target, flags; |
789 | volatile unsigned int *vector | 790 | unsigned int *vector = (unsigned int *)(KERNELBASE+0x100); |
790 | = ((volatile unsigned int *)(KERNELBASE+0x100)); | ||
791 | 791 | ||
792 | if (nr < 0 || nr > 3) | 792 | if (nr < 0 || nr > 3) |
793 | return; | 793 | return; |
@@ -804,7 +804,7 @@ static void __devinit smp_core99_kick_cpu(int nr) | |||
804 | * b __secondary_start_pmac_0 + nr*8 - KERNELBASE | 804 | * b __secondary_start_pmac_0 + nr*8 - KERNELBASE |
805 | */ | 805 | */ |
806 | target = (unsigned long) __secondary_start_pmac_0 + nr * 8; | 806 | target = (unsigned long) __secondary_start_pmac_0 + nr * 8; |
807 | create_branch((unsigned long)vector, target, BRANCH_SET_LINK); | 807 | patch_branch(vector, target, BRANCH_SET_LINK); |
808 | 808 | ||
809 | /* Put some life in our friend */ | 809 | /* Put some life in our friend */ |
810 | pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0); | 810 | pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0); |
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c index f0b12f212363..a0927a3bacb7 100644 --- a/arch/powerpc/platforms/ps3/smp.c +++ b/arch/powerpc/platforms/ps3/smp.c | |||
@@ -105,9 +105,10 @@ static void __init ps3_smp_setup_cpu(int cpu) | |||
105 | * to index needs to be setup. | 105 | * to index needs to be setup. |
106 | */ | 106 | */ |
107 | 107 | ||
108 | BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0); | 108 | BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0); |
109 | BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1); | 109 | BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1); |
110 | BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); | 110 | BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2); |
111 | BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); | ||
111 | 112 | ||
112 | for (i = 0; i < MSG_COUNT; i++) { | 113 | for (i = 0; i < MSG_COUNT; i++) { |
113 | result = ps3_event_receive_port_setup(cpu, &virqs[i]); | 114 | result = ps3_event_receive_port_setup(cpu, &virqs[i]); |
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 43c493fca2d0..d66c3628a112 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c | |||
@@ -349,9 +349,14 @@ static int ps3_system_bus_match(struct device *_dev, | |||
349 | 349 | ||
350 | result = dev->match_id == drv->match_id; | 350 | result = dev->match_id == drv->match_id; |
351 | 351 | ||
352 | pr_info("%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, __LINE__, | 352 | if (result) |
353 | dev->match_id, dev->core.bus_id, drv->match_id, drv->core.name, | 353 | pr_info("%s:%d: dev=%u(%s), drv=%u(%s): match\n", __func__, |
354 | (result ? "match" : "miss")); | 354 | __LINE__, dev->match_id, dev->core.bus_id, |
355 | drv->match_id, drv->core.name); | ||
356 | else | ||
357 | pr_debug("%s:%d: dev=%u(%s), drv=%u(%s): miss\n", __func__, | ||
358 | __LINE__, dev->match_id, dev->core.bus_id, | ||
359 | drv->match_id, drv->core.name); | ||
355 | return result; | 360 | return result; |
356 | } | 361 | } |
357 | 362 | ||
@@ -362,7 +367,7 @@ static int ps3_system_bus_probe(struct device *_dev) | |||
362 | struct ps3_system_bus_driver *drv; | 367 | struct ps3_system_bus_driver *drv; |
363 | 368 | ||
364 | BUG_ON(!dev); | 369 | BUG_ON(!dev); |
365 | pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); | 370 | pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); |
366 | 371 | ||
367 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); | 372 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); |
368 | BUG_ON(!drv); | 373 | BUG_ON(!drv); |
@@ -370,10 +375,10 @@ static int ps3_system_bus_probe(struct device *_dev) | |||
370 | if (drv->probe) | 375 | if (drv->probe) |
371 | result = drv->probe(dev); | 376 | result = drv->probe(dev); |
372 | else | 377 | else |
373 | pr_info("%s:%d: %s no probe method\n", __func__, __LINE__, | 378 | pr_debug("%s:%d: %s no probe method\n", __func__, __LINE__, |
374 | dev->core.bus_id); | 379 | dev->core.bus_id); |
375 | 380 | ||
376 | pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); | 381 | pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); |
377 | return result; | 382 | return result; |
378 | } | 383 | } |
379 | 384 | ||
@@ -384,7 +389,7 @@ static int ps3_system_bus_remove(struct device *_dev) | |||
384 | struct ps3_system_bus_driver *drv; | 389 | struct ps3_system_bus_driver *drv; |
385 | 390 | ||
386 | BUG_ON(!dev); | 391 | BUG_ON(!dev); |
387 | pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); | 392 | pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); |
388 | 393 | ||
389 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); | 394 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); |
390 | BUG_ON(!drv); | 395 | BUG_ON(!drv); |
@@ -395,7 +400,7 @@ static int ps3_system_bus_remove(struct device *_dev) | |||
395 | dev_dbg(&dev->core, "%s:%d %s: no remove method\n", | 400 | dev_dbg(&dev->core, "%s:%d %s: no remove method\n", |
396 | __func__, __LINE__, drv->core.name); | 401 | __func__, __LINE__, drv->core.name); |
397 | 402 | ||
398 | pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); | 403 | pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); |
399 | return result; | 404 | return result; |
400 | } | 405 | } |
401 | 406 | ||
@@ -550,7 +555,7 @@ static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, | |||
550 | */ | 555 | */ |
551 | 556 | ||
552 | static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size, | 557 | static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size, |
553 | enum dma_data_direction direction) | 558 | enum dma_data_direction direction, struct dma_attrs *attrs) |
554 | { | 559 | { |
555 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | 560 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
556 | int result; | 561 | int result; |
@@ -570,7 +575,8 @@ static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size, | |||
570 | 575 | ||
571 | static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr, | 576 | static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr, |
572 | size_t size, | 577 | size_t size, |
573 | enum dma_data_direction direction) | 578 | enum dma_data_direction direction, |
579 | struct dma_attrs *attrs) | ||
574 | { | 580 | { |
575 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | 581 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
576 | int result; | 582 | int result; |
@@ -603,7 +609,7 @@ static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr, | |||
603 | } | 609 | } |
604 | 610 | ||
605 | static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, | 611 | static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, |
606 | size_t size, enum dma_data_direction direction) | 612 | size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) |
607 | { | 613 | { |
608 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | 614 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
609 | int result; | 615 | int result; |
@@ -617,7 +623,7 @@ static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, | |||
617 | } | 623 | } |
618 | 624 | ||
619 | static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl, | 625 | static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl, |
620 | int nents, enum dma_data_direction direction) | 626 | int nents, enum dma_data_direction direction, struct dma_attrs *attrs) |
621 | { | 627 | { |
622 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | 628 | #if defined(CONFIG_PS3_DYNAMIC_DMA) |
623 | BUG_ON("do"); | 629 | BUG_ON("do"); |
@@ -646,14 +652,15 @@ static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl, | |||
646 | 652 | ||
647 | static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg, | 653 | static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg, |
648 | int nents, | 654 | int nents, |
649 | enum dma_data_direction direction) | 655 | enum dma_data_direction direction, |
656 | struct dma_attrs *attrs) | ||
650 | { | 657 | { |
651 | BUG(); | 658 | BUG(); |
652 | return 0; | 659 | return 0; |
653 | } | 660 | } |
654 | 661 | ||
655 | static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg, | 662 | static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg, |
656 | int nents, enum dma_data_direction direction) | 663 | int nents, enum dma_data_direction direction, struct dma_attrs *attrs) |
657 | { | 664 | { |
658 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | 665 | #if defined(CONFIG_PS3_DYNAMIC_DMA) |
659 | BUG_ON("do"); | 666 | BUG_ON("do"); |
@@ -661,7 +668,8 @@ static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg, | |||
661 | } | 668 | } |
662 | 669 | ||
663 | static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg, | 670 | static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg, |
664 | int nents, enum dma_data_direction direction) | 671 | int nents, enum dma_data_direction direction, |
672 | struct dma_attrs *attrs) | ||
665 | { | 673 | { |
666 | BUG(); | 674 | BUG(); |
667 | } | 675 | } |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 6f544ba4b37f..c027f0a70a04 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -812,6 +812,7 @@ int rtas_set_slot_reset(struct pci_dn *pdn) | |||
812 | static inline void __restore_bars (struct pci_dn *pdn) | 812 | static inline void __restore_bars (struct pci_dn *pdn) |
813 | { | 813 | { |
814 | int i; | 814 | int i; |
815 | u32 cmd; | ||
815 | 816 | ||
816 | if (NULL==pdn->phb) return; | 817 | if (NULL==pdn->phb) return; |
817 | for (i=4; i<10; i++) { | 818 | for (i=4; i<10; i++) { |
@@ -832,6 +833,19 @@ static inline void __restore_bars (struct pci_dn *pdn) | |||
832 | 833 | ||
833 | /* max latency, min grant, interrupt pin and line */ | 834 | /* max latency, min grant, interrupt pin and line */ |
834 | rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]); | 835 | rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]); |
836 | |||
837 | /* Restore PERR & SERR bits, some devices require it, | ||
838 | don't touch the other command bits */ | ||
839 | rtas_read_config(pdn, PCI_COMMAND, 4, &cmd); | ||
840 | if (pdn->config_space[1] & PCI_COMMAND_PARITY) | ||
841 | cmd |= PCI_COMMAND_PARITY; | ||
842 | else | ||
843 | cmd &= ~PCI_COMMAND_PARITY; | ||
844 | if (pdn->config_space[1] & PCI_COMMAND_SERR) | ||
845 | cmd |= PCI_COMMAND_SERR; | ||
846 | else | ||
847 | cmd &= ~PCI_COMMAND_SERR; | ||
848 | rtas_write_config(pdn, PCI_COMMAND, 4, cmd); | ||
835 | } | 849 | } |
836 | 850 | ||
837 | /** | 851 | /** |
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 68ea5eee39a8..8c1ca477c52c 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
@@ -42,17 +42,20 @@ static inline const char * pcid_name (struct pci_dev *pdev) | |||
42 | } | 42 | } |
43 | 43 | ||
44 | #ifdef DEBUG | 44 | #ifdef DEBUG |
45 | static void print_device_node_tree (struct pci_dn *pdn, int dent) | 45 | static void print_device_node_tree(struct pci_dn *pdn, int dent) |
46 | { | 46 | { |
47 | int i; | 47 | int i; |
48 | if (!pdn) return; | 48 | struct device_node *pc; |
49 | for (i=0;i<dent; i++) | 49 | |
50 | if (!pdn) | ||
51 | return; | ||
52 | for (i = 0; i < dent; i++) | ||
50 | printk(" "); | 53 | printk(" "); |
51 | printk("dn=%s mode=%x \tcfg_addr=%x pe_addr=%x \tfull=%s\n", | 54 | printk("dn=%s mode=%x \tcfg_addr=%x pe_addr=%x \tfull=%s\n", |
52 | pdn->node->name, pdn->eeh_mode, pdn->eeh_config_addr, | 55 | pdn->node->name, pdn->eeh_mode, pdn->eeh_config_addr, |
53 | pdn->eeh_pe_config_addr, pdn->node->full_name); | 56 | pdn->eeh_pe_config_addr, pdn->node->full_name); |
54 | dent += 3; | 57 | dent += 3; |
55 | struct device_node *pc = pdn->node->child; | 58 | pc = pdn->node->child; |
56 | while (pc) { | 59 | while (pc) { |
57 | print_device_node_tree(PCI_DN(pc), dent); | 60 | print_device_node_tree(PCI_DN(pc), dent); |
58 | pc = pc->sibling; | 61 | pc = pc->sibling; |
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 9d3a40f45974..5a707da3f5c2 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/prom.h> | 26 | #include <asm/prom.h> |
27 | #include <asm/udbg.h> | 27 | #include <asm/udbg.h> |
28 | 28 | ||
29 | #include "pseries.h" | ||
29 | 30 | ||
30 | typedef struct { | 31 | typedef struct { |
31 | unsigned long val; | 32 | unsigned long val; |
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 3c5727dd5aa5..a1a368dd2d99 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c | |||
@@ -15,34 +15,13 @@ | |||
15 | #include <asm/machdep.h> | 15 | #include <asm/machdep.h> |
16 | #include <asm/pSeries_reconfig.h> | 16 | #include <asm/pSeries_reconfig.h> |
17 | 17 | ||
18 | static int pseries_remove_memory(struct device_node *np) | 18 | static int pseries_remove_lmb(unsigned long base, unsigned int lmb_size) |
19 | { | 19 | { |
20 | const char *type; | 20 | unsigned long start, start_pfn; |
21 | const unsigned int *my_index; | ||
22 | const unsigned int *regs; | ||
23 | u64 start_pfn, start; | ||
24 | struct zone *zone; | 21 | struct zone *zone; |
25 | int ret = -EINVAL; | 22 | int ret; |
26 | |||
27 | /* | ||
28 | * Check to see if we are actually removing memory | ||
29 | */ | ||
30 | type = of_get_property(np, "device_type", NULL); | ||
31 | if (type == NULL || strcmp(type, "memory") != 0) | ||
32 | return 0; | ||
33 | 23 | ||
34 | /* | 24 | start_pfn = base >> PFN_SECTION_SHIFT; |
35 | * Find the memory index and size of the removing section | ||
36 | */ | ||
37 | my_index = of_get_property(np, "ibm,my-drc-index", NULL); | ||
38 | if (!my_index) | ||
39 | return ret; | ||
40 | |||
41 | regs = of_get_property(np, "reg", NULL); | ||
42 | if (!regs) | ||
43 | return ret; | ||
44 | |||
45 | start_pfn = section_nr_to_pfn(*my_index & 0xffff); | ||
46 | zone = page_zone(pfn_to_page(start_pfn)); | 25 | zone = page_zone(pfn_to_page(start_pfn)); |
47 | 26 | ||
48 | /* | 27 | /* |
@@ -54,56 +33,111 @@ static int pseries_remove_memory(struct device_node *np) | |||
54 | * to sysfs "state" file and we can't remove sysfs entries | 33 | * to sysfs "state" file and we can't remove sysfs entries |
55 | * while writing to it. So we have to defer it to here. | 34 | * while writing to it. So we have to defer it to here. |
56 | */ | 35 | */ |
57 | ret = __remove_pages(zone, start_pfn, regs[3] >> PAGE_SHIFT); | 36 | ret = __remove_pages(zone, start_pfn, lmb_size >> PAGE_SHIFT); |
58 | if (ret) | 37 | if (ret) |
59 | return ret; | 38 | return ret; |
60 | 39 | ||
61 | /* | 40 | /* |
62 | * Update memory regions for memory remove | 41 | * Update memory regions for memory remove |
63 | */ | 42 | */ |
64 | lmb_remove(start_pfn << PAGE_SHIFT, regs[3]); | 43 | lmb_remove(base, lmb_size); |
65 | 44 | ||
66 | /* | 45 | /* |
67 | * Remove htab bolted mappings for this section of memory | 46 | * Remove htab bolted mappings for this section of memory |
68 | */ | 47 | */ |
69 | start = (unsigned long)__va(start_pfn << PAGE_SHIFT); | 48 | start = (unsigned long)__va(base); |
70 | ret = remove_section_mapping(start, start + regs[3]); | 49 | ret = remove_section_mapping(start, start + lmb_size); |
71 | return ret; | 50 | return ret; |
72 | } | 51 | } |
73 | 52 | ||
74 | static int pseries_add_memory(struct device_node *np) | 53 | static int pseries_remove_memory(struct device_node *np) |
75 | { | 54 | { |
76 | const char *type; | 55 | const char *type; |
77 | const unsigned int *my_index; | ||
78 | const unsigned int *regs; | 56 | const unsigned int *regs; |
79 | u64 start_pfn; | 57 | unsigned long base; |
58 | unsigned int lmb_size; | ||
80 | int ret = -EINVAL; | 59 | int ret = -EINVAL; |
81 | 60 | ||
82 | /* | 61 | /* |
83 | * Check to see if we are actually adding memory | 62 | * Check to see if we are actually removing memory |
84 | */ | 63 | */ |
85 | type = of_get_property(np, "device_type", NULL); | 64 | type = of_get_property(np, "device_type", NULL); |
86 | if (type == NULL || strcmp(type, "memory") != 0) | 65 | if (type == NULL || strcmp(type, "memory") != 0) |
87 | return 0; | 66 | return 0; |
88 | 67 | ||
89 | /* | 68 | /* |
90 | * Find the memory index and size of the added section | 69 | * Find the bae address and size of the lmb |
91 | */ | 70 | */ |
92 | my_index = of_get_property(np, "ibm,my-drc-index", NULL); | 71 | regs = of_get_property(np, "reg", NULL); |
93 | if (!my_index) | 72 | if (!regs) |
94 | return ret; | 73 | return ret; |
95 | 74 | ||
75 | base = *(unsigned long *)regs; | ||
76 | lmb_size = regs[3]; | ||
77 | |||
78 | ret = pseries_remove_lmb(base, lmb_size); | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | static int pseries_add_memory(struct device_node *np) | ||
83 | { | ||
84 | const char *type; | ||
85 | const unsigned int *regs; | ||
86 | unsigned long base; | ||
87 | unsigned int lmb_size; | ||
88 | int ret = -EINVAL; | ||
89 | |||
90 | /* | ||
91 | * Check to see if we are actually adding memory | ||
92 | */ | ||
93 | type = of_get_property(np, "device_type", NULL); | ||
94 | if (type == NULL || strcmp(type, "memory") != 0) | ||
95 | return 0; | ||
96 | |||
97 | /* | ||
98 | * Find the base and size of the lmb | ||
99 | */ | ||
96 | regs = of_get_property(np, "reg", NULL); | 100 | regs = of_get_property(np, "reg", NULL); |
97 | if (!regs) | 101 | if (!regs) |
98 | return ret; | 102 | return ret; |
99 | 103 | ||
100 | start_pfn = section_nr_to_pfn(*my_index & 0xffff); | 104 | base = *(unsigned long *)regs; |
105 | lmb_size = regs[3]; | ||
101 | 106 | ||
102 | /* | 107 | /* |
103 | * Update memory region to represent the memory add | 108 | * Update memory region to represent the memory add |
104 | */ | 109 | */ |
105 | lmb_add(start_pfn << PAGE_SHIFT, regs[3]); | 110 | ret = lmb_add(base, lmb_size); |
106 | return 0; | 111 | return (ret < 0) ? -EINVAL : 0; |
112 | } | ||
113 | |||
114 | static int pseries_drconf_memory(unsigned long *base, unsigned int action) | ||
115 | { | ||
116 | struct device_node *np; | ||
117 | const unsigned long *lmb_size; | ||
118 | int rc; | ||
119 | |||
120 | np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); | ||
121 | if (!np) | ||
122 | return -EINVAL; | ||
123 | |||
124 | lmb_size = of_get_property(np, "ibm,lmb-size", NULL); | ||
125 | if (!lmb_size) { | ||
126 | of_node_put(np); | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | |||
130 | if (action == PSERIES_DRCONF_MEM_ADD) { | ||
131 | rc = lmb_add(*base, *lmb_size); | ||
132 | rc = (rc < 0) ? -EINVAL : 0; | ||
133 | } else if (action == PSERIES_DRCONF_MEM_REMOVE) { | ||
134 | rc = pseries_remove_lmb(*base, *lmb_size); | ||
135 | } else { | ||
136 | rc = -EINVAL; | ||
137 | } | ||
138 | |||
139 | of_node_put(np); | ||
140 | return rc; | ||
107 | } | 141 | } |
108 | 142 | ||
109 | static int pseries_memory_notifier(struct notifier_block *nb, | 143 | static int pseries_memory_notifier(struct notifier_block *nb, |
@@ -120,6 +154,11 @@ static int pseries_memory_notifier(struct notifier_block *nb, | |||
120 | if (pseries_remove_memory(node)) | 154 | if (pseries_remove_memory(node)) |
121 | err = NOTIFY_BAD; | 155 | err = NOTIFY_BAD; |
122 | break; | 156 | break; |
157 | case PSERIES_DRCONF_MEM_ADD: | ||
158 | case PSERIES_DRCONF_MEM_REMOVE: | ||
159 | if (pseries_drconf_memory(node, action)) | ||
160 | err = NOTIFY_BAD; | ||
161 | break; | ||
123 | default: | 162 | default: |
124 | err = NOTIFY_DONE; | 163 | err = NOTIFY_DONE; |
125 | break; | 164 | break; |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 176f1f39d2d5..9a12908510fb 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -135,9 +135,10 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
135 | u64 rpn; | 135 | u64 rpn; |
136 | long l, limit; | 136 | long l, limit; |
137 | 137 | ||
138 | if (npages == 1) | 138 | if (npages == 1) { |
139 | return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, | 139 | tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, direction); |
140 | direction); | 140 | return; |
141 | } | ||
141 | 142 | ||
142 | tcep = __get_cpu_var(tce_page); | 143 | tcep = __get_cpu_var(tce_page); |
143 | 144 | ||
@@ -147,9 +148,11 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
147 | if (!tcep) { | 148 | if (!tcep) { |
148 | tcep = (u64 *)__get_free_page(GFP_ATOMIC); | 149 | tcep = (u64 *)__get_free_page(GFP_ATOMIC); |
149 | /* If allocation fails, fall back to the loop implementation */ | 150 | /* If allocation fails, fall back to the loop implementation */ |
150 | if (!tcep) | 151 | if (!tcep) { |
151 | return tce_build_pSeriesLP(tbl, tcenum, npages, | 152 | tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, |
152 | uaddr, direction); | 153 | direction); |
154 | return; | ||
155 | } | ||
153 | __get_cpu_var(tce_page) = tcep; | 156 | __get_cpu_var(tce_page) = tcep; |
154 | } | 157 | } |
155 | 158 | ||
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c index e9dd5fe081c9..53cbd53d8740 100644 --- a/arch/powerpc/platforms/pseries/kexec.c +++ b/arch/powerpc/platforms/pseries/kexec.c | |||
@@ -70,4 +70,4 @@ static int __init pseries_kexec_setup(void) | |||
70 | 70 | ||
71 | return 0; | 71 | return 0; |
72 | } | 72 | } |
73 | __initcall(pseries_kexec_setup); | 73 | machine_device_initcall(pseries, pseries_kexec_setup); |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 2cbaedb17f3e..52a80e5840e8 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -52,7 +52,7 @@ EXPORT_SYMBOL(plpar_hcall_norets); | |||
52 | extern void pSeries_find_serial_port(void); | 52 | extern void pSeries_find_serial_port(void); |
53 | 53 | ||
54 | 54 | ||
55 | int vtermno; /* virtual terminal# for udbg */ | 55 | static int vtermno; /* virtual terminal# for udbg */ |
56 | 56 | ||
57 | #define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) | 57 | #define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) |
58 | static void udbg_hvsi_putc(char c) | 58 | static void udbg_hvsi_putc(char c) |
@@ -305,7 +305,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | |||
305 | flags = 0; | 305 | flags = 0; |
306 | 306 | ||
307 | /* Make pHyp happy */ | 307 | /* Make pHyp happy */ |
308 | if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) | 308 | if ((rflags & _PAGE_NO_CACHE) & !(rflags & _PAGE_WRITETHRU)) |
309 | hpte_r &= ~_PAGE_COHERENT; | 309 | hpte_r &= ~_PAGE_COHERENT; |
310 | 310 | ||
311 | lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot); | 311 | lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot); |
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index f68903e15bd5..42f7e384e6c4 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c | |||
@@ -131,8 +131,10 @@ int __init pSeries_nvram_init(void) | |||
131 | return -ENODEV; | 131 | return -ENODEV; |
132 | 132 | ||
133 | nbytes_p = of_get_property(nvram, "#bytes", &proplen); | 133 | nbytes_p = of_get_property(nvram, "#bytes", &proplen); |
134 | if (nbytes_p == NULL || proplen != sizeof(unsigned int)) | 134 | if (nbytes_p == NULL || proplen != sizeof(unsigned int)) { |
135 | of_node_put(nvram); | ||
135 | return -EIO; | 136 | return -EIO; |
137 | } | ||
136 | 138 | ||
137 | nvram_size = *nbytes_p; | 139 | nvram_size = *nbytes_p; |
138 | 140 | ||
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 2b548afd1003..d20b96e22c2e 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
@@ -55,7 +55,7 @@ | |||
55 | static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX]; | 55 | static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX]; |
56 | static DEFINE_SPINLOCK(ras_log_buf_lock); | 56 | static DEFINE_SPINLOCK(ras_log_buf_lock); |
57 | 57 | ||
58 | char mce_data_buf[RTAS_ERROR_LOG_MAX]; | 58 | static char mce_data_buf[RTAS_ERROR_LOG_MAX]; |
59 | 59 | ||
60 | static int ras_get_sensor_state_token; | 60 | static int ras_get_sensor_state_token; |
61 | static int ras_check_exception_token; | 61 | static int ras_check_exception_token; |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 75769aae41d5..7637bd38c795 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -365,7 +365,7 @@ static char *parse_node(char *buf, size_t bufsize, struct device_node **npp) | |||
365 | *buf = '\0'; | 365 | *buf = '\0'; |
366 | buf++; | 366 | buf++; |
367 | 367 | ||
368 | handle = simple_strtoul(handle_str, NULL, 10); | 368 | handle = simple_strtoul(handle_str, NULL, 0); |
369 | 369 | ||
370 | *npp = of_find_node_by_phandle(handle); | 370 | *npp = of_find_node_by_phandle(handle); |
371 | return buf; | 371 | return buf; |
@@ -422,8 +422,8 @@ static int do_update_property(char *buf, size_t bufsize) | |||
422 | { | 422 | { |
423 | struct device_node *np; | 423 | struct device_node *np; |
424 | unsigned char *value; | 424 | unsigned char *value; |
425 | char *name, *end; | 425 | char *name, *end, *next_prop; |
426 | int length; | 426 | int rc, length; |
427 | struct property *newprop, *oldprop; | 427 | struct property *newprop, *oldprop; |
428 | buf = parse_node(buf, bufsize, &np); | 428 | buf = parse_node(buf, bufsize, &np); |
429 | end = buf + bufsize; | 429 | end = buf + bufsize; |
@@ -431,7 +431,8 @@ static int do_update_property(char *buf, size_t bufsize) | |||
431 | if (!np) | 431 | if (!np) |
432 | return -ENODEV; | 432 | return -ENODEV; |
433 | 433 | ||
434 | if (parse_next_property(buf, end, &name, &length, &value) == NULL) | 434 | next_prop = parse_next_property(buf, end, &name, &length, &value); |
435 | if (!next_prop) | ||
435 | return -EINVAL; | 436 | return -EINVAL; |
436 | 437 | ||
437 | newprop = new_property(name, length, value, NULL); | 438 | newprop = new_property(name, length, value, NULL); |
@@ -442,7 +443,34 @@ static int do_update_property(char *buf, size_t bufsize) | |||
442 | if (!oldprop) | 443 | if (!oldprop) |
443 | return -ENODEV; | 444 | return -ENODEV; |
444 | 445 | ||
445 | return prom_update_property(np, newprop, oldprop); | 446 | rc = prom_update_property(np, newprop, oldprop); |
447 | if (rc) | ||
448 | return rc; | ||
449 | |||
450 | /* For memory under the ibm,dynamic-reconfiguration-memory node | ||
451 | * of the device tree, adding and removing memory is just an update | ||
452 | * to the ibm,dynamic-memory property instead of adding/removing a | ||
453 | * memory node in the device tree. For these cases we still need to | ||
454 | * involve the notifier chain. | ||
455 | */ | ||
456 | if (!strcmp(name, "ibm,dynamic-memory")) { | ||
457 | int action; | ||
458 | |||
459 | next_prop = parse_next_property(next_prop, end, &name, | ||
460 | &length, &value); | ||
461 | if (!next_prop) | ||
462 | return -EINVAL; | ||
463 | |||
464 | if (!strcmp(name, "add")) | ||
465 | action = PSERIES_DRCONF_MEM_ADD; | ||
466 | else | ||
467 | action = PSERIES_DRCONF_MEM_REMOVE; | ||
468 | |||
469 | blocking_notifier_call_chain(&pSeries_reconfig_chain, | ||
470 | action, value); | ||
471 | } | ||
472 | |||
473 | return 0; | ||
446 | } | 474 | } |
447 | 475 | ||
448 | /** | 476 | /** |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index 7d3e2b0bd4d2..c9ffd8c225f1 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | static DEFINE_SPINLOCK(rtasd_log_lock); | 33 | static DEFINE_SPINLOCK(rtasd_log_lock); |
34 | 34 | ||
35 | DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait); | 35 | static DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait); |
36 | 36 | ||
37 | static char *rtas_log_buf; | 37 | static char *rtas_log_buf; |
38 | static unsigned long rtas_log_start; | 38 | static unsigned long rtas_log_start; |
@@ -329,7 +329,7 @@ static unsigned int rtas_log_poll(struct file *file, poll_table * wait) | |||
329 | return 0; | 329 | return 0; |
330 | } | 330 | } |
331 | 331 | ||
332 | const struct file_operations proc_rtas_log_operations = { | 332 | static const struct file_operations proc_rtas_log_operations = { |
333 | .read = rtas_log_read, | 333 | .read = rtas_log_read, |
334 | .poll = rtas_log_poll, | 334 | .poll = rtas_log_poll, |
335 | .open = rtas_log_open, | 335 | .open = rtas_log_open, |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index f5d29f5b13c1..90beb444e1dd 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -109,7 +109,7 @@ static void __init fwnmi_init(void) | |||
109 | fwnmi_active = 1; | 109 | fwnmi_active = 1; |
110 | } | 110 | } |
111 | 111 | ||
112 | void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc) | 112 | static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc) |
113 | { | 113 | { |
114 | unsigned int cascade_irq = i8259_irq(); | 114 | unsigned int cascade_irq = i8259_irq(); |
115 | if (cascade_irq != NO_IRQ) | 115 | if (cascade_irq != NO_IRQ) |
@@ -482,7 +482,7 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) | |||
482 | * possible with power button press. If ibm,power-off-ups token is used | 482 | * possible with power button press. If ibm,power-off-ups token is used |
483 | * it will allow auto poweron after power is restored. | 483 | * it will allow auto poweron after power is restored. |
484 | */ | 484 | */ |
485 | void pSeries_power_off(void) | 485 | static void pSeries_power_off(void) |
486 | { | 486 | { |
487 | int rc; | 487 | int rc; |
488 | int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups"); | 488 | int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups"); |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index ebebc28fe895..0fc830f576f5 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -383,13 +383,11 @@ static irqreturn_t xics_ipi_dispatch(int cpu) | |||
383 | mb(); | 383 | mb(); |
384 | smp_message_recv(PPC_MSG_RESCHEDULE); | 384 | smp_message_recv(PPC_MSG_RESCHEDULE); |
385 | } | 385 | } |
386 | #if 0 | 386 | if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE, |
387 | if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, | ||
388 | &xics_ipi_message[cpu].value)) { | 387 | &xics_ipi_message[cpu].value)) { |
389 | mb(); | 388 | mb(); |
390 | smp_message_recv(PPC_MSG_MIGRATE_TASK); | 389 | smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE); |
391 | } | 390 | } |
392 | #endif | ||
393 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) | 391 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) |
394 | if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK, | 392 | if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK, |
395 | &xics_ipi_message[cpu].value)) { | 393 | &xics_ipi_message[cpu].value)) { |