提交 b6d92b4a 编写于 作者: S Steven J. Hill

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: NSteven J. Hill <Steven.Hill@imgtec.com>
上级 c34c09c8
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org>
*
*/
#ifndef __ASM_DMA_COHERENCE_H
#define __ASM_DMA_COHERENCE_H
extern int coherentio;
extern int hw_coherentio;
#endif
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _ASM_DMA_MAPPING_H #define _ASM_DMA_MAPPING_H
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
#include <asm/dma-coherence.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm-generic/dma-coherent.h> #include <asm-generic/dma-coherent.h>
......
...@@ -61,9 +61,8 @@ static inline int plat_device_is_coherent(struct device *dev) ...@@ -61,9 +61,8 @@ static inline int plat_device_is_coherent(struct device *dev)
{ {
#ifdef CONFIG_DMA_COHERENT #ifdef CONFIG_DMA_COHERENT
return 1; return 1;
#endif #else
#ifdef CONFIG_DMA_NONCOHERENT return coherentio;
return 0;
#endif #endif
} }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <asm/war.h> #include <asm/war.h>
#include <asm/cacheflush.h> /* for run_uncached() */ #include <asm/cacheflush.h> /* for run_uncached() */
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/dma-coherence.h>
/* /*
* Special Variant of smp_call_function for use by cache functions: * Special Variant of smp_call_function for use by cache functions:
...@@ -1377,20 +1378,6 @@ static void __cpuinit coherency_setup(void) ...@@ -1377,20 +1378,6 @@ static void __cpuinit coherency_setup(void)
} }
} }
#if defined(CONFIG_DMA_NONCOHERENT)
static int __cpuinitdata coherentio;
static int __init setcoherentio(char *str)
{
coherentio = 1;
return 0;
}
early_param("coherentio", setcoherentio);
#endif
static void __cpuinit r4k_cache_error_setup(void) static void __cpuinit r4k_cache_error_setup(void)
{ {
extern char __weak except_vec2_generic; extern char __weak except_vec2_generic;
...@@ -1472,9 +1459,14 @@ void __cpuinit r4k_cache_init(void) ...@@ -1472,9 +1459,14 @@ void __cpuinit r4k_cache_init(void)
build_clear_page(); build_clear_page();
build_copy_page(); build_copy_page();
#if !defined(CONFIG_MIPS_CMP)
/*
* We want to run CMP kernels on core with and without coherent
* caches. Therefore, do not use CONFIG_MIPS_CMP to decide whether
* or not to flush caches.
*/
local_r4k___flush_cache_all(NULL); local_r4k___flush_cache_all(NULL);
#endif
coherency_setup(); coherency_setup();
board_cache_error_setup = r4k_cache_error_setup; board_cache_error_setup = r4k_cache_error_setup;
} }
...@@ -22,6 +22,26 @@ ...@@ -22,6 +22,26 @@
#include <dma-coherence.h> #include <dma-coherence.h>
int coherentio = 0; /* User defined DMA coherency from command line. */
EXPORT_SYMBOL_GPL(coherentio);
int hw_coherentio = 0; /* Actual hardware supported DMA coherency setting. */
static int __init setcoherentio(char *str)
{
coherentio = 1;
pr_info("Hardware DMA cache coherency (command line)\n");
return 0;
}
early_param("coherentio", setcoherentio);
static int __init setnocoherentio(char *str)
{
coherentio = 0;
pr_info("Software DMA cache coherency (command line)\n");
return 0;
}
early_param("nocoherentio", setnocoherentio);
static inline struct page *dma_addr_to_page(struct device *dev, static inline struct page *dma_addr_to_page(struct device *dev,
dma_addr_t dma_addr) dma_addr_t dma_addr)
{ {
...@@ -115,7 +135,8 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size, ...@@ -115,7 +135,8 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
if (!plat_device_is_coherent(dev)) { if (!plat_device_is_coherent(dev)) {
dma_cache_wback_inv((unsigned long) ret, size); dma_cache_wback_inv((unsigned long) ret, size);
ret = UNCAC_ADDR(ret); if (!hw_coherentio)
ret = UNCAC_ADDR(ret);
} }
} }
...@@ -142,7 +163,7 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr, ...@@ -142,7 +163,7 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL); plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
if (!plat_device_is_coherent(dev)) if (!plat_device_is_coherent(dev) && !hw_coherentio)
addr = CAC_ADDR(addr); addr = CAC_ADDR(addr);
free_pages(addr, get_order(size)); free_pages(addr, get_order(size));
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <asm/mips-boards/maltaint.h> #include <asm/mips-boards/maltaint.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/gcmpregs.h>
#ifdef CONFIG_VT #ifdef CONFIG_VT
#include <linux/console.h> #include <linux/console.h>
#endif #endif
...@@ -105,6 +106,66 @@ static void __init fd_activate(void) ...@@ -105,6 +106,66 @@ static void __init fd_activate(void)
} }
#endif #endif
static int __init plat_enable_iocoherency(void)
{
int supported = 0;
if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
pr_info("Enabled Bonito CPU coherency\n");
supported = 1;
}
if (strstr(fw_getcmdline(), "iobcuncached")) {
BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
pr_info("Disabled Bonito IOBC coherency\n");
} else {
BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
BONITO_PCIMEMBASECFG |=
(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
pr_info("Enabled Bonito IOBC coherency\n");
}
} else if (gcmp_niocu() != 0) {
/* Nothing special needs to be done to enable coherency */
pr_info("CMP IOCU detected\n");
if ((*(unsigned int *)0xbf403000 & 0x81) != 0x81) {
pr_crit("IOCU OPERATION DISABLED BY SWITCH - DEFAULTING TO SW IO COHERENCY\n");
return 0;
}
supported = 1;
}
hw_coherentio = supported;
return supported;
}
static void __init plat_setup_iocoherency(void)
{
#ifdef CONFIG_DMA_NONCOHERENT
/*
* Kernel has been configured with software coherency
* but we might choose to turn it off and use hardware
* coherency instead.
*/
if (plat_enable_iocoherency()) {
if (coherentio == 0)
pr_info("Hardware DMA cache coherency disabled\n");
else
pr_info("Hardware DMA cache coherency enabled\n");
} else {
if (coherentio == 1)
pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n");
else
pr_info("Software DMA cache coherency enabled\n");
}
#else
if (!plat_enable_iocoherency())
panic("Hardware DMA cache coherency not supported!");
#endif
}
#ifdef CONFIG_BLK_DEV_IDE #ifdef CONFIG_BLK_DEV_IDE
static void __init pci_clock_check(void) static void __init pci_clock_check(void)
{ {
...@@ -207,6 +268,8 @@ void __init plat_mem_setup(void) ...@@ -207,6 +268,8 @@ void __init plat_mem_setup(void)
if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO)
bonito_quirks_setup(); bonito_quirks_setup();
plat_setup_iocoherency();
#ifdef CONFIG_BLK_DEV_IDE #ifdef CONFIG_BLK_DEV_IDE
pci_clock_check(); pci_clock_check();
#endif #endif
......
...@@ -13,9 +13,6 @@ ...@@ -13,9 +13,6 @@
#include <asm/mips-boards/generic.h> #include <asm/mips-boards/generic.h>
#include <asm/prom.h> #include <asm/prom.h>
int coherentio; /* 0 => no DMA cache coherency (may be set by user) */
int hw_coherentio; /* 0 => no HW DMA cache coherency (reflects real HW) */
const char *get_system_type(void) const char *get_system_type(void)
{ {
return "MIPS SEAD3"; return "MIPS SEAD3";
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册