forked from luck/tmp_suning_uos_patched
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>
This commit is contained in:
parent
c34c09c81d
commit
b6d92b4a6b
15
arch/mips/include/asm/dma-coherence.h
Normal file
15
arch/mips/include/asm/dma-coherence.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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 @@
|
|||
#define _ASM_DMA_MAPPING_H
|
||||
|
||||
#include <asm/scatterlist.h>
|
||||
#include <asm/dma-coherence.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm-generic/dma-coherent.h>
|
||||
|
||||
|
|
|
@ -61,9 +61,8 @@ static inline int plat_device_is_coherent(struct device *dev)
|
|||
{
|
||||
#ifdef CONFIG_DMA_COHERENT
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef CONFIG_DMA_NONCOHERENT
|
||||
return 0;
|
||||
#else
|
||||
return coherentio;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <asm/war.h>
|
||||
#include <asm/cacheflush.h> /* for run_uncached() */
|
||||
#include <asm/traps.h>
|
||||
#include <asm/dma-coherence.h>
|
||||
|
||||
/*
|
||||
* Special Variant of smp_call_function for use by cache functions:
|
||||
|
@ -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)
|
||||
{
|
||||
extern char __weak except_vec2_generic;
|
||||
|
@ -1472,9 +1459,14 @@ void __cpuinit r4k_cache_init(void)
|
|||
|
||||
build_clear_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);
|
||||
#endif
|
||||
|
||||
coherency_setup();
|
||||
board_cache_error_setup = r4k_cache_error_setup;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,26 @@
|
|||
|
||||
#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,
|
||||
dma_addr_t dma_addr)
|
||||
{
|
||||
|
@ -115,6 +135,7 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
|
|||
|
||||
if (!plat_device_is_coherent(dev)) {
|
||||
dma_cache_wback_inv((unsigned long) ret, size);
|
||||
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,
|
|||
|
||||
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);
|
||||
|
||||
free_pages(addr, get_order(size));
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <asm/mips-boards/maltaint.h>
|
||||
#include <asm/dma.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/gcmpregs.h>
|
||||
#ifdef CONFIG_VT
|
||||
#include <linux/console.h>
|
||||
#endif
|
||||
|
@ -105,6 +106,66 @@ static void __init fd_activate(void)
|
|||
}
|
||||
#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
|
||||
static void __init pci_clock_check(void)
|
||||
{
|
||||
|
@ -207,6 +268,8 @@ void __init plat_mem_setup(void)
|
|||
if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO)
|
||||
bonito_quirks_setup();
|
||||
|
||||
plat_setup_iocoherency();
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_IDE
|
||||
pci_clock_check();
|
||||
#endif
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
#include <asm/mips-boards/generic.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)
|
||||
{
|
||||
return "MIPS SEAD3";
|
||||
|
|
Loading…
Reference in New Issue
Block a user