aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSteven J. Hill <Steven.Hill@imgtec.com>2013-03-25 14:47:29 -0400
committerSteven J. Hill <Steven.Hill@imgtec.com>2013-05-01 17:32:49 -0400
commitb6d92b4a6bdb880b39789c677b952c53a437028d (patch)
treef14d30f02314d75860aa1ed12449410e6659513b /arch
parentc34c09c81d659e13e15947580198fa652af3ca1a (diff)
MIPS: Add option to disable software I/O coherency.
Some MIPS controllers have hardware I/O coherency. This patch detects those and turns off software coherency. A new kernel command line option also allows the user to manually turn software coherency on or off. Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/include/asm/dma-coherence.h15
-rw-r--r--arch/mips/include/asm/dma-mapping.h1
-rw-r--r--arch/mips/include/asm/mach-generic/dma-coherence.h5
-rw-r--r--arch/mips/mm/c-r4k.c24
-rw-r--r--arch/mips/mm/dma-default.c25
-rw-r--r--arch/mips/mti-malta/malta-setup.c63
-rw-r--r--arch/mips/mti-sead3/sead3-setup.c3
7 files changed, 112 insertions, 24 deletions
diff --git a/arch/mips/include/asm/dma-coherence.h b/arch/mips/include/asm/dma-coherence.h
new file mode 100644
index 000000000000..242cbb3ca582
--- /dev/null
+++ b/arch/mips/include/asm/dma-coherence.h
@@ -0,0 +1,15 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org>
7 *
8 */
9#ifndef __ASM_DMA_COHERENCE_H
10#define __ASM_DMA_COHERENCE_H
11
12extern int coherentio;
13extern int hw_coherentio;
14
15#endif
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
index f8fc74b6cb47..84238c574d5e 100644
--- a/arch/mips/include/asm/dma-mapping.h
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -2,6 +2,7 @@
2#define _ASM_DMA_MAPPING_H 2#define _ASM_DMA_MAPPING_H
3 3
4#include <asm/scatterlist.h> 4#include <asm/scatterlist.h>
5#include <asm/dma-coherence.h>
5#include <asm/cache.h> 6#include <asm/cache.h>
6#include <asm-generic/dma-coherent.h> 7#include <asm-generic/dma-coherent.h>
7 8
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 9c95177f7a7e..fe23034aaf72 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -61,9 +61,8 @@ static inline int plat_device_is_coherent(struct device *dev)
61{ 61{
62#ifdef CONFIG_DMA_COHERENT 62#ifdef CONFIG_DMA_COHERENT
63 return 1; 63 return 1;
64#endif 64#else
65#ifdef CONFIG_DMA_NONCOHERENT 65 return coherentio;
66 return 0;
67#endif 66#endif
68} 67}
69 68
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 2078915eacb9..f5943ab44987 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -33,6 +33,7 @@
33#include <asm/war.h> 33#include <asm/war.h>
34#include <asm/cacheflush.h> /* for run_uncached() */ 34#include <asm/cacheflush.h> /* for run_uncached() */
35#include <asm/traps.h> 35#include <asm/traps.h>
36#include <asm/dma-coherence.h>
36 37
37/* 38/*
38 * Special Variant of smp_call_function for use by cache functions: 39 * Special Variant of smp_call_function for use by cache functions:
@@ -1377,20 +1378,6 @@ static void __cpuinit coherency_setup(void)
1377 } 1378 }
1378} 1379}
1379 1380
1380#if defined(CONFIG_DMA_NONCOHERENT)
1381
1382static int __cpuinitdata coherentio;
1383
1384static int __init setcoherentio(char *str)
1385{
1386 coherentio = 1;
1387
1388 return 0;
1389}
1390
1391early_param("coherentio", setcoherentio);
1392#endif
1393
1394static void __cpuinit r4k_cache_error_setup(void) 1381static void __cpuinit r4k_cache_error_setup(void)
1395{ 1382{
1396 extern char __weak except_vec2_generic; 1383 extern char __weak except_vec2_generic;
@@ -1472,9 +1459,14 @@ void __cpuinit r4k_cache_init(void)
1472 1459
1473 build_clear_page(); 1460 build_clear_page();
1474 build_copy_page(); 1461 build_copy_page();
1475#if !defined(CONFIG_MIPS_CMP) 1462
1463 /*
1464 * We want to run CMP kernels on core with and without coherent
1465 * caches. Therefore, do not use CONFIG_MIPS_CMP to decide whether
1466 * or not to flush caches.
1467 */
1476 local_r4k___flush_cache_all(NULL); 1468 local_r4k___flush_cache_all(NULL);
1477#endif 1469
1478 coherency_setup(); 1470 coherency_setup();
1479 board_cache_error_setup = r4k_cache_error_setup; 1471 board_cache_error_setup = r4k_cache_error_setup;
1480} 1472}
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index f9ef83829a52..caf92ecb37d6 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -22,6 +22,26 @@
22 22
23#include <dma-coherence.h> 23#include <dma-coherence.h>
24 24
25int coherentio = 0; /* User defined DMA coherency from command line. */
26EXPORT_SYMBOL_GPL(coherentio);
27int hw_coherentio = 0; /* Actual hardware supported DMA coherency setting. */
28
29static int __init setcoherentio(char *str)
30{
31 coherentio = 1;
32 pr_info("Hardware DMA cache coherency (command line)\n");
33 return 0;
34}
35early_param("coherentio", setcoherentio);
36
37static int __init setnocoherentio(char *str)
38{
39 coherentio = 0;
40 pr_info("Software DMA cache coherency (command line)\n");
41 return 0;
42}
43early_param("nocoherentio", setnocoherentio);
44
25static inline struct page *dma_addr_to_page(struct device *dev, 45static inline struct page *dma_addr_to_page(struct device *dev,
26 dma_addr_t dma_addr) 46 dma_addr_t dma_addr)
27{ 47{
@@ -115,7 +135,8 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
115 135
116 if (!plat_device_is_coherent(dev)) { 136 if (!plat_device_is_coherent(dev)) {
117 dma_cache_wback_inv((unsigned long) ret, size); 137 dma_cache_wback_inv((unsigned long) ret, size);
118 ret = UNCAC_ADDR(ret); 138 if (!hw_coherentio)
139 ret = UNCAC_ADDR(ret);
119 } 140 }
120 } 141 }
121 142
@@ -142,7 +163,7 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
142 163
143 plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL); 164 plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
144 165
145 if (!plat_device_is_coherent(dev)) 166 if (!plat_device_is_coherent(dev) && !hw_coherentio)
146 addr = CAC_ADDR(addr); 167 addr = CAC_ADDR(addr);
147 168
148 free_pages(addr, get_order(size)); 169 free_pages(addr, get_order(size));
diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c
index 200f64df2c9b..a85557171faa 100644
--- a/arch/mips/mti-malta/malta-setup.c
+++ b/arch/mips/mti-malta/malta-setup.c
@@ -32,6 +32,7 @@
32#include <asm/mips-boards/maltaint.h> 32#include <asm/mips-boards/maltaint.h>
33#include <asm/dma.h> 33#include <asm/dma.h>
34#include <asm/traps.h> 34#include <asm/traps.h>
35#include <asm/gcmpregs.h>
35#ifdef CONFIG_VT 36#ifdef CONFIG_VT
36#include <linux/console.h> 37#include <linux/console.h>
37#endif 38#endif
@@ -105,6 +106,66 @@ static void __init fd_activate(void)
105} 106}
106#endif 107#endif
107 108
109static int __init plat_enable_iocoherency(void)
110{
111 int supported = 0;
112 if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
113 if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
114 BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
115 pr_info("Enabled Bonito CPU coherency\n");
116 supported = 1;
117 }
118 if (strstr(fw_getcmdline(), "iobcuncached")) {
119 BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
120 BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
121 ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
122 BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
123 pr_info("Disabled Bonito IOBC coherency\n");
124 } else {
125 BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
126 BONITO_PCIMEMBASECFG |=
127 (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
128 BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
129 pr_info("Enabled Bonito IOBC coherency\n");
130 }
131 } else if (gcmp_niocu() != 0) {
132 /* Nothing special needs to be done to enable coherency */
133 pr_info("CMP IOCU detected\n");
134 if ((*(unsigned int *)0xbf403000 & 0x81) != 0x81) {
135 pr_crit("IOCU OPERATION DISABLED BY SWITCH - DEFAULTING TO SW IO COHERENCY\n");
136 return 0;
137 }
138 supported = 1;
139 }
140 hw_coherentio = supported;
141 return supported;
142}
143
144static void __init plat_setup_iocoherency(void)
145{
146#ifdef CONFIG_DMA_NONCOHERENT
147 /*
148 * Kernel has been configured with software coherency
149 * but we might choose to turn it off and use hardware
150 * coherency instead.
151 */
152 if (plat_enable_iocoherency()) {
153 if (coherentio == 0)
154 pr_info("Hardware DMA cache coherency disabled\n");
155 else
156 pr_info("Hardware DMA cache coherency enabled\n");
157 } else {
158 if (coherentio == 1)
159 pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n");
160 else
161 pr_info("Software DMA cache coherency enabled\n");
162 }
163#else
164 if (!plat_enable_iocoherency())
165 panic("Hardware DMA cache coherency not supported!");
166#endif
167}
168
108#ifdef CONFIG_BLK_DEV_IDE 169#ifdef CONFIG_BLK_DEV_IDE
109static void __init pci_clock_check(void) 170static void __init pci_clock_check(void)
110{ 171{
@@ -207,6 +268,8 @@ void __init plat_mem_setup(void)
207 if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) 268 if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO)
208 bonito_quirks_setup(); 269 bonito_quirks_setup();
209 270
271 plat_setup_iocoherency();
272
210#ifdef CONFIG_BLK_DEV_IDE 273#ifdef CONFIG_BLK_DEV_IDE
211 pci_clock_check(); 274 pci_clock_check();
212#endif 275#endif
diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c
index f012fd164cee..14633bc80049 100644
--- a/arch/mips/mti-sead3/sead3-setup.c
+++ b/arch/mips/mti-sead3/sead3-setup.c
@@ -13,9 +13,6 @@
13#include <asm/mips-boards/generic.h> 13#include <asm/mips-boards/generic.h>
14#include <asm/prom.h> 14#include <asm/prom.h>
15 15
16int coherentio; /* 0 => no DMA cache coherency (may be set by user) */
17int hw_coherentio; /* 0 => no HW DMA cache coherency (reflects real HW) */
18
19const char *get_system_type(void) 16const char *get_system_type(void)
20{ 17{
21 return "MIPS SEAD3"; 18 return "MIPS SEAD3";