aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/cell
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-22 16:16:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-22 16:16:01 -0400
commit06b8147c5dbd385b5b97ca74e19f6f3951ebc1cb (patch)
tree6ed9de7ca0ab3a65af6a189a89deb0a36ab35f6b /arch/powerpc/platforms/cell
parent53baaaa9682c230410a057263d1ce2922f43ddc4 (diff)
parent8725f25acc656c1522d48a6746055099efdaca4c (diff)
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (49 commits) powerpc: Fix build bug with binutils < 2.18 and GCC < 4.2 powerpc/eeh: Don't panic when EEH_MAX_FAILS is exceeded fbdev: Teaches offb about palette on radeon r5xx/r6xx powerpc/cell/edac: Log a syndrome code in case of correctable error powerpc/cell: Add DMA_ATTR_WEAK_ORDERING dma attribute and use in Cell IOMMU code powerpc: Indicate which oprofile counters to use while in compat mode powerpc/boot: Change spaces to tabs powerpc: Remove duplicate 6xx option in Kconfig powerpc: Use PPC_LONG and PPC_LONG_ALIGN in lib/string.S powerpc: Use PPC_LONG_ALIGN in uaccess.h powerpc: Add a #define for aligning to a long-sized boundary powerpc: Fix OF parsing of 64 bits PCI addresses powerpc: Use WARN_ON(1) instead of __WARN() powerpc: Fix support for latencytop powerpc/ps3: Update ps3_defconfig powerpc/ps3: Add a sub-match id to ps3_system_bus powerpc: Add a 6xx defconfig powerpc/dma: Use the struct dma_attrs in iommu code powerpc/cell: Add support for power button of future IBM cell blades powerpc/cell: Cleanup sysreset_hack for IBM cell blades ...
Diffstat (limited to 'arch/powerpc/platforms/cell')
-rw-r--r--arch/powerpc/platforms/cell/Kconfig25
-rw-r--r--arch/powerpc/platforms/cell/Makefile3
-rw-r--r--arch/powerpc/platforms/cell/cbe_powerbutton.c117
-rw-r--r--arch/powerpc/platforms/cell/cpufreq_spudemand.c184
-rw-r--r--arch/powerpc/platforms/cell/iommu.c118
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c27
-rw-r--r--arch/powerpc/platforms/cell/pervasive.h9
-rw-r--r--arch/powerpc/platforms/cell/ras.c46
8 files changed, 496 insertions, 33 deletions
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3959fcfe731c..c14d7d8d96c8 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -83,6 +83,22 @@ config CBE_RAS
83 depends on PPC_CELL_NATIVE 83 depends on PPC_CELL_NATIVE
84 default y 84 default y
85 85
86config PPC_IBM_CELL_RESETBUTTON
87 bool "IBM Cell Blade Pinhole reset button"
88 depends on CBE_RAS && PPC_IBM_CELL_BLADE
89 default y
90 help
91 Support Pinhole Resetbutton on IBM Cell blades.
92 This adds a method to trigger system reset via front panel pinhole button.
93
94config PPC_IBM_CELL_POWERBUTTON
95 tristate "IBM Cell Blade power button"
96 depends on PPC_IBM_CELL_BLADE && PPC_PMI && INPUT_EVDEV
97 default y
98 help
99 Support Powerbutton on IBM Cell blades.
100 This will enable the powerbutton as an input device.
101
86config CBE_THERM 102config CBE_THERM
87 tristate "CBE thermal support" 103 tristate "CBE thermal support"
88 default m 104 default m
@@ -107,6 +123,15 @@ config CBE_CPUFREQ_PMI
107 processor will not only be able to run at lower speed, 123 processor will not only be able to run at lower speed,
108 but also at lower core voltage. 124 but also at lower core voltage.
109 125
126config CBE_CPUFREQ_SPU_GOVERNOR
127 tristate "CBE frequency scaling based on SPU usage"
128 depends on SPU_FS && CPU_FREQ
129 default m
130 help
131 This governor checks for spu usage to adjust the cpu frequency.
132 If no spu is running on a given cpu, that cpu will be throttled to
133 the minimal possible frequency.
134
110endmenu 135endmenu
111 136
112config OPROFILE_CELL 137config OPROFILE_CELL
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index c2a7e4e5ddf9..7fd830872c43 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -8,6 +8,9 @@ obj-$(CONFIG_CBE_THERM) += cbe_thermal.o
8obj-$(CONFIG_CBE_CPUFREQ_PMI) += cbe_cpufreq_pmi.o 8obj-$(CONFIG_CBE_CPUFREQ_PMI) += cbe_cpufreq_pmi.o
9obj-$(CONFIG_CBE_CPUFREQ) += cbe-cpufreq.o 9obj-$(CONFIG_CBE_CPUFREQ) += cbe-cpufreq.o
10cbe-cpufreq-y += cbe_cpufreq_pervasive.o cbe_cpufreq.o 10cbe-cpufreq-y += cbe_cpufreq_pervasive.o cbe_cpufreq.o
11obj-$(CONFIG_CBE_CPUFREQ_SPU_GOVERNOR) += cpufreq_spudemand.o
12
13obj-$(CONFIG_PPC_IBM_CELL_POWERBUTTON) += cbe_powerbutton.o
11 14
12ifeq ($(CONFIG_SMP),y) 15ifeq ($(CONFIG_SMP),y)
13obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o 16obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o
diff --git a/arch/powerpc/platforms/cell/cbe_powerbutton.c b/arch/powerpc/platforms/cell/cbe_powerbutton.c
new file mode 100644
index 000000000000..dcddaa5fcb66
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_powerbutton.c
@@ -0,0 +1,117 @@
1/*
2 * driver for powerbutton on IBM cell blades
3 *
4 * (C) Copyright IBM Corp. 2005-2008
5 *
6 * Author: Christian Krafft <krafft@de.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/input.h>
24#include <linux/platform_device.h>
25#include <asm/pmi.h>
26#include <asm/prom.h>
27
28static struct input_dev *button_dev;
29static struct platform_device *button_pdev;
30
31static void cbe_powerbutton_handle_pmi(pmi_message_t pmi_msg)
32{
33 BUG_ON(pmi_msg.type != PMI_TYPE_POWER_BUTTON);
34
35 input_report_key(button_dev, KEY_POWER, 1);
36 input_sync(button_dev);
37 input_report_key(button_dev, KEY_POWER, 0);
38 input_sync(button_dev);
39}
40
41static struct pmi_handler cbe_pmi_handler = {
42 .type = PMI_TYPE_POWER_BUTTON,
43 .handle_pmi_message = cbe_powerbutton_handle_pmi,
44};
45
46static int __init cbe_powerbutton_init(void)
47{
48 int ret = 0;
49 struct input_dev *dev;
50
51 if (!machine_is_compatible("IBM,CBPLUS-1.0")) {
52 printk(KERN_ERR "%s: Not a cell blade.\n", __func__);
53 ret = -ENODEV;
54 goto out;
55 }
56
57 dev = input_allocate_device();
58 if (!dev) {
59 ret = -ENOMEM;
60 printk(KERN_ERR "%s: Not enough memory.\n", __func__);
61 goto out;
62 }
63
64 set_bit(EV_KEY, dev->evbit);
65 set_bit(KEY_POWER, dev->keybit);
66
67 dev->name = "Power Button";
68 dev->id.bustype = BUS_HOST;
69
70 /* this makes the button look like an acpi power button
71 * no clue whether anyone relies on that though */
72 dev->id.product = 0x02;
73 dev->phys = "LNXPWRBN/button/input0";
74
75 button_pdev = platform_device_register_simple("power_button", 0, NULL, 0);
76 if (IS_ERR(button_pdev)) {
77 ret = PTR_ERR(button_pdev);
78 goto out_free_input;
79 }
80
81 dev->dev.parent = &button_pdev->dev;
82 ret = input_register_device(dev);
83 if (ret) {
84 printk(KERN_ERR "%s: Failed to register device\n", __func__);
85 goto out_free_pdev;
86 }
87
88 button_dev = dev;
89
90 ret = pmi_register_handler(&cbe_pmi_handler);
91 if (ret) {
92 printk(KERN_ERR "%s: Failed to register with pmi.\n", __func__);
93 goto out_free_pdev;
94 }
95
96 goto out;
97
98out_free_pdev:
99 platform_device_unregister(button_pdev);
100out_free_input:
101 input_free_device(dev);
102out:
103 return ret;
104}
105
106static void __exit cbe_powerbutton_exit(void)
107{
108 pmi_unregister_handler(&cbe_pmi_handler);
109 platform_device_unregister(button_pdev);
110 input_free_device(button_dev);
111}
112
113module_init(cbe_powerbutton_init);
114module_exit(cbe_powerbutton_exit);
115
116MODULE_LICENSE("GPL");
117MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
new file mode 100644
index 000000000000..a3c6c01bd6db
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -0,0 +1,184 @@
1/*
2 * spu aware cpufreq governor for the cell processor
3 *
4 * © Copyright IBM Corporation 2006-2008
5 *
6 * Author: Christian Krafft <krafft@de.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/cpufreq.h>
24#include <linux/sched.h>
25#include <linux/timer.h>
26#include <linux/workqueue.h>
27#include <asm/atomic.h>
28#include <asm/machdep.h>
29#include <asm/spu.h>
30
31#define POLL_TIME 100000 /* in µs */
32#define EXP 753 /* exp(-1) in fixed-point */
33
34struct spu_gov_info_struct {
35 unsigned long busy_spus; /* fixed-point */
36 struct cpufreq_policy *policy;
37 struct delayed_work work;
38 unsigned int poll_int; /* µs */
39};
40static DEFINE_PER_CPU(struct spu_gov_info_struct, spu_gov_info);
41
42static struct workqueue_struct *kspugov_wq;
43
44static int calc_freq(struct spu_gov_info_struct *info)
45{
46 int cpu;
47 int busy_spus;
48
49 cpu = info->policy->cpu;
50 busy_spus = atomic_read(&cbe_spu_info[cpu_to_node(cpu)].busy_spus);
51
52 CALC_LOAD(info->busy_spus, EXP, busy_spus * FIXED_1);
53 pr_debug("cpu %d: busy_spus=%d, info->busy_spus=%ld\n",
54 cpu, busy_spus, info->busy_spus);
55
56 return info->policy->max * info->busy_spus / FIXED_1;
57}
58
59static void spu_gov_work(struct work_struct *work)
60{
61 struct spu_gov_info_struct *info;
62 int delay;
63 unsigned long target_freq;
64
65 info = container_of(work, struct spu_gov_info_struct, work.work);
66
67 /* after cancel_delayed_work_sync we unset info->policy */
68 BUG_ON(info->policy == NULL);
69
70 target_freq = calc_freq(info);
71 __cpufreq_driver_target(info->policy, target_freq, CPUFREQ_RELATION_H);
72
73 delay = usecs_to_jiffies(info->poll_int);
74 queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
75}
76
77static void spu_gov_init_work(struct spu_gov_info_struct *info)
78{
79 int delay = usecs_to_jiffies(info->poll_int);
80 INIT_DELAYED_WORK_DEFERRABLE(&info->work, spu_gov_work);
81 queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
82}
83
84static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
85{
86 cancel_delayed_work_sync(&info->work);
87}
88
89static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
90{
91 unsigned int cpu = policy->cpu;
92 struct spu_gov_info_struct *info, *affected_info;
93 int i;
94 int ret = 0;
95
96 info = &per_cpu(spu_gov_info, cpu);
97
98 switch (event) {
99 case CPUFREQ_GOV_START:
100 if (!cpu_online(cpu)) {
101 printk(KERN_ERR "cpu %d is not online\n", cpu);
102 ret = -EINVAL;
103 break;
104 }
105
106 if (!policy->cur) {
107 printk(KERN_ERR "no cpu specified in policy\n");
108 ret = -EINVAL;
109 break;
110 }
111
112 /* initialize spu_gov_info for all affected cpus */
113 for_each_cpu_mask(i, policy->cpus) {
114 affected_info = &per_cpu(spu_gov_info, i);
115 affected_info->policy = policy;
116 }
117
118 info->poll_int = POLL_TIME;
119
120 /* setup timer */
121 spu_gov_init_work(info);
122
123 break;
124
125 case CPUFREQ_GOV_STOP:
126 /* cancel timer */
127 spu_gov_cancel_work(info);
128
129 /* clean spu_gov_info for all affected cpus */
130 for_each_cpu_mask (i, policy->cpus) {
131 info = &per_cpu(spu_gov_info, i);
132 info->policy = NULL;
133 }
134
135 break;
136 }
137
138 return ret;
139}
140
141static struct cpufreq_governor spu_governor = {
142 .name = "spudemand",
143 .governor = spu_gov_govern,
144 .owner = THIS_MODULE,
145};
146
147/*
148 * module init and destoy
149 */
150
151static int __init spu_gov_init(void)
152{
153 int ret;
154
155 kspugov_wq = create_workqueue("kspugov");
156 if (!kspugov_wq) {
157 printk(KERN_ERR "creation of kspugov failed\n");
158 ret = -EFAULT;
159 goto out;
160 }
161
162 ret = cpufreq_register_governor(&spu_governor);
163 if (ret) {
164 printk(KERN_ERR "registration of governor failed\n");
165 destroy_workqueue(kspugov_wq);
166 goto out;
167 }
168out:
169 return ret;
170}
171
172static void __exit spu_gov_exit(void)
173{
174 cpufreq_unregister_governor(&spu_governor);
175 destroy_workqueue(kspugov_wq);
176}
177
178
179module_init(spu_gov_init);
180module_exit(spu_gov_exit);
181
182MODULE_LICENSE("GPL");
183MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
184
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index eeacb3a52ca1..208005ca262c 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -173,7 +173,8 @@ static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte,
173} 173}
174 174
175static void tce_build_cell(struct iommu_table *tbl, long index, long npages, 175static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
176 unsigned long uaddr, enum dma_data_direction direction) 176 unsigned long uaddr, enum dma_data_direction direction,
177 struct dma_attrs *attrs)
177{ 178{
178 int i; 179 int i;
179 unsigned long *io_pte, base_pte; 180 unsigned long *io_pte, base_pte;
@@ -198,6 +199,8 @@ static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
198 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW | 199 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW |
199 (window->ioid & IOPTE_IOID_Mask); 200 (window->ioid & IOPTE_IOID_Mask);
200#endif 201#endif
202 if (unlikely(dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs)))
203 base_pte &= ~IOPTE_SO_RW;
201 204
202 io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset); 205 io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
203 206
@@ -519,7 +522,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
519 522
520 __set_bit(0, window->table.it_map); 523 __set_bit(0, window->table.it_map);
521 tce_build_cell(&window->table, window->table.it_offset, 1, 524 tce_build_cell(&window->table, window->table.it_offset, 1,
522 (unsigned long)iommu->pad_page, DMA_TO_DEVICE); 525 (unsigned long)iommu->pad_page, DMA_TO_DEVICE, NULL);
523 window->table.it_hint = window->table.it_blocksize; 526 window->table.it_hint = window->table.it_blocksize;
524 527
525 return window; 528 return window;
@@ -538,7 +541,9 @@ static struct cbe_iommu *cell_iommu_for_node(int nid)
538static unsigned long cell_dma_direct_offset; 541static unsigned long cell_dma_direct_offset;
539 542
540static unsigned long dma_iommu_fixed_base; 543static unsigned long dma_iommu_fixed_base;
541struct dma_mapping_ops dma_iommu_fixed_ops; 544
545/* iommu_fixed_is_weak is set if booted with iommu_fixed=weak */
546static int iommu_fixed_is_weak;
542 547
543static struct iommu_table *cell_get_iommu_table(struct device *dev) 548static struct iommu_table *cell_get_iommu_table(struct device *dev)
544{ 549{
@@ -562,6 +567,98 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
562 return &window->table; 567 return &window->table;
563} 568}
564 569
570/* A coherent allocation implies strong ordering */
571
572static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
573 dma_addr_t *dma_handle, gfp_t flag)
574{
575 if (iommu_fixed_is_weak)
576 return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
577 size, dma_handle,
578 device_to_mask(dev), flag,
579 dev->archdata.numa_node);
580 else
581 return dma_direct_ops.alloc_coherent(dev, size, dma_handle,
582 flag);
583}
584
585static void dma_fixed_free_coherent(struct device *dev, size_t size,
586 void *vaddr, dma_addr_t dma_handle)
587{
588 if (iommu_fixed_is_weak)
589 iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr,
590 dma_handle);
591 else
592 dma_direct_ops.free_coherent(dev, size, vaddr, dma_handle);
593}
594
595static dma_addr_t dma_fixed_map_single(struct device *dev, void *ptr,
596 size_t size,
597 enum dma_data_direction direction,
598 struct dma_attrs *attrs)
599{
600 if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
601 return dma_direct_ops.map_single(dev, ptr, size, direction,
602 attrs);
603 else
604 return iommu_map_single(dev, cell_get_iommu_table(dev), ptr,
605 size, device_to_mask(dev), direction,
606 attrs);
607}
608
609static void dma_fixed_unmap_single(struct device *dev, dma_addr_t dma_addr,
610 size_t size,
611 enum dma_data_direction direction,
612 struct dma_attrs *attrs)
613{
614 if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
615 dma_direct_ops.unmap_single(dev, dma_addr, size, direction,
616 attrs);
617 else
618 iommu_unmap_single(cell_get_iommu_table(dev), dma_addr, size,
619 direction, attrs);
620}
621
622static int dma_fixed_map_sg(struct device *dev, struct scatterlist *sg,
623 int nents, enum dma_data_direction direction,
624 struct dma_attrs *attrs)
625{
626 if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
627 return dma_direct_ops.map_sg(dev, sg, nents, direction, attrs);
628 else
629 return iommu_map_sg(dev, cell_get_iommu_table(dev), sg, nents,
630 device_to_mask(dev), direction, attrs);
631}
632
633static void dma_fixed_unmap_sg(struct device *dev, struct scatterlist *sg,
634 int nents, enum dma_data_direction direction,
635 struct dma_attrs *attrs)
636{
637 if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
638 dma_direct_ops.unmap_sg(dev, sg, nents, direction, attrs);
639 else
640 iommu_unmap_sg(cell_get_iommu_table(dev), sg, nents, direction,
641 attrs);
642}
643
644static int dma_fixed_dma_supported(struct device *dev, u64 mask)
645{
646 return mask == DMA_64BIT_MASK;
647}
648
649static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
650
651struct dma_mapping_ops dma_iommu_fixed_ops = {
652 .alloc_coherent = dma_fixed_alloc_coherent,
653 .free_coherent = dma_fixed_free_coherent,
654 .map_single = dma_fixed_map_single,
655 .unmap_single = dma_fixed_unmap_single,
656 .map_sg = dma_fixed_map_sg,
657 .unmap_sg = dma_fixed_unmap_sg,
658 .dma_supported = dma_fixed_dma_supported,
659 .set_dma_mask = dma_set_mask_and_switch,
660};
661
565static void cell_dma_dev_setup_fixed(struct device *dev); 662static void cell_dma_dev_setup_fixed(struct device *dev);
566 663
567static void cell_dma_dev_setup(struct device *dev) 664static void cell_dma_dev_setup(struct device *dev)
@@ -918,9 +1015,16 @@ static void cell_iommu_setup_fixed_ptab(struct cbe_iommu *iommu,
918 1015
919 pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase); 1016 pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase);
920 1017
921 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW 1018 base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M
922 | (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask); 1019 | (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask);
923 1020
1021 if (iommu_fixed_is_weak)
1022 pr_info("IOMMU: Using weak ordering for fixed mapping\n");
1023 else {
1024 pr_info("IOMMU: Using strong ordering for fixed mapping\n");
1025 base_pte |= IOPTE_SO_RW;
1026 }
1027
924 for (uaddr = 0; uaddr < fsize; uaddr += (1 << 24)) { 1028 for (uaddr = 0; uaddr < fsize; uaddr += (1 << 24)) {
925 /* Don't touch the dynamic region */ 1029 /* Don't touch the dynamic region */
926 ioaddr = uaddr + fbase; 1030 ioaddr = uaddr + fbase;
@@ -1036,9 +1140,6 @@ static int __init cell_iommu_fixed_mapping_init(void)
1036 cell_iommu_setup_window(iommu, np, dbase, dsize, 0); 1140 cell_iommu_setup_window(iommu, np, dbase, dsize, 0);
1037 } 1141 }
1038 1142
1039 dma_iommu_fixed_ops = dma_direct_ops;
1040 dma_iommu_fixed_ops.set_dma_mask = dma_set_mask_and_switch;
1041
1042 dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch; 1143 dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch;
1043 set_pci_dma_ops(&dma_iommu_ops); 1144 set_pci_dma_ops(&dma_iommu_ops);
1044 1145
@@ -1052,6 +1153,9 @@ static int __init setup_iommu_fixed(char *str)
1052 if (strcmp(str, "off") == 0) 1153 if (strcmp(str, "off") == 0)
1053 iommu_fixed_disabled = 1; 1154 iommu_fixed_disabled = 1;
1054 1155
1156 else if (strcmp(str, "weak") == 0)
1157 iommu_fixed_is_weak = 1;
1158
1055 return 1; 1159 return 1;
1056} 1160}
1057__setup("iommu_fixed=", setup_iommu_fixed); 1161__setup("iommu_fixed=", setup_iommu_fixed);
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 8a3631ce912b..efdacc829576 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -38,8 +38,6 @@
38 38
39#include "pervasive.h" 39#include "pervasive.h"
40 40
41static int sysreset_hack;
42
43static void cbe_power_save(void) 41static void cbe_power_save(void)
44{ 42{
45 unsigned long ctrl, thread_switch_control; 43 unsigned long ctrl, thread_switch_control;
@@ -87,9 +85,6 @@ static void cbe_power_save(void)
87 85
88static int cbe_system_reset_exception(struct pt_regs *regs) 86static int cbe_system_reset_exception(struct pt_regs *regs)
89{ 87{
90 int cpu;
91 struct cbe_pmd_regs __iomem *pmd;
92
93 switch (regs->msr & SRR1_WAKEMASK) { 88 switch (regs->msr & SRR1_WAKEMASK) {
94 case SRR1_WAKEEE: 89 case SRR1_WAKEEE:
95 do_IRQ(regs); 90 do_IRQ(regs);
@@ -98,19 +93,7 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
98 timer_interrupt(regs); 93 timer_interrupt(regs);
99 break; 94 break;
100 case SRR1_WAKEMT: 95 case SRR1_WAKEMT:
101 /* 96 return cbe_sysreset_hack();
102 * The BMC can inject user triggered system reset exceptions,
103 * but cannot set the system reset reason in srr1,
104 * so check an extra register here.
105 */
106 if (sysreset_hack && (cpu = smp_processor_id()) == 0) {
107 pmd = cbe_get_cpu_pmd_regs(cpu);
108 if (in_be64(&pmd->ras_esc_0) & 0xffff) {
109 out_be64(&pmd->ras_esc_0, 0);
110 return 0;
111 }
112 }
113 break;
114#ifdef CONFIG_CBE_RAS 97#ifdef CONFIG_CBE_RAS
115 case SRR1_WAKESYSERR: 98 case SRR1_WAKESYSERR:
116 cbe_system_error_exception(regs); 99 cbe_system_error_exception(regs);
@@ -134,8 +117,6 @@ void __init cbe_pervasive_init(void)
134 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) 117 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
135 return; 118 return;
136 119
137 sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0");
138
139 for_each_possible_cpu(cpu) { 120 for_each_possible_cpu(cpu) {
140 struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu); 121 struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
141 if (!regs) 122 if (!regs)
@@ -144,12 +125,6 @@ void __init cbe_pervasive_init(void)
144 /* Enable Pause(0) control bit */ 125 /* Enable Pause(0) control bit */
145 out_be64(&regs->pmcr, in_be64(&regs->pmcr) | 126 out_be64(&regs->pmcr, in_be64(&regs->pmcr) |
146 CBE_PMD_PAUSE_ZERO_CONTROL); 127 CBE_PMD_PAUSE_ZERO_CONTROL);
147
148 /* Enable JTAG system-reset hack */
149 if (sysreset_hack)
150 out_be32(&regs->fir_mode_reg,
151 in_be32(&regs->fir_mode_reg) |
152 CBE_PMD_FIR_MODE_M8);
153 } 128 }
154 129
155 ppc_md.power_save = cbe_power_save; 130 ppc_md.power_save = cbe_power_save;
diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h
index 7b50947f8044..fd4d7b7092b4 100644
--- a/arch/powerpc/platforms/cell/pervasive.h
+++ b/arch/powerpc/platforms/cell/pervasive.h
@@ -30,4 +30,13 @@ extern void cbe_system_error_exception(struct pt_regs *regs);
30extern void cbe_maintenance_exception(struct pt_regs *regs); 30extern void cbe_maintenance_exception(struct pt_regs *regs);
31extern void cbe_thermal_exception(struct pt_regs *regs); 31extern void cbe_thermal_exception(struct pt_regs *regs);
32 32
33#ifdef CONFIG_PPC_IBM_CELL_RESETBUTTON
34extern int cbe_sysreset_hack(void);
35#else
36static inline int cbe_sysreset_hack(void)
37{
38 return 1;
39}
40#endif /* CONFIG_PPC_IBM_CELL_RESETBUTTON */
41
33#endif 42#endif
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 505f9b9bdf0c..2a14b052abcd 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -236,6 +236,52 @@ static struct notifier_block cbe_ptcal_reboot_notifier = {
236 .notifier_call = cbe_ptcal_notify_reboot 236 .notifier_call = cbe_ptcal_notify_reboot
237}; 237};
238 238
239#ifdef CONFIG_PPC_IBM_CELL_RESETBUTTON
240static int sysreset_hack;
241
242static int __init cbe_sysreset_init(void)
243{
244 struct cbe_pmd_regs __iomem *regs;
245
246 sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0");
247 if (!sysreset_hack)
248 return 0;
249
250 regs = cbe_get_cpu_pmd_regs(0);
251 if (!regs)
252 return 0;
253
254 /* Enable JTAG system-reset hack */
255 out_be32(&regs->fir_mode_reg,
256 in_be32(&regs->fir_mode_reg) |
257 CBE_PMD_FIR_MODE_M8);
258
259 return 0;
260}
261device_initcall(cbe_sysreset_init);
262
263int cbe_sysreset_hack(void)
264{
265 struct cbe_pmd_regs __iomem *regs;
266
267 /*
268 * The BMC can inject user triggered system reset exceptions,
269 * but cannot set the system reset reason in srr1,
270 * so check an extra register here.
271 */
272 if (sysreset_hack && (smp_processor_id() == 0)) {
273 regs = cbe_get_cpu_pmd_regs(0);
274 if (!regs)
275 return 0;
276 if (in_be64(&regs->ras_esc_0) & 0x0000ffff) {
277 out_be64(&regs->ras_esc_0, 0);
278 return 0;
279 }
280 }
281 return 1;
282}
283#endif /* CONFIG_PPC_IBM_CELL_RESETBUTTON */
284
239int __init cbe_ptcal_init(void) 285int __init cbe_ptcal_init(void)
240{ 286{
241 int ret; 287 int ret;