mirror of
				https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
				synced 2025-11-04 08:34:47 +10:00 
			
		
		
		
	Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (45 commits) [MIPS] Pb1200/DBAu1200: move platform code to its proper place [MIPS] Fix handling of trap and breakpoint instructions [MIPS] Pb1200: do register SMC 91C111 [MIPS] DBAu1200: fix bad SMC 91C111 resource size [NET] Kconfig: Rename MIKROTIK_RB500 -> MIKROTIK_RB532 [MIPS] IP27: Fix build bug due to missing include [MIPS] Fix some sparse warnings on traps.c and irq-msc01.c [MIPS] cevt-gt641xx: Kill unnecessary include [MIPS] DS1287: Add clockevent driver [MIPS] add DECstation I/O ASIC clocksource [MIPS] rbtx4938: minor cleanup [MIPS] Alchemy: kill unused PCI_IRQ_TABLE_LOOKUP macro [MIPS] rbtx4938: misc cleanups [MIPS] jmr3927: use generic txx9 gpio [MIPS] rbhma4500: use generic txx9 gpio [MIPS] generic txx9 gpio support [MIPS] make fallback gpio.h gpiolib-friendly [MIPS] unexport null_perf_irq() and make it static [MIPS] unexport rtc_mips_set_time() [MIPS] unexport copy_from_user_page() ...
This commit is contained in:
		
						commit
						e31a94ed37
					
				@ -81,7 +81,9 @@ config MIPS_COBALT
 | 
			
		||||
config MACH_DECSTATION
 | 
			
		||||
	bool "DECstations"
 | 
			
		||||
	select BOOT_ELF32
 | 
			
		||||
	select CEVT_DS1287
 | 
			
		||||
	select CEVT_R4K
 | 
			
		||||
	select CSRC_IOASIC
 | 
			
		||||
	select CSRC_R4K
 | 
			
		||||
	select CPU_DADDI_WORKAROUNDS if 64BIT
 | 
			
		||||
	select CPU_R4000_WORKAROUNDS if 64BIT
 | 
			
		||||
@ -221,6 +223,7 @@ config MIPS_MALTA
 | 
			
		||||
	select DMA_NONCOHERENT
 | 
			
		||||
	select GENERIC_ISA_DMA
 | 
			
		||||
	select IRQ_CPU
 | 
			
		||||
	select IRQ_GIC
 | 
			
		||||
	select HW_HAS_PCI
 | 
			
		||||
	select I8253
 | 
			
		||||
	select I8259
 | 
			
		||||
@ -309,12 +312,12 @@ config MACH_VR41XX
 | 
			
		||||
	select GENERIC_HARDIRQS_NO__DO_IRQ
 | 
			
		||||
 | 
			
		||||
config PNX8550_JBS
 | 
			
		||||
	bool "Philips PNX8550 based JBS board"
 | 
			
		||||
	bool "NXP PNX8550 based JBS board"
 | 
			
		||||
	select PNX8550
 | 
			
		||||
	select SYS_SUPPORTS_LITTLE_ENDIAN
 | 
			
		||||
 | 
			
		||||
config PNX8550_STB810
 | 
			
		||||
	bool "Philips PNX8550 based STB810 board"
 | 
			
		||||
	bool "NXP PNX8550 based STB810 board"
 | 
			
		||||
	select PNX8550
 | 
			
		||||
	select SYS_SUPPORTS_LITTLE_ENDIAN
 | 
			
		||||
 | 
			
		||||
@ -612,6 +615,7 @@ config TOSHIBA_JMR3927
 | 
			
		||||
	select SYS_SUPPORTS_LITTLE_ENDIAN
 | 
			
		||||
	select SYS_SUPPORTS_BIG_ENDIAN
 | 
			
		||||
	select GENERIC_HARDIRQS_NO__DO_IRQ
 | 
			
		||||
	select GPIO_TXX9
 | 
			
		||||
 | 
			
		||||
config TOSHIBA_RBTX4927
 | 
			
		||||
	bool "Toshiba RBTX49[23]7 board"
 | 
			
		||||
@ -653,7 +657,7 @@ config TOSHIBA_RBTX4938
 | 
			
		||||
	select SYS_SUPPORTS_BIG_ENDIAN
 | 
			
		||||
	select SYS_SUPPORTS_KGDB
 | 
			
		||||
	select GENERIC_HARDIRQS_NO__DO_IRQ
 | 
			
		||||
	select GENERIC_GPIO
 | 
			
		||||
	select GPIO_TXX9
 | 
			
		||||
	help
 | 
			
		||||
	  This Toshiba board is based on the TX4938 processor. Say Y here to
 | 
			
		||||
	  support this machine type
 | 
			
		||||
@ -767,6 +771,9 @@ config BOOT_RAW
 | 
			
		||||
config CEVT_BCM1480
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config CEVT_DS1287
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config CEVT_GT641XX
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
@ -782,12 +789,20 @@ config CEVT_TXX9
 | 
			
		||||
config CSRC_BCM1480
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config CSRC_IOASIC
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config CSRC_R4K
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config CSRC_SB1250
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config GPIO_TXX9
 | 
			
		||||
	select GENERIC_GPIO
 | 
			
		||||
	select HAVE_GPIO_LIB
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config CFE
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
@ -840,6 +855,9 @@ config MIPS_NILE4
 | 
			
		||||
config MIPS_DISABLE_OBSOLETE_IDE
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config SYNC_R4K
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config NO_IOPORT
 | 
			
		||||
	def_bool n
 | 
			
		||||
 | 
			
		||||
@ -909,6 +927,9 @@ config IRQ_TXX9
 | 
			
		||||
config IRQ_GT641XX
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config IRQ_GIC
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
config MIPS_BOARDS_GEN
 | 
			
		||||
	bool
 | 
			
		||||
 | 
			
		||||
@ -1811,6 +1832,17 @@ config NR_CPUS
 | 
			
		||||
	  performance should round up your number of processors to the next
 | 
			
		||||
	  power of two.
 | 
			
		||||
 | 
			
		||||
config MIPS_CMP
 | 
			
		||||
	bool "MIPS CMP framework support"
 | 
			
		||||
	depends on SMP
 | 
			
		||||
	select SYNC_R4K
 | 
			
		||||
	select SYS_SUPPORTS_SCHED_SMT
 | 
			
		||||
	select WEAK_ORDERING
 | 
			
		||||
	default n
 | 
			
		||||
	help
 | 
			
		||||
	  This is a placeholder option for the GCMP work. It will need to
 | 
			
		||||
	  be handled differently...
 | 
			
		||||
 | 
			
		||||
source "kernel/time/Kconfig"
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
@ -73,14 +73,4 @@ config RUNTIME_DEBUG
 | 
			
		||||
	  include/asm-mips/debug.h for debuging macros.
 | 
			
		||||
	  If unsure, say N.
 | 
			
		||||
 | 
			
		||||
config MIPS_UNCACHED
 | 
			
		||||
	bool "Run uncached"
 | 
			
		||||
	depends on DEBUG_KERNEL && !SMP && !SGI_IP27
 | 
			
		||||
	help
 | 
			
		||||
	  If you say Y here there kernel will disable all CPU caches.  This will
 | 
			
		||||
	  reduce the system's performance dramatically but can help finding
 | 
			
		||||
	  otherwise hard to track bugs.  It can also useful if you're doing
 | 
			
		||||
	  hardware debugging with a logic analyzer and need to see all traffic
 | 
			
		||||
	  on the bus.
 | 
			
		||||
 | 
			
		||||
endmenu
 | 
			
		||||
 | 
			
		||||
@ -410,21 +410,21 @@ load-$(CONFIG_CASIO_E55)	+= 0xffffffff80004000
 | 
			
		||||
load-$(CONFIG_TANBAC_TB022X)	+= 0xffffffff80000000
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Common Philips PNX8550
 | 
			
		||||
# Common NXP PNX8550
 | 
			
		||||
#
 | 
			
		||||
core-$(CONFIG_SOC_PNX8550)	+= arch/mips/philips/pnx8550/common/
 | 
			
		||||
core-$(CONFIG_SOC_PNX8550)	+= arch/mips/nxp/pnx8550/common/
 | 
			
		||||
cflags-$(CONFIG_SOC_PNX8550)	+= -Iinclude/asm-mips/mach-pnx8550
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Philips PNX8550 JBS board
 | 
			
		||||
# NXP PNX8550 JBS board
 | 
			
		||||
#
 | 
			
		||||
libs-$(CONFIG_PNX8550_JBS)	+= arch/mips/philips/pnx8550/jbs/
 | 
			
		||||
libs-$(CONFIG_PNX8550_JBS)	+= arch/mips/nxp/pnx8550/jbs/
 | 
			
		||||
#cflags-$(CONFIG_PNX8550_JBS)	+= -Iinclude/asm-mips/mach-pnx8550
 | 
			
		||||
load-$(CONFIG_PNX8550_JBS)	+= 0xffffffff80060000
 | 
			
		||||
 | 
			
		||||
# Philips PNX8550 STB810 board
 | 
			
		||||
# NXP PNX8550 STB810 board
 | 
			
		||||
#
 | 
			
		||||
libs-$(CONFIG_PNX8550_STB810)	+= arch/mips/philips/pnx8550/stb810/
 | 
			
		||||
libs-$(CONFIG_PNX8550_STB810)	+= arch/mips/nxp/pnx8550/stb810/
 | 
			
		||||
load-$(CONFIG_PNX8550_STB810)	+= 0xffffffff80060000
 | 
			
		||||
 | 
			
		||||
# NEC EMMA2RH boards
 | 
			
		||||
 | 
			
		||||
@ -11,10 +11,7 @@
 | 
			
		||||
 *  as published by the Free Software Foundation; either version
 | 
			
		||||
 *  2 of the License, or (at your option) any later version.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/threads.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
struct cpu_spec* cur_cpu_spec[NR_CPUS];
 | 
			
		||||
 | 
			
		||||
@ -31,18 +31,12 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1xxx_dbdma.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_KGDB
 | 
			
		||||
@ -55,8 +54,7 @@ typedef         unsigned int  uint32;
 | 
			
		||||
#define UART16550_READ(y)    (au_readl(DEBUG_BASE + y) & 0xff)
 | 
			
		||||
#define UART16550_WRITE(y, z) (au_writel(z&0xff, DEBUG_BASE + y))
 | 
			
		||||
 | 
			
		||||
extern unsigned long get_au1x00_uart_baud_base(void);
 | 
			
		||||
extern unsigned long cal_r4koff(void);
 | 
			
		||||
extern unsigned long calc_clock(void);
 | 
			
		||||
 | 
			
		||||
void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
 | 
			
		||||
{
 | 
			
		||||
@ -64,7 +62,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
 | 
			
		||||
	if (UART16550_READ(UART_MOD_CNTRL) != 0x3) {
 | 
			
		||||
		UART16550_WRITE(UART_MOD_CNTRL, 3);
 | 
			
		||||
	}
 | 
			
		||||
	cal_r4koff();
 | 
			
		||||
	calc_clock();
 | 
			
		||||
 | 
			
		||||
	/* disable interrupts */
 | 
			
		||||
	UART16550_WRITE(UART_IER, 0);
 | 
			
		||||
 | 
			
		||||
@ -33,12 +33,9 @@
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000_dma.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,13 +27,8 @@
 | 
			
		||||
 * 	others have a second one : GPIO2
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
#include <asm/gpio.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2001 MontaVista Software Inc.
 | 
			
		||||
 * Author: MontaVista Software, Inc.
 | 
			
		||||
 *		ppopov@mvista.com or source@mvista.com
 | 
			
		||||
 * Copyright 2001, 2007-2008 MontaVista Software Inc.
 | 
			
		||||
 * Author: MontaVista Software, Inc. <source@mvista.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
 | 
			
		||||
 *
 | 
			
		||||
@ -27,7 +26,6 @@
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
 | 
			
		||||
@ -591,7 +589,7 @@ void __init arch_init_irq(void)
 | 
			
		||||
		imp++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	set_c0_status(ALLINTS);
 | 
			
		||||
	set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
 | 
			
		||||
 | 
			
		||||
	/* Board specific IRQ initialization.
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/pci.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
@ -3,18 +3,65 @@
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
 | 
			
		||||
 *
 | 
			
		||||
 * (C) Copyright Embedded Alley Solutions, Inc 2005
 | 
			
		||||
 * Author: Pantelis Antoniou <pantelis@embeddedalley.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This file is licensed under the terms of the GNU General Public
 | 
			
		||||
 * License version 2.  This program is licensed "as is" without any
 | 
			
		||||
 * warranty of any kind, whether express or implied.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/device.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/platform_device.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/serial_8250.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/resource.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1xxx.h>
 | 
			
		||||
 | 
			
		||||
#define PORT(_base, _irq)				\
 | 
			
		||||
	{						\
 | 
			
		||||
		.iobase		= _base,		\
 | 
			
		||||
		.membase	= (void __iomem *)_base,\
 | 
			
		||||
		.mapbase	= CPHYSADDR(_base),	\
 | 
			
		||||
		.irq		= _irq,			\
 | 
			
		||||
		.regshift	= 2,			\
 | 
			
		||||
		.iotype		= UPIO_AU,		\
 | 
			
		||||
		.flags		= UPF_SKIP_TEST 	\
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
static struct plat_serial8250_port au1x00_uart_data[] = {
 | 
			
		||||
#if defined(CONFIG_SERIAL_8250_AU1X00)
 | 
			
		||||
#if defined(CONFIG_SOC_AU1000)
 | 
			
		||||
	PORT(UART0_ADDR, AU1000_UART0_INT),
 | 
			
		||||
	PORT(UART1_ADDR, AU1000_UART1_INT),
 | 
			
		||||
	PORT(UART2_ADDR, AU1000_UART2_INT),
 | 
			
		||||
	PORT(UART3_ADDR, AU1000_UART3_INT),
 | 
			
		||||
#elif defined(CONFIG_SOC_AU1500)
 | 
			
		||||
	PORT(UART0_ADDR, AU1500_UART0_INT),
 | 
			
		||||
	PORT(UART3_ADDR, AU1500_UART3_INT),
 | 
			
		||||
#elif defined(CONFIG_SOC_AU1100)
 | 
			
		||||
	PORT(UART0_ADDR, AU1100_UART0_INT),
 | 
			
		||||
	PORT(UART1_ADDR, AU1100_UART1_INT),
 | 
			
		||||
	PORT(UART3_ADDR, AU1100_UART3_INT),
 | 
			
		||||
#elif defined(CONFIG_SOC_AU1550)
 | 
			
		||||
	PORT(UART0_ADDR, AU1550_UART0_INT),
 | 
			
		||||
	PORT(UART1_ADDR, AU1550_UART1_INT),
 | 
			
		||||
	PORT(UART3_ADDR, AU1550_UART3_INT),
 | 
			
		||||
#elif defined(CONFIG_SOC_AU1200)
 | 
			
		||||
	PORT(UART0_ADDR, AU1200_UART0_INT),
 | 
			
		||||
	PORT(UART1_ADDR, AU1200_UART1_INT),
 | 
			
		||||
#endif
 | 
			
		||||
#endif	/* CONFIG_SERIAL_8250_AU1X00 */
 | 
			
		||||
	{ },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct platform_device au1xx0_uart_device = {
 | 
			
		||||
	.name			= "serial8250",
 | 
			
		||||
	.id			= PLAT8250_DEV_AU1X00,
 | 
			
		||||
	.dev			= {
 | 
			
		||||
		.platform_data	= au1x00_uart_data,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* OHCI (USB full speed host controller) */
 | 
			
		||||
static struct resource au1xxx_usb_ohci_resources[] = {
 | 
			
		||||
	[0] = {
 | 
			
		||||
@ -186,19 +233,6 @@ static struct resource au1200_lcd_resources[] = {
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct resource au1200_ide0_resources[] = {
 | 
			
		||||
	[0] = {
 | 
			
		||||
		.start		= AU1XXX_ATA_PHYS_ADDR,
 | 
			
		||||
		.end 		= AU1XXX_ATA_PHYS_ADDR + AU1XXX_ATA_PHYS_LEN - 1,
 | 
			
		||||
		.flags		= IORESOURCE_MEM,
 | 
			
		||||
	},
 | 
			
		||||
	[1] = {
 | 
			
		||||
		.start		= AU1XXX_ATA_INT,
 | 
			
		||||
		.end		= AU1XXX_ATA_INT,
 | 
			
		||||
		.flags		= IORESOURCE_IRQ,
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static u64 au1200_lcd_dmamask = ~(u32)0;
 | 
			
		||||
 | 
			
		||||
static struct platform_device au1200_lcd_device = {
 | 
			
		||||
@ -212,20 +246,6 @@ static struct platform_device au1200_lcd_device = {
 | 
			
		||||
	.resource       = au1200_lcd_resources,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static u64 ide0_dmamask = ~(u32)0;
 | 
			
		||||
 | 
			
		||||
static struct platform_device au1200_ide0_device = {
 | 
			
		||||
	.name		= "au1200-ide",
 | 
			
		||||
	.id		= 0,
 | 
			
		||||
	.dev = {
 | 
			
		||||
		.dma_mask 		= &ide0_dmamask,
 | 
			
		||||
		.coherent_dma_mask	= 0xffffffff,
 | 
			
		||||
	},
 | 
			
		||||
	.num_resources = ARRAY_SIZE(au1200_ide0_resources),
 | 
			
		||||
	.resource	= au1200_ide0_resources,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static u64 au1xxx_mmc_dmamask =  ~(u32)0;
 | 
			
		||||
 | 
			
		||||
static struct platform_device au1xxx_mmc_device = {
 | 
			
		||||
@ -245,31 +265,6 @@ static struct platform_device au1x00_pcmcia_device = {
 | 
			
		||||
	.id 		= 0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_DB1200
 | 
			
		||||
 | 
			
		||||
static struct resource smc91x_resources[] = {
 | 
			
		||||
	[0] = {
 | 
			
		||||
		.name	= "smc91x-regs",
 | 
			
		||||
		.start	= AU1XXX_SMC91111_PHYS_ADDR,
 | 
			
		||||
		.end	= AU1XXX_SMC91111_PHYS_ADDR + 0xfffff,
 | 
			
		||||
		.flags	= IORESOURCE_MEM,
 | 
			
		||||
	},
 | 
			
		||||
	[1] = {
 | 
			
		||||
		.start	= AU1XXX_SMC91111_IRQ,
 | 
			
		||||
		.end	= AU1XXX_SMC91111_IRQ,
 | 
			
		||||
		.flags	= IORESOURCE_IRQ,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct platform_device smc91x_device = {
 | 
			
		||||
	.name		= "smc91x",
 | 
			
		||||
	.id		= -1,
 | 
			
		||||
	.num_resources	= ARRAY_SIZE(smc91x_resources),
 | 
			
		||||
	.resource	= smc91x_resources,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* All Alchemy demoboards with I2C have this #define in their headers */
 | 
			
		||||
#ifdef SMBUS_PSC_BASE
 | 
			
		||||
static struct resource pbdb_smbus_resources[] = {
 | 
			
		||||
@ -289,6 +284,7 @@ static struct platform_device pbdb_smbus_device = {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static struct platform_device *au1xxx_platform_devices[] __initdata = {
 | 
			
		||||
	&au1xx0_uart_device,
 | 
			
		||||
	&au1xxx_usb_ohci_device,
 | 
			
		||||
	&au1x00_pcmcia_device,
 | 
			
		||||
#ifdef CONFIG_FB_AU1100
 | 
			
		||||
@ -299,12 +295,8 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = {
 | 
			
		||||
	&au1xxx_usb_gdt_device,
 | 
			
		||||
	&au1xxx_usb_otg_device,
 | 
			
		||||
	&au1200_lcd_device,
 | 
			
		||||
	&au1200_ide0_device,
 | 
			
		||||
	&au1xxx_mmc_device,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_MIPS_DB1200
 | 
			
		||||
	&smc91x_device,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SMBUS_PSC_BASE
 | 
			
		||||
	&pbdb_smbus_device,
 | 
			
		||||
#endif
 | 
			
		||||
@ -312,6 +304,13 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = {
 | 
			
		||||
 | 
			
		||||
int __init au1xxx_platform_init(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int uartclk = get_au1x00_uart_baud_base() * 16;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	/* Fill up uartclk. */
 | 
			
		||||
	for (i = 0; au1x00_uart_data[i].flags ; i++)
 | 
			
		||||
		au1x00_uart_data[i].uartclk = uartclk;
 | 
			
		||||
 | 
			
		||||
	return platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -29,17 +29,14 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/pm.h>
 | 
			
		||||
#include <linux/pm_legacy.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/sysctl.h>
 | 
			
		||||
#include <linux/jiffies.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/string.h>
 | 
			
		||||
#include <asm/uaccess.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <asm/cacheflush.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
@ -47,17 +44,13 @@
 | 
			
		||||
 | 
			
		||||
#define DEBUG 1
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
#  define DPRINTK(fmt, args...)	printk("%s: " fmt, __FUNCTION__ , ## args)
 | 
			
		||||
#  define DPRINTK(fmt, args...)	printk("%s: " fmt, __func__, ## args)
 | 
			
		||||
#else
 | 
			
		||||
#  define DPRINTK(fmt, args...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void au1000_calibrate_delay(void);
 | 
			
		||||
 | 
			
		||||
extern void set_au1x00_speed(unsigned int new_freq);
 | 
			
		||||
extern unsigned int get_au1x00_speed(void);
 | 
			
		||||
extern unsigned long get_au1x00_uart_baud_base(void);
 | 
			
		||||
extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
 | 
			
		||||
extern unsigned long save_local_and_disable(int controller);
 | 
			
		||||
extern void restore_local_and_enable(int controller, unsigned long mask);
 | 
			
		||||
extern void local_enable_irq(unsigned int irq_nr);
 | 
			
		||||
 | 
			
		||||
@ -33,8 +33,8 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,6 @@
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
#define SERIAL_BASE   UART_BASE
 | 
			
		||||
 | 
			
		||||
@ -27,13 +27,7 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <asm/processor.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
extern int au_sleep(void);
 | 
			
		||||
 | 
			
		||||
@ -25,21 +25,14 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/pm.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <asm/time.h>
 | 
			
		||||
 | 
			
		||||
#include <au1000.h>
 | 
			
		||||
@ -49,8 +42,6 @@ extern void __init board_setup(void);
 | 
			
		||||
extern void au1000_restart(char *);
 | 
			
		||||
extern void au1000_halt(void);
 | 
			
		||||
extern void au1000_power_off(void);
 | 
			
		||||
extern void au1x_time_init(void);
 | 
			
		||||
extern void au1x_timer_setup(struct irqaction *irq);
 | 
			
		||||
extern void set_cpuspec(void);
 | 
			
		||||
 | 
			
		||||
void __init plat_mem_setup(void)
 | 
			
		||||
 | 
			
		||||
@ -9,9 +9,9 @@
 | 
			
		||||
 * Free Software Foundation;  either version 2 of the  License, or (at your
 | 
			
		||||
 * option) any later version.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <asm/asm.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <asm/regdef.h>
 | 
			
		||||
#include <asm/stackframe.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2001 MontaVista Software, ppopov@mvista.com
 | 
			
		||||
 * Copyright (C) 2001, 2006, 2008 MontaVista Software, <source@mvista.com>
 | 
			
		||||
 * Copied and modified Carsten Langgaard's time.c
 | 
			
		||||
 *
 | 
			
		||||
 * Carsten Langgaard, carstenl@mips.com
 | 
			
		||||
@ -34,23 +34,13 @@
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/kernel_stat.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/hardirq.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/compiler.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/time.h>
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/mc146818rtc.h>
 | 
			
		||||
#include <linux/timex.h>
 | 
			
		||||
 | 
			
		||||
static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 | 
			
		||||
static unsigned long r4k_cur;    /* What counter should be at next timer irq */
 | 
			
		||||
int	no_au1xxx_32khz;
 | 
			
		||||
static int no_au1xxx_32khz;
 | 
			
		||||
extern int allow_au1k_wait; /* default off for CP0 Counter */
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_PM
 | 
			
		||||
@ -184,7 +174,7 @@ wakeup_counter0_set(int ticks)
 | 
			
		||||
 * "wait" is enabled, and we need to detect if the 32KHz isn't present
 | 
			
		||||
 * but requested......got it? :-)		-- Dan
 | 
			
		||||
 */
 | 
			
		||||
unsigned long cal_r4koff(void)
 | 
			
		||||
unsigned long calc_clock(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long cpu_speed;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
@ -229,19 +219,13 @@ unsigned long cal_r4koff(void)
 | 
			
		||||
	// Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16)
 | 
			
		||||
	set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
 | 
			
		||||
	spin_unlock_irqrestore(&time_lock, flags);
 | 
			
		||||
	return (cpu_speed / HZ);
 | 
			
		||||
	return cpu_speed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init plat_time_init(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int est_freq;
 | 
			
		||||
	unsigned int est_freq = calc_clock();
 | 
			
		||||
 | 
			
		||||
	printk("calculating r4koff... ");
 | 
			
		||||
	r4k_offset = cal_r4koff();
 | 
			
		||||
	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
 | 
			
		||||
 | 
			
		||||
	//est_freq = 2*r4k_offset*HZ;
 | 
			
		||||
	est_freq = r4k_offset*HZ;
 | 
			
		||||
	est_freq += 5000;    /* round */
 | 
			
		||||
	est_freq -= est_freq%10000;
 | 
			
		||||
	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
 | 
			
		||||
@ -249,9 +233,6 @@ void __init plat_time_init(void)
 | 
			
		||||
 	set_au1x00_speed(est_freq);
 | 
			
		||||
 	set_au1x00_lcd_clock(); // program the LCD clock
 | 
			
		||||
 | 
			
		||||
	r4k_cur = (read_c0_count() + r4k_offset);
 | 
			
		||||
	write_c0_compare(r4k_cur);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_PM
 | 
			
		||||
	/*
 | 
			
		||||
	 * setup counter 0, since it keeps ticking after a
 | 
			
		||||
@ -265,12 +246,8 @@ void __init plat_time_init(void)
 | 
			
		||||
	 * Check to ensure we really have a 32KHz oscillator before
 | 
			
		||||
	 * we do this.
 | 
			
		||||
	 */
 | 
			
		||||
	if (no_au1xxx_32khz) {
 | 
			
		||||
	if (no_au1xxx_32khz)
 | 
			
		||||
		printk("WARNING: no 32KHz clock found.\n");
 | 
			
		||||
 | 
			
		||||
		/* Ensure we get CPO_COUNTER interrupts.  */
 | 
			
		||||
		set_c0_status(IE_IRQ5);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
 | 
			
		||||
		au_writel(0, SYS_TOYWRITE);
 | 
			
		||||
 | 
			
		||||
@ -27,20 +27,9 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/console.h>
 | 
			
		||||
#include <linux/mc146818rtc.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
#include <asm/mach-db1x00/db1x00.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -28,13 +28,8 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/bootmem.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
 | 
			
		||||
#include <prom.h>
 | 
			
		||||
 | 
			
		||||
@ -25,26 +25,9 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/kernel_stat.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/signal.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/timex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_DB1500
 | 
			
		||||
 | 
			
		||||
@ -28,19 +28,9 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/console.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
extern int (*board_pci_idsel)(unsigned int devsel, int assert);
 | 
			
		||||
 | 
			
		||||
@ -28,14 +28,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/bootmem.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
 | 
			
		||||
#include <prom.h>
 | 
			
		||||
 | 
			
		||||
@ -25,26 +25,9 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/kernel_stat.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/signal.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/timex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
char irq_tab_alchemy[][5] __initdata = {
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,6 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/platform_device.h>
 | 
			
		||||
#include <linux/leds.h>
 | 
			
		||||
#include <linux/gpio_keys.h>
 | 
			
		||||
 | 
			
		||||
@ -23,19 +23,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/console.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
#include <asm/mach-pb1x00/pb1000.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,14 +26,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/bootmem.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
 | 
			
		||||
#include <prom.h>
 | 
			
		||||
 | 
			
		||||
@ -25,26 +25,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/kernel_stat.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/signal.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/timex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
 | 
			
		||||
 | 
			
		||||
@ -23,19 +23,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/console.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
#include <asm/mach-pb1x00/pb1100.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,14 +27,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/bootmem.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
 | 
			
		||||
#include <prom.h>
 | 
			
		||||
 | 
			
		||||
@ -25,26 +25,9 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/kernel_stat.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/signal.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/timex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
 | 
			
		||||
 | 
			
		||||
@ -3,5 +3,6 @@
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
lib-y := init.o board_setup.o irqmap.o
 | 
			
		||||
obj-y += platform.o
 | 
			
		||||
 | 
			
		||||
EXTRA_CFLAGS += -Werror
 | 
			
		||||
 | 
			
		||||
@ -23,27 +23,11 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/console.h>
 | 
			
		||||
#include <linux/mc146818rtc.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
 | 
			
		||||
#include <linux/ide.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
 | 
			
		||||
#include <au1000.h>
 | 
			
		||||
#include <au1xxx_dbdma.h>
 | 
			
		||||
#include <prom.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_PB1200
 | 
			
		||||
@ -52,8 +36,6 @@
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_DB1200
 | 
			
		||||
#include <asm/mach-db1x00/db1200.h>
 | 
			
		||||
#define PB1200_ETH_INT DB1200_ETH_INT
 | 
			
		||||
#define PB1200_IDE_INT DB1200_IDE_INT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern void _board_init_irq(void);
 | 
			
		||||
 | 
			
		||||
@ -27,14 +27,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/bootmem.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
 | 
			
		||||
#include <prom.h>
 | 
			
		||||
 | 
			
		||||
@ -22,26 +22,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/kernel_stat.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/signal.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/timex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_PB1200
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										84
									
								
								arch/mips/au1000/pb1200/platform.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								arch/mips/au1000/pb1200/platform.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,84 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Pb1200/DBAu1200 board platform device registration
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2008 MontaVista Software Inc. <source@mvista.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/platform_device.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1xxx.h>
 | 
			
		||||
 | 
			
		||||
static struct resource ide_resources[] = {
 | 
			
		||||
	[0] = {
 | 
			
		||||
		.start	= IDE_PHYS_ADDR,
 | 
			
		||||
		.end 	= IDE_PHYS_ADDR + IDE_PHYS_LEN - 1,
 | 
			
		||||
		.flags	= IORESOURCE_MEM
 | 
			
		||||
	},
 | 
			
		||||
	[1] = {
 | 
			
		||||
		.start	= IDE_INT,
 | 
			
		||||
		.end	= IDE_INT,
 | 
			
		||||
		.flags	= IORESOURCE_IRQ
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static u64 ide_dmamask = ~(u32)0;
 | 
			
		||||
 | 
			
		||||
static struct platform_device ide_device = {
 | 
			
		||||
	.name		= "au1200-ide",
 | 
			
		||||
	.id		= 0,
 | 
			
		||||
	.dev = {
 | 
			
		||||
		.dma_mask 		= &ide_dmamask,
 | 
			
		||||
		.coherent_dma_mask	= 0xffffffff,
 | 
			
		||||
	},
 | 
			
		||||
	.num_resources	= ARRAY_SIZE(ide_resources),
 | 
			
		||||
	.resource	= ide_resources
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct resource smc91c111_resources[] = {
 | 
			
		||||
	[0] = {
 | 
			
		||||
		.name	= "smc91x-regs",
 | 
			
		||||
		.start	= SMC91C111_PHYS_ADDR,
 | 
			
		||||
		.end	= SMC91C111_PHYS_ADDR + 0xf,
 | 
			
		||||
		.flags	= IORESOURCE_MEM
 | 
			
		||||
	},
 | 
			
		||||
	[1] = {
 | 
			
		||||
		.start	= SMC91C111_INT,
 | 
			
		||||
		.end	= SMC91C111_INT,
 | 
			
		||||
		.flags	= IORESOURCE_IRQ
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct platform_device smc91c111_device = {
 | 
			
		||||
	.name		= "smc91x",
 | 
			
		||||
	.id		= -1,
 | 
			
		||||
	.num_resources	= ARRAY_SIZE(smc91c111_resources),
 | 
			
		||||
	.resource	= smc91c111_resources
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct platform_device *board_platform_devices[] __initdata = {
 | 
			
		||||
	&ide_device,
 | 
			
		||||
	&smc91c111_device
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int __init board_register_devices(void)
 | 
			
		||||
{
 | 
			
		||||
	return platform_add_devices(board_platform_devices,
 | 
			
		||||
				    ARRAY_SIZE(board_platform_devices));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
arch_initcall(board_register_devices);
 | 
			
		||||
@ -23,19 +23,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/console.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
#include <asm/mach-pb1x00/pb1500.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,14 +27,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/bootmem.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
 | 
			
		||||
#include <prom.h>
 | 
			
		||||
 | 
			
		||||
@ -25,26 +25,9 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/kernel_stat.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/signal.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/timex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
char irq_tab_alchemy[][5] __initdata = {
 | 
			
		||||
 | 
			
		||||
@ -27,20 +27,9 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/console.h>
 | 
			
		||||
#include <linux/mc146818rtc.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
#include <asm/mach-pb1x00/pb1550.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,14 +27,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/bootmem.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
 | 
			
		||||
#include <prom.h>
 | 
			
		||||
 | 
			
		||||
@ -25,26 +25,9 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/kernel_stat.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/signal.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/timex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
char irq_tab_alchemy[][5] __initdata = {
 | 
			
		||||
 | 
			
		||||
@ -23,19 +23,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/console.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
void board_reset(void)
 | 
			
		||||
 | 
			
		||||
@ -26,14 +26,10 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/bootmem.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
 | 
			
		||||
#include <prom.h>
 | 
			
		||||
 | 
			
		||||
@ -25,26 +25,9 @@
 | 
			
		||||
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/kernel_stat.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/signal.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/timex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/mach-au1x00/au1000.h>
 | 
			
		||||
 | 
			
		||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
 | 
			
		||||
 | 
			
		||||
@ -641,7 +641,6 @@ CONFIG_CROSSCOMPILE=y
 | 
			
		||||
CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
 | 
			
		||||
# CONFIG_DEBUG_STACK_USAGE is not set
 | 
			
		||||
# CONFIG_RUNTIME_DEBUG is not set
 | 
			
		||||
# CONFIG_MIPS_UNCACHED is not set
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Security options
 | 
			
		||||
 | 
			
		||||
@ -1223,7 +1223,6 @@ CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
 | 
			
		||||
# CONFIG_KGDB is not set
 | 
			
		||||
CONFIG_SYS_SUPPORTS_KGDB=y
 | 
			
		||||
# CONFIG_RUNTIME_DEBUG is not set
 | 
			
		||||
# CONFIG_MIPS_UNCACHED is not set
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Security options
 | 
			
		||||
 | 
			
		||||
@ -1213,7 +1213,6 @@ CONFIG_CMDLINE="console=ttyS1,38400n8 kgdb=ttyS0 root=/dev/nfs ip=bootp"
 | 
			
		||||
# CONFIG_KGDB is not set
 | 
			
		||||
CONFIG_SYS_SUPPORTS_KGDB=y
 | 
			
		||||
# CONFIG_RUNTIME_DEBUG is not set
 | 
			
		||||
# CONFIG_MIPS_UNCACHED is not set
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Security options
 | 
			
		||||
 | 
			
		||||
@ -9,30 +9,15 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/bcd.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/mc146818rtc.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/param.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/time.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/sections.h>
 | 
			
		||||
#include <asm/cpu-features.h>
 | 
			
		||||
#include <asm/ds1287.h>
 | 
			
		||||
#include <asm/time.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/dec/interrupts.h>
 | 
			
		||||
#include <asm/dec/ioasic.h>
 | 
			
		||||
#include <asm/dec/ioasic_addrs.h>
 | 
			
		||||
#include <asm/dec/machtype.h>
 | 
			
		||||
 | 
			
		||||
unsigned long read_persistent_clock(void)
 | 
			
		||||
@ -139,42 +124,32 @@ int rtc_mips_set_mmss(unsigned long nowtime)
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dec_timer_state(void)
 | 
			
		||||
{
 | 
			
		||||
	return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dec_timer_ack(void)
 | 
			
		||||
{
 | 
			
		||||
	CMOS_READ(RTC_REG_C);			/* Ack the RTC interrupt.  */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cycle_t dec_ioasic_hpt_read(void)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * The free-running counter is 32-bit which is good for about
 | 
			
		||||
	 * 2 minutes, 50 seconds at possible count rates of up to 25MHz.
 | 
			
		||||
	 */
 | 
			
		||||
	return ioasic_read(IO_REG_FCTR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void __init plat_time_init(void)
 | 
			
		||||
{
 | 
			
		||||
	mips_timer_ack = dec_timer_ack;
 | 
			
		||||
	u32 start, end;
 | 
			
		||||
	int i = HZ / 10;
 | 
			
		||||
 | 
			
		||||
	if (!cpu_has_counter && IOASIC)
 | 
			
		||||
	/* Set up the rate of periodic DS1287 interrupts. */
 | 
			
		||||
	ds1287_set_base_clock(HZ);
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_counter) {
 | 
			
		||||
		while (!ds1287_timer_state())
 | 
			
		||||
			;
 | 
			
		||||
 | 
			
		||||
		start = read_c0_count();
 | 
			
		||||
 | 
			
		||||
		while (i--)
 | 
			
		||||
			while (!ds1287_timer_state())
 | 
			
		||||
				;
 | 
			
		||||
 | 
			
		||||
		end = read_c0_count();
 | 
			
		||||
 | 
			
		||||
		mips_hpt_frequency = (end - start) * 10;
 | 
			
		||||
		printk(KERN_INFO "MIPS counter frequency %dHz\n",
 | 
			
		||||
			mips_hpt_frequency);
 | 
			
		||||
	} else if (IOASIC)
 | 
			
		||||
		/* For pre-R4k systems we use the I/O ASIC's counter.  */
 | 
			
		||||
		clocksource_mips.read = dec_ioasic_hpt_read;
 | 
			
		||||
		dec_ioasic_clocksource_init();
 | 
			
		||||
 | 
			
		||||
	/* Set up the rate of periodic DS1287 interrupts.  */
 | 
			
		||||
	CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init plat_timer_setup(struct irqaction *irq)
 | 
			
		||||
{
 | 
			
		||||
	setup_irq(dec_interrupt[DEC_IRQ_RTC], irq);
 | 
			
		||||
 | 
			
		||||
	/* Enable periodic DS1287 interrupts.  */
 | 
			
		||||
	CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B);
 | 
			
		||||
	ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -36,11 +36,13 @@
 | 
			
		||||
#include <linux/pm.h>
 | 
			
		||||
#include <linux/platform_device.h>
 | 
			
		||||
#include <linux/clk.h>
 | 
			
		||||
#include <linux/gpio.h>
 | 
			
		||||
#ifdef CONFIG_SERIAL_TXX9
 | 
			
		||||
#include <linux/serial_core.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <asm/txx9tmr.h>
 | 
			
		||||
#include <asm/txx9pio.h>
 | 
			
		||||
#include <asm/reboot.h>
 | 
			
		||||
#include <asm/jmr3927/jmr3927.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
@ -340,9 +342,12 @@ static void __init tx3927_setup(void)
 | 
			
		||||
 | 
			
		||||
	/* PIO */
 | 
			
		||||
	/* PIO[15:12] connected to LEDs */
 | 
			
		||||
	tx3927_pioptr->dir = 0x0000f000;
 | 
			
		||||
	tx3927_pioptr->maskcpu = 0;
 | 
			
		||||
	tx3927_pioptr->maskext = 0;
 | 
			
		||||
	__raw_writel(0x0000f000, &tx3927_pioptr->dir);
 | 
			
		||||
	__raw_writel(0, &tx3927_pioptr->maskcpu);
 | 
			
		||||
	__raw_writel(0, &tx3927_pioptr->maskext);
 | 
			
		||||
	txx9_gpio_init(TX3927_PIO_REG, 0, 16);
 | 
			
		||||
	gpio_request(11, "dipsw1");
 | 
			
		||||
	gpio_request(10, "dipsw2");
 | 
			
		||||
	{
 | 
			
		||||
		unsigned int conf;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -10,12 +10,15 @@ obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_CEVT_BCM1480)	+= cevt-bcm1480.o
 | 
			
		||||
obj-$(CONFIG_CEVT_R4K)		+= cevt-r4k.o
 | 
			
		||||
obj-$(CONFIG_CEVT_DS1287)	+= cevt-ds1287.o
 | 
			
		||||
obj-$(CONFIG_CEVT_GT641XX)	+= cevt-gt641xx.o
 | 
			
		||||
obj-$(CONFIG_CEVT_SB1250)	+= cevt-sb1250.o
 | 
			
		||||
obj-$(CONFIG_CEVT_TXX9)		+= cevt-txx9.o
 | 
			
		||||
obj-$(CONFIG_CSRC_BCM1480)	+= csrc-bcm1480.o
 | 
			
		||||
obj-$(CONFIG_CSRC_IOASIC)	+= csrc-ioasic.o
 | 
			
		||||
obj-$(CONFIG_CSRC_R4K)		+= csrc-r4k.o
 | 
			
		||||
obj-$(CONFIG_CSRC_SB1250)	+= csrc-sb1250.o
 | 
			
		||||
obj-$(CONFIG_SYNC_R4K)		+= sync-r4k.o
 | 
			
		||||
 | 
			
		||||
binfmt_irix-objs	:= irixelf.o irixinv.o irixioctl.o irixsig.o	\
 | 
			
		||||
			   irix5sys.o sysirix.o
 | 
			
		||||
@ -50,6 +53,8 @@ obj-$(CONFIG_MIPS_MT)		+= mips-mt.o
 | 
			
		||||
obj-$(CONFIG_MIPS_MT_FPAFF)	+= mips-mt-fpaff.o
 | 
			
		||||
obj-$(CONFIG_MIPS_MT_SMTC)	+= smtc.o smtc-asm.o smtc-proc.o
 | 
			
		||||
obj-$(CONFIG_MIPS_MT_SMP)	+= smp-mt.o
 | 
			
		||||
obj-$(CONFIG_MIPS_CMP)		+= smp-cmp.o
 | 
			
		||||
obj-$(CONFIG_CPU_MIPSR2)	+= spram.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_MIPS_APSP_KSPD)	+= kspd.o
 | 
			
		||||
obj-$(CONFIG_MIPS_VPE_LOADER)	+= vpe.o
 | 
			
		||||
@ -62,6 +67,7 @@ obj-$(CONFIG_IRQ_CPU_RM9K)	+= irq-rm9000.o
 | 
			
		||||
obj-$(CONFIG_MIPS_BOARDS_GEN)	+= irq-msc01.o
 | 
			
		||||
obj-$(CONFIG_IRQ_TXX9)		+= irq_txx9.o
 | 
			
		||||
obj-$(CONFIG_IRQ_GT641XX)	+= irq-gt641xx.o
 | 
			
		||||
obj-$(CONFIG_IRQ_GIC)		+= irq-gic.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_32BIT)		+= scall32-o32.o
 | 
			
		||||
obj-$(CONFIG_64BIT)		+= scall64-64.o
 | 
			
		||||
@ -77,6 +83,8 @@ obj-$(CONFIG_64BIT)		+= cpu-bugs64.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_I8253)		+= i8253.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_GPIO_TXX9)		+= gpio_txx9.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 | 
			
		||||
obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										129
									
								
								arch/mips/kernel/cevt-ds1287.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								arch/mips/kernel/cevt-ds1287.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,129 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  DS1287 clockevent driver
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 *  it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *  the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 *  (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License
 | 
			
		||||
 *  along with this program; if not, write to the Free Software
 | 
			
		||||
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/clockchips.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/mc146818rtc.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/time.h>
 | 
			
		||||
 | 
			
		||||
int ds1287_timer_state(void)
 | 
			
		||||
{
 | 
			
		||||
	return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ds1287_set_base_clock(unsigned int hz)
 | 
			
		||||
{
 | 
			
		||||
	u8 rate;
 | 
			
		||||
 | 
			
		||||
	switch (hz) {
 | 
			
		||||
	case 128:
 | 
			
		||||
		rate = 0x9;
 | 
			
		||||
		break;
 | 
			
		||||
	case 256:
 | 
			
		||||
		rate = 0x8;
 | 
			
		||||
		break;
 | 
			
		||||
	case 1024:
 | 
			
		||||
		rate = 0x6;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CMOS_WRITE(RTC_REF_CLCK_32KHZ | rate, RTC_REG_A);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ds1287_set_next_event(unsigned long delta,
 | 
			
		||||
				 struct clock_event_device *evt)
 | 
			
		||||
{
 | 
			
		||||
	return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ds1287_set_mode(enum clock_event_mode mode,
 | 
			
		||||
			    struct clock_event_device *evt)
 | 
			
		||||
{
 | 
			
		||||
	u8 val;
 | 
			
		||||
 | 
			
		||||
	spin_lock(&rtc_lock);
 | 
			
		||||
 | 
			
		||||
	val = CMOS_READ(RTC_REG_B);
 | 
			
		||||
 | 
			
		||||
	switch (mode) {
 | 
			
		||||
	case CLOCK_EVT_MODE_PERIODIC:
 | 
			
		||||
		val |= RTC_PIE;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		val &= ~RTC_PIE;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CMOS_WRITE(val, RTC_REG_B);
 | 
			
		||||
 | 
			
		||||
	spin_unlock(&rtc_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ds1287_event_handler(struct clock_event_device *dev)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct clock_event_device ds1287_clockevent = {
 | 
			
		||||
	.name		= "ds1287",
 | 
			
		||||
	.features	= CLOCK_EVT_FEAT_PERIODIC,
 | 
			
		||||
	.cpumask	= CPU_MASK_CPU0,
 | 
			
		||||
	.set_next_event	= ds1287_set_next_event,
 | 
			
		||||
	.set_mode	= ds1287_set_mode,
 | 
			
		||||
	.event_handler	= ds1287_event_handler,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static irqreturn_t ds1287_interrupt(int irq, void *dev_id)
 | 
			
		||||
{
 | 
			
		||||
	struct clock_event_device *cd = &ds1287_clockevent;
 | 
			
		||||
 | 
			
		||||
	/* Ack the RTC interrupt. */
 | 
			
		||||
	CMOS_READ(RTC_REG_C);
 | 
			
		||||
 | 
			
		||||
	cd->event_handler(cd);
 | 
			
		||||
 | 
			
		||||
	return IRQ_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct irqaction ds1287_irqaction = {
 | 
			
		||||
	.handler	= ds1287_interrupt,
 | 
			
		||||
	.flags		= IRQF_DISABLED | IRQF_PERCPU,
 | 
			
		||||
	.name		= "ds1287",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int __init ds1287_clockevent_init(int irq)
 | 
			
		||||
{
 | 
			
		||||
	struct clock_event_device *cd;
 | 
			
		||||
 | 
			
		||||
	cd = &ds1287_clockevent;
 | 
			
		||||
	cd->rating = 100;
 | 
			
		||||
	cd->irq = irq;
 | 
			
		||||
	clockevent_set_clock(cd, 32768);
 | 
			
		||||
	cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
 | 
			
		||||
	cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
 | 
			
		||||
 | 
			
		||||
	clockevents_register_device(&ds1287_clockevent);
 | 
			
		||||
 | 
			
		||||
	return setup_irq(irq, &ds1287_irqaction);
 | 
			
		||||
}
 | 
			
		||||
@ -25,8 +25,6 @@
 | 
			
		||||
#include <asm/gt64120.h>
 | 
			
		||||
#include <asm/time.h>
 | 
			
		||||
 | 
			
		||||
#include <irq.h>
 | 
			
		||||
 | 
			
		||||
static DEFINE_SPINLOCK(gt641xx_timer_lock);
 | 
			
		||||
static unsigned int gt641xx_base_clock;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -169,6 +169,7 @@ static inline void check_wait(void)
 | 
			
		||||
 | 
			
		||||
	case CPU_24K:
 | 
			
		||||
	case CPU_34K:
 | 
			
		||||
	case CPU_1004K:
 | 
			
		||||
		cpu_wait = r4k_wait;
 | 
			
		||||
		if (read_c0_config7() & MIPS_CONF7_WII)
 | 
			
		||||
			cpu_wait = r4k_wait_irqoff;
 | 
			
		||||
@ -675,6 +676,12 @@ static void __cpuinit decode_configs(struct cpuinfo_mips *c)
 | 
			
		||||
		return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_CPU_MIPSR2
 | 
			
		||||
extern void spram_config(void);
 | 
			
		||||
#else
 | 
			
		||||
static inline void spram_config(void) {}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline void cpu_probe_mips(struct cpuinfo_mips *c)
 | 
			
		||||
{
 | 
			
		||||
	decode_configs(c);
 | 
			
		||||
@ -711,7 +718,12 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
 | 
			
		||||
	case PRID_IMP_74K:
 | 
			
		||||
		c->cputype = CPU_74K;
 | 
			
		||||
		break;
 | 
			
		||||
	case PRID_IMP_1004K:
 | 
			
		||||
		c->cputype = CPU_1004K;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	spram_config();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void cpu_probe_alchemy(struct cpuinfo_mips *c)
 | 
			
		||||
@ -778,7 +790,7 @@ static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void cpu_probe_philips(struct cpuinfo_mips *c)
 | 
			
		||||
static inline void cpu_probe_nxp(struct cpuinfo_mips *c)
 | 
			
		||||
{
 | 
			
		||||
	decode_configs(c);
 | 
			
		||||
	switch (c->processor_id & 0xff00) {
 | 
			
		||||
@ -787,7 +799,7 @@ static inline void cpu_probe_philips(struct cpuinfo_mips *c)
 | 
			
		||||
		c->isa_level = MIPS_CPU_ISA_M32R1;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		panic("Unknown Philips Core!"); /* REVISIT: die? */
 | 
			
		||||
		panic("Unknown NXP Core!"); /* REVISIT: die? */
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -876,6 +888,7 @@ static __cpuinit const char *cpu_to_name(struct cpuinfo_mips *c)
 | 
			
		||||
	case CPU_24K:		name = "MIPS 24K"; break;
 | 
			
		||||
	case CPU_25KF:		name = "MIPS 25Kf"; break;
 | 
			
		||||
	case CPU_34K:		name = "MIPS 34K"; break;
 | 
			
		||||
	case CPU_1004K:		name = "MIPS 1004K"; break;
 | 
			
		||||
	case CPU_74K:		name = "MIPS 74K"; break;
 | 
			
		||||
	case CPU_VR4111:	name = "NEC VR4111"; break;
 | 
			
		||||
	case CPU_VR4121:	name = "NEC VR4121"; break;
 | 
			
		||||
@ -925,8 +938,8 @@ __cpuinit void cpu_probe(void)
 | 
			
		||||
	case PRID_COMP_SANDCRAFT:
 | 
			
		||||
		cpu_probe_sandcraft(c);
 | 
			
		||||
		break;
 | 
			
		||||
 	case PRID_COMP_PHILIPS:
 | 
			
		||||
		cpu_probe_philips(c);
 | 
			
		||||
	case PRID_COMP_NXP:
 | 
			
		||||
		cpu_probe_nxp(c);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		c->cputype = CPU_UNKNOWN;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										65
									
								
								arch/mips/kernel/csrc-ioasic.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								arch/mips/kernel/csrc-ioasic.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  DEC I/O ASIC's counter clocksource
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 *  it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *  the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 *  (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License
 | 
			
		||||
 *  along with this program; if not, write to the Free Software
 | 
			
		||||
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/clocksource.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/ds1287.h>
 | 
			
		||||
#include <asm/time.h>
 | 
			
		||||
#include <asm/dec/ioasic.h>
 | 
			
		||||
#include <asm/dec/ioasic_addrs.h>
 | 
			
		||||
 | 
			
		||||
static cycle_t dec_ioasic_hpt_read(void)
 | 
			
		||||
{
 | 
			
		||||
	return ioasic_read(IO_REG_FCTR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct clocksource clocksource_dec = {
 | 
			
		||||
	.name		= "dec-ioasic",
 | 
			
		||||
	.read		= dec_ioasic_hpt_read,
 | 
			
		||||
	.mask		= CLOCKSOURCE_MASK(32),
 | 
			
		||||
	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void __init dec_ioasic_clocksource_init(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int freq;
 | 
			
		||||
	u32 start, end;
 | 
			
		||||
	int i = HZ / 10;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	while (!ds1287_timer_state())
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
	start = dec_ioasic_hpt_read();
 | 
			
		||||
 | 
			
		||||
	while (i--)
 | 
			
		||||
		while (!ds1287_timer_state())
 | 
			
		||||
			;
 | 
			
		||||
 | 
			
		||||
	end = dec_ioasic_hpt_read();
 | 
			
		||||
 | 
			
		||||
	freq = (end - start) * 10;
 | 
			
		||||
	printk(KERN_INFO "I/O ASIC clock frequency %dHz\n", freq);
 | 
			
		||||
 | 
			
		||||
	clocksource_dec.rating = 200 + freq / 10000000;
 | 
			
		||||
	clocksource_set_clock(&clocksource_dec, freq);
 | 
			
		||||
 | 
			
		||||
	clocksource_register(&clocksource_dec);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										87
									
								
								arch/mips/kernel/gpio_txx9.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								arch/mips/kernel/gpio_txx9.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
			
		||||
/*
 | 
			
		||||
 * A gpio chip driver for TXx9 SoCs
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2008 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License version 2 as
 | 
			
		||||
 * published by the Free Software Foundation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/gpio.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/txx9pio.h>
 | 
			
		||||
 | 
			
		||||
static DEFINE_SPINLOCK(txx9_gpio_lock);
 | 
			
		||||
 | 
			
		||||
static struct txx9_pio_reg __iomem *txx9_pioptr;
 | 
			
		||||
 | 
			
		||||
static int txx9_gpio_get(struct gpio_chip *chip, unsigned int offset)
 | 
			
		||||
{
 | 
			
		||||
	return __raw_readl(&txx9_pioptr->din) & (1 << offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void txx9_gpio_set_raw(unsigned int offset, int value)
 | 
			
		||||
{
 | 
			
		||||
	u32 val;
 | 
			
		||||
	val = __raw_readl(&txx9_pioptr->dout);
 | 
			
		||||
	if (value)
 | 
			
		||||
		val |= 1 << offset;
 | 
			
		||||
	else
 | 
			
		||||
		val &= ~(1 << offset);
 | 
			
		||||
	__raw_writel(val, &txx9_pioptr->dout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void txx9_gpio_set(struct gpio_chip *chip, unsigned int offset,
 | 
			
		||||
			  int value)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	spin_lock_irqsave(&txx9_gpio_lock, flags);
 | 
			
		||||
	txx9_gpio_set_raw(offset, value);
 | 
			
		||||
	mmiowb();
 | 
			
		||||
	spin_unlock_irqrestore(&txx9_gpio_lock, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int txx9_gpio_dir_in(struct gpio_chip *chip, unsigned int offset)
 | 
			
		||||
{
 | 
			
		||||
	spin_lock_irq(&txx9_gpio_lock);
 | 
			
		||||
	__raw_writel(__raw_readl(&txx9_pioptr->dir) & ~(1 << offset),
 | 
			
		||||
		     &txx9_pioptr->dir);
 | 
			
		||||
	mmiowb();
 | 
			
		||||
	spin_unlock_irq(&txx9_gpio_lock);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int txx9_gpio_dir_out(struct gpio_chip *chip, unsigned int offset,
 | 
			
		||||
			     int value)
 | 
			
		||||
{
 | 
			
		||||
	spin_lock_irq(&txx9_gpio_lock);
 | 
			
		||||
	txx9_gpio_set_raw(offset, value);
 | 
			
		||||
	__raw_writel(__raw_readl(&txx9_pioptr->dir) | (1 << offset),
 | 
			
		||||
		     &txx9_pioptr->dir);
 | 
			
		||||
	mmiowb();
 | 
			
		||||
	spin_unlock_irq(&txx9_gpio_lock);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct gpio_chip txx9_gpio_chip = {
 | 
			
		||||
	.get = txx9_gpio_get,
 | 
			
		||||
	.set = txx9_gpio_set,
 | 
			
		||||
	.direction_input = txx9_gpio_dir_in,
 | 
			
		||||
	.direction_output = txx9_gpio_dir_out,
 | 
			
		||||
	.label = "TXx9",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int __init txx9_gpio_init(unsigned long baseaddr,
 | 
			
		||||
			  unsigned int base, unsigned int num)
 | 
			
		||||
{
 | 
			
		||||
	txx9_pioptr = ioremap(baseaddr, sizeof(struct txx9_pio_reg));
 | 
			
		||||
	if (!txx9_pioptr)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	txx9_gpio_chip.base = base;
 | 
			
		||||
	txx9_gpio_chip.ngpio = num;
 | 
			
		||||
	return gpiochip_add(&txx9_gpio_chip);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										295
									
								
								arch/mips/kernel/irq-gic.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								arch/mips/kernel/irq-gic.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,295 @@
 | 
			
		||||
#undef DEBUG
 | 
			
		||||
 | 
			
		||||
#include <linux/bitmap.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/gic.h>
 | 
			
		||||
#include <asm/gcmpregs.h>
 | 
			
		||||
#include <asm/mips-boards/maltaint.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <linux/hardirq.h>
 | 
			
		||||
#include <asm-generic/bitops/find.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static unsigned long _gic_base;
 | 
			
		||||
static unsigned int _irqbase, _mapsize, numvpes, numintrs;
 | 
			
		||||
static struct gic_intr_map *_intrmap;
 | 
			
		||||
 | 
			
		||||
static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 | 
			
		||||
static struct gic_pending_regs pending_regs[NR_CPUS];
 | 
			
		||||
static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
 | 
			
		||||
 | 
			
		||||
#define gic_wedgeb2bok 0	/*
 | 
			
		||||
				 * Can GIC handle b2b writes to wedge register?
 | 
			
		||||
				 */
 | 
			
		||||
#if gic_wedgeb2bok == 0
 | 
			
		||||
static DEFINE_SPINLOCK(gic_wedgeb2b_lock);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void gic_send_ipi(unsigned int intr)
 | 
			
		||||
{
 | 
			
		||||
#if gic_wedgeb2bok == 0
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
#endif
 | 
			
		||||
	pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__,
 | 
			
		||||
		 read_c0_status());
 | 
			
		||||
	if (!gic_wedgeb2bok)
 | 
			
		||||
		spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
 | 
			
		||||
	GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
 | 
			
		||||
	if (!gic_wedgeb2bok) {
 | 
			
		||||
		(void) GIC_REG(SHARED, GIC_SH_CONFIG);
 | 
			
		||||
		spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is Malta specific and needs to be exported */
 | 
			
		||||
static void vpe_local_setup(unsigned int numvpes)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned long timer_interrupt = 5, perf_interrupt = 5;
 | 
			
		||||
	unsigned int vpe_ctl;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Setup the default performance counter timer interrupts
 | 
			
		||||
	 * for all VPEs
 | 
			
		||||
	 */
 | 
			
		||||
	for (i = 0; i < numvpes; i++) {
 | 
			
		||||
		GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
 | 
			
		||||
 | 
			
		||||
		/* Are Interrupts locally routable? */
 | 
			
		||||
		GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl);
 | 
			
		||||
		if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK)
 | 
			
		||||
			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
 | 
			
		||||
				 GIC_MAP_TO_PIN_MSK | timer_interrupt);
 | 
			
		||||
 | 
			
		||||
		if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
 | 
			
		||||
			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
 | 
			
		||||
				 GIC_MAP_TO_PIN_MSK | perf_interrupt);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int gic_get_int(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
	unsigned long *pending, *intrmask, *pcpu_mask;
 | 
			
		||||
	unsigned long *pending_abs, *intrmask_abs;
 | 
			
		||||
 | 
			
		||||
	/* Get per-cpu bitmaps */
 | 
			
		||||
	pending = pending_regs[smp_processor_id()].pending;
 | 
			
		||||
	intrmask = intrmask_regs[smp_processor_id()].intrmask;
 | 
			
		||||
	pcpu_mask = pcpu_masks[smp_processor_id()].pcpu_mask;
 | 
			
		||||
 | 
			
		||||
	pending_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
 | 
			
		||||
							 GIC_SH_PEND_31_0_OFS);
 | 
			
		||||
	intrmask_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
 | 
			
		||||
							  GIC_SH_MASK_31_0_OFS);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < BITS_TO_LONGS(GIC_NUM_INTRS); i++) {
 | 
			
		||||
		GICREAD(*pending_abs, pending[i]);
 | 
			
		||||
		GICREAD(*intrmask_abs, intrmask[i]);
 | 
			
		||||
		pending_abs++;
 | 
			
		||||
		intrmask_abs++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
 | 
			
		||||
	bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
 | 
			
		||||
 | 
			
		||||
	i = find_first_bit(pending, GIC_NUM_INTRS);
 | 
			
		||||
 | 
			
		||||
	pr_debug("CPU%d: %s pend=%d\n", smp_processor_id(), __func__, i);
 | 
			
		||||
 | 
			
		||||
	return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned int gic_irq_startup(unsigned int irq)
 | 
			
		||||
{
 | 
			
		||||
	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 | 
			
		||||
	irq -= _irqbase;
 | 
			
		||||
	/* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
 | 
			
		||||
	GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
 | 
			
		||||
		 1 << (irq % 32));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gic_irq_ack(unsigned int irq)
 | 
			
		||||
{
 | 
			
		||||
#if gic_wedgeb2bok == 0
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
#endif
 | 
			
		||||
	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 | 
			
		||||
	irq -= _irqbase;
 | 
			
		||||
	GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
 | 
			
		||||
		 1 << (irq % 32));
 | 
			
		||||
 | 
			
		||||
	if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) {
 | 
			
		||||
		if (!gic_wedgeb2bok)
 | 
			
		||||
			spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
 | 
			
		||||
		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
 | 
			
		||||
		if (!gic_wedgeb2bok) {
 | 
			
		||||
			(void) GIC_REG(SHARED, GIC_SH_CONFIG);
 | 
			
		||||
			spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gic_mask_irq(unsigned int irq)
 | 
			
		||||
{
 | 
			
		||||
	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 | 
			
		||||
	irq -= _irqbase;
 | 
			
		||||
	/* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
 | 
			
		||||
	GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
 | 
			
		||||
		 1 << (irq % 32));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gic_unmask_irq(unsigned int irq)
 | 
			
		||||
{
 | 
			
		||||
	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 | 
			
		||||
	irq -= _irqbase;
 | 
			
		||||
	/* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
 | 
			
		||||
	GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
 | 
			
		||||
		 1 << (irq % 32));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SMP
 | 
			
		||||
 | 
			
		||||
static DEFINE_SPINLOCK(gic_lock);
 | 
			
		||||
 | 
			
		||||
static void gic_set_affinity(unsigned int irq, cpumask_t cpumask)
 | 
			
		||||
{
 | 
			
		||||
	cpumask_t	tmp = CPU_MASK_NONE;
 | 
			
		||||
	unsigned long	flags;
 | 
			
		||||
	int		i;
 | 
			
		||||
 | 
			
		||||
	pr_debug(KERN_DEBUG "%s called\n", __func__);
 | 
			
		||||
	irq -= _irqbase;
 | 
			
		||||
 | 
			
		||||
	cpus_and(tmp, cpumask, cpu_online_map);
 | 
			
		||||
	if (cpus_empty(tmp))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Assumption : cpumask refers to a single CPU */
 | 
			
		||||
	spin_lock_irqsave(&gic_lock, flags);
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		/* Re-route this IRQ */
 | 
			
		||||
		GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp));
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * FIXME: assumption that _intrmap is ordered and has no holes
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
		/* Update the intr_map */
 | 
			
		||||
		_intrmap[irq].cpunum = first_cpu(tmp);
 | 
			
		||||
 | 
			
		||||
		/* Update the pcpu_masks */
 | 
			
		||||
		for (i = 0; i < NR_CPUS; i++)
 | 
			
		||||
			clear_bit(irq, pcpu_masks[i].pcpu_mask);
 | 
			
		||||
		set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	irq_desc[irq].affinity = cpumask;
 | 
			
		||||
	spin_unlock_irqrestore(&gic_lock, flags);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static struct irq_chip gic_irq_controller = {
 | 
			
		||||
	.name		=	"MIPS GIC",
 | 
			
		||||
	.startup	=	gic_irq_startup,
 | 
			
		||||
	.ack		=	gic_irq_ack,
 | 
			
		||||
	.mask		=	gic_mask_irq,
 | 
			
		||||
	.mask_ack	=	gic_mask_irq,
 | 
			
		||||
	.unmask		=	gic_unmask_irq,
 | 
			
		||||
	.eoi		=	gic_unmask_irq,
 | 
			
		||||
#ifdef CONFIG_SMP
 | 
			
		||||
	.set_affinity	=	gic_set_affinity,
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void __init setup_intr(unsigned int intr, unsigned int cpu,
 | 
			
		||||
	unsigned int pin, unsigned int polarity, unsigned int trigtype)
 | 
			
		||||
{
 | 
			
		||||
	/* Setup Intr to Pin mapping */
 | 
			
		||||
	if (pin & GIC_MAP_TO_NMI_MSK) {
 | 
			
		||||
		GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
 | 
			
		||||
		/* FIXME: hack to route NMI to all cpu's */
 | 
			
		||||
		for (cpu = 0; cpu < NR_CPUS; cpu += 32) {
 | 
			
		||||
			GICWRITE(GIC_REG_ADDR(SHARED,
 | 
			
		||||
					  GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)),
 | 
			
		||||
				 0xffffffff);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)),
 | 
			
		||||
			 GIC_MAP_TO_PIN_MSK | pin);
 | 
			
		||||
		/* Setup Intr to CPU mapping */
 | 
			
		||||
		GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Setup Intr Polarity */
 | 
			
		||||
	GIC_SET_POLARITY(intr, polarity);
 | 
			
		||||
 | 
			
		||||
	/* Setup Intr Trigger Type */
 | 
			
		||||
	GIC_SET_TRIGGER(intr, trigtype);
 | 
			
		||||
 | 
			
		||||
	/* Init Intr Masks */
 | 
			
		||||
	GIC_SET_INTR_MASK(intr, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __init gic_basic_init(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i, cpu;
 | 
			
		||||
 | 
			
		||||
	/* Setup defaults */
 | 
			
		||||
	for (i = 0; i < GIC_NUM_INTRS; i++) {
 | 
			
		||||
		GIC_SET_POLARITY(i, GIC_POL_POS);
 | 
			
		||||
		GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
 | 
			
		||||
		GIC_SET_INTR_MASK(i, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Setup specifics */
 | 
			
		||||
	for (i = 0; i < _mapsize; i++) {
 | 
			
		||||
		cpu = _intrmap[i].cpunum;
 | 
			
		||||
		if (cpu == X)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		setup_intr(_intrmap[i].intrnum,
 | 
			
		||||
				_intrmap[i].cpunum,
 | 
			
		||||
				_intrmap[i].pin,
 | 
			
		||||
				_intrmap[i].polarity,
 | 
			
		||||
				_intrmap[i].trigtype);
 | 
			
		||||
		/* Initialise per-cpu Interrupt software masks */
 | 
			
		||||
		if (_intrmap[i].ipiflag)
 | 
			
		||||
			set_bit(_intrmap[i].intrnum, pcpu_masks[cpu].pcpu_mask);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vpe_local_setup(numvpes);
 | 
			
		||||
 | 
			
		||||
	for (i = _irqbase; i < (_irqbase + numintrs); i++)
 | 
			
		||||
		set_irq_chip(i, &gic_irq_controller);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init gic_init(unsigned long gic_base_addr,
 | 
			
		||||
		     unsigned long gic_addrspace_size,
 | 
			
		||||
		     struct gic_intr_map *intr_map, unsigned int intr_map_size,
 | 
			
		||||
		     unsigned int irqbase)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int gicconfig;
 | 
			
		||||
 | 
			
		||||
	_gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
 | 
			
		||||
						    gic_addrspace_size);
 | 
			
		||||
	_irqbase = irqbase;
 | 
			
		||||
	_intrmap = intr_map;
 | 
			
		||||
	_mapsize = intr_map_size;
 | 
			
		||||
 | 
			
		||||
	GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
 | 
			
		||||
	numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
 | 
			
		||||
		   GIC_SH_CONFIG_NUMINTRS_SHF;
 | 
			
		||||
	numintrs = ((numintrs + 1) * 8);
 | 
			
		||||
 | 
			
		||||
	numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
 | 
			
		||||
		  GIC_SH_CONFIG_NUMVPES_SHF;
 | 
			
		||||
 | 
			
		||||
	pr_debug("%s called\n", __func__);
 | 
			
		||||
 | 
			
		||||
	gic_basic_init();
 | 
			
		||||
}
 | 
			
		||||
@ -17,6 +17,7 @@
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/msc01_ic.h>
 | 
			
		||||
#include <asm/traps.h>
 | 
			
		||||
 | 
			
		||||
static unsigned long _icctrl_msc;
 | 
			
		||||
#define MSC01_IC_REG_BASE	_icctrl_msc
 | 
			
		||||
@ -98,14 +99,13 @@ void ll_msc_irq(void)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
msc_bind_eic_interrupt(unsigned int irq, unsigned int set)
 | 
			
		||||
static void msc_bind_eic_interrupt(int irq, int set)
 | 
			
		||||
{
 | 
			
		||||
	MSCIC_WRITE(MSC01_IC_RAMW,
 | 
			
		||||
		    (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct irq_chip msc_levelirq_type = {
 | 
			
		||||
static struct irq_chip msc_levelirq_type = {
 | 
			
		||||
	.name = "SOC-it-Level",
 | 
			
		||||
	.ack = level_mask_and_ack_msc_irq,
 | 
			
		||||
	.mask = mask_msc_irq,
 | 
			
		||||
@ -115,7 +115,7 @@ struct irq_chip msc_levelirq_type = {
 | 
			
		||||
	.end = end_msc_irq,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct irq_chip msc_edgeirq_type = {
 | 
			
		||||
static struct irq_chip msc_edgeirq_type = {
 | 
			
		||||
	.name = "SOC-it-Edge",
 | 
			
		||||
	.ack = edge_mask_and_ack_msc_irq,
 | 
			
		||||
	.mask = mask_msc_irq,
 | 
			
		||||
@ -128,8 +128,6 @@ struct irq_chip msc_edgeirq_type = {
 | 
			
		||||
 | 
			
		||||
void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq)
 | 
			
		||||
{
 | 
			
		||||
	extern void (*board_bind_eic_interrupt)(unsigned int irq, unsigned int regset);
 | 
			
		||||
 | 
			
		||||
	_icctrl_msc = (unsigned long) ioremap(icubase, 0x40000);
 | 
			
		||||
 | 
			
		||||
	/* Reset interrupt controller - initialises all registers to 0 */
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@
 | 
			
		||||
/* #define DEBUG_SIG */
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_SIG
 | 
			
		||||
#  define DEBUGP(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
 | 
			
		||||
#  define DEBUGP(fmt, args...) printk("%s: " fmt, __func__, ##args)
 | 
			
		||||
#else
 | 
			
		||||
#  define DEBUGP(fmt, args...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										265
									
								
								arch/mips/kernel/smp-cmp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										265
									
								
								arch/mips/kernel/smp-cmp.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,265 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  This program is free software; you can distribute it and/or modify it
 | 
			
		||||
 *  under the terms of the GNU General Public License (Version 2) as
 | 
			
		||||
 *  published by the Free Software Foundation.
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is distributed in the hope it will be useful, but WITHOUT
 | 
			
		||||
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
			
		||||
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 | 
			
		||||
 *  for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License along
 | 
			
		||||
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2007 MIPS Technologies, Inc.
 | 
			
		||||
 *    Chris Dearman (chris@mips.com)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#undef DEBUG
 | 
			
		||||
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/cpumask.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/compiler.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/atomic.h>
 | 
			
		||||
#include <asm/cacheflush.h>
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/processor.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <asm/hardirq.h>
 | 
			
		||||
#include <asm/mmu_context.h>
 | 
			
		||||
#include <asm/smp.h>
 | 
			
		||||
#include <asm/time.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/mipsmtregs.h>
 | 
			
		||||
#include <asm/mips_mt.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Crude manipulation of the CPU masks to control which
 | 
			
		||||
 * which CPU's are brought online during initialisation
 | 
			
		||||
 *
 | 
			
		||||
 * Beware... this needs to be called after CPU discovery
 | 
			
		||||
 * but before CPU bringup
 | 
			
		||||
 */
 | 
			
		||||
static int __init allowcpus(char *str)
 | 
			
		||||
{
 | 
			
		||||
	cpumask_t cpu_allow_map;
 | 
			
		||||
	char buf[256];
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	cpus_clear(cpu_allow_map);
 | 
			
		||||
	if (cpulist_parse(str, cpu_allow_map) == 0) {
 | 
			
		||||
		cpu_set(0, cpu_allow_map);
 | 
			
		||||
		cpus_and(cpu_possible_map, cpu_possible_map, cpu_allow_map);
 | 
			
		||||
		len = cpulist_scnprintf(buf, sizeof(buf)-1, cpu_possible_map);
 | 
			
		||||
		buf[len] = '\0';
 | 
			
		||||
		pr_debug("Allowable CPUs: %s\n", buf);
 | 
			
		||||
		return 1;
 | 
			
		||||
	} else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
__setup("allowcpus=", allowcpus);
 | 
			
		||||
 | 
			
		||||
static void ipi_call_function(unsigned int cpu)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int action = 0;
 | 
			
		||||
 | 
			
		||||
	pr_debug("CPU%d: %s cpu %d status %08x\n",
 | 
			
		||||
		 smp_processor_id(), __func__, cpu, read_c0_status());
 | 
			
		||||
 | 
			
		||||
	switch (cpu) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		action = GIC_IPI_EXT_INTR_CALLFNC_VPE0;
 | 
			
		||||
		break;
 | 
			
		||||
	case 1:
 | 
			
		||||
		action = GIC_IPI_EXT_INTR_CALLFNC_VPE1;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		action = GIC_IPI_EXT_INTR_CALLFNC_VPE2;
 | 
			
		||||
		break;
 | 
			
		||||
	case 3:
 | 
			
		||||
		action = GIC_IPI_EXT_INTR_CALLFNC_VPE3;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	gic_send_ipi(action);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void ipi_resched(unsigned int cpu)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int action = 0;
 | 
			
		||||
 | 
			
		||||
	pr_debug("CPU%d: %s cpu %d status %08x\n",
 | 
			
		||||
		 smp_processor_id(), __func__, cpu, read_c0_status());
 | 
			
		||||
 | 
			
		||||
	switch (cpu) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		action = GIC_IPI_EXT_INTR_RESCHED_VPE0;
 | 
			
		||||
		break;
 | 
			
		||||
	case 1:
 | 
			
		||||
		action = GIC_IPI_EXT_INTR_RESCHED_VPE1;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		action = GIC_IPI_EXT_INTR_RESCHED_VPE2;
 | 
			
		||||
		break;
 | 
			
		||||
	case 3:
 | 
			
		||||
		action = GIC_IPI_EXT_INTR_RESCHED_VPE3;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	gic_send_ipi(action);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FIXME: This isn't restricted to CMP
 | 
			
		||||
 * The SMVP kernel could use GIC interrupts if available
 | 
			
		||||
 */
 | 
			
		||||
void cmp_send_ipi_single(int cpu, unsigned int action)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
 | 
			
		||||
	local_irq_save(flags);
 | 
			
		||||
 | 
			
		||||
	switch (action) {
 | 
			
		||||
	case SMP_CALL_FUNCTION:
 | 
			
		||||
		ipi_call_function(cpu);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case SMP_RESCHEDULE_YOURSELF:
 | 
			
		||||
		ipi_resched(cpu);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	local_irq_restore(flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cmp_send_ipi_mask(cpumask_t mask, unsigned int action)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
 | 
			
		||||
	for_each_cpu_mask(i, mask)
 | 
			
		||||
		cmp_send_ipi_single(i, action);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cmp_init_secondary(void)
 | 
			
		||||
{
 | 
			
		||||
	struct cpuinfo_mips *c = ¤t_cpu_data;
 | 
			
		||||
 | 
			
		||||
	/* Assume GIC is present */
 | 
			
		||||
	change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP6 |
 | 
			
		||||
				 STATUSF_IP7);
 | 
			
		||||
 | 
			
		||||
	/* Enable per-cpu interrupts: platform specific */
 | 
			
		||||
 | 
			
		||||
	c->core = (read_c0_ebase() >> 1) & 0xff;
 | 
			
		||||
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
 | 
			
		||||
	c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_SMTC
 | 
			
		||||
	c->tc_id  = (read_c0_tcbind() >> TCBIND_CURTC_SHIFT) & TCBIND_CURTC;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cmp_smp_finish(void)
 | 
			
		||||
{
 | 
			
		||||
	pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__);
 | 
			
		||||
 | 
			
		||||
	/* CDFIXME: remove this? */
 | 
			
		||||
	write_c0_compare(read_c0_count() + (8 * mips_hpt_frequency / HZ));
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_FPAFF
 | 
			
		||||
	/* If we have an FPU, enroll ourselves in the FPU-full mask */
 | 
			
		||||
	if (cpu_has_fpu)
 | 
			
		||||
		cpu_set(smp_processor_id(), mt_fpu_cpumask);
 | 
			
		||||
#endif /* CONFIG_MIPS_MT_FPAFF */
 | 
			
		||||
 | 
			
		||||
	local_irq_enable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cmp_cpus_done(void)
 | 
			
		||||
{
 | 
			
		||||
	pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Setup the PC, SP, and GP of a secondary processor and start it running
 | 
			
		||||
 * smp_bootstrap is the place to resume from
 | 
			
		||||
 * __KSTK_TOS(idle) is apparently the stack pointer
 | 
			
		||||
 * (unsigned long)idle->thread_info the gp
 | 
			
		||||
 */
 | 
			
		||||
static void cmp_boot_secondary(int cpu, struct task_struct *idle)
 | 
			
		||||
{
 | 
			
		||||
	struct thread_info *gp = task_thread_info(idle);
 | 
			
		||||
	unsigned long sp = __KSTK_TOS(idle);
 | 
			
		||||
	unsigned long pc = (unsigned long)&smp_bootstrap;
 | 
			
		||||
	unsigned long a0 = 0;
 | 
			
		||||
 | 
			
		||||
	pr_debug("SMPCMP: CPU%d: %s cpu %d\n", smp_processor_id(),
 | 
			
		||||
		__func__, cpu);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	/* Needed? */
 | 
			
		||||
	flush_icache_range((unsigned long)gp,
 | 
			
		||||
			   (unsigned long)(gp + sizeof(struct thread_info)));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	amon_cpu_start(cpu, pc, sp, gp, a0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Common setup before any secondaries are started
 | 
			
		||||
 */
 | 
			
		||||
void __init cmp_smp_setup(void)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int ncpu = 0;
 | 
			
		||||
 | 
			
		||||
	pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_FPAFF
 | 
			
		||||
	/* If we have an FPU, enroll ourselves in the FPU-full mask */
 | 
			
		||||
	if (cpu_has_fpu)
 | 
			
		||||
		cpu_set(0, mt_fpu_cpumask);
 | 
			
		||||
#endif /* CONFIG_MIPS_MT_FPAFF */
 | 
			
		||||
 | 
			
		||||
	for (i = 1; i < NR_CPUS; i++) {
 | 
			
		||||
		if (amon_cpu_avail(i)) {
 | 
			
		||||
			cpu_set(i, phys_cpu_present_map);
 | 
			
		||||
			__cpu_number_map[i]	= ++ncpu;
 | 
			
		||||
			__cpu_logical_map[ncpu]	= i;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_mipsmt) {
 | 
			
		||||
		unsigned int nvpe, mvpconf0 = read_c0_mvpconf0();
 | 
			
		||||
 | 
			
		||||
		nvpe = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
 | 
			
		||||
		smp_num_siblings = nvpe;
 | 
			
		||||
	}
 | 
			
		||||
	pr_info("Detected %i available secondary CPU(s)\n", ncpu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init cmp_prepare_cpus(unsigned int max_cpus)
 | 
			
		||||
{
 | 
			
		||||
	pr_debug("SMPCMP: CPU%d: %s max_cpus=%d\n",
 | 
			
		||||
		 smp_processor_id(), __func__, max_cpus);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * FIXME: some of these options are per-system, some per-core and
 | 
			
		||||
	 * some per-cpu
 | 
			
		||||
	 */
 | 
			
		||||
	mips_mt_set_cpuoptions();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct plat_smp_ops cmp_smp_ops = {
 | 
			
		||||
	.send_ipi_single	= cmp_send_ipi_single,
 | 
			
		||||
	.send_ipi_mask		= cmp_send_ipi_mask,
 | 
			
		||||
	.init_secondary		= cmp_init_secondary,
 | 
			
		||||
	.smp_finish		= cmp_smp_finish,
 | 
			
		||||
	.cpus_done		= cmp_cpus_done,
 | 
			
		||||
	.boot_secondary		= cmp_boot_secondary,
 | 
			
		||||
	.smp_setup		= cmp_smp_setup,
 | 
			
		||||
	.prepare_cpus		= cmp_prepare_cpus,
 | 
			
		||||
};
 | 
			
		||||
@ -36,110 +36,7 @@
 | 
			
		||||
#include <asm/mipsmtregs.h>
 | 
			
		||||
#include <asm/mips_mt.h>
 | 
			
		||||
 | 
			
		||||
#define MIPS_CPU_IPI_RESCHED_IRQ 0
 | 
			
		||||
#define MIPS_CPU_IPI_CALL_IRQ 1
 | 
			
		||||
 | 
			
		||||
static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static void dump_mtregisters(int vpe, int tc)
 | 
			
		||||
{
 | 
			
		||||
	printk("vpe %d tc %d\n", vpe, tc);
 | 
			
		||||
 | 
			
		||||
	settc(tc);
 | 
			
		||||
 | 
			
		||||
	printk("  c0 status  0x%lx\n", read_vpe_c0_status());
 | 
			
		||||
	printk("  vpecontrol 0x%lx\n", read_vpe_c0_vpecontrol());
 | 
			
		||||
	printk("  vpeconf0    0x%lx\n", read_vpe_c0_vpeconf0());
 | 
			
		||||
	printk("  tcstatus 0x%lx\n", read_tc_c0_tcstatus());
 | 
			
		||||
	printk("  tcrestart 0x%lx\n", read_tc_c0_tcrestart());
 | 
			
		||||
	printk("  tcbind 0x%lx\n", read_tc_c0_tcbind());
 | 
			
		||||
	printk("  tchalt 0x%lx\n", read_tc_c0_tchalt());
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void __init sanitize_tlb_entries(void)
 | 
			
		||||
{
 | 
			
		||||
	int i, tlbsiz;
 | 
			
		||||
	unsigned long mvpconf0, ncpu;
 | 
			
		||||
 | 
			
		||||
	if (!cpu_has_mipsmt)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Enable VPC */
 | 
			
		||||
	set_c0_mvpcontrol(MVPCONTROL_VPC);
 | 
			
		||||
 | 
			
		||||
	back_to_back_c0_hazard();
 | 
			
		||||
 | 
			
		||||
	/* Disable TLB sharing */
 | 
			
		||||
	clear_c0_mvpcontrol(MVPCONTROL_STLB);
 | 
			
		||||
 | 
			
		||||
	mvpconf0 = read_c0_mvpconf0();
 | 
			
		||||
 | 
			
		||||
	printk(KERN_INFO "MVPConf0 0x%lx TLBS %lx PTLBE %ld\n", mvpconf0,
 | 
			
		||||
		   (mvpconf0 & MVPCONF0_TLBS) >> MVPCONF0_TLBS_SHIFT,
 | 
			
		||||
			   (mvpconf0 & MVPCONF0_PTLBE) >> MVPCONF0_PTLBE_SHIFT);
 | 
			
		||||
 | 
			
		||||
	tlbsiz = (mvpconf0 & MVPCONF0_PTLBE) >> MVPCONF0_PTLBE_SHIFT;
 | 
			
		||||
	ncpu = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
 | 
			
		||||
 | 
			
		||||
	printk(" tlbsiz %d ncpu %ld\n", tlbsiz, ncpu);
 | 
			
		||||
 | 
			
		||||
	if (tlbsiz > 0) {
 | 
			
		||||
		/* share them out across the vpe's */
 | 
			
		||||
		tlbsiz /= ncpu;
 | 
			
		||||
 | 
			
		||||
		printk(KERN_INFO "setting Config1.MMU_size to %d\n", tlbsiz);
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < ncpu; i++) {
 | 
			
		||||
			settc(i);
 | 
			
		||||
 | 
			
		||||
			if (i == 0)
 | 
			
		||||
				write_c0_config1((read_c0_config1() & ~(0x3f << 25)) | (tlbsiz << 25));
 | 
			
		||||
			else
 | 
			
		||||
				write_vpe_c0_config1((read_vpe_c0_config1() & ~(0x3f << 25)) |
 | 
			
		||||
						   (tlbsiz << 25));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	clear_c0_mvpcontrol(MVPCONTROL_VPC);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipi_resched_dispatch(void)
 | 
			
		||||
{
 | 
			
		||||
	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipi_call_dispatch(void)
 | 
			
		||||
{
 | 
			
		||||
	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
 | 
			
		||||
{
 | 
			
		||||
	return IRQ_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
 | 
			
		||||
{
 | 
			
		||||
	smp_call_function_interrupt();
 | 
			
		||||
 | 
			
		||||
	return IRQ_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct irqaction irq_resched = {
 | 
			
		||||
	.handler	= ipi_resched_interrupt,
 | 
			
		||||
	.flags		= IRQF_DISABLED|IRQF_PERCPU,
 | 
			
		||||
	.name		= "IPI_resched"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct irqaction irq_call = {
 | 
			
		||||
	.handler	= ipi_call_interrupt,
 | 
			
		||||
	.flags		= IRQF_DISABLED|IRQF_PERCPU,
 | 
			
		||||
	.name		= "IPI_call"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void __init smp_copy_vpe_config(void)
 | 
			
		||||
static void __init smvp_copy_vpe_config(void)
 | 
			
		||||
{
 | 
			
		||||
	write_vpe_c0_status(
 | 
			
		||||
		(read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0);
 | 
			
		||||
@ -156,7 +53,7 @@ static void __init smp_copy_vpe_config(void)
 | 
			
		||||
	write_vpe_c0_count(read_c0_count());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned int __init smp_vpe_init(unsigned int tc, unsigned int mvpconf0,
 | 
			
		||||
static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0,
 | 
			
		||||
	unsigned int ncpu)
 | 
			
		||||
{
 | 
			
		||||
	if (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT))
 | 
			
		||||
@ -182,12 +79,12 @@ static unsigned int __init smp_vpe_init(unsigned int tc, unsigned int mvpconf0,
 | 
			
		||||
	write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);
 | 
			
		||||
 | 
			
		||||
	if (tc != 0)
 | 
			
		||||
		smp_copy_vpe_config();
 | 
			
		||||
		smvp_copy_vpe_config();
 | 
			
		||||
 | 
			
		||||
	return ncpu;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0)
 | 
			
		||||
static void __init smvp_tc_init(unsigned int tc, unsigned int mvpconf0)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long tmp;
 | 
			
		||||
 | 
			
		||||
@ -254,15 +151,20 @@ static void vsmp_send_ipi_mask(cpumask_t mask, unsigned int action)
 | 
			
		||||
 | 
			
		||||
static void __cpuinit vsmp_init_secondary(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Enable per-cpu interrupts */
 | 
			
		||||
	extern int gic_present;
 | 
			
		||||
 | 
			
		||||
	/* This is Malta specific: IPI,performance and timer inetrrupts */
 | 
			
		||||
	write_c0_status((read_c0_status() & ~ST0_IM ) |
 | 
			
		||||
	                (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7));
 | 
			
		||||
	if (gic_present)
 | 
			
		||||
		change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
 | 
			
		||||
					 STATUSF_IP6 | STATUSF_IP7);
 | 
			
		||||
	else
 | 
			
		||||
		change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 |
 | 
			
		||||
					 STATUSF_IP6 | STATUSF_IP7);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __cpuinit vsmp_smp_finish(void)
 | 
			
		||||
{
 | 
			
		||||
	/* CDFIXME: remove this? */
 | 
			
		||||
	write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_FPAFF
 | 
			
		||||
@ -323,7 +225,7 @@ static void __cpuinit vsmp_boot_secondary(int cpu, struct task_struct *idle)
 | 
			
		||||
/*
 | 
			
		||||
 * Common setup before any secondaries are started
 | 
			
		||||
 * Make sure all CPU's are in a sensible state before we boot any of the
 | 
			
		||||
 * secondarys
 | 
			
		||||
 * secondaries
 | 
			
		||||
 */
 | 
			
		||||
static void __init vsmp_smp_setup(void)
 | 
			
		||||
{
 | 
			
		||||
@ -356,8 +258,8 @@ static void __init vsmp_smp_setup(void)
 | 
			
		||||
	for (tc = 0; tc <= ntc; tc++) {
 | 
			
		||||
		settc(tc);
 | 
			
		||||
 | 
			
		||||
		smp_tc_init(tc, mvpconf0);
 | 
			
		||||
		ncpu = smp_vpe_init(tc, mvpconf0, ncpu);
 | 
			
		||||
		smvp_tc_init(tc, mvpconf0);
 | 
			
		||||
		ncpu = smvp_vpe_init(tc, mvpconf0, ncpu);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Release config state */
 | 
			
		||||
@ -371,21 +273,6 @@ static void __init vsmp_smp_setup(void)
 | 
			
		||||
static void __init vsmp_prepare_cpus(unsigned int max_cpus)
 | 
			
		||||
{
 | 
			
		||||
	mips_mt_set_cpuoptions();
 | 
			
		||||
 | 
			
		||||
	/* set up ipi interrupts */
 | 
			
		||||
	if (cpu_has_vint) {
 | 
			
		||||
		set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
 | 
			
		||||
		set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
 | 
			
		||||
	cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
 | 
			
		||||
 | 
			
		||||
	setup_irq(cpu_ipi_resched_irq, &irq_resched);
 | 
			
		||||
	setup_irq(cpu_ipi_call_irq, &irq_call);
 | 
			
		||||
 | 
			
		||||
	set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
 | 
			
		||||
	set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct plat_smp_ops vsmp_smp_ops = {
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@
 | 
			
		||||
#include <asm/atomic.h>
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/processor.h>
 | 
			
		||||
#include <asm/r4k-timer.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <asm/mmu_context.h>
 | 
			
		||||
#include <asm/time.h>
 | 
			
		||||
@ -125,6 +126,8 @@ asmlinkage __cpuinit void start_secondary(void)
 | 
			
		||||
 | 
			
		||||
	cpu_set(cpu, cpu_callin_map);
 | 
			
		||||
 | 
			
		||||
	synchronise_count_slave();
 | 
			
		||||
 | 
			
		||||
	cpu_idle();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -287,6 +290,7 @@ void smp_send_stop(void)
 | 
			
		||||
void __init smp_cpus_done(unsigned int max_cpus)
 | 
			
		||||
{
 | 
			
		||||
	mp_ops->cpus_done();
 | 
			
		||||
	synchronise_count_master();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* called from main before smp_init() */
 | 
			
		||||
 | 
			
		||||
@ -174,14 +174,6 @@ static int clock_hang_reported[NR_CPUS];
 | 
			
		||||
 | 
			
		||||
#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */
 | 
			
		||||
 | 
			
		||||
/* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */
 | 
			
		||||
 | 
			
		||||
void __init sanitize_tlb_entries(void)
 | 
			
		||||
{
 | 
			
		||||
	printk("Deprecated sanitize_tlb_entries() invoked\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Configure shared TLB - VPC configuration bit must be set by caller
 | 
			
		||||
 */
 | 
			
		||||
@ -339,7 +331,8 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
 | 
			
		||||
	/* In general, all TCs should have the same cpu_data indications */
 | 
			
		||||
	memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
 | 
			
		||||
	/* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
 | 
			
		||||
	if (cpu_data[0].cputype == CPU_34K)
 | 
			
		||||
	if (cpu_data[0].cputype == CPU_34K ||
 | 
			
		||||
	    cpu_data[0].cputype == CPU_1004K)
 | 
			
		||||
		cpu_data[cpu].options &= ~MIPS_CPU_FPU;
 | 
			
		||||
	cpu_data[cpu].vpe_id = vpe;
 | 
			
		||||
	cpu_data[cpu].tc_id = tc;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										221
									
								
								arch/mips/kernel/spram.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								arch/mips/kernel/spram.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,221 @@
 | 
			
		||||
/*
 | 
			
		||||
 * MIPS SPRAM support
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version
 | 
			
		||||
 * 2 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2007, 2008 MIPS Technologies, Inc.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/ptrace.h>
 | 
			
		||||
#include <linux/stddef.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/fpu.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <asm/r4kcache.h>
 | 
			
		||||
#include <asm/hazards.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * These definitions are correct for the 24K/34K/74K SPRAM sample
 | 
			
		||||
 * implementation. The 4KS interpreted the tags differently...
 | 
			
		||||
 */
 | 
			
		||||
#define SPRAM_TAG0_ENABLE	0x00000080
 | 
			
		||||
#define SPRAM_TAG0_PA_MASK	0xfffff000
 | 
			
		||||
#define SPRAM_TAG1_SIZE_MASK	0xfffff000
 | 
			
		||||
 | 
			
		||||
#define SPRAM_TAG_STRIDE	8
 | 
			
		||||
 | 
			
		||||
#define ERRCTL_SPRAM		(1 << 28)
 | 
			
		||||
 | 
			
		||||
/* errctl access */
 | 
			
		||||
#define read_c0_errctl(x) read_c0_ecc(x)
 | 
			
		||||
#define write_c0_errctl(x) write_c0_ecc(x)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Different semantics to the set_c0_* function built by __BUILD_SET_C0
 | 
			
		||||
 */
 | 
			
		||||
static __cpuinit unsigned int bis_c0_errctl(unsigned int set)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int res;
 | 
			
		||||
	res = read_c0_errctl();
 | 
			
		||||
	write_c0_errctl(res | set);
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static __cpuinit void ispram_store_tag(unsigned int offset, unsigned int data)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int errctl;
 | 
			
		||||
 | 
			
		||||
	/* enable SPRAM tag access */
 | 
			
		||||
	errctl = bis_c0_errctl(ERRCTL_SPRAM);
 | 
			
		||||
	ehb();
 | 
			
		||||
 | 
			
		||||
	write_c0_taglo(data);
 | 
			
		||||
	ehb();
 | 
			
		||||
 | 
			
		||||
	cache_op(Index_Store_Tag_I, CKSEG0|offset);
 | 
			
		||||
	ehb();
 | 
			
		||||
 | 
			
		||||
	write_c0_errctl(errctl);
 | 
			
		||||
	ehb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static __cpuinit unsigned int ispram_load_tag(unsigned int offset)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int data;
 | 
			
		||||
	unsigned int errctl;
 | 
			
		||||
 | 
			
		||||
	/* enable SPRAM tag access */
 | 
			
		||||
	errctl = bis_c0_errctl(ERRCTL_SPRAM);
 | 
			
		||||
	ehb();
 | 
			
		||||
	cache_op(Index_Load_Tag_I, CKSEG0 | offset);
 | 
			
		||||
	ehb();
 | 
			
		||||
	data = read_c0_taglo();
 | 
			
		||||
	ehb();
 | 
			
		||||
	write_c0_errctl(errctl);
 | 
			
		||||
	ehb();
 | 
			
		||||
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static __cpuinit void dspram_store_tag(unsigned int offset, unsigned int data)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int errctl;
 | 
			
		||||
 | 
			
		||||
	/* enable SPRAM tag access */
 | 
			
		||||
	errctl = bis_c0_errctl(ERRCTL_SPRAM);
 | 
			
		||||
	ehb();
 | 
			
		||||
	write_c0_dtaglo(data);
 | 
			
		||||
	ehb();
 | 
			
		||||
	cache_op(Index_Store_Tag_D, CKSEG0 | offset);
 | 
			
		||||
	ehb();
 | 
			
		||||
	write_c0_errctl(errctl);
 | 
			
		||||
	ehb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static __cpuinit unsigned int dspram_load_tag(unsigned int offset)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int data;
 | 
			
		||||
	unsigned int errctl;
 | 
			
		||||
 | 
			
		||||
	errctl = bis_c0_errctl(ERRCTL_SPRAM);
 | 
			
		||||
	ehb();
 | 
			
		||||
	cache_op(Index_Load_Tag_D, CKSEG0 | offset);
 | 
			
		||||
	ehb();
 | 
			
		||||
	data = read_c0_dtaglo();
 | 
			
		||||
	ehb();
 | 
			
		||||
	write_c0_errctl(errctl);
 | 
			
		||||
	ehb();
 | 
			
		||||
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static __cpuinit void probe_spram(char *type,
 | 
			
		||||
	    unsigned int base,
 | 
			
		||||
	    unsigned int (*read)(unsigned int),
 | 
			
		||||
	    void (*write)(unsigned int, unsigned int))
 | 
			
		||||
{
 | 
			
		||||
	unsigned int firstsize = 0, lastsize = 0;
 | 
			
		||||
	unsigned int firstpa = 0, lastpa = 0, pa = 0;
 | 
			
		||||
	unsigned int offset = 0;
 | 
			
		||||
	unsigned int size, tag0, tag1;
 | 
			
		||||
	unsigned int enabled;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The limit is arbitrary but avoids the loop running away if
 | 
			
		||||
	 * the SPRAM tags are implemented differently
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 8; i++) {
 | 
			
		||||
		tag0 = read(offset);
 | 
			
		||||
		tag1 = read(offset+SPRAM_TAG_STRIDE);
 | 
			
		||||
		pr_debug("DBG %s%d: tag0=%08x tag1=%08x\n",
 | 
			
		||||
			 type, i, tag0, tag1);
 | 
			
		||||
 | 
			
		||||
		size = tag1 & SPRAM_TAG1_SIZE_MASK;
 | 
			
		||||
 | 
			
		||||
		if (size == 0)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		if (i != 0) {
 | 
			
		||||
			/* tags may repeat... */
 | 
			
		||||
			if ((pa == firstpa && size == firstsize) ||
 | 
			
		||||
			    (pa == lastpa && size == lastsize))
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Align base with size */
 | 
			
		||||
		base = (base + size - 1) & ~(size-1);
 | 
			
		||||
 | 
			
		||||
		/* reprogram the base address base address and enable */
 | 
			
		||||
		tag0 = (base & SPRAM_TAG0_PA_MASK) | SPRAM_TAG0_ENABLE;
 | 
			
		||||
		write(offset, tag0);
 | 
			
		||||
 | 
			
		||||
		base += size;
 | 
			
		||||
 | 
			
		||||
		/* reread the tag */
 | 
			
		||||
		tag0 = read(offset);
 | 
			
		||||
		pa = tag0 & SPRAM_TAG0_PA_MASK;
 | 
			
		||||
		enabled = tag0 & SPRAM_TAG0_ENABLE;
 | 
			
		||||
 | 
			
		||||
		if (i == 0) {
 | 
			
		||||
			firstpa = pa;
 | 
			
		||||
			firstsize = size;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		lastpa = pa;
 | 
			
		||||
		lastsize = size;
 | 
			
		||||
 | 
			
		||||
		if (strcmp(type, "DSPRAM") == 0) {
 | 
			
		||||
			unsigned int *vp = (unsigned int *)(CKSEG1 | pa);
 | 
			
		||||
			unsigned int v;
 | 
			
		||||
#define TDAT	0x5a5aa5a5
 | 
			
		||||
			vp[0] = TDAT;
 | 
			
		||||
			vp[1] = ~TDAT;
 | 
			
		||||
 | 
			
		||||
			mb();
 | 
			
		||||
 | 
			
		||||
			v = vp[0];
 | 
			
		||||
			if (v != TDAT)
 | 
			
		||||
				printk(KERN_ERR "vp=%p wrote=%08x got=%08x\n",
 | 
			
		||||
				       vp, TDAT, v);
 | 
			
		||||
			v = vp[1];
 | 
			
		||||
			if (v != ~TDAT)
 | 
			
		||||
				printk(KERN_ERR "vp=%p wrote=%08x got=%08x\n",
 | 
			
		||||
				       vp+1, ~TDAT, v);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		pr_info("%s%d: PA=%08x,Size=%08x%s\n",
 | 
			
		||||
			type, i, pa, size, enabled ? ",enabled" : "");
 | 
			
		||||
		offset += 2 * SPRAM_TAG_STRIDE;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__cpuinit void spram_config(void)
 | 
			
		||||
{
 | 
			
		||||
	struct cpuinfo_mips *c = ¤t_cpu_data;
 | 
			
		||||
	unsigned int config0;
 | 
			
		||||
 | 
			
		||||
	switch (c->cputype) {
 | 
			
		||||
	case CPU_24K:
 | 
			
		||||
	case CPU_34K:
 | 
			
		||||
	case CPU_74K:
 | 
			
		||||
		config0 = read_c0_config();
 | 
			
		||||
		/* FIXME: addresses are Malta specific */
 | 
			
		||||
		if (config0 & (1<<24)) {
 | 
			
		||||
			probe_spram("ISPRAM", 0x1c000000,
 | 
			
		||||
				    &ispram_load_tag, &ispram_store_tag);
 | 
			
		||||
		}
 | 
			
		||||
		if (config0 & (1<<23))
 | 
			
		||||
			probe_spram("DSPRAM", 0x1c100000,
 | 
			
		||||
				    &dspram_load_tag, &dspram_store_tag);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										159
									
								
								arch/mips/kernel/sync-r4k.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								arch/mips/kernel/sync-r4k.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,159 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Count register synchronisation.
 | 
			
		||||
 *
 | 
			
		||||
 * All CPUs will have their count registers synchronised to the CPU0 expirelo
 | 
			
		||||
 * value. This can cause a small timewarp for CPU0. All other CPU's should
 | 
			
		||||
 * not have done anything significant (but they may have had interrupts
 | 
			
		||||
 * enabled briefly - prom_smp_finish() should not be responsible for enabling
 | 
			
		||||
 * interrupts...)
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: broken for SMTC
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irqflags.h>
 | 
			
		||||
#include <linux/r4k-timer.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/atomic.h>
 | 
			
		||||
#include <asm/barrier.h>
 | 
			
		||||
#include <asm/cpumask.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
 | 
			
		||||
static atomic_t __initdata count_start_flag = ATOMIC_INIT(0);
 | 
			
		||||
static atomic_t __initdata count_count_start = ATOMIC_INIT(0);
 | 
			
		||||
static atomic_t __initdata count_count_stop = ATOMIC_INIT(0);
 | 
			
		||||
 | 
			
		||||
#define COUNTON	100
 | 
			
		||||
#define NR_LOOPS 5
 | 
			
		||||
 | 
			
		||||
void __init synchronise_count_master(void)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	unsigned int initcount;
 | 
			
		||||
	int nslaves;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_SMTC
 | 
			
		||||
	/*
 | 
			
		||||
	 * SMTC needs to synchronise per VPE, not per CPU
 | 
			
		||||
	 * ignore for now
 | 
			
		||||
	 */
 | 
			
		||||
	return;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	pr_info("Checking COUNT synchronization across %u CPUs: ",
 | 
			
		||||
		num_online_cpus());
 | 
			
		||||
 | 
			
		||||
	local_irq_save(flags);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Notify the slaves that it's time to start
 | 
			
		||||
	 */
 | 
			
		||||
	atomic_set(&count_start_flag, 1);
 | 
			
		||||
	smp_wmb();
 | 
			
		||||
 | 
			
		||||
	/* Count will be initialised to expirelo for all CPU's */
 | 
			
		||||
	initcount = expirelo;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * We loop a few times to get a primed instruction cache,
 | 
			
		||||
	 * then the last pass is more or less synchronised and
 | 
			
		||||
	 * the master and slaves each set their cycle counters to a known
 | 
			
		||||
	 * value all at once. This reduces the chance of having random offsets
 | 
			
		||||
	 * between the processors, and guarantees that the maximum
 | 
			
		||||
	 * delay between the cycle counters is never bigger than
 | 
			
		||||
	 * the latency of information-passing (cachelines) between
 | 
			
		||||
	 * two CPUs.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	nslaves = num_online_cpus()-1;
 | 
			
		||||
	for (i = 0; i < NR_LOOPS; i++) {
 | 
			
		||||
		/* slaves loop on '!= ncpus' */
 | 
			
		||||
		while (atomic_read(&count_count_start) != nslaves)
 | 
			
		||||
			mb();
 | 
			
		||||
		atomic_set(&count_count_stop, 0);
 | 
			
		||||
		smp_wmb();
 | 
			
		||||
 | 
			
		||||
		/* this lets the slaves write their count register */
 | 
			
		||||
		atomic_inc(&count_count_start);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Everyone initialises count in the last loop:
 | 
			
		||||
		 */
 | 
			
		||||
		if (i == NR_LOOPS-1)
 | 
			
		||||
			write_c0_count(initcount);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Wait for all slaves to leave the synchronization point:
 | 
			
		||||
		 */
 | 
			
		||||
		while (atomic_read(&count_count_stop) != nslaves)
 | 
			
		||||
			mb();
 | 
			
		||||
		atomic_set(&count_count_start, 0);
 | 
			
		||||
		smp_wmb();
 | 
			
		||||
		atomic_inc(&count_count_stop);
 | 
			
		||||
	}
 | 
			
		||||
	/* Arrange for an interrupt in a short while */
 | 
			
		||||
	write_c0_compare(read_c0_count() + COUNTON);
 | 
			
		||||
 | 
			
		||||
	local_irq_restore(flags);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * i386 code reported the skew here, but the
 | 
			
		||||
	 * count registers were almost certainly out of sync
 | 
			
		||||
	 * so no point in alarming people
 | 
			
		||||
	 */
 | 
			
		||||
	printk("done.\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init synchronise_count_slave(void)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	unsigned int initcount;
 | 
			
		||||
	int ncpus;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_SMTC
 | 
			
		||||
	/*
 | 
			
		||||
	 * SMTC needs to synchronise per VPE, not per CPU
 | 
			
		||||
	 * ignore for now
 | 
			
		||||
	 */
 | 
			
		||||
	return;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	local_irq_save(flags);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Not every cpu is online at the time this gets called,
 | 
			
		||||
	 * so we first wait for the master to say everyone is ready
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	while (!atomic_read(&count_start_flag))
 | 
			
		||||
		mb();
 | 
			
		||||
 | 
			
		||||
	/* Count will be initialised to expirelo for all CPU's */
 | 
			
		||||
	initcount = expirelo;
 | 
			
		||||
 | 
			
		||||
	ncpus = num_online_cpus();
 | 
			
		||||
	for (i = 0; i < NR_LOOPS; i++) {
 | 
			
		||||
		atomic_inc(&count_count_start);
 | 
			
		||||
		while (atomic_read(&count_count_start) != ncpus)
 | 
			
		||||
			mb();
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Everyone initialises count in the last loop:
 | 
			
		||||
		 */
 | 
			
		||||
		if (i == NR_LOOPS-1)
 | 
			
		||||
			write_c0_count(initcount);
 | 
			
		||||
 | 
			
		||||
		atomic_inc(&count_count_stop);
 | 
			
		||||
		while (atomic_read(&count_count_stop) != ncpus)
 | 
			
		||||
			mb();
 | 
			
		||||
	}
 | 
			
		||||
	/* Arrange for an interrupt in a short while */
 | 
			
		||||
	write_c0_compare(read_c0_count() + COUNTON);
 | 
			
		||||
 | 
			
		||||
	local_irq_restore(flags);
 | 
			
		||||
}
 | 
			
		||||
#undef NR_LOOPS
 | 
			
		||||
#endif
 | 
			
		||||
@ -38,7 +38,6 @@ int __weak rtc_mips_set_time(unsigned long sec)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(rtc_mips_set_time);
 | 
			
		||||
 | 
			
		||||
int __weak rtc_mips_set_mmss(unsigned long nowtime)
 | 
			
		||||
{
 | 
			
		||||
@ -50,13 +49,11 @@ int update_persistent_clock(struct timespec now)
 | 
			
		||||
	return rtc_mips_set_mmss(now.tv_sec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int null_perf_irq(void)
 | 
			
		||||
static int null_perf_irq(void)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(null_perf_irq);
 | 
			
		||||
 | 
			
		||||
int (*perf_irq)(void) = null_perf_irq;
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(perf_irq);
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@
 | 
			
		||||
#include <linux/kallsyms.h>
 | 
			
		||||
#include <linux/bootmem.h>
 | 
			
		||||
#include <linux/interrupt.h>
 | 
			
		||||
#include <linux/ptrace.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/branch.h>
 | 
			
		||||
@ -80,19 +81,22 @@ void (*board_bind_eic_interrupt)(int irq, int regset);
 | 
			
		||||
 | 
			
		||||
static void show_raw_backtrace(unsigned long reg29)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long *sp = (unsigned long *)reg29;
 | 
			
		||||
	unsigned long *sp = (unsigned long *)(reg29 & ~3);
 | 
			
		||||
	unsigned long addr;
 | 
			
		||||
 | 
			
		||||
	printk("Call Trace:");
 | 
			
		||||
#ifdef CONFIG_KALLSYMS
 | 
			
		||||
	printk("\n");
 | 
			
		||||
#endif
 | 
			
		||||
	while (!kstack_end(sp)) {
 | 
			
		||||
		addr = *sp++;
 | 
			
		||||
		if (__kernel_text_address(addr))
 | 
			
		||||
			print_ip_sym(addr);
 | 
			
		||||
#define IS_KVA01(a) ((((unsigned int)a) & 0xc0000000) == 0x80000000)
 | 
			
		||||
	if (IS_KVA01(sp)) {
 | 
			
		||||
		while (!kstack_end(sp)) {
 | 
			
		||||
			addr = *sp++;
 | 
			
		||||
			if (__kernel_text_address(addr))
 | 
			
		||||
				print_ip_sym(addr);
 | 
			
		||||
		}
 | 
			
		||||
		printk("\n");
 | 
			
		||||
	}
 | 
			
		||||
	printk("\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_KALLSYMS
 | 
			
		||||
@ -192,16 +196,19 @@ EXPORT_SYMBOL(dump_stack);
 | 
			
		||||
static void show_code(unsigned int __user *pc)
 | 
			
		||||
{
 | 
			
		||||
	long i;
 | 
			
		||||
	unsigned short __user *pc16 = NULL;
 | 
			
		||||
 | 
			
		||||
	printk("\nCode:");
 | 
			
		||||
 | 
			
		||||
	if ((unsigned long)pc & 1)
 | 
			
		||||
		pc16 = (unsigned short __user *)((unsigned long)pc & ~1);
 | 
			
		||||
	for(i = -3 ; i < 6 ; i++) {
 | 
			
		||||
		unsigned int insn;
 | 
			
		||||
		if (__get_user(insn, pc + i)) {
 | 
			
		||||
		if (pc16 ? __get_user(insn, pc16 + i) : __get_user(insn, pc + i)) {
 | 
			
		||||
			printk(" (Bad address in epc)\n");
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		printk("%c%08x%c", (i?' ':'<'), insn, (i?' ':'>'));
 | 
			
		||||
		printk("%c%0*x%c", (i?' ':'<'), pc16 ? 4 : 8, insn, (i?' ':'>'));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -311,10 +318,21 @@ void show_regs(struct pt_regs *regs)
 | 
			
		||||
 | 
			
		||||
void show_registers(const struct pt_regs *regs)
 | 
			
		||||
{
 | 
			
		||||
	const int field = 2 * sizeof(unsigned long);
 | 
			
		||||
 | 
			
		||||
	__show_regs(regs);
 | 
			
		||||
	print_modules();
 | 
			
		||||
	printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
 | 
			
		||||
	        current->comm, task_pid_nr(current), current_thread_info(), current);
 | 
			
		||||
	printk("Process %s (pid: %d, threadinfo=%p, task=%p, tls=%0*lx)\n",
 | 
			
		||||
	       current->comm, current->pid, current_thread_info(), current,
 | 
			
		||||
	      field, current_thread_info()->tp_value);
 | 
			
		||||
	if (cpu_has_userlocal) {
 | 
			
		||||
		unsigned long tls;
 | 
			
		||||
 | 
			
		||||
		tls = read_c0_userlocal();
 | 
			
		||||
		if (tls != current_thread_info()->tp_value)
 | 
			
		||||
			printk("*HwTLS: %0*lx\n", field, tls);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	show_stacktrace(current, regs);
 | 
			
		||||
	show_code((unsigned int __user *) regs->cp0_epc);
 | 
			
		||||
	printk("\n");
 | 
			
		||||
@ -657,10 +675,46 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 | 
			
		||||
	force_sig_info(SIGFPE, &info, current);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
 | 
			
		||||
	const char *str)
 | 
			
		||||
{
 | 
			
		||||
	siginfo_t info;
 | 
			
		||||
	char b[40];
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * A short test says that IRIX 5.3 sends SIGTRAP for all trap
 | 
			
		||||
	 * insns, even for trap and break codes that indicate arithmetic
 | 
			
		||||
	 * failures.  Weird ...
 | 
			
		||||
	 * But should we continue the brokenness???  --macro
 | 
			
		||||
	 */
 | 
			
		||||
	switch (code) {
 | 
			
		||||
	case BRK_OVERFLOW:
 | 
			
		||||
	case BRK_DIVZERO:
 | 
			
		||||
		scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
 | 
			
		||||
		die_if_kernel(b, regs);
 | 
			
		||||
		if (code == BRK_DIVZERO)
 | 
			
		||||
			info.si_code = FPE_INTDIV;
 | 
			
		||||
		else
 | 
			
		||||
			info.si_code = FPE_INTOVF;
 | 
			
		||||
		info.si_signo = SIGFPE;
 | 
			
		||||
		info.si_errno = 0;
 | 
			
		||||
		info.si_addr = (void __user *) regs->cp0_epc;
 | 
			
		||||
		force_sig_info(SIGFPE, &info, current);
 | 
			
		||||
		break;
 | 
			
		||||
	case BRK_BUG:
 | 
			
		||||
		die_if_kernel("Kernel bug detected", regs);
 | 
			
		||||
		force_sig(SIGTRAP, current);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
 | 
			
		||||
		die_if_kernel(b, regs);
 | 
			
		||||
		force_sig(SIGTRAP, current);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
asmlinkage void do_bp(struct pt_regs *regs)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int opcode, bcode;
 | 
			
		||||
	siginfo_t info;
 | 
			
		||||
 | 
			
		||||
	if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
 | 
			
		||||
		goto out_sigsegv;
 | 
			
		||||
@ -672,35 +726,10 @@ asmlinkage void do_bp(struct pt_regs *regs)
 | 
			
		||||
	 * We handle both cases with a simple heuristics.  --macro
 | 
			
		||||
	 */
 | 
			
		||||
	bcode = ((opcode >> 6) & ((1 << 20) - 1));
 | 
			
		||||
	if (bcode < (1 << 10))
 | 
			
		||||
		bcode <<= 10;
 | 
			
		||||
	if (bcode >= (1 << 10))
 | 
			
		||||
		bcode >>= 10;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * (A short test says that IRIX 5.3 sends SIGTRAP for all break
 | 
			
		||||
	 * insns, even for break codes that indicate arithmetic failures.
 | 
			
		||||
	 * Weird ...)
 | 
			
		||||
	 * But should we continue the brokenness???  --macro
 | 
			
		||||
	 */
 | 
			
		||||
	switch (bcode) {
 | 
			
		||||
	case BRK_OVERFLOW << 10:
 | 
			
		||||
	case BRK_DIVZERO << 10:
 | 
			
		||||
		die_if_kernel("Break instruction in kernel code", regs);
 | 
			
		||||
		if (bcode == (BRK_DIVZERO << 10))
 | 
			
		||||
			info.si_code = FPE_INTDIV;
 | 
			
		||||
		else
 | 
			
		||||
			info.si_code = FPE_INTOVF;
 | 
			
		||||
		info.si_signo = SIGFPE;
 | 
			
		||||
		info.si_errno = 0;
 | 
			
		||||
		info.si_addr = (void __user *) regs->cp0_epc;
 | 
			
		||||
		force_sig_info(SIGFPE, &info, current);
 | 
			
		||||
		break;
 | 
			
		||||
	case BRK_BUG:
 | 
			
		||||
		die("Kernel bug detected", regs);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		die_if_kernel("Break instruction in kernel code", regs);
 | 
			
		||||
		force_sig(SIGTRAP, current);
 | 
			
		||||
	}
 | 
			
		||||
	do_trap_or_bp(regs, bcode, "Break");
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
out_sigsegv:
 | 
			
		||||
@ -710,7 +739,6 @@ out_sigsegv:
 | 
			
		||||
asmlinkage void do_tr(struct pt_regs *regs)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int opcode, tcode = 0;
 | 
			
		||||
	siginfo_t info;
 | 
			
		||||
 | 
			
		||||
	if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
 | 
			
		||||
		goto out_sigsegv;
 | 
			
		||||
@ -719,32 +747,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
 | 
			
		||||
	if (!(opcode & OPCODE))
 | 
			
		||||
		tcode = ((opcode >> 6) & ((1 << 10) - 1));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * (A short test says that IRIX 5.3 sends SIGTRAP for all trap
 | 
			
		||||
	 * insns, even for trap codes that indicate arithmetic failures.
 | 
			
		||||
	 * Weird ...)
 | 
			
		||||
	 * But should we continue the brokenness???  --macro
 | 
			
		||||
	 */
 | 
			
		||||
	switch (tcode) {
 | 
			
		||||
	case BRK_OVERFLOW:
 | 
			
		||||
	case BRK_DIVZERO:
 | 
			
		||||
		die_if_kernel("Trap instruction in kernel code", regs);
 | 
			
		||||
		if (tcode == BRK_DIVZERO)
 | 
			
		||||
			info.si_code = FPE_INTDIV;
 | 
			
		||||
		else
 | 
			
		||||
			info.si_code = FPE_INTOVF;
 | 
			
		||||
		info.si_signo = SIGFPE;
 | 
			
		||||
		info.si_errno = 0;
 | 
			
		||||
		info.si_addr = (void __user *) regs->cp0_epc;
 | 
			
		||||
		force_sig_info(SIGFPE, &info, current);
 | 
			
		||||
		break;
 | 
			
		||||
	case BRK_BUG:
 | 
			
		||||
		die("Kernel bug detected", regs);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		die_if_kernel("Trap instruction in kernel code", regs);
 | 
			
		||||
		force_sig(SIGTRAP, current);
 | 
			
		||||
	}
 | 
			
		||||
	do_trap_or_bp(regs, tcode, "Trap");
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
out_sigsegv:
 | 
			
		||||
@ -985,6 +988,21 @@ asmlinkage void do_reserved(struct pt_regs *regs)
 | 
			
		||||
	      (regs->cp0_cause & 0x7f) >> 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __initdata l1parity = 1;
 | 
			
		||||
static int __init nol1parity(char *s)
 | 
			
		||||
{
 | 
			
		||||
	l1parity = 0;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
__setup("nol1par", nol1parity);
 | 
			
		||||
static int __initdata l2parity = 1;
 | 
			
		||||
static int __init nol2parity(char *s)
 | 
			
		||||
{
 | 
			
		||||
	l2parity = 0;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
__setup("nol2par", nol2parity);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Some MIPS CPUs can enable/disable for cache parity detection, but do
 | 
			
		||||
 * it different ways.
 | 
			
		||||
@ -994,6 +1012,62 @@ static inline void parity_protection_init(void)
 | 
			
		||||
	switch (current_cpu_type()) {
 | 
			
		||||
	case CPU_24K:
 | 
			
		||||
	case CPU_34K:
 | 
			
		||||
	case CPU_74K:
 | 
			
		||||
	case CPU_1004K:
 | 
			
		||||
		{
 | 
			
		||||
#define ERRCTL_PE	0x80000000
 | 
			
		||||
#define ERRCTL_L2P	0x00800000
 | 
			
		||||
			unsigned long errctl;
 | 
			
		||||
			unsigned int l1parity_present, l2parity_present;
 | 
			
		||||
 | 
			
		||||
			errctl = read_c0_ecc();
 | 
			
		||||
			errctl &= ~(ERRCTL_PE|ERRCTL_L2P);
 | 
			
		||||
 | 
			
		||||
			/* probe L1 parity support */
 | 
			
		||||
			write_c0_ecc(errctl | ERRCTL_PE);
 | 
			
		||||
			back_to_back_c0_hazard();
 | 
			
		||||
			l1parity_present = (read_c0_ecc() & ERRCTL_PE);
 | 
			
		||||
 | 
			
		||||
			/* probe L2 parity support */
 | 
			
		||||
			write_c0_ecc(errctl|ERRCTL_L2P);
 | 
			
		||||
			back_to_back_c0_hazard();
 | 
			
		||||
			l2parity_present = (read_c0_ecc() & ERRCTL_L2P);
 | 
			
		||||
 | 
			
		||||
			if (l1parity_present && l2parity_present) {
 | 
			
		||||
				if (l1parity)
 | 
			
		||||
					errctl |= ERRCTL_PE;
 | 
			
		||||
				if (l1parity ^ l2parity)
 | 
			
		||||
					errctl |= ERRCTL_L2P;
 | 
			
		||||
			} else if (l1parity_present) {
 | 
			
		||||
				if (l1parity)
 | 
			
		||||
					errctl |= ERRCTL_PE;
 | 
			
		||||
			} else if (l2parity_present) {
 | 
			
		||||
				if (l2parity)
 | 
			
		||||
					errctl |= ERRCTL_L2P;
 | 
			
		||||
			} else {
 | 
			
		||||
				/* No parity available */
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			printk(KERN_INFO "Writing ErrCtl register=%08lx\n", errctl);
 | 
			
		||||
 | 
			
		||||
			write_c0_ecc(errctl);
 | 
			
		||||
			back_to_back_c0_hazard();
 | 
			
		||||
			errctl = read_c0_ecc();
 | 
			
		||||
			printk(KERN_INFO "Readback ErrCtl register=%08lx\n", errctl);
 | 
			
		||||
 | 
			
		||||
			if (l1parity_present)
 | 
			
		||||
				printk(KERN_INFO "Cache parity protection %sabled\n",
 | 
			
		||||
				       (errctl & ERRCTL_PE) ? "en" : "dis");
 | 
			
		||||
 | 
			
		||||
			if (l2parity_present) {
 | 
			
		||||
				if (l1parity_present && l1parity)
 | 
			
		||||
					errctl ^= ERRCTL_L2P;
 | 
			
		||||
				printk(KERN_INFO "L2 cache parity protection %sabled\n",
 | 
			
		||||
				       (errctl & ERRCTL_L2P) ? "en" : "dis");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CPU_5KC:
 | 
			
		||||
		write_c0_ecc(0x80000000);
 | 
			
		||||
		back_to_back_c0_hazard();
 | 
			
		||||
@ -1306,6 +1380,17 @@ int cp0_compare_irq;
 | 
			
		||||
int cp0_perfcount_irq;
 | 
			
		||||
EXPORT_SYMBOL_GPL(cp0_perfcount_irq);
 | 
			
		||||
 | 
			
		||||
static int __cpuinitdata noulri;
 | 
			
		||||
 | 
			
		||||
static int __init ulri_disable(char *s)
 | 
			
		||||
{
 | 
			
		||||
	pr_info("Disabling ulri\n");
 | 
			
		||||
	noulri = 1;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
__setup("noulri", ulri_disable);
 | 
			
		||||
 | 
			
		||||
void __cpuinit per_cpu_trap_init(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int cpu = smp_processor_id();
 | 
			
		||||
@ -1342,16 +1427,14 @@ void __cpuinit per_cpu_trap_init(void)
 | 
			
		||||
	change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
 | 
			
		||||
			 status_set);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_CPU_MIPSR2
 | 
			
		||||
	if (cpu_has_mips_r2) {
 | 
			
		||||
		unsigned int enable = 0x0000000f;
 | 
			
		||||
 | 
			
		||||
		if (cpu_has_userlocal)
 | 
			
		||||
		if (!noulri && cpu_has_userlocal)
 | 
			
		||||
			enable |= (1 << 29);
 | 
			
		||||
 | 
			
		||||
		write_c0_hwrena(enable);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_SMTC
 | 
			
		||||
	if (!secondaryTC) {
 | 
			
		||||
 | 
			
		||||
@ -46,7 +46,7 @@
 | 
			
		||||
#define DPDNORMX	DPDNORMx(xm, xe)
 | 
			
		||||
#define DPDNORMY	DPDNORMx(ym, ye)
 | 
			
		||||
 | 
			
		||||
static __inline ieee754dp builddp(int s, int bx, u64 m)
 | 
			
		||||
static inline ieee754dp builddp(int s, int bx, u64 m)
 | 
			
		||||
{
 | 
			
		||||
	ieee754dp r;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@
 | 
			
		||||
#define SPDNORMX	SPDNORMx(xm, xe)
 | 
			
		||||
#define SPDNORMY	SPDNORMx(ym, ye)
 | 
			
		||||
 | 
			
		||||
static __inline ieee754sp buildsp(int s, int bx, unsigned m)
 | 
			
		||||
static inline ieee754sp buildsp(int s, int bx, unsigned m)
 | 
			
		||||
{
 | 
			
		||||
	ieee754sp r;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@
 | 
			
		||||
 | 
			
		||||
obj-y				:= reset.o display.o init.o memory.o \
 | 
			
		||||
				   cmdline.o time.o
 | 
			
		||||
obj-y				+= amon.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_EARLY_PRINTK)	+= console.o
 | 
			
		||||
obj-$(CONFIG_PCI)		+= pci.o
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										80
									
								
								arch/mips/mips-boards/generic/amon.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								arch/mips/mips-boards/generic/amon.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,80 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2007  MIPS Technologies, Inc.
 | 
			
		||||
 *	All rights reserved.
 | 
			
		||||
 | 
			
		||||
 *  This program is free software; you can distribute it and/or modify it
 | 
			
		||||
 *  under the terms of the GNU General Public License (Version 2) as
 | 
			
		||||
 *  published by the Free Software Foundation.
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is distributed in the hope it will be useful, but WITHOUT
 | 
			
		||||
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
			
		||||
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 | 
			
		||||
 *  for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License along
 | 
			
		||||
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
 *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Arbitrary Monitor interface
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/smp.h>
 | 
			
		||||
 | 
			
		||||
#include <asm-mips/addrspace.h>
 | 
			
		||||
#include <asm-mips/mips-boards/launch.h>
 | 
			
		||||
#include <asm-mips/mipsmtregs.h>
 | 
			
		||||
 | 
			
		||||
int amon_cpu_avail(int cpu)
 | 
			
		||||
{
 | 
			
		||||
	struct cpulaunch *launch = (struct cpulaunch *)KSEG0ADDR(CPULAUNCH);
 | 
			
		||||
 | 
			
		||||
	if (cpu < 0 || cpu >= NCPULAUNCH) {
 | 
			
		||||
		pr_debug("avail: cpu%d is out of range\n", cpu);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	launch += cpu;
 | 
			
		||||
	if (!(launch->flags & LAUNCH_FREADY)) {
 | 
			
		||||
		pr_debug("avail: cpu%d is not ready\n", cpu);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
 | 
			
		||||
		pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void amon_cpu_start(int cpu,
 | 
			
		||||
		    unsigned long pc, unsigned long sp,
 | 
			
		||||
		    unsigned long gp, unsigned long a0)
 | 
			
		||||
{
 | 
			
		||||
	volatile struct cpulaunch *launch =
 | 
			
		||||
		(struct cpulaunch  *)KSEG0ADDR(CPULAUNCH);
 | 
			
		||||
 | 
			
		||||
	if (!amon_cpu_avail(cpu))
 | 
			
		||||
		return;
 | 
			
		||||
	if (cpu == smp_processor_id()) {
 | 
			
		||||
		pr_debug("launch: I am cpu%d!\n", cpu);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	launch += cpu;
 | 
			
		||||
 | 
			
		||||
	pr_debug("launch: starting cpu%d\n", cpu);
 | 
			
		||||
 | 
			
		||||
	launch->pc = pc;
 | 
			
		||||
	launch->gp = gp;
 | 
			
		||||
	launch->sp = sp;
 | 
			
		||||
	launch->a0 = a0;
 | 
			
		||||
 | 
			
		||||
	/* Make sure target sees parameters before the go bit */
 | 
			
		||||
	smp_mb();
 | 
			
		||||
 | 
			
		||||
	launch->flags |= LAUNCH_FGO;
 | 
			
		||||
	while ((launch->flags & LAUNCH_FGONE) == 0)
 | 
			
		||||
		;
 | 
			
		||||
	pr_debug("launch: cpu%d gone!\n", cpu);
 | 
			
		||||
}
 | 
			
		||||
@ -226,7 +226,7 @@ void __init kgdb_config(void)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void __init mips_nmi_setup(void)
 | 
			
		||||
static void __init mips_nmi_setup(void)
 | 
			
		||||
{
 | 
			
		||||
	void *base;
 | 
			
		||||
	extern char except_vec_nmi;
 | 
			
		||||
@ -238,7 +238,7 @@ void __init mips_nmi_setup(void)
 | 
			
		||||
	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init mips_ejtag_setup(void)
 | 
			
		||||
static void __init mips_ejtag_setup(void)
 | 
			
		||||
{
 | 
			
		||||
	void *base;
 | 
			
		||||
	extern char except_vec_ejtag_debug;
 | 
			
		||||
@ -295,15 +295,21 @@ void __init prom_init(void)
 | 
			
		||||
			break;
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_MSC:
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_FPGA2:
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_FPGA3:
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_FPGA4:
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_24K:
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_EMUL_MSC:
 | 
			
		||||
			/*
 | 
			
		||||
			 * SOCit/ROCit support is essentially identical
 | 
			
		||||
			 * but make an attempt to distinguish them
 | 
			
		||||
			 */
 | 
			
		||||
			mips_revision_sconid = MIPS_REVISION_SCON_SOCIT;
 | 
			
		||||
			break;
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_FPGA3:
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_FPGA4:
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_FPGA5:
 | 
			
		||||
		case MIPS_REVISION_CORID_CORE_EMUL_MSC:
 | 
			
		||||
		default:
 | 
			
		||||
			mips_display_message("CC Error");
 | 
			
		||||
			while (1);   /* We die here... */
 | 
			
		||||
			/* See above */
 | 
			
		||||
			mips_revision_sconid = MIPS_REVISION_SCON_ROCIT;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -418,6 +424,9 @@ void __init prom_init(void)
 | 
			
		||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
 | 
			
		||||
	console_config();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_MIPS_CMP
 | 
			
		||||
	register_smp_ops(&cmp_smp_ops);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_SMP
 | 
			
		||||
	register_smp_ops(&vsmp_smp_ops);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@ enum yamon_memtypes {
 | 
			
		||||
	yamon_prom,
 | 
			
		||||
	yamon_free,
 | 
			
		||||
};
 | 
			
		||||
struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
 | 
			
		||||
static struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
static char *mtypes[3] = {
 | 
			
		||||
@ -50,7 +50,7 @@ static char *mtypes[3] = {
 | 
			
		||||
/* determined physical memory size, not overridden by command line args  */
 | 
			
		||||
unsigned long physical_memsize = 0L;
 | 
			
		||||
 | 
			
		||||
struct prom_pmemblock * __init prom_getmdesc(void)
 | 
			
		||||
static struct prom_pmemblock * __init prom_getmdesc(void)
 | 
			
		||||
{
 | 
			
		||||
	char *memsize_str;
 | 
			
		||||
	unsigned int memsize;
 | 
			
		||||
 | 
			
		||||
@ -55,16 +55,36 @@
 | 
			
		||||
unsigned long cpu_khz;
 | 
			
		||||
 | 
			
		||||
static int mips_cpu_timer_irq;
 | 
			
		||||
static int mips_cpu_perf_irq;
 | 
			
		||||
extern int cp0_perfcount_irq;
 | 
			
		||||
 | 
			
		||||
DEFINE_PER_CPU(unsigned int, tickcount);
 | 
			
		||||
#define tickcount_this_cpu __get_cpu_var(tickcount)
 | 
			
		||||
static unsigned long ledbitmask;
 | 
			
		||||
 | 
			
		||||
static void mips_timer_dispatch(void)
 | 
			
		||||
{
 | 
			
		||||
#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_ATLAS)
 | 
			
		||||
	/*
 | 
			
		||||
	 * Yes, this is very tacky, won't work as expected with SMTC and
 | 
			
		||||
	 * dyntick will break it,
 | 
			
		||||
	 * but it gives me a nice warm feeling during debug
 | 
			
		||||
	 */
 | 
			
		||||
#define LEDBAR 0xbf000408
 | 
			
		||||
	if (tickcount_this_cpu++ >= HZ) {
 | 
			
		||||
		tickcount_this_cpu = 0;
 | 
			
		||||
		change_bit(smp_processor_id(), &ledbitmask);
 | 
			
		||||
		smp_wmb(); /* Make sure every one else sees the change */
 | 
			
		||||
		/* This will pick up any recent changes made by other CPU's */
 | 
			
		||||
		*(unsigned int *)LEDBAR = ledbitmask;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	do_IRQ(mips_cpu_timer_irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mips_perf_dispatch(void)
 | 
			
		||||
{
 | 
			
		||||
	do_IRQ(cp0_perfcount_irq);
 | 
			
		||||
	do_IRQ(mips_cpu_perf_irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -127,21 +147,20 @@ unsigned long read_persistent_clock(void)
 | 
			
		||||
	return mc146818_get_cmos_time();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init plat_perf_setup(void)
 | 
			
		||||
static void __init plat_perf_setup(void)
 | 
			
		||||
{
 | 
			
		||||
	cp0_perfcount_irq = -1;
 | 
			
		||||
 | 
			
		||||
#ifdef MSC01E_INT_BASE
 | 
			
		||||
	if (cpu_has_veic) {
 | 
			
		||||
		set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch);
 | 
			
		||||
		cp0_perfcount_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
 | 
			
		||||
		mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
 | 
			
		||||
	} else
 | 
			
		||||
#endif
 | 
			
		||||
	if (cp0_perfcount_irq >= 0) {
 | 
			
		||||
		if (cpu_has_vint)
 | 
			
		||||
			set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
 | 
			
		||||
		mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
 | 
			
		||||
#ifdef CONFIG_SMP
 | 
			
		||||
		set_irq_handler(cp0_perfcount_irq, handle_percpu_irq);
 | 
			
		||||
		set_irq_handler(mips_cpu_perf_irq, handle_percpu_irq);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@
 | 
			
		||||
obj-y := malta_int.o malta_platform.o malta_setup.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_MTD) += malta_mtd.o
 | 
			
		||||
# FIXME FIXME FIXME
 | 
			
		||||
obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
 | 
			
		||||
 | 
			
		||||
EXTRA_CFLAGS += -Werror
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,7 @@
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/random.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/traps.h>
 | 
			
		||||
#include <asm/i8259.h>
 | 
			
		||||
#include <asm/irq_cpu.h>
 | 
			
		||||
#include <asm/irq_regs.h>
 | 
			
		||||
@ -41,6 +42,14 @@
 | 
			
		||||
#include <asm/mips-boards/generic.h>
 | 
			
		||||
#include <asm/mips-boards/msc01_pci.h>
 | 
			
		||||
#include <asm/msc01_ic.h>
 | 
			
		||||
#include <asm/gic.h>
 | 
			
		||||
#include <asm/gcmpregs.h>
 | 
			
		||||
 | 
			
		||||
int gcmp_present = -1;
 | 
			
		||||
int gic_present;
 | 
			
		||||
static unsigned long _msc01_biu_base;
 | 
			
		||||
static unsigned long _gcmp_base;
 | 
			
		||||
static unsigned int ipi_map[NR_CPUS];
 | 
			
		||||
 | 
			
		||||
static DEFINE_SPINLOCK(mips_irq_lock);
 | 
			
		||||
 | 
			
		||||
@ -121,6 +130,17 @@ static void malta_hw0_irqdispatch(void)
 | 
			
		||||
	do_IRQ(MALTA_INT_BASE + irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void malta_ipi_irqdispatch(void)
 | 
			
		||||
{
 | 
			
		||||
	int irq;
 | 
			
		||||
 | 
			
		||||
	irq = gic_get_int();
 | 
			
		||||
	if (irq < 0)
 | 
			
		||||
		return;  /* interrupt has already been cleared */
 | 
			
		||||
 | 
			
		||||
	do_IRQ(MIPS_GIC_IRQ_BASE + irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void corehi_irqdispatch(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int intedge, intsteer, pcicmd, pcibadaddr;
 | 
			
		||||
@ -257,12 +277,61 @@ asmlinkage void plat_irq_dispatch(void)
 | 
			
		||||
 | 
			
		||||
	if (irq == MIPSCPU_INT_I8259A)
 | 
			
		||||
		malta_hw0_irqdispatch();
 | 
			
		||||
	else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()]))
 | 
			
		||||
		malta_ipi_irqdispatch();
 | 
			
		||||
	else if (irq >= 0)
 | 
			
		||||
		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
 | 
			
		||||
	else
 | 
			
		||||
		spurious_interrupt();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_SMP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define GIC_MIPS_CPU_IPI_RESCHED_IRQ	3
 | 
			
		||||
#define GIC_MIPS_CPU_IPI_CALL_IRQ	4
 | 
			
		||||
 | 
			
		||||
#define MIPS_CPU_IPI_RESCHED_IRQ 0	/* SW int 0 for resched */
 | 
			
		||||
#define C_RESCHED C_SW0
 | 
			
		||||
#define MIPS_CPU_IPI_CALL_IRQ 1		/* SW int 1 for resched */
 | 
			
		||||
#define C_CALL C_SW1
 | 
			
		||||
static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
 | 
			
		||||
 | 
			
		||||
static void ipi_resched_dispatch(void)
 | 
			
		||||
{
 | 
			
		||||
	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipi_call_dispatch(void)
 | 
			
		||||
{
 | 
			
		||||
	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
 | 
			
		||||
{
 | 
			
		||||
	return IRQ_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
 | 
			
		||||
{
 | 
			
		||||
	smp_call_function_interrupt();
 | 
			
		||||
 | 
			
		||||
	return IRQ_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct irqaction irq_resched = {
 | 
			
		||||
	.handler	= ipi_resched_interrupt,
 | 
			
		||||
	.flags		= IRQF_DISABLED|IRQF_PERCPU,
 | 
			
		||||
	.name		= "IPI_resched"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct irqaction irq_call = {
 | 
			
		||||
	.handler	= ipi_call_interrupt,
 | 
			
		||||
	.flags		= IRQF_DISABLED|IRQF_PERCPU,
 | 
			
		||||
	.name		= "IPI_call"
 | 
			
		||||
};
 | 
			
		||||
#endif /* CONFIG_MIPS_MT_SMP */
 | 
			
		||||
 | 
			
		||||
static struct irqaction i8259irq = {
 | 
			
		||||
	.handler = no_action,
 | 
			
		||||
	.name = "XT-PIC cascade"
 | 
			
		||||
@ -273,13 +342,13 @@ static struct irqaction corehi_irqaction = {
 | 
			
		||||
	.name = "CoreHi"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
msc_irqmap_t __initdata msc_irqmap[] = {
 | 
			
		||||
static msc_irqmap_t __initdata msc_irqmap[] = {
 | 
			
		||||
	{MSC01C_INT_TMR,		MSC01_IRQ_EDGE, 0},
 | 
			
		||||
	{MSC01C_INT_PCI,		MSC01_IRQ_LEVEL, 0},
 | 
			
		||||
};
 | 
			
		||||
int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
 | 
			
		||||
static int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
 | 
			
		||||
 | 
			
		||||
msc_irqmap_t __initdata msc_eicirqmap[] = {
 | 
			
		||||
static msc_irqmap_t __initdata msc_eicirqmap[] = {
 | 
			
		||||
	{MSC01E_INT_SW0,		MSC01_IRQ_LEVEL, 0},
 | 
			
		||||
	{MSC01E_INT_SW1,		MSC01_IRQ_LEVEL, 0},
 | 
			
		||||
	{MSC01E_INT_I8259A,		MSC01_IRQ_LEVEL, 0},
 | 
			
		||||
@ -291,15 +360,90 @@ msc_irqmap_t __initdata msc_eicirqmap[] = {
 | 
			
		||||
	{MSC01E_INT_PERFCTR,		MSC01_IRQ_LEVEL, 0},
 | 
			
		||||
	{MSC01E_INT_CPUCTR,		MSC01_IRQ_LEVEL, 0}
 | 
			
		||||
};
 | 
			
		||||
int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
 | 
			
		||||
 | 
			
		||||
static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This GIC specific tabular array defines the association between External
 | 
			
		||||
 * Interrupts and CPUs/Core Interrupts. The nature of the External
 | 
			
		||||
 * Interrupts is also defined here - polarity/trigger.
 | 
			
		||||
 */
 | 
			
		||||
static struct gic_intr_map gic_intr_map[] = {
 | 
			
		||||
	{ GIC_EXT_INTR(0), 	X,	X,		X, 		X,		0 },
 | 
			
		||||
	{ GIC_EXT_INTR(1), 	X,	X,		X, 		X,		0 },
 | 
			
		||||
	{ GIC_EXT_INTR(2), 	X,	X,		X, 		X,		0 },
 | 
			
		||||
	{ GIC_EXT_INTR(3), 	0,	GIC_CPU_INT0,	GIC_POL_POS, 	GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(4), 	0,	GIC_CPU_INT1,	GIC_POL_POS, 	GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(5), 	0,	GIC_CPU_INT2,	GIC_POL_POS, 	GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(6), 	0,	GIC_CPU_INT3,	GIC_POL_POS, 	GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(7), 	0,	GIC_CPU_INT4,	GIC_POL_POS, 	GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(8), 	0,	GIC_CPU_INT3,	GIC_POL_POS, 	GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(9), 	0,	GIC_CPU_INT3,	GIC_POL_POS, 	GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(10), 	X,	X,		X, 		X,		0 },
 | 
			
		||||
	{ GIC_EXT_INTR(11), 	X,	X,		X, 		X,		0 },
 | 
			
		||||
	{ GIC_EXT_INTR(12), 	0,	GIC_CPU_INT3,	GIC_POL_POS, 	GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(13), 	0,	GIC_MAP_TO_NMI_MSK,	GIC_POL_POS, GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(14), 	0,	GIC_MAP_TO_NMI_MSK,	GIC_POL_POS, GIC_TRIG_LEVEL,	0 },
 | 
			
		||||
	{ GIC_EXT_INTR(15), 	X,	X,		X, 		X,		0 },
 | 
			
		||||
	{ GIC_EXT_INTR(16), 	0,	GIC_CPU_INT1,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
 | 
			
		||||
	{ GIC_EXT_INTR(17), 	0,	GIC_CPU_INT2,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
 | 
			
		||||
	{ GIC_EXT_INTR(18), 	1,	GIC_CPU_INT1,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
 | 
			
		||||
	{ GIC_EXT_INTR(19), 	1,	GIC_CPU_INT2,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
 | 
			
		||||
	{ GIC_EXT_INTR(20), 	2,	GIC_CPU_INT1,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
 | 
			
		||||
	{ GIC_EXT_INTR(21), 	2,	GIC_CPU_INT2,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
 | 
			
		||||
	{ GIC_EXT_INTR(22), 	3,	GIC_CPU_INT1,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
 | 
			
		||||
	{ GIC_EXT_INTR(23), 	3,	GIC_CPU_INT2,	GIC_POL_POS, GIC_TRIG_EDGE,	1 },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * GCMP needs to be detected before any SMP initialisation
 | 
			
		||||
 */
 | 
			
		||||
int __init gcmp_probe(unsigned long addr, unsigned long size)
 | 
			
		||||
{
 | 
			
		||||
	if (gcmp_present >= 0)
 | 
			
		||||
		return gcmp_present;
 | 
			
		||||
 | 
			
		||||
	_gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
 | 
			
		||||
	_msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ);
 | 
			
		||||
	gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR;
 | 
			
		||||
 | 
			
		||||
	if (gcmp_present)
 | 
			
		||||
		printk(KERN_DEBUG "GCMP present\n");
 | 
			
		||||
	return gcmp_present;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init fill_ipi_map(void)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) {
 | 
			
		||||
		if (gic_intr_map[i].ipiflag && (gic_intr_map[i].cpunum != X))
 | 
			
		||||
			ipi_map[gic_intr_map[i].cpunum] |=
 | 
			
		||||
				(1 << (gic_intr_map[i].pin + 2));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __init arch_init_irq(void)
 | 
			
		||||
{
 | 
			
		||||
	int gic_present, gcmp_present;
 | 
			
		||||
 | 
			
		||||
	init_i8259_irqs();
 | 
			
		||||
 | 
			
		||||
	if (!cpu_has_veic)
 | 
			
		||||
		mips_cpu_irq_init();
 | 
			
		||||
 | 
			
		||||
	gcmp_present = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
 | 
			
		||||
	if (gcmp_present)  {
 | 
			
		||||
		GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
 | 
			
		||||
		gic_present = 1;
 | 
			
		||||
	} else {
 | 
			
		||||
		_msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ);
 | 
			
		||||
		gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) &
 | 
			
		||||
		MSC01_SC_CFG_GICPRES_MSK) >> MSC01_SC_CFG_GICPRES_SHF;
 | 
			
		||||
	}
 | 
			
		||||
	if (gic_present)
 | 
			
		||||
		printk(KERN_DEBUG "GIC present\n");
 | 
			
		||||
 | 
			
		||||
	switch (mips_revision_sconid) {
 | 
			
		||||
	case MIPS_REVISION_SCON_SOCIT:
 | 
			
		||||
	case MIPS_REVISION_SCON_ROCIT:
 | 
			
		||||
@ -360,4 +504,206 @@ void __init arch_init_irq(void)
 | 
			
		||||
		setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
 | 
			
		||||
						&corehi_irqaction);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_MIPS_MT_SMP)
 | 
			
		||||
	if (gic_present) {
 | 
			
		||||
		/* FIXME */
 | 
			
		||||
		int i;
 | 
			
		||||
		struct {
 | 
			
		||||
			unsigned int resched;
 | 
			
		||||
			unsigned int call;
 | 
			
		||||
		} ipiirq[] = {
 | 
			
		||||
			{
 | 
			
		||||
				.resched = GIC_IPI_EXT_INTR_RESCHED_VPE0,
 | 
			
		||||
				.call =  GIC_IPI_EXT_INTR_CALLFNC_VPE0},
 | 
			
		||||
			{
 | 
			
		||||
				.resched = GIC_IPI_EXT_INTR_RESCHED_VPE1,
 | 
			
		||||
				.call =  GIC_IPI_EXT_INTR_CALLFNC_VPE1
 | 
			
		||||
			}, {
 | 
			
		||||
				.resched = GIC_IPI_EXT_INTR_RESCHED_VPE2,
 | 
			
		||||
				.call =  GIC_IPI_EXT_INTR_CALLFNC_VPE2
 | 
			
		||||
			}, {
 | 
			
		||||
				.resched = GIC_IPI_EXT_INTR_RESCHED_VPE3,
 | 
			
		||||
				.call =  GIC_IPI_EXT_INTR_CALLFNC_VPE3
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
#define NIPI (sizeof(ipiirq)/sizeof(ipiirq[0]))
 | 
			
		||||
		fill_ipi_map();
 | 
			
		||||
		gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
 | 
			
		||||
		if (!gcmp_present) {
 | 
			
		||||
			/* Enable the GIC */
 | 
			
		||||
			i = REG(_msc01_biu_base, MSC01_SC_CFG);
 | 
			
		||||
			REG(_msc01_biu_base, MSC01_SC_CFG) =
 | 
			
		||||
				(i | (0x1 << MSC01_SC_CFG_GICENA_SHF));
 | 
			
		||||
			pr_debug("GIC Enabled\n");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* set up ipi interrupts */
 | 
			
		||||
		if (cpu_has_vint) {
 | 
			
		||||
			set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch);
 | 
			
		||||
			set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch);
 | 
			
		||||
		}
 | 
			
		||||
		/* Argh.. this really needs sorting out.. */
 | 
			
		||||
		printk("CPU%d: status register was %08x\n", smp_processor_id(), read_c0_status());
 | 
			
		||||
		write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4);
 | 
			
		||||
		printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status());
 | 
			
		||||
		write_c0_status(0x1100dc00);
 | 
			
		||||
		printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
 | 
			
		||||
		for (i = 0; i < NIPI; i++) {
 | 
			
		||||
			setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, &irq_resched);
 | 
			
		||||
			setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].call, &irq_call);
 | 
			
		||||
 | 
			
		||||
			set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, handle_percpu_irq);
 | 
			
		||||
			set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].call, handle_percpu_irq);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* set up ipi interrupts */
 | 
			
		||||
		if (cpu_has_veic) {
 | 
			
		||||
			set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch);
 | 
			
		||||
			set_vi_handler (MSC01E_INT_SW1, ipi_call_dispatch);
 | 
			
		||||
			cpu_ipi_resched_irq = MSC01E_INT_SW0;
 | 
			
		||||
			cpu_ipi_call_irq = MSC01E_INT_SW1;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (cpu_has_vint) {
 | 
			
		||||
				set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
 | 
			
		||||
				set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
 | 
			
		||||
			}
 | 
			
		||||
			cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
 | 
			
		||||
			cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		setup_irq(cpu_ipi_resched_irq, &irq_resched);
 | 
			
		||||
		setup_irq(cpu_ipi_call_irq, &irq_call);
 | 
			
		||||
 | 
			
		||||
		set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
 | 
			
		||||
		set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void malta_be_init(void)
 | 
			
		||||
{
 | 
			
		||||
	if (gcmp_present) {
 | 
			
		||||
		/* Could change CM error mask register */
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static char *tr[8] = {
 | 
			
		||||
	"mem",	"gcr",	"gic",	"mmio",
 | 
			
		||||
	"0x04",	"0x05",	"0x06",	"0x07"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static char *mcmd[32] = {
 | 
			
		||||
	[0x00] = "0x00",
 | 
			
		||||
	[0x01] = "Legacy Write",
 | 
			
		||||
	[0x02] = "Legacy Read",
 | 
			
		||||
	[0x03] = "0x03",
 | 
			
		||||
	[0x04] = "0x04",
 | 
			
		||||
	[0x05] = "0x05",
 | 
			
		||||
	[0x06] = "0x06",
 | 
			
		||||
	[0x07] = "0x07",
 | 
			
		||||
	[0x08] = "Coherent Read Own",
 | 
			
		||||
	[0x09] = "Coherent Read Share",
 | 
			
		||||
	[0x0a] = "Coherent Read Discard",
 | 
			
		||||
	[0x0b] = "Coherent Ready Share Always",
 | 
			
		||||
	[0x0c] = "Coherent Upgrade",
 | 
			
		||||
	[0x0d] = "Coherent Writeback",
 | 
			
		||||
	[0x0e] = "0x0e",
 | 
			
		||||
	[0x0f] = "0x0f",
 | 
			
		||||
	[0x10] = "Coherent Copyback",
 | 
			
		||||
	[0x11] = "Coherent Copyback Invalidate",
 | 
			
		||||
	[0x12] = "Coherent Invalidate",
 | 
			
		||||
	[0x13] = "Coherent Write Invalidate",
 | 
			
		||||
	[0x14] = "Coherent Completion Sync",
 | 
			
		||||
	[0x15] = "0x15",
 | 
			
		||||
	[0x16] = "0x16",
 | 
			
		||||
	[0x17] = "0x17",
 | 
			
		||||
	[0x18] = "0x18",
 | 
			
		||||
	[0x19] = "0x19",
 | 
			
		||||
	[0x1a] = "0x1a",
 | 
			
		||||
	[0x1b] = "0x1b",
 | 
			
		||||
	[0x1c] = "0x1c",
 | 
			
		||||
	[0x1d] = "0x1d",
 | 
			
		||||
	[0x1e] = "0x1e",
 | 
			
		||||
	[0x1f] = "0x1f"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static char *core[8] = {
 | 
			
		||||
	"Invalid/OK", 	"Invalid/Data",
 | 
			
		||||
	"Shared/OK",	"Shared/Data",
 | 
			
		||||
	"Modified/OK",	"Modified/Data",
 | 
			
		||||
	"Exclusive/OK",	"Exclusive/Data"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static char *causes[32] = {
 | 
			
		||||
	"None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
 | 
			
		||||
	"COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
 | 
			
		||||
	"0x08", "0x09", "0x0a", "0x0b",
 | 
			
		||||
	"0x0c", "0x0d", "0x0e", "0x0f",
 | 
			
		||||
	"0x10", "0x11", "0x12", "0x13",
 | 
			
		||||
	"0x14", "0x15", "0x16", "INTVN_WR_ERR",
 | 
			
		||||
	"INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
 | 
			
		||||
	"0x1c", "0x1d", "0x1e", "0x1f"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int malta_be_handler(struct pt_regs *regs, int is_fixup)
 | 
			
		||||
{
 | 
			
		||||
	/* This duplicates the handling in do_be which seems wrong */
 | 
			
		||||
	int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
 | 
			
		||||
 | 
			
		||||
	if (gcmp_present) {
 | 
			
		||||
		unsigned long cm_error = GCMPGCB(GCMEC);
 | 
			
		||||
		unsigned long cm_addr = GCMPGCB(GCMEA);
 | 
			
		||||
		unsigned long cm_other = GCMPGCB(GCMEO);
 | 
			
		||||
		unsigned long cause, ocause;
 | 
			
		||||
		char buf[256];
 | 
			
		||||
 | 
			
		||||
		cause = (cm_error & GCMP_GCB_GMEC_ERROR_TYPE_MSK);
 | 
			
		||||
		if (cause != 0) {
 | 
			
		||||
			cause >>= GCMP_GCB_GMEC_ERROR_TYPE_SHF;
 | 
			
		||||
			if (cause < 16) {
 | 
			
		||||
				unsigned long cca_bits = (cm_error >> 15) & 7;
 | 
			
		||||
				unsigned long tr_bits = (cm_error >> 12) & 7;
 | 
			
		||||
				unsigned long mcmd_bits = (cm_error >> 7) & 0x1f;
 | 
			
		||||
				unsigned long stag_bits = (cm_error >> 3) & 15;
 | 
			
		||||
				unsigned long sport_bits = (cm_error >> 0) & 7;
 | 
			
		||||
 | 
			
		||||
				snprintf(buf, sizeof(buf),
 | 
			
		||||
					 "CCA=%lu TR=%s MCmd=%s STag=%lu "
 | 
			
		||||
					 "SPort=%lu\n",
 | 
			
		||||
					 cca_bits, tr[tr_bits], mcmd[mcmd_bits],
 | 
			
		||||
					 stag_bits, sport_bits);
 | 
			
		||||
			} else {
 | 
			
		||||
				/* glob state & sresp together */
 | 
			
		||||
				unsigned long c3_bits = (cm_error >> 18) & 7;
 | 
			
		||||
				unsigned long c2_bits = (cm_error >> 15) & 7;
 | 
			
		||||
				unsigned long c1_bits = (cm_error >> 12) & 7;
 | 
			
		||||
				unsigned long c0_bits = (cm_error >> 9) & 7;
 | 
			
		||||
				unsigned long sc_bit = (cm_error >> 8) & 1;
 | 
			
		||||
				unsigned long mcmd_bits = (cm_error >> 3) & 0x1f;
 | 
			
		||||
				unsigned long sport_bits = (cm_error >> 0) & 7;
 | 
			
		||||
				snprintf(buf, sizeof(buf),
 | 
			
		||||
					 "C3=%s C2=%s C1=%s C0=%s SC=%s "
 | 
			
		||||
					 "MCmd=%s SPort=%lu\n",
 | 
			
		||||
					 core[c3_bits], core[c2_bits],
 | 
			
		||||
					 core[c1_bits], core[c0_bits],
 | 
			
		||||
					 sc_bit ? "True" : "False",
 | 
			
		||||
					 mcmd[mcmd_bits], sport_bits);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >>
 | 
			
		||||
				 GCMP_GCB_GMEO_ERROR_2ND_SHF;
 | 
			
		||||
 | 
			
		||||
			printk("CM_ERROR=%08lx %s <%s>\n", cm_error,
 | 
			
		||||
			       causes[cause], buf);
 | 
			
		||||
			printk("CM_ADDR =%08lx\n", cm_addr);
 | 
			
		||||
			printk("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
 | 
			
		||||
 | 
			
		||||
			/* reprime cause register */
 | 
			
		||||
			GCMPGCB(GCMEC) = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Carsten Langgaard, carstenl@mips.com
 | 
			
		||||
 * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
 | 
			
		||||
 * Copyright (C) Dmitri Vorobiev
 | 
			
		||||
 * Copyright (C) 2008 Dmitri Vorobiev
 | 
			
		||||
 *
 | 
			
		||||
 *  This program is free software; you can distribute it and/or modify it
 | 
			
		||||
 *  under the terms of the GNU General Public License (Version 2) as
 | 
			
		||||
@ -36,7 +36,10 @@
 | 
			
		||||
#include <linux/console.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct resource standard_io_resources[] = {
 | 
			
		||||
extern void malta_be_init(void);
 | 
			
		||||
extern int malta_be_handler(struct pt_regs *regs, int is_fixup);
 | 
			
		||||
 | 
			
		||||
static struct resource standard_io_resources[] = {
 | 
			
		||||
	{
 | 
			
		||||
		.name = "dma1",
 | 
			
		||||
		.start = 0x00,
 | 
			
		||||
@ -220,4 +223,7 @@ void __init plat_mem_setup(void)
 | 
			
		||||
	screen_info_setup();
 | 
			
		||||
#endif
 | 
			
		||||
	mips_reboot_setup();
 | 
			
		||||
 | 
			
		||||
	board_be_init = malta_be_init;
 | 
			
		||||
	board_be_handler = malta_be_handler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -39,9 +39,6 @@
 | 
			
		||||
static void __init serial_init(void);
 | 
			
		||||
unsigned int _isbonito = 0;
 | 
			
		||||
 | 
			
		||||
extern void __init sanitize_tlb_entries(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const char *get_system_type(void)
 | 
			
		||||
{
 | 
			
		||||
	return "MIPSsim";
 | 
			
		||||
@ -55,9 +52,6 @@ void __init plat_mem_setup(void)
 | 
			
		||||
 | 
			
		||||
	pr_info("Linux started...\n");
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MIPS_MT_SMP
 | 
			
		||||
	sanitize_tlb_entries();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern struct plat_smp_ops ssmtc_smp_ops;
 | 
			
		||||
 | 
			
		||||
@ -4,30 +4,29 @@
 | 
			
		||||
 | 
			
		||||
obj-y				+= cache.o dma-default.o extable.o fault.o \
 | 
			
		||||
				   init.o pgtable.o tlbex.o tlbex-fault.o \
 | 
			
		||||
				   uasm.o
 | 
			
		||||
				   uasm.o page.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_32BIT)		+= ioremap.o pgtable-32.o
 | 
			
		||||
obj-$(CONFIG_64BIT)		+= pgtable-64.o
 | 
			
		||||
obj-$(CONFIG_HIGHMEM)		+= highmem.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_CPU_LOONGSON2)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_MIPS32)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_MIPS64)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_NEVADA)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R10000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R3000)		+= c-r3k.o tlb-r3k.o pg-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R4300)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R4X00)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R5000)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R5432)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R8000)		+= c-r4k.o cex-gen.o pg-r4k.o tlb-r8k.o
 | 
			
		||||
obj-$(CONFIG_CPU_RM7000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_RM9000)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_SB1)		+= c-r4k.o cerr-sb1.o cex-sb1.o pg-sb1.o \
 | 
			
		||||
				   tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_TX39XX)	+= c-tx39.o pg-r4k.o tlb-r3k.o
 | 
			
		||||
obj-$(CONFIG_CPU_TX49XX)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_VR41XX)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_LOONGSON2)	+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_MIPS32)	+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_MIPS64)	+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_NEVADA)	+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R10000)	+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R3000)		+= c-r3k.o tlb-r3k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R4300)		+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R4X00)		+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R5000)		+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R5432)		+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_R8000)		+= c-r4k.o cex-gen.o tlb-r8k.o
 | 
			
		||||
obj-$(CONFIG_CPU_RM7000)	+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_RM9000)	+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_SB1)		+= c-r4k.o cerr-sb1.o cex-sb1.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_TX39XX)	+= c-tx39.o tlb-r3k.o
 | 
			
		||||
obj-$(CONFIG_CPU_TX49XX)	+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
obj-$(CONFIG_CPU_VR41XX)	+= c-r4k.o cex-gen.o tlb-r4k.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_IP22_CPU_SCACHE)	+= sc-ip22.o
 | 
			
		||||
obj-$(CONFIG_R5000_CPU_SCACHE)  += sc-r5k.o
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@
 | 
			
		||||
#include <linux/linkage.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bcache.h>
 | 
			
		||||
@ -53,6 +54,12 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info,
 | 
			
		||||
	preempt_enable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_MIPS_CMP)
 | 
			
		||||
#define cpu_has_safe_index_cacheops 0
 | 
			
		||||
#else
 | 
			
		||||
#define cpu_has_safe_index_cacheops 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Must die.
 | 
			
		||||
 */
 | 
			
		||||
@ -481,6 +488,8 @@ static inline void local_r4k_flush_cache_page(void *args)
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
 | 
			
		||||
		r4k_blast_dcache_page(addr);
 | 
			
		||||
		if (exec && !cpu_icache_snoops_remote_store)
 | 
			
		||||
			r4k_blast_scache_page(addr);
 | 
			
		||||
	}
 | 
			
		||||
	if (exec) {
 | 
			
		||||
		if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) {
 | 
			
		||||
@ -583,7 +592,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 | 
			
		||||
	 * subset property so we have to flush the primary caches
 | 
			
		||||
	 * explicitly
 | 
			
		||||
	 */
 | 
			
		||||
	if (size >= dcache_size) {
 | 
			
		||||
	if (cpu_has_safe_index_cacheops && size >= dcache_size) {
 | 
			
		||||
		r4k_blast_dcache();
 | 
			
		||||
	} else {
 | 
			
		||||
		R4600_HIT_CACHEOP_WAR_IMPL;
 | 
			
		||||
@ -606,7 +615,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (size >= dcache_size) {
 | 
			
		||||
	if (cpu_has_safe_index_cacheops && size >= dcache_size) {
 | 
			
		||||
		r4k_blast_dcache();
 | 
			
		||||
	} else {
 | 
			
		||||
		R4600_HIT_CACHEOP_WAR_IMPL;
 | 
			
		||||
@ -968,6 +977,7 @@ static void __cpuinit probe_pcache(void)
 | 
			
		||||
	case CPU_24K:
 | 
			
		||||
	case CPU_34K:
 | 
			
		||||
	case CPU_74K:
 | 
			
		||||
	case CPU_1004K:
 | 
			
		||||
		if ((read_c0_config7() & (1 << 16))) {
 | 
			
		||||
			/* effectively physically indexed dcache,
 | 
			
		||||
			   thus no virtual aliases. */
 | 
			
		||||
@ -1216,9 +1226,25 @@ void au1x00_fixup_config_od(void)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __cpuinitdata cca = -1;
 | 
			
		||||
 | 
			
		||||
static int __init cca_setup(char *str)
 | 
			
		||||
{
 | 
			
		||||
	get_option(&str, &cca);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__setup("cca=", cca_setup);
 | 
			
		||||
 | 
			
		||||
static void __cpuinit coherency_setup(void)
 | 
			
		||||
{
 | 
			
		||||
	change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
 | 
			
		||||
	if (cca < 0 || cca > 7)
 | 
			
		||||
		cca = read_c0_config() & CONF_CM_CMASK;
 | 
			
		||||
	_page_cachable_default = cca << _CACHE_SHIFT;
 | 
			
		||||
 | 
			
		||||
	pr_debug("Using cache attribute %d\n", cca);
 | 
			
		||||
	change_c0_config(CONF_CM_CMASK, cca);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * c0_status.cu=0 specifies that updates by the sc instruction use
 | 
			
		||||
@ -1248,6 +1274,20 @@ static void __cpuinit coherency_setup(void)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_DMA_NONCOHERENT)
 | 
			
		||||
 | 
			
		||||
static int __cpuinitdata coherentio;
 | 
			
		||||
 | 
			
		||||
static int __init setcoherentio(char *str)
 | 
			
		||||
{
 | 
			
		||||
	coherentio = 1;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__setup("coherentio", setcoherentio);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void __cpuinit r4k_cache_init(void)
 | 
			
		||||
{
 | 
			
		||||
	extern void build_clear_page(void);
 | 
			
		||||
@ -1307,14 +1347,22 @@ void __cpuinit r4k_cache_init(void)
 | 
			
		||||
	flush_data_cache_page	= r4k_flush_data_cache_page;
 | 
			
		||||
	flush_icache_range	= r4k_flush_icache_range;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DMA_NONCOHERENT
 | 
			
		||||
	_dma_cache_wback_inv	= r4k_dma_cache_wback_inv;
 | 
			
		||||
	_dma_cache_wback	= r4k_dma_cache_wback_inv;
 | 
			
		||||
	_dma_cache_inv		= r4k_dma_cache_inv;
 | 
			
		||||
#if defined(CONFIG_DMA_NONCOHERENT)
 | 
			
		||||
	if (coherentio) {
 | 
			
		||||
		_dma_cache_wback_inv	= (void *)cache_noop;
 | 
			
		||||
		_dma_cache_wback	= (void *)cache_noop;
 | 
			
		||||
		_dma_cache_inv		= (void *)cache_noop;
 | 
			
		||||
	} else {
 | 
			
		||||
		_dma_cache_wback_inv	= r4k_dma_cache_wback_inv;
 | 
			
		||||
		_dma_cache_wback	= r4k_dma_cache_wback_inv;
 | 
			
		||||
		_dma_cache_inv		= r4k_dma_cache_inv;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	build_clear_page();
 | 
			
		||||
	build_copy_page();
 | 
			
		||||
#if !defined(CONFIG_MIPS_CMP)
 | 
			
		||||
	local_r4k___flush_cache_all(NULL);
 | 
			
		||||
#endif
 | 
			
		||||
	coherency_setup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -130,8 +130,28 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char cache_panic[] __cpuinitdata =
 | 
			
		||||
	"Yeee, unsupported cache architecture.";
 | 
			
		||||
unsigned long _page_cachable_default;
 | 
			
		||||
EXPORT_SYMBOL_GPL(_page_cachable_default);
 | 
			
		||||
 | 
			
		||||
static inline void setup_protection_map(void)
 | 
			
		||||
{
 | 
			
		||||
	protection_map[0] = PAGE_NONE;
 | 
			
		||||
	protection_map[1] = PAGE_READONLY;
 | 
			
		||||
	protection_map[2] = PAGE_COPY;
 | 
			
		||||
	protection_map[3] = PAGE_COPY;
 | 
			
		||||
	protection_map[4] = PAGE_READONLY;
 | 
			
		||||
	protection_map[5] = PAGE_READONLY;
 | 
			
		||||
	protection_map[6] = PAGE_COPY;
 | 
			
		||||
	protection_map[7] = PAGE_COPY;
 | 
			
		||||
	protection_map[8] = PAGE_NONE;
 | 
			
		||||
	protection_map[9] = PAGE_READONLY;
 | 
			
		||||
	protection_map[10] = PAGE_SHARED;
 | 
			
		||||
	protection_map[11] = PAGE_SHARED;
 | 
			
		||||
	protection_map[12] = PAGE_READONLY;
 | 
			
		||||
	protection_map[13] = PAGE_READONLY;
 | 
			
		||||
	protection_map[14] = PAGE_SHARED;
 | 
			
		||||
	protection_map[15] = PAGE_SHARED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __devinit cpu_cache_init(void)
 | 
			
		||||
{
 | 
			
		||||
@ -139,34 +159,29 @@ void __devinit cpu_cache_init(void)
 | 
			
		||||
		extern void __weak r3k_cache_init(void);
 | 
			
		||||
 | 
			
		||||
		r3k_cache_init();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (cpu_has_6k_cache) {
 | 
			
		||||
		extern void __weak r6k_cache_init(void);
 | 
			
		||||
 | 
			
		||||
		r6k_cache_init();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (cpu_has_4k_cache) {
 | 
			
		||||
		extern void __weak r4k_cache_init(void);
 | 
			
		||||
 | 
			
		||||
		r4k_cache_init();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (cpu_has_8k_cache) {
 | 
			
		||||
		extern void __weak r8k_cache_init(void);
 | 
			
		||||
 | 
			
		||||
		r8k_cache_init();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (cpu_has_tx39_cache) {
 | 
			
		||||
		extern void __weak tx39_cache_init(void);
 | 
			
		||||
 | 
			
		||||
		tx39_cache_init();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	panic(cache_panic);
 | 
			
		||||
	setup_protection_map();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int __weak __uncached_access(struct file *file, unsigned long addr)
 | 
			
		||||
 | 
			
		||||
@ -142,7 +142,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
 | 
			
		||||
#endif
 | 
			
		||||
	vaddr = __fix_to_virt(FIX_CMAP_END - idx);
 | 
			
		||||
	pte = mk_pte(page, PAGE_KERNEL);
 | 
			
		||||
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
 | 
			
		||||
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
 | 
			
		||||
	entrylo = pte.pte_high;
 | 
			
		||||
#else
 | 
			
		||||
	entrylo = pte_val(pte) >> 6;
 | 
			
		||||
@ -221,7 +221,7 @@ void copy_user_highpage(struct page *to, struct page *from,
 | 
			
		||||
		copy_page(vto, vfrom);
 | 
			
		||||
		kunmap_atomic(vfrom, KM_USER0);
 | 
			
		||||
	}
 | 
			
		||||
	if (((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) ||
 | 
			
		||||
	if ((!cpu_has_ic_fills_f_dc) ||
 | 
			
		||||
	    pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
 | 
			
		||||
		flush_data_cache_page((unsigned long)vto);
 | 
			
		||||
	kunmap_atomic(vto, KM_USER1);
 | 
			
		||||
@ -229,8 +229,6 @@ void copy_user_highpage(struct page *to, struct page *from,
 | 
			
		||||
	smp_wmb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(copy_user_highpage);
 | 
			
		||||
 | 
			
		||||
void copy_to_user_page(struct vm_area_struct *vma,
 | 
			
		||||
	struct page *page, unsigned long vaddr, void *dst, const void *src,
 | 
			
		||||
	unsigned long len)
 | 
			
		||||
@ -249,8 +247,6 @@ void copy_to_user_page(struct vm_area_struct *vma,
 | 
			
		||||
		flush_cache_page(vma, vaddr, page_to_pfn(page));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(copy_to_user_page);
 | 
			
		||||
 | 
			
		||||
void copy_from_user_page(struct vm_area_struct *vma,
 | 
			
		||||
	struct page *page, unsigned long vaddr, void *dst, const void *src,
 | 
			
		||||
	unsigned long len)
 | 
			
		||||
@ -267,9 +263,6 @@ void copy_from_user_page(struct vm_area_struct *vma,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(copy_from_user_page);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_HIGHMEM
 | 
			
		||||
unsigned long highstart_pfn, highend_pfn;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										684
									
								
								arch/mips/mm/page.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										684
									
								
								arch/mips/mm/page.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,684 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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) 2003, 04, 05 Ralf Baechle (ralf@linux-mips.org)
 | 
			
		||||
 * Copyright (C) 2007  Maciej W. Rozycki
 | 
			
		||||
 * Copyright (C) 2008  Thiemo Seufer
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/proc_fs.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bugs.h>
 | 
			
		||||
#include <asm/cacheops.h>
 | 
			
		||||
#include <asm/inst.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/page.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <asm/prefetch.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/mmu_context.h>
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/war.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
 | 
			
		||||
#include <asm/sibyte/sb1250.h>
 | 
			
		||||
#include <asm/sibyte/sb1250_regs.h>
 | 
			
		||||
#include <asm/sibyte/sb1250_dma.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "uasm.h"
 | 
			
		||||
 | 
			
		||||
/* Registers used in the assembled routines. */
 | 
			
		||||
#define ZERO 0
 | 
			
		||||
#define AT 2
 | 
			
		||||
#define A0 4
 | 
			
		||||
#define A1 5
 | 
			
		||||
#define A2 6
 | 
			
		||||
#define T0 8
 | 
			
		||||
#define T1 9
 | 
			
		||||
#define T2 10
 | 
			
		||||
#define T3 11
 | 
			
		||||
#define T9 25
 | 
			
		||||
#define RA 31
 | 
			
		||||
 | 
			
		||||
/* Handle labels (which must be positive integers). */
 | 
			
		||||
enum label_id {
 | 
			
		||||
	label_clear_nopref = 1,
 | 
			
		||||
	label_clear_pref,
 | 
			
		||||
	label_copy_nopref,
 | 
			
		||||
	label_copy_pref_both,
 | 
			
		||||
	label_copy_pref_store,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
UASM_L_LA(_clear_nopref)
 | 
			
		||||
UASM_L_LA(_clear_pref)
 | 
			
		||||
UASM_L_LA(_copy_nopref)
 | 
			
		||||
UASM_L_LA(_copy_pref_both)
 | 
			
		||||
UASM_L_LA(_copy_pref_store)
 | 
			
		||||
 | 
			
		||||
/* We need one branch and therefore one relocation per target label. */
 | 
			
		||||
static struct uasm_label __cpuinitdata labels[5];
 | 
			
		||||
static struct uasm_reloc __cpuinitdata relocs[5];
 | 
			
		||||
 | 
			
		||||
#define cpu_is_r4600_v1_x()	((read_c0_prid() & 0xfffffff0) == 0x00002010)
 | 
			
		||||
#define cpu_is_r4600_v2_x()	((read_c0_prid() & 0xfffffff0) == 0x00002020)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Maximum sizes:
 | 
			
		||||
 *
 | 
			
		||||
 * R4000 128 bytes S-cache:		0x058 bytes
 | 
			
		||||
 * R4600 v1.7:				0x05c bytes
 | 
			
		||||
 * R4600 v2.0:				0x060 bytes
 | 
			
		||||
 * With prefetching, 16 word strides	0x120 bytes
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static u32 clear_page_array[0x120 / 4];
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
 | 
			
		||||
void clear_page_cpu(void *page) __attribute__((alias("clear_page_array")));
 | 
			
		||||
#else
 | 
			
		||||
void clear_page(void *page) __attribute__((alias("clear_page_array")));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(clear_page);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Maximum sizes:
 | 
			
		||||
 *
 | 
			
		||||
 * R4000 128 bytes S-cache:		0x11c bytes
 | 
			
		||||
 * R4600 v1.7:				0x080 bytes
 | 
			
		||||
 * R4600 v2.0:				0x07c bytes
 | 
			
		||||
 * With prefetching, 16 word strides	0x540 bytes
 | 
			
		||||
 */
 | 
			
		||||
static u32 copy_page_array[0x540 / 4];
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
 | 
			
		||||
void
 | 
			
		||||
copy_page_cpu(void *to, void *from) __attribute__((alias("copy_page_array")));
 | 
			
		||||
#else
 | 
			
		||||
void copy_page(void *to, void *from) __attribute__((alias("copy_page_array")));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(copy_page);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int pref_bias_clear_store __cpuinitdata;
 | 
			
		||||
static int pref_bias_copy_load __cpuinitdata;
 | 
			
		||||
static int pref_bias_copy_store __cpuinitdata;
 | 
			
		||||
 | 
			
		||||
static u32 pref_src_mode __cpuinitdata;
 | 
			
		||||
static u32 pref_dst_mode __cpuinitdata;
 | 
			
		||||
 | 
			
		||||
static int clear_word_size __cpuinitdata;
 | 
			
		||||
static int copy_word_size __cpuinitdata;
 | 
			
		||||
 | 
			
		||||
static int half_clear_loop_size __cpuinitdata;
 | 
			
		||||
static int half_copy_loop_size __cpuinitdata;
 | 
			
		||||
 | 
			
		||||
static int cache_line_size __cpuinitdata;
 | 
			
		||||
#define cache_line_mask() (cache_line_size - 1)
 | 
			
		||||
 | 
			
		||||
static inline void __cpuinit
 | 
			
		||||
pg_addiu(u32 **buf, unsigned int reg1, unsigned int reg2, unsigned int off)
 | 
			
		||||
{
 | 
			
		||||
	if (cpu_has_64bit_gp_regs && DADDI_WAR && r4k_daddiu_bug()) {
 | 
			
		||||
		if (off > 0x7fff) {
 | 
			
		||||
			uasm_i_lui(buf, T9, uasm_rel_hi(off));
 | 
			
		||||
			uasm_i_addiu(buf, T9, T9, uasm_rel_lo(off));
 | 
			
		||||
		} else
 | 
			
		||||
			uasm_i_addiu(buf, T9, ZERO, off);
 | 
			
		||||
		uasm_i_daddu(buf, reg1, reg2, T9);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (off > 0x7fff) {
 | 
			
		||||
			uasm_i_lui(buf, T9, uasm_rel_hi(off));
 | 
			
		||||
			uasm_i_addiu(buf, T9, T9, uasm_rel_lo(off));
 | 
			
		||||
			UASM_i_ADDU(buf, reg1, reg2, T9);
 | 
			
		||||
		} else
 | 
			
		||||
			UASM_i_ADDIU(buf, reg1, reg2, off);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __cpuinit set_prefetch_parameters(void)
 | 
			
		||||
{
 | 
			
		||||
	if (cpu_has_64bit_gp_regs || cpu_has_64bit_zero_reg)
 | 
			
		||||
		clear_word_size = 8;
 | 
			
		||||
	else
 | 
			
		||||
		clear_word_size = 4;
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_64bit_gp_regs)
 | 
			
		||||
		copy_word_size = 8;
 | 
			
		||||
	else
 | 
			
		||||
		copy_word_size = 4;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The pref's used here are using "streaming" hints, which cause the
 | 
			
		||||
	 * copied data to be kicked out of the cache sooner.  A page copy often
 | 
			
		||||
	 * ends up copying a lot more data than is commonly used, so this seems
 | 
			
		||||
	 * to make sense in terms of reducing cache pollution, but I've no real
 | 
			
		||||
	 * performance data to back this up.
 | 
			
		||||
	 */
 | 
			
		||||
	if (cpu_has_prefetch) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * XXX: Most prefetch bias values in here are based on
 | 
			
		||||
		 * guesswork.
 | 
			
		||||
		 */
 | 
			
		||||
		cache_line_size = cpu_dcache_line_size();
 | 
			
		||||
		switch (current_cpu_type()) {
 | 
			
		||||
		case CPU_TX49XX:
 | 
			
		||||
			/* TX49 supports only Pref_Load */
 | 
			
		||||
			pref_bias_copy_load = 256;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case CPU_RM9000:
 | 
			
		||||
			/*
 | 
			
		||||
			 * As a workaround for erratum G105 which make the
 | 
			
		||||
			 * PrepareForStore hint unusable we fall back to
 | 
			
		||||
			 * StoreRetained on the RM9000.  Once it is known which
 | 
			
		||||
			 * versions of the RM9000 we'll be able to condition-
 | 
			
		||||
			 * alize this.
 | 
			
		||||
			 */
 | 
			
		||||
 | 
			
		||||
		case CPU_R10000:
 | 
			
		||||
		case CPU_R12000:
 | 
			
		||||
		case CPU_R14000:
 | 
			
		||||
			/*
 | 
			
		||||
			 * Those values have been experimentally tuned for an
 | 
			
		||||
			 * Origin 200.
 | 
			
		||||
			 */
 | 
			
		||||
			pref_bias_clear_store = 512;
 | 
			
		||||
			pref_bias_copy_load = 256;
 | 
			
		||||
			pref_bias_copy_store = 256;
 | 
			
		||||
			pref_src_mode = Pref_LoadStreamed;
 | 
			
		||||
			pref_dst_mode = Pref_StoreStreamed;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case CPU_SB1:
 | 
			
		||||
		case CPU_SB1A:
 | 
			
		||||
			pref_bias_clear_store = 128;
 | 
			
		||||
			pref_bias_copy_load = 128;
 | 
			
		||||
			pref_bias_copy_store = 128;
 | 
			
		||||
			/*
 | 
			
		||||
			 * SB1 pass1 Pref_LoadStreamed/Pref_StoreStreamed
 | 
			
		||||
			 * hints are broken.
 | 
			
		||||
			 */
 | 
			
		||||
			if (current_cpu_type() == CPU_SB1 &&
 | 
			
		||||
			    (current_cpu_data.processor_id & 0xff) < 0x02) {
 | 
			
		||||
				pref_src_mode = Pref_Load;
 | 
			
		||||
				pref_dst_mode = Pref_Store;
 | 
			
		||||
			} else {
 | 
			
		||||
				pref_src_mode = Pref_LoadStreamed;
 | 
			
		||||
				pref_dst_mode = Pref_StoreStreamed;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			pref_bias_clear_store = 128;
 | 
			
		||||
			pref_bias_copy_load = 256;
 | 
			
		||||
			pref_bias_copy_store = 128;
 | 
			
		||||
			pref_src_mode = Pref_LoadStreamed;
 | 
			
		||||
			pref_dst_mode = Pref_PrepareForStore;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (cpu_has_cache_cdex_s)
 | 
			
		||||
			cache_line_size = cpu_scache_line_size();
 | 
			
		||||
		else if (cpu_has_cache_cdex_p)
 | 
			
		||||
			cache_line_size = cpu_dcache_line_size();
 | 
			
		||||
	}
 | 
			
		||||
	/*
 | 
			
		||||
	 * Too much unrolling will overflow the available space in
 | 
			
		||||
	 * clear_space_array / copy_page_array. 8 words sounds generous,
 | 
			
		||||
	 * but a R4000 with 128 byte L2 line length can exceed even that.
 | 
			
		||||
	 */
 | 
			
		||||
	half_clear_loop_size = min(8 * clear_word_size,
 | 
			
		||||
				   max(cache_line_size >> 1,
 | 
			
		||||
				       4 * clear_word_size));
 | 
			
		||||
	half_copy_loop_size = min(8 * copy_word_size,
 | 
			
		||||
				  max(cache_line_size >> 1,
 | 
			
		||||
				      4 * copy_word_size));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __cpuinit build_clear_store(u32 **buf, int off)
 | 
			
		||||
{
 | 
			
		||||
	if (cpu_has_64bit_gp_regs || cpu_has_64bit_zero_reg) {
 | 
			
		||||
		uasm_i_sd(buf, ZERO, off, A0);
 | 
			
		||||
	} else {
 | 
			
		||||
		uasm_i_sw(buf, ZERO, off, A0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void __cpuinit build_clear_pref(u32 **buf, int off)
 | 
			
		||||
{
 | 
			
		||||
	if (off & cache_line_mask())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (pref_bias_clear_store) {
 | 
			
		||||
		uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off,
 | 
			
		||||
			    A0);
 | 
			
		||||
	} else if (cpu_has_cache_cdex_s) {
 | 
			
		||||
		uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0);
 | 
			
		||||
	} else if (cpu_has_cache_cdex_p) {
 | 
			
		||||
		if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
 | 
			
		||||
			uasm_i_nop(buf);
 | 
			
		||||
			uasm_i_nop(buf);
 | 
			
		||||
			uasm_i_nop(buf);
 | 
			
		||||
			uasm_i_nop(buf);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 | 
			
		||||
			uasm_i_lw(buf, ZERO, ZERO, AT);
 | 
			
		||||
 | 
			
		||||
		uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __cpuinit build_clear_page(void)
 | 
			
		||||
{
 | 
			
		||||
	int off;
 | 
			
		||||
	u32 *buf = (u32 *)&clear_page_array;
 | 
			
		||||
	struct uasm_label *l = labels;
 | 
			
		||||
	struct uasm_reloc *r = relocs;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	memset(labels, 0, sizeof(labels));
 | 
			
		||||
	memset(relocs, 0, sizeof(relocs));
 | 
			
		||||
 | 
			
		||||
	set_prefetch_parameters();
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * This algorithm makes the following assumptions:
 | 
			
		||||
	 *   - The prefetch bias is a multiple of 2 words.
 | 
			
		||||
	 *   - The prefetch bias is less than one page.
 | 
			
		||||
	 */
 | 
			
		||||
	BUG_ON(pref_bias_clear_store % (2 * clear_word_size));
 | 
			
		||||
	BUG_ON(PAGE_SIZE < pref_bias_clear_store);
 | 
			
		||||
 | 
			
		||||
	off = PAGE_SIZE - pref_bias_clear_store;
 | 
			
		||||
	if (off > 0xffff || !pref_bias_clear_store)
 | 
			
		||||
		pg_addiu(&buf, A2, A0, off);
 | 
			
		||||
	else
 | 
			
		||||
		uasm_i_ori(&buf, A2, A0, off);
 | 
			
		||||
 | 
			
		||||
	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 | 
			
		||||
		uasm_i_lui(&buf, AT, 0xa000);
 | 
			
		||||
 | 
			
		||||
	off = min(8, pref_bias_clear_store / cache_line_size) *
 | 
			
		||||
	      cache_line_size;
 | 
			
		||||
	while (off) {
 | 
			
		||||
		build_clear_pref(&buf, -off);
 | 
			
		||||
		off -= cache_line_size;
 | 
			
		||||
	}
 | 
			
		||||
	uasm_l_clear_pref(&l, buf);
 | 
			
		||||
	do {
 | 
			
		||||
		build_clear_pref(&buf, off);
 | 
			
		||||
		build_clear_store(&buf, off);
 | 
			
		||||
		off += clear_word_size;
 | 
			
		||||
	} while (off < half_clear_loop_size);
 | 
			
		||||
	pg_addiu(&buf, A0, A0, 2 * off);
 | 
			
		||||
	off = -off;
 | 
			
		||||
	do {
 | 
			
		||||
		build_clear_pref(&buf, off);
 | 
			
		||||
		if (off == -clear_word_size)
 | 
			
		||||
			uasm_il_bne(&buf, &r, A0, A2, label_clear_pref);
 | 
			
		||||
		build_clear_store(&buf, off);
 | 
			
		||||
		off += clear_word_size;
 | 
			
		||||
	} while (off < 0);
 | 
			
		||||
 | 
			
		||||
	if (pref_bias_clear_store) {
 | 
			
		||||
		pg_addiu(&buf, A2, A0, pref_bias_clear_store);
 | 
			
		||||
		uasm_l_clear_nopref(&l, buf);
 | 
			
		||||
		off = 0;
 | 
			
		||||
		do {
 | 
			
		||||
			build_clear_store(&buf, off);
 | 
			
		||||
			off += clear_word_size;
 | 
			
		||||
		} while (off < half_clear_loop_size);
 | 
			
		||||
		pg_addiu(&buf, A0, A0, 2 * off);
 | 
			
		||||
		off = -off;
 | 
			
		||||
		do {
 | 
			
		||||
			if (off == -clear_word_size)
 | 
			
		||||
				uasm_il_bne(&buf, &r, A0, A2,
 | 
			
		||||
					    label_clear_nopref);
 | 
			
		||||
			build_clear_store(&buf, off);
 | 
			
		||||
			off += clear_word_size;
 | 
			
		||||
		} while (off < 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uasm_i_jr(&buf, RA);
 | 
			
		||||
	uasm_i_nop(&buf);
 | 
			
		||||
 | 
			
		||||
	BUG_ON(buf > clear_page_array + ARRAY_SIZE(clear_page_array));
 | 
			
		||||
 | 
			
		||||
	uasm_resolve_relocs(relocs, labels);
 | 
			
		||||
 | 
			
		||||
	pr_debug("Synthesized clear page handler (%u instructions).\n",
 | 
			
		||||
		 (u32)(buf - clear_page_array));
 | 
			
		||||
 | 
			
		||||
	pr_debug("\t.set push\n");
 | 
			
		||||
	pr_debug("\t.set noreorder\n");
 | 
			
		||||
	for (i = 0; i < (buf - clear_page_array); i++)
 | 
			
		||||
		pr_debug("\t.word 0x%08x\n", clear_page_array[i]);
 | 
			
		||||
	pr_debug("\t.set pop\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __cpuinit build_copy_load(u32 **buf, int reg, int off)
 | 
			
		||||
{
 | 
			
		||||
	if (cpu_has_64bit_gp_regs) {
 | 
			
		||||
		uasm_i_ld(buf, reg, off, A1);
 | 
			
		||||
	} else {
 | 
			
		||||
		uasm_i_lw(buf, reg, off, A1);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __cpuinit build_copy_store(u32 **buf, int reg, int off)
 | 
			
		||||
{
 | 
			
		||||
	if (cpu_has_64bit_gp_regs) {
 | 
			
		||||
		uasm_i_sd(buf, reg, off, A0);
 | 
			
		||||
	} else {
 | 
			
		||||
		uasm_i_sw(buf, reg, off, A0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_copy_load_pref(u32 **buf, int off)
 | 
			
		||||
{
 | 
			
		||||
	if (off & cache_line_mask())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (pref_bias_copy_load)
 | 
			
		||||
		uasm_i_pref(buf, pref_src_mode, pref_bias_copy_load + off, A1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_copy_store_pref(u32 **buf, int off)
 | 
			
		||||
{
 | 
			
		||||
	if (off & cache_line_mask())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (pref_bias_copy_store) {
 | 
			
		||||
		uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off,
 | 
			
		||||
			    A0);
 | 
			
		||||
	} else if (cpu_has_cache_cdex_s) {
 | 
			
		||||
		uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0);
 | 
			
		||||
	} else if (cpu_has_cache_cdex_p) {
 | 
			
		||||
		if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
 | 
			
		||||
			uasm_i_nop(buf);
 | 
			
		||||
			uasm_i_nop(buf);
 | 
			
		||||
			uasm_i_nop(buf);
 | 
			
		||||
			uasm_i_nop(buf);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 | 
			
		||||
			uasm_i_lw(buf, ZERO, ZERO, AT);
 | 
			
		||||
 | 
			
		||||
		uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __cpuinit build_copy_page(void)
 | 
			
		||||
{
 | 
			
		||||
	int off;
 | 
			
		||||
	u32 *buf = (u32 *)©_page_array;
 | 
			
		||||
	struct uasm_label *l = labels;
 | 
			
		||||
	struct uasm_reloc *r = relocs;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	memset(labels, 0, sizeof(labels));
 | 
			
		||||
	memset(relocs, 0, sizeof(relocs));
 | 
			
		||||
 | 
			
		||||
	set_prefetch_parameters();
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * This algorithm makes the following assumptions:
 | 
			
		||||
	 *   - All prefetch biases are multiples of 8 words.
 | 
			
		||||
	 *   - The prefetch biases are less than one page.
 | 
			
		||||
	 *   - The store prefetch bias isn't greater than the load
 | 
			
		||||
	 *     prefetch bias.
 | 
			
		||||
	 */
 | 
			
		||||
	BUG_ON(pref_bias_copy_load % (8 * copy_word_size));
 | 
			
		||||
	BUG_ON(pref_bias_copy_store % (8 * copy_word_size));
 | 
			
		||||
	BUG_ON(PAGE_SIZE < pref_bias_copy_load);
 | 
			
		||||
	BUG_ON(pref_bias_copy_store > pref_bias_copy_load);
 | 
			
		||||
 | 
			
		||||
	off = PAGE_SIZE - pref_bias_copy_load;
 | 
			
		||||
	if (off > 0xffff || !pref_bias_copy_load)
 | 
			
		||||
		pg_addiu(&buf, A2, A0, off);
 | 
			
		||||
	else
 | 
			
		||||
		uasm_i_ori(&buf, A2, A0, off);
 | 
			
		||||
 | 
			
		||||
	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 | 
			
		||||
		uasm_i_lui(&buf, AT, 0xa000);
 | 
			
		||||
 | 
			
		||||
	off = min(8, pref_bias_copy_load / cache_line_size) * cache_line_size;
 | 
			
		||||
	while (off) {
 | 
			
		||||
		build_copy_load_pref(&buf, -off);
 | 
			
		||||
		off -= cache_line_size;
 | 
			
		||||
	}
 | 
			
		||||
	off = min(8, pref_bias_copy_store / cache_line_size) * cache_line_size;
 | 
			
		||||
	while (off) {
 | 
			
		||||
		build_copy_store_pref(&buf, -off);
 | 
			
		||||
		off -= cache_line_size;
 | 
			
		||||
	}
 | 
			
		||||
	uasm_l_copy_pref_both(&l, buf);
 | 
			
		||||
	do {
 | 
			
		||||
		build_copy_load_pref(&buf, off);
 | 
			
		||||
		build_copy_load(&buf, T0, off);
 | 
			
		||||
		build_copy_load_pref(&buf, off + copy_word_size);
 | 
			
		||||
		build_copy_load(&buf, T1, off + copy_word_size);
 | 
			
		||||
		build_copy_load_pref(&buf, off + 2 * copy_word_size);
 | 
			
		||||
		build_copy_load(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
		build_copy_load_pref(&buf, off + 3 * copy_word_size);
 | 
			
		||||
		build_copy_load(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
		build_copy_store_pref(&buf, off);
 | 
			
		||||
		build_copy_store(&buf, T0, off);
 | 
			
		||||
		build_copy_store_pref(&buf, off + copy_word_size);
 | 
			
		||||
		build_copy_store(&buf, T1, off + copy_word_size);
 | 
			
		||||
		build_copy_store_pref(&buf, off + 2 * copy_word_size);
 | 
			
		||||
		build_copy_store(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
		build_copy_store_pref(&buf, off + 3 * copy_word_size);
 | 
			
		||||
		build_copy_store(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
		off += 4 * copy_word_size;
 | 
			
		||||
	} while (off < half_copy_loop_size);
 | 
			
		||||
	pg_addiu(&buf, A1, A1, 2 * off);
 | 
			
		||||
	pg_addiu(&buf, A0, A0, 2 * off);
 | 
			
		||||
	off = -off;
 | 
			
		||||
	do {
 | 
			
		||||
		build_copy_load_pref(&buf, off);
 | 
			
		||||
		build_copy_load(&buf, T0, off);
 | 
			
		||||
		build_copy_load_pref(&buf, off + copy_word_size);
 | 
			
		||||
		build_copy_load(&buf, T1, off + copy_word_size);
 | 
			
		||||
		build_copy_load_pref(&buf, off + 2 * copy_word_size);
 | 
			
		||||
		build_copy_load(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
		build_copy_load_pref(&buf, off + 3 * copy_word_size);
 | 
			
		||||
		build_copy_load(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
		build_copy_store_pref(&buf, off);
 | 
			
		||||
		build_copy_store(&buf, T0, off);
 | 
			
		||||
		build_copy_store_pref(&buf, off + copy_word_size);
 | 
			
		||||
		build_copy_store(&buf, T1, off + copy_word_size);
 | 
			
		||||
		build_copy_store_pref(&buf, off + 2 * copy_word_size);
 | 
			
		||||
		build_copy_store(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
		build_copy_store_pref(&buf, off + 3 * copy_word_size);
 | 
			
		||||
		if (off == -(4 * copy_word_size))
 | 
			
		||||
			uasm_il_bne(&buf, &r, A2, A0, label_copy_pref_both);
 | 
			
		||||
		build_copy_store(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
		off += 4 * copy_word_size;
 | 
			
		||||
	} while (off < 0);
 | 
			
		||||
 | 
			
		||||
	if (pref_bias_copy_load - pref_bias_copy_store) {
 | 
			
		||||
		pg_addiu(&buf, A2, A0,
 | 
			
		||||
			 pref_bias_copy_load - pref_bias_copy_store);
 | 
			
		||||
		uasm_l_copy_pref_store(&l, buf);
 | 
			
		||||
		off = 0;
 | 
			
		||||
		do {
 | 
			
		||||
			build_copy_load(&buf, T0, off);
 | 
			
		||||
			build_copy_load(&buf, T1, off + copy_word_size);
 | 
			
		||||
			build_copy_load(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
			build_copy_load(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
			build_copy_store_pref(&buf, off);
 | 
			
		||||
			build_copy_store(&buf, T0, off);
 | 
			
		||||
			build_copy_store_pref(&buf, off + copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T1, off + copy_word_size);
 | 
			
		||||
			build_copy_store_pref(&buf, off + 2 * copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
			build_copy_store_pref(&buf, off + 3 * copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
			off += 4 * copy_word_size;
 | 
			
		||||
		} while (off < half_copy_loop_size);
 | 
			
		||||
		pg_addiu(&buf, A1, A1, 2 * off);
 | 
			
		||||
		pg_addiu(&buf, A0, A0, 2 * off);
 | 
			
		||||
		off = -off;
 | 
			
		||||
		do {
 | 
			
		||||
			build_copy_load(&buf, T0, off);
 | 
			
		||||
			build_copy_load(&buf, T1, off + copy_word_size);
 | 
			
		||||
			build_copy_load(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
			build_copy_load(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
			build_copy_store_pref(&buf, off);
 | 
			
		||||
			build_copy_store(&buf, T0, off);
 | 
			
		||||
			build_copy_store_pref(&buf, off + copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T1, off + copy_word_size);
 | 
			
		||||
			build_copy_store_pref(&buf, off + 2 * copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
			build_copy_store_pref(&buf, off + 3 * copy_word_size);
 | 
			
		||||
			if (off == -(4 * copy_word_size))
 | 
			
		||||
				uasm_il_bne(&buf, &r, A2, A0,
 | 
			
		||||
					    label_copy_pref_store);
 | 
			
		||||
			build_copy_store(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
			off += 4 * copy_word_size;
 | 
			
		||||
		} while (off < 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pref_bias_copy_store) {
 | 
			
		||||
		pg_addiu(&buf, A2, A0, pref_bias_copy_store);
 | 
			
		||||
		uasm_l_copy_nopref(&l, buf);
 | 
			
		||||
		off = 0;
 | 
			
		||||
		do {
 | 
			
		||||
			build_copy_load(&buf, T0, off);
 | 
			
		||||
			build_copy_load(&buf, T1, off + copy_word_size);
 | 
			
		||||
			build_copy_load(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
			build_copy_load(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T0, off);
 | 
			
		||||
			build_copy_store(&buf, T1, off + copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
			off += 4 * copy_word_size;
 | 
			
		||||
		} while (off < half_copy_loop_size);
 | 
			
		||||
		pg_addiu(&buf, A1, A1, 2 * off);
 | 
			
		||||
		pg_addiu(&buf, A0, A0, 2 * off);
 | 
			
		||||
		off = -off;
 | 
			
		||||
		do {
 | 
			
		||||
			build_copy_load(&buf, T0, off);
 | 
			
		||||
			build_copy_load(&buf, T1, off + copy_word_size);
 | 
			
		||||
			build_copy_load(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
			build_copy_load(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T0, off);
 | 
			
		||||
			build_copy_store(&buf, T1, off + copy_word_size);
 | 
			
		||||
			build_copy_store(&buf, T2, off + 2 * copy_word_size);
 | 
			
		||||
			if (off == -(4 * copy_word_size))
 | 
			
		||||
				uasm_il_bne(&buf, &r, A2, A0,
 | 
			
		||||
					    label_copy_nopref);
 | 
			
		||||
			build_copy_store(&buf, T3, off + 3 * copy_word_size);
 | 
			
		||||
			off += 4 * copy_word_size;
 | 
			
		||||
		} while (off < 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uasm_i_jr(&buf, RA);
 | 
			
		||||
	uasm_i_nop(&buf);
 | 
			
		||||
 | 
			
		||||
	BUG_ON(buf > copy_page_array + ARRAY_SIZE(copy_page_array));
 | 
			
		||||
 | 
			
		||||
	uasm_resolve_relocs(relocs, labels);
 | 
			
		||||
 | 
			
		||||
	pr_debug("Synthesized copy page handler (%u instructions).\n",
 | 
			
		||||
		 (u32)(buf - copy_page_array));
 | 
			
		||||
 | 
			
		||||
	pr_debug("\t.set push\n");
 | 
			
		||||
	pr_debug("\t.set noreorder\n");
 | 
			
		||||
	for (i = 0; i < (buf - copy_page_array); i++)
 | 
			
		||||
		pr_debug("\t.word 0x%08x\n", copy_page_array[i]);
 | 
			
		||||
	pr_debug("\t.set pop\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Pad descriptors to cacheline, since each is exclusively owned by a
 | 
			
		||||
 * particular CPU.
 | 
			
		||||
 */
 | 
			
		||||
struct dmadscr {
 | 
			
		||||
	u64 dscr_a;
 | 
			
		||||
	u64 dscr_b;
 | 
			
		||||
	u64 pad_a;
 | 
			
		||||
	u64 pad_b;
 | 
			
		||||
} ____cacheline_aligned_in_smp page_descr[DM_NUM_CHANNELS];
 | 
			
		||||
 | 
			
		||||
void sb1_dma_init(void)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < DM_NUM_CHANNELS; i++) {
 | 
			
		||||
		const u64 base_val = CPHYSADDR((unsigned long)&page_descr[i]) |
 | 
			
		||||
				     V_DM_DSCR_BASE_RINGSZ(1);
 | 
			
		||||
		void *base_reg = IOADDR(A_DM_REGISTER(i, R_DM_DSCR_BASE));
 | 
			
		||||
 | 
			
		||||
		__raw_writeq(base_val, base_reg);
 | 
			
		||||
		__raw_writeq(base_val | M_DM_DSCR_BASE_RESET, base_reg);
 | 
			
		||||
		__raw_writeq(base_val | M_DM_DSCR_BASE_ENABL, base_reg);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clear_page(void *page)
 | 
			
		||||
{
 | 
			
		||||
	u64 to_phys = CPHYSADDR((unsigned long)page);
 | 
			
		||||
	unsigned int cpu = smp_processor_id();
 | 
			
		||||
 | 
			
		||||
	/* if the page is not in KSEG0, use old way */
 | 
			
		||||
	if ((long)KSEGX((unsigned long)page) != (long)CKSEG0)
 | 
			
		||||
		return clear_page_cpu(page);
 | 
			
		||||
 | 
			
		||||
	page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_ZERO_MEM |
 | 
			
		||||
				 M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
 | 
			
		||||
	page_descr[cpu].dscr_b = V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
 | 
			
		||||
	__raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Don't really want to do it this way, but there's no
 | 
			
		||||
	 * reliable way to delay completion detection.
 | 
			
		||||
	 */
 | 
			
		||||
	while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
 | 
			
		||||
		 & M_DM_DSCR_BASE_INTERRUPT))
 | 
			
		||||
		;
 | 
			
		||||
	__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void copy_page(void *to, void *from)
 | 
			
		||||
{
 | 
			
		||||
	u64 from_phys = CPHYSADDR((unsigned long)from);
 | 
			
		||||
	u64 to_phys = CPHYSADDR((unsigned long)to);
 | 
			
		||||
	unsigned int cpu = smp_processor_id();
 | 
			
		||||
 | 
			
		||||
	/* if any page is not in KSEG0, use old way */
 | 
			
		||||
	if ((long)KSEGX((unsigned long)to) != (long)CKSEG0
 | 
			
		||||
	    || (long)KSEGX((unsigned long)from) != (long)CKSEG0)
 | 
			
		||||
		return copy_page_cpu(to, from);
 | 
			
		||||
 | 
			
		||||
	page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_L2C_DEST |
 | 
			
		||||
				 M_DM_DSCRA_INTERRUPT;
 | 
			
		||||
	page_descr[cpu].dscr_b = from_phys | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
 | 
			
		||||
	__raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Don't really want to do it this way, but there's no
 | 
			
		||||
	 * reliable way to delay completion detection.
 | 
			
		||||
	 */
 | 
			
		||||
	while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
 | 
			
		||||
		 & M_DM_DSCR_BASE_INTERRUPT))
 | 
			
		||||
		;
 | 
			
		||||
	__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* CONFIG_SIBYTE_DMA_PAGEOPS */
 | 
			
		||||
@ -1,534 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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) 2003, 04, 05 Ralf Baechle (ralf@linux-mips.org)
 | 
			
		||||
 * Copyright (C) 2007  Maciej W. Rozycki
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/proc_fs.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/bugs.h>
 | 
			
		||||
#include <asm/cacheops.h>
 | 
			
		||||
#include <asm/inst.h>
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/page.h>
 | 
			
		||||
#include <asm/pgtable.h>
 | 
			
		||||
#include <asm/prefetch.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <asm/bootinfo.h>
 | 
			
		||||
#include <asm/mipsregs.h>
 | 
			
		||||
#include <asm/mmu_context.h>
 | 
			
		||||
#include <asm/cpu.h>
 | 
			
		||||
#include <asm/war.h>
 | 
			
		||||
 | 
			
		||||
#define half_scache_line_size()	(cpu_scache_line_size() >> 1)
 | 
			
		||||
#define cpu_is_r4600_v1_x()	((read_c0_prid() & 0xfffffff0) == 0x00002010)
 | 
			
		||||
#define cpu_is_r4600_v2_x()	((read_c0_prid() & 0xfffffff0) == 0x00002020)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Maximum sizes:
 | 
			
		||||
 *
 | 
			
		||||
 * R4000 128 bytes S-cache:		0x58 bytes
 | 
			
		||||
 * R4600 v1.7:				0x5c bytes
 | 
			
		||||
 * R4600 v2.0:				0x60 bytes
 | 
			
		||||
 * With prefetching, 16 byte strides	0xa0 bytes
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static unsigned int clear_page_array[0x130 / 4];
 | 
			
		||||
 | 
			
		||||
void clear_page(void * page) __attribute__((alias("clear_page_array")));
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(clear_page);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Maximum sizes:
 | 
			
		||||
 *
 | 
			
		||||
 * R4000 128 bytes S-cache:		0x11c bytes
 | 
			
		||||
 * R4600 v1.7:				0x080 bytes
 | 
			
		||||
 * R4600 v2.0:				0x07c bytes
 | 
			
		||||
 * With prefetching, 16 byte strides	0x0b8 bytes
 | 
			
		||||
 */
 | 
			
		||||
static unsigned int copy_page_array[0x148 / 4];
 | 
			
		||||
 | 
			
		||||
void copy_page(void *to, void *from) __attribute__((alias("copy_page_array")));
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(copy_page);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This is suboptimal for 32-bit kernels; we assume that R10000 is only used
 | 
			
		||||
 * with 64-bit kernels.  The prefetch offsets have been experimentally tuned
 | 
			
		||||
 * an Origin 200.
 | 
			
		||||
 */
 | 
			
		||||
static int pref_offset_clear __cpuinitdata = 512;
 | 
			
		||||
static int pref_offset_copy  __cpuinitdata = 256;
 | 
			
		||||
 | 
			
		||||
static unsigned int pref_src_mode __cpuinitdata;
 | 
			
		||||
static unsigned int pref_dst_mode __cpuinitdata;
 | 
			
		||||
 | 
			
		||||
static int load_offset __cpuinitdata;
 | 
			
		||||
static int store_offset __cpuinitdata;
 | 
			
		||||
 | 
			
		||||
static unsigned int __cpuinitdata *dest, *epc;
 | 
			
		||||
 | 
			
		||||
static unsigned int instruction_pending;
 | 
			
		||||
static union mips_instruction delayed_mi;
 | 
			
		||||
 | 
			
		||||
static void __cpuinit emit_instruction(union mips_instruction mi)
 | 
			
		||||
{
 | 
			
		||||
	if (instruction_pending)
 | 
			
		||||
		*epc++ = delayed_mi.word;
 | 
			
		||||
 | 
			
		||||
	instruction_pending = 1;
 | 
			
		||||
	delayed_mi = mi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void flush_delay_slot_or_nop(void)
 | 
			
		||||
{
 | 
			
		||||
	if (instruction_pending) {
 | 
			
		||||
		*epc++ = delayed_mi.word;
 | 
			
		||||
		instruction_pending = 0;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*epc++ = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline unsigned int *label(void)
 | 
			
		||||
{
 | 
			
		||||
	if (instruction_pending) {
 | 
			
		||||
		*epc++ = delayed_mi.word;
 | 
			
		||||
		instruction_pending = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return epc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_insn_word(unsigned int word)
 | 
			
		||||
{
 | 
			
		||||
	union mips_instruction mi;
 | 
			
		||||
 | 
			
		||||
	mi.word		 = word;
 | 
			
		||||
 | 
			
		||||
	emit_instruction(mi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_nop(void)
 | 
			
		||||
{
 | 
			
		||||
	build_insn_word(0);			/* nop */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_src_pref(int advance)
 | 
			
		||||
{
 | 
			
		||||
	if (!(load_offset & (cpu_dcache_line_size() - 1)) && advance) {
 | 
			
		||||
		union mips_instruction mi;
 | 
			
		||||
 | 
			
		||||
		mi.i_format.opcode     = pref_op;
 | 
			
		||||
		mi.i_format.rs         = 5;		/* $a1 */
 | 
			
		||||
		mi.i_format.rt         = pref_src_mode;
 | 
			
		||||
		mi.i_format.simmediate = load_offset + advance;
 | 
			
		||||
 | 
			
		||||
		emit_instruction(mi);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void __build_load_reg(int reg)
 | 
			
		||||
{
 | 
			
		||||
	union mips_instruction mi;
 | 
			
		||||
	unsigned int width;
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_64bit_gp_regs) {
 | 
			
		||||
		mi.i_format.opcode     = ld_op;
 | 
			
		||||
		width = 8;
 | 
			
		||||
	} else {
 | 
			
		||||
		mi.i_format.opcode     = lw_op;
 | 
			
		||||
		width = 4;
 | 
			
		||||
	}
 | 
			
		||||
	mi.i_format.rs         = 5;		/* $a1 */
 | 
			
		||||
	mi.i_format.rt         = reg;		/* $reg */
 | 
			
		||||
	mi.i_format.simmediate = load_offset;
 | 
			
		||||
 | 
			
		||||
	load_offset += width;
 | 
			
		||||
	emit_instruction(mi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_load_reg(int reg)
 | 
			
		||||
{
 | 
			
		||||
	if (cpu_has_prefetch)
 | 
			
		||||
		build_src_pref(pref_offset_copy);
 | 
			
		||||
 | 
			
		||||
	__build_load_reg(reg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_dst_pref(int advance)
 | 
			
		||||
{
 | 
			
		||||
	if (!(store_offset & (cpu_dcache_line_size() - 1)) && advance) {
 | 
			
		||||
		union mips_instruction mi;
 | 
			
		||||
 | 
			
		||||
		mi.i_format.opcode     = pref_op;
 | 
			
		||||
		mi.i_format.rs         = 4;		/* $a0 */
 | 
			
		||||
		mi.i_format.rt         = pref_dst_mode;
 | 
			
		||||
		mi.i_format.simmediate = store_offset + advance;
 | 
			
		||||
 | 
			
		||||
		emit_instruction(mi);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_cdex_s(void)
 | 
			
		||||
{
 | 
			
		||||
	union mips_instruction mi;
 | 
			
		||||
 | 
			
		||||
	if ((store_offset & (cpu_scache_line_size() - 1)))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	mi.c_format.opcode     = cache_op;
 | 
			
		||||
	mi.c_format.rs         = 4;		/* $a0 */
 | 
			
		||||
	mi.c_format.c_op       = 3;		/* Create Dirty Exclusive */
 | 
			
		||||
	mi.c_format.cache      = 3;		/* Secondary Data Cache */
 | 
			
		||||
	mi.c_format.simmediate = store_offset;
 | 
			
		||||
 | 
			
		||||
	emit_instruction(mi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_cdex_p(void)
 | 
			
		||||
{
 | 
			
		||||
	union mips_instruction mi;
 | 
			
		||||
 | 
			
		||||
	if (store_offset & (cpu_dcache_line_size() - 1))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
 | 
			
		||||
		build_nop();
 | 
			
		||||
		build_nop();
 | 
			
		||||
		build_nop();
 | 
			
		||||
		build_nop();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 | 
			
		||||
		build_insn_word(0x8c200000);	/* lw      $zero, ($at) */
 | 
			
		||||
 | 
			
		||||
	mi.c_format.opcode     = cache_op;
 | 
			
		||||
	mi.c_format.rs         = 4;		/* $a0 */
 | 
			
		||||
	mi.c_format.c_op       = 3;		/* Create Dirty Exclusive */
 | 
			
		||||
	mi.c_format.cache      = 1;		/* Data Cache */
 | 
			
		||||
	mi.c_format.simmediate = store_offset;
 | 
			
		||||
 | 
			
		||||
	emit_instruction(mi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __cpuinit __build_store_reg(int reg)
 | 
			
		||||
{
 | 
			
		||||
	union mips_instruction mi;
 | 
			
		||||
	unsigned int width;
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_64bit_gp_regs ||
 | 
			
		||||
	    (cpu_has_64bit_zero_reg && reg == 0)) {
 | 
			
		||||
		mi.i_format.opcode     = sd_op;
 | 
			
		||||
		width = 8;
 | 
			
		||||
	} else {
 | 
			
		||||
		mi.i_format.opcode     = sw_op;
 | 
			
		||||
		width = 4;
 | 
			
		||||
	}
 | 
			
		||||
	mi.i_format.rs         = 4;		/* $a0 */
 | 
			
		||||
	mi.i_format.rt         = reg;		/* $reg */
 | 
			
		||||
	mi.i_format.simmediate = store_offset;
 | 
			
		||||
 | 
			
		||||
	store_offset += width;
 | 
			
		||||
	emit_instruction(mi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_store_reg(int reg)
 | 
			
		||||
{
 | 
			
		||||
	int pref_off = cpu_has_prefetch ?
 | 
			
		||||
		(reg ? pref_offset_copy : pref_offset_clear) : 0;
 | 
			
		||||
	if (pref_off)
 | 
			
		||||
		build_dst_pref(pref_off);
 | 
			
		||||
	else if (cpu_has_cache_cdex_s)
 | 
			
		||||
		build_cdex_s();
 | 
			
		||||
	else if (cpu_has_cache_cdex_p)
 | 
			
		||||
		build_cdex_p();
 | 
			
		||||
 | 
			
		||||
	__build_store_reg(reg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_addiu_rt_rs(unsigned int rt, unsigned int rs,
 | 
			
		||||
				     unsigned long offset)
 | 
			
		||||
{
 | 
			
		||||
	union mips_instruction mi;
 | 
			
		||||
 | 
			
		||||
	BUG_ON(offset > 0x7fff);
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_64bit_gp_regs && DADDI_WAR && r4k_daddiu_bug()) {
 | 
			
		||||
		mi.i_format.opcode     = addiu_op;
 | 
			
		||||
		mi.i_format.rs         = 0;	/* $zero */
 | 
			
		||||
		mi.i_format.rt         = 25;	/* $t9 */
 | 
			
		||||
		mi.i_format.simmediate = offset;
 | 
			
		||||
		emit_instruction(mi);
 | 
			
		||||
 | 
			
		||||
		mi.r_format.opcode     = spec_op;
 | 
			
		||||
		mi.r_format.rs         = rs;
 | 
			
		||||
		mi.r_format.rt         = 25;	/* $t9 */
 | 
			
		||||
		mi.r_format.rd         = rt;
 | 
			
		||||
		mi.r_format.re         = 0;
 | 
			
		||||
		mi.r_format.func       = daddu_op;
 | 
			
		||||
	} else {
 | 
			
		||||
		mi.i_format.opcode     = cpu_has_64bit_gp_regs ?
 | 
			
		||||
					 daddiu_op : addiu_op;
 | 
			
		||||
		mi.i_format.rs         = rs;
 | 
			
		||||
		mi.i_format.rt         = rt;
 | 
			
		||||
		mi.i_format.simmediate = offset;
 | 
			
		||||
	}
 | 
			
		||||
	emit_instruction(mi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_addiu_a2_a0(unsigned long offset)
 | 
			
		||||
{
 | 
			
		||||
	build_addiu_rt_rs(6, 4, offset);	/* $a2, $a0, offset */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_addiu_a2(unsigned long offset)
 | 
			
		||||
{
 | 
			
		||||
	build_addiu_rt_rs(6, 6, offset);	/* $a2, $a2, offset */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_addiu_a1(unsigned long offset)
 | 
			
		||||
{
 | 
			
		||||
	build_addiu_rt_rs(5, 5, offset);	/* $a1, $a1, offset */
 | 
			
		||||
 | 
			
		||||
	load_offset -= offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_addiu_a0(unsigned long offset)
 | 
			
		||||
{
 | 
			
		||||
	build_addiu_rt_rs(4, 4, offset);	/* $a0, $a0, offset */
 | 
			
		||||
 | 
			
		||||
	store_offset -= offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_bne(unsigned int *dest)
 | 
			
		||||
{
 | 
			
		||||
	union mips_instruction mi;
 | 
			
		||||
 | 
			
		||||
	mi.i_format.opcode = bne_op;
 | 
			
		||||
	mi.i_format.rs     = 6;			/* $a2 */
 | 
			
		||||
	mi.i_format.rt     = 4;			/* $a0 */
 | 
			
		||||
	mi.i_format.simmediate = dest - epc - 1;
 | 
			
		||||
 | 
			
		||||
	*epc++ = mi.word;
 | 
			
		||||
	flush_delay_slot_or_nop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void build_jr_ra(void)
 | 
			
		||||
{
 | 
			
		||||
	union mips_instruction mi;
 | 
			
		||||
 | 
			
		||||
	mi.r_format.opcode = spec_op;
 | 
			
		||||
	mi.r_format.rs     = 31;
 | 
			
		||||
	mi.r_format.rt     = 0;
 | 
			
		||||
	mi.r_format.rd     = 0;
 | 
			
		||||
	mi.r_format.re     = 0;
 | 
			
		||||
	mi.r_format.func   = jr_op;
 | 
			
		||||
 | 
			
		||||
	*epc++ = mi.word;
 | 
			
		||||
	flush_delay_slot_or_nop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __cpuinit build_clear_page(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int loop_start;
 | 
			
		||||
	unsigned long off;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	epc = (unsigned int *) &clear_page_array;
 | 
			
		||||
	instruction_pending = 0;
 | 
			
		||||
	store_offset = 0;
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_prefetch) {
 | 
			
		||||
		switch (current_cpu_type()) {
 | 
			
		||||
		case CPU_TX49XX:
 | 
			
		||||
			/* TX49 supports only Pref_Load */
 | 
			
		||||
			pref_offset_clear = 0;
 | 
			
		||||
			pref_offset_copy = 0;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case CPU_RM9000:
 | 
			
		||||
			/*
 | 
			
		||||
			 * As a workaround for erratum G105 which make the
 | 
			
		||||
			 * PrepareForStore hint unusable we fall back to
 | 
			
		||||
			 * StoreRetained on the RM9000.  Once it is known which
 | 
			
		||||
			 * versions of the RM9000 we'll be able to condition-
 | 
			
		||||
			 * alize this.
 | 
			
		||||
			 */
 | 
			
		||||
 | 
			
		||||
		case CPU_R10000:
 | 
			
		||||
		case CPU_R12000:
 | 
			
		||||
		case CPU_R14000:
 | 
			
		||||
			pref_src_mode = Pref_LoadStreamed;
 | 
			
		||||
			pref_dst_mode = Pref_StoreStreamed;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			pref_src_mode = Pref_LoadStreamed;
 | 
			
		||||
			pref_dst_mode = Pref_PrepareForStore;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0);
 | 
			
		||||
	if (off > 0x7fff) {
 | 
			
		||||
		build_addiu_a2_a0(off >> 1);
 | 
			
		||||
		build_addiu_a2(off >> 1);
 | 
			
		||||
	} else
 | 
			
		||||
		build_addiu_a2_a0(off);
 | 
			
		||||
 | 
			
		||||
	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 | 
			
		||||
		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
 | 
			
		||||
 | 
			
		||||
dest = label();
 | 
			
		||||
	do {
 | 
			
		||||
		build_store_reg(0);
 | 
			
		||||
		build_store_reg(0);
 | 
			
		||||
		build_store_reg(0);
 | 
			
		||||
		build_store_reg(0);
 | 
			
		||||
	} while (store_offset < half_scache_line_size());
 | 
			
		||||
	build_addiu_a0(2 * store_offset);
 | 
			
		||||
	loop_start = store_offset;
 | 
			
		||||
	do {
 | 
			
		||||
		build_store_reg(0);
 | 
			
		||||
		build_store_reg(0);
 | 
			
		||||
		build_store_reg(0);
 | 
			
		||||
		build_store_reg(0);
 | 
			
		||||
	} while ((store_offset - loop_start) < half_scache_line_size());
 | 
			
		||||
	build_bne(dest);
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_prefetch && pref_offset_clear) {
 | 
			
		||||
		build_addiu_a2_a0(pref_offset_clear);
 | 
			
		||||
	dest = label();
 | 
			
		||||
		loop_start = store_offset;
 | 
			
		||||
		do {
 | 
			
		||||
			__build_store_reg(0);
 | 
			
		||||
			__build_store_reg(0);
 | 
			
		||||
			__build_store_reg(0);
 | 
			
		||||
			__build_store_reg(0);
 | 
			
		||||
		} while ((store_offset - loop_start) < half_scache_line_size());
 | 
			
		||||
		build_addiu_a0(2 * store_offset);
 | 
			
		||||
		loop_start = store_offset;
 | 
			
		||||
		do {
 | 
			
		||||
			__build_store_reg(0);
 | 
			
		||||
			__build_store_reg(0);
 | 
			
		||||
			__build_store_reg(0);
 | 
			
		||||
			__build_store_reg(0);
 | 
			
		||||
		} while ((store_offset - loop_start) < half_scache_line_size());
 | 
			
		||||
		build_bne(dest);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	build_jr_ra();
 | 
			
		||||
 | 
			
		||||
	BUG_ON(epc > clear_page_array + ARRAY_SIZE(clear_page_array));
 | 
			
		||||
 | 
			
		||||
	pr_info("Synthesized clear page handler (%u instructions).\n",
 | 
			
		||||
		(unsigned int)(epc - clear_page_array));
 | 
			
		||||
 | 
			
		||||
	pr_debug("\t.set push\n");
 | 
			
		||||
	pr_debug("\t.set noreorder\n");
 | 
			
		||||
	for (i = 0; i < (epc - clear_page_array); i++)
 | 
			
		||||
		pr_debug("\t.word 0x%08x\n", clear_page_array[i]);
 | 
			
		||||
	pr_debug("\t.set pop\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __cpuinit build_copy_page(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int loop_start;
 | 
			
		||||
	unsigned long off;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	epc = (unsigned int *) ©_page_array;
 | 
			
		||||
	store_offset = load_offset = 0;
 | 
			
		||||
	instruction_pending = 0;
 | 
			
		||||
 | 
			
		||||
	off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0);
 | 
			
		||||
	if (off > 0x7fff) {
 | 
			
		||||
		build_addiu_a2_a0(off >> 1);
 | 
			
		||||
		build_addiu_a2(off >> 1);
 | 
			
		||||
	} else
 | 
			
		||||
		build_addiu_a2_a0(off);
 | 
			
		||||
 | 
			
		||||
	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
 | 
			
		||||
		build_insn_word(0x3c01a000);	/* lui     $at, 0xa000  */
 | 
			
		||||
 | 
			
		||||
dest = label();
 | 
			
		||||
	loop_start = store_offset;
 | 
			
		||||
	do {
 | 
			
		||||
		build_load_reg( 8);
 | 
			
		||||
		build_load_reg( 9);
 | 
			
		||||
		build_load_reg(10);
 | 
			
		||||
		build_load_reg(11);
 | 
			
		||||
		build_store_reg( 8);
 | 
			
		||||
		build_store_reg( 9);
 | 
			
		||||
		build_store_reg(10);
 | 
			
		||||
		build_store_reg(11);
 | 
			
		||||
	} while ((store_offset - loop_start) < half_scache_line_size());
 | 
			
		||||
	build_addiu_a0(2 * store_offset);
 | 
			
		||||
	build_addiu_a1(2 * load_offset);
 | 
			
		||||
	loop_start = store_offset;
 | 
			
		||||
	do {
 | 
			
		||||
		build_load_reg( 8);
 | 
			
		||||
		build_load_reg( 9);
 | 
			
		||||
		build_load_reg(10);
 | 
			
		||||
		build_load_reg(11);
 | 
			
		||||
		build_store_reg( 8);
 | 
			
		||||
		build_store_reg( 9);
 | 
			
		||||
		build_store_reg(10);
 | 
			
		||||
		build_store_reg(11);
 | 
			
		||||
	} while ((store_offset - loop_start) < half_scache_line_size());
 | 
			
		||||
	build_bne(dest);
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_prefetch && pref_offset_copy) {
 | 
			
		||||
		build_addiu_a2_a0(pref_offset_copy);
 | 
			
		||||
	dest = label();
 | 
			
		||||
		loop_start = store_offset;
 | 
			
		||||
		do {
 | 
			
		||||
			__build_load_reg( 8);
 | 
			
		||||
			__build_load_reg( 9);
 | 
			
		||||
			__build_load_reg(10);
 | 
			
		||||
			__build_load_reg(11);
 | 
			
		||||
			__build_store_reg( 8);
 | 
			
		||||
			__build_store_reg( 9);
 | 
			
		||||
			__build_store_reg(10);
 | 
			
		||||
			__build_store_reg(11);
 | 
			
		||||
		} while ((store_offset - loop_start) < half_scache_line_size());
 | 
			
		||||
		build_addiu_a0(2 * store_offset);
 | 
			
		||||
		build_addiu_a1(2 * load_offset);
 | 
			
		||||
		loop_start = store_offset;
 | 
			
		||||
		do {
 | 
			
		||||
			__build_load_reg( 8);
 | 
			
		||||
			__build_load_reg( 9);
 | 
			
		||||
			__build_load_reg(10);
 | 
			
		||||
			__build_load_reg(11);
 | 
			
		||||
			__build_store_reg( 8);
 | 
			
		||||
			__build_store_reg( 9);
 | 
			
		||||
			__build_store_reg(10);
 | 
			
		||||
			__build_store_reg(11);
 | 
			
		||||
		} while ((store_offset - loop_start) < half_scache_line_size());
 | 
			
		||||
		build_bne(dest);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	build_jr_ra();
 | 
			
		||||
 | 
			
		||||
	BUG_ON(epc > copy_page_array + ARRAY_SIZE(copy_page_array));
 | 
			
		||||
 | 
			
		||||
	pr_info("Synthesized copy page handler (%u instructions).\n",
 | 
			
		||||
		(unsigned int)(epc - copy_page_array));
 | 
			
		||||
 | 
			
		||||
	pr_debug("\t.set push\n");
 | 
			
		||||
	pr_debug("\t.set noreorder\n");
 | 
			
		||||
	for (i = 0; i < (epc - copy_page_array); i++)
 | 
			
		||||
		pr_debug("\t.word 0x%08x\n", copy_page_array[i]);
 | 
			
		||||
	pr_debug("\t.set pop\n");
 | 
			
		||||
}
 | 
			
		||||
@ -1,302 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
 | 
			
		||||
 * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org)
 | 
			
		||||
 * Copyright (C) 2000 SiByte, Inc.
 | 
			
		||||
 * Copyright (C) 2005 Thiemo Seufer
 | 
			
		||||
 *
 | 
			
		||||
 * Written by Justin Carlson of SiByte, Inc.
 | 
			
		||||
 *         and Kip Walker of Broadcom Corp.
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/smp.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/io.h>
 | 
			
		||||
#include <asm/sibyte/sb1250.h>
 | 
			
		||||
#include <asm/sibyte/sb1250_regs.h>
 | 
			
		||||
#include <asm/sibyte/sb1250_dma.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
 | 
			
		||||
#define SB1_PREF_LOAD_STREAMED_HINT "0"
 | 
			
		||||
#define SB1_PREF_STORE_STREAMED_HINT "1"
 | 
			
		||||
#else
 | 
			
		||||
#define SB1_PREF_LOAD_STREAMED_HINT "4"
 | 
			
		||||
#define SB1_PREF_STORE_STREAMED_HINT "5"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline void clear_page_cpu(void *page)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char *addr = (unsigned char *) page;
 | 
			
		||||
	unsigned char *end = addr + PAGE_SIZE;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * JDCXXX - This should be bottlenecked by the write buffer, but these
 | 
			
		||||
	 * things tend to be mildly unpredictable...should check this on the
 | 
			
		||||
	 * performance model
 | 
			
		||||
	 *
 | 
			
		||||
	 * We prefetch 4 lines ahead.  We're also "cheating" slightly here...
 | 
			
		||||
	 * since we know we're on an SB1, we force the assembler to take
 | 
			
		||||
	 * 64-bit operands to speed things up
 | 
			
		||||
	 */
 | 
			
		||||
	__asm__ __volatile__(
 | 
			
		||||
	"	.set	push		\n"
 | 
			
		||||
	"	.set	mips4		\n"
 | 
			
		||||
	"	.set	noreorder	\n"
 | 
			
		||||
#ifdef CONFIG_CPU_HAS_PREFETCH
 | 
			
		||||
	"	daddiu	%0, %0, 128	\n"
 | 
			
		||||
	"	pref	" SB1_PREF_STORE_STREAMED_HINT ", -128(%0)  \n"
 | 
			
		||||
					     /* Prefetch the first 4 lines */
 | 
			
		||||
	"	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -96(%0)  \n"
 | 
			
		||||
	"	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -64(%0)  \n"
 | 
			
		||||
	"	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -32(%0)  \n"
 | 
			
		||||
	"1:	sd	$0, -128(%0)	\n"  /* Throw out a cacheline of 0's */
 | 
			
		||||
	"	sd	$0, -120(%0)	\n"
 | 
			
		||||
	"	sd	$0, -112(%0)	\n"
 | 
			
		||||
	"	sd	$0, -104(%0)	\n"
 | 
			
		||||
	"	daddiu	%0, %0, 32	\n"
 | 
			
		||||
	"	bnel	%0, %1, 1b	\n"
 | 
			
		||||
	"	 pref	" SB1_PREF_STORE_STREAMED_HINT ",  -32(%0)  \n"
 | 
			
		||||
	"	daddiu	%0, %0, -128	\n"
 | 
			
		||||
#endif
 | 
			
		||||
	"	sd	$0, 0(%0)	\n"  /* Throw out a cacheline of 0's */
 | 
			
		||||
	"1:	sd	$0, 8(%0)	\n"
 | 
			
		||||
	"	sd	$0, 16(%0)	\n"
 | 
			
		||||
	"	sd	$0, 24(%0)	\n"
 | 
			
		||||
	"	daddiu	%0, %0, 32	\n"
 | 
			
		||||
	"	bnel	%0, %1, 1b	\n"
 | 
			
		||||
	"	 sd	$0, 0(%0)	\n"
 | 
			
		||||
	"	.set	pop		\n"
 | 
			
		||||
	: "+r" (addr)
 | 
			
		||||
	: "r" (end)
 | 
			
		||||
	: "memory");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void copy_page_cpu(void *to, void *from)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char *src = (unsigned char *)from;
 | 
			
		||||
	unsigned char *dst = (unsigned char *)to;
 | 
			
		||||
	unsigned char *end = src + PAGE_SIZE;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The pref's used here are using "streaming" hints, which cause the
 | 
			
		||||
	 * copied data to be kicked out of the cache sooner.  A page copy often
 | 
			
		||||
	 * ends up copying a lot more data than is commonly used, so this seems
 | 
			
		||||
	 * to make sense in terms of reducing cache pollution, but I've no real
 | 
			
		||||
	 * performance data to back this up
 | 
			
		||||
	 */
 | 
			
		||||
	__asm__ __volatile__(
 | 
			
		||||
	"	.set	push		\n"
 | 
			
		||||
	"	.set	mips4		\n"
 | 
			
		||||
	"	.set	noreorder	\n"
 | 
			
		||||
#ifdef CONFIG_CPU_HAS_PREFETCH
 | 
			
		||||
	"	daddiu	%0, %0, 128	\n"
 | 
			
		||||
	"	daddiu	%1, %1, 128	\n"
 | 
			
		||||
	"	pref	" SB1_PREF_LOAD_STREAMED_HINT  ", -128(%0)\n"
 | 
			
		||||
					     /* Prefetch the first 4 lines */
 | 
			
		||||
	"	pref	" SB1_PREF_STORE_STREAMED_HINT ", -128(%1)\n"
 | 
			
		||||
	"	pref	" SB1_PREF_LOAD_STREAMED_HINT  ",  -96(%0)\n"
 | 
			
		||||
	"	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -96(%1)\n"
 | 
			
		||||
	"	pref	" SB1_PREF_LOAD_STREAMED_HINT  ",  -64(%0)\n"
 | 
			
		||||
	"	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -64(%1)\n"
 | 
			
		||||
	"	pref	" SB1_PREF_LOAD_STREAMED_HINT  ",  -32(%0)\n"
 | 
			
		||||
	"1:	pref	" SB1_PREF_STORE_STREAMED_HINT ",  -32(%1)\n"
 | 
			
		||||
# ifdef CONFIG_64BIT
 | 
			
		||||
	"	ld	$8, -128(%0)	\n"  /* Block copy a cacheline */
 | 
			
		||||
	"	ld	$9, -120(%0)	\n"
 | 
			
		||||
	"	ld	$10, -112(%0)	\n"
 | 
			
		||||
	"	ld	$11, -104(%0)	\n"
 | 
			
		||||
	"	sd	$8, -128(%1)	\n"
 | 
			
		||||
	"	sd	$9, -120(%1)	\n"
 | 
			
		||||
	"	sd	$10, -112(%1)	\n"
 | 
			
		||||
	"	sd	$11, -104(%1)	\n"
 | 
			
		||||
# else
 | 
			
		||||
	"	lw	$2, -128(%0)	\n"  /* Block copy a cacheline */
 | 
			
		||||
	"	lw	$3, -124(%0)	\n"
 | 
			
		||||
	"	lw	$6, -120(%0)	\n"
 | 
			
		||||
	"	lw	$7, -116(%0)	\n"
 | 
			
		||||
	"	lw	$8, -112(%0)	\n"
 | 
			
		||||
	"	lw	$9, -108(%0)	\n"
 | 
			
		||||
	"	lw	$10, -104(%0)	\n"
 | 
			
		||||
	"	lw	$11, -100(%0)	\n"
 | 
			
		||||
	"	sw	$2, -128(%1)	\n"
 | 
			
		||||
	"	sw	$3, -124(%1)	\n"
 | 
			
		||||
	"	sw	$6, -120(%1)	\n"
 | 
			
		||||
	"	sw	$7, -116(%1)	\n"
 | 
			
		||||
	"	sw	$8, -112(%1)	\n"
 | 
			
		||||
	"	sw	$9, -108(%1)	\n"
 | 
			
		||||
	"	sw	$10, -104(%1)	\n"
 | 
			
		||||
	"	sw	$11, -100(%1)	\n"
 | 
			
		||||
# endif
 | 
			
		||||
	"	daddiu	%0, %0, 32	\n"
 | 
			
		||||
	"	daddiu	%1, %1, 32	\n"
 | 
			
		||||
	"	bnel	%0, %2, 1b	\n"
 | 
			
		||||
	"	 pref	" SB1_PREF_LOAD_STREAMED_HINT  ",  -32(%0)\n"
 | 
			
		||||
	"	daddiu	%0, %0, -128	\n"
 | 
			
		||||
	"	daddiu	%1, %1, -128	\n"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_64BIT
 | 
			
		||||
	"	ld	$8, 0(%0)	\n"  /* Block copy a cacheline */
 | 
			
		||||
	"1:	ld	$9, 8(%0)	\n"
 | 
			
		||||
	"	ld	$10, 16(%0)	\n"
 | 
			
		||||
	"	ld	$11, 24(%0)	\n"
 | 
			
		||||
	"	sd	$8, 0(%1)	\n"
 | 
			
		||||
	"	sd	$9, 8(%1)	\n"
 | 
			
		||||
	"	sd	$10, 16(%1)	\n"
 | 
			
		||||
	"	sd	$11, 24(%1)	\n"
 | 
			
		||||
#else
 | 
			
		||||
	"	lw	$2, 0(%0)	\n"  /* Block copy a cacheline */
 | 
			
		||||
	"1:	lw	$3, 4(%0)	\n"
 | 
			
		||||
	"	lw	$6, 8(%0)	\n"
 | 
			
		||||
	"	lw	$7, 12(%0)	\n"
 | 
			
		||||
	"	lw	$8, 16(%0)	\n"
 | 
			
		||||
	"	lw	$9, 20(%0)	\n"
 | 
			
		||||
	"	lw	$10, 24(%0)	\n"
 | 
			
		||||
	"	lw	$11, 28(%0)	\n"
 | 
			
		||||
	"	sw	$2, 0(%1)	\n"
 | 
			
		||||
	"	sw	$3, 4(%1)	\n"
 | 
			
		||||
	"	sw	$6, 8(%1)	\n"
 | 
			
		||||
	"	sw	$7, 12(%1)	\n"
 | 
			
		||||
	"	sw	$8, 16(%1)	\n"
 | 
			
		||||
	"	sw	$9, 20(%1)	\n"
 | 
			
		||||
	"	sw	$10, 24(%1)	\n"
 | 
			
		||||
	"	sw	$11, 28(%1)	\n"
 | 
			
		||||
#endif
 | 
			
		||||
	"	daddiu	%0, %0, 32	\n"
 | 
			
		||||
	"	daddiu	%1, %1, 32	\n"
 | 
			
		||||
	"	bnel	%0, %2, 1b	\n"
 | 
			
		||||
#ifdef CONFIG_64BIT
 | 
			
		||||
	"	 ld	$8, 0(%0)	\n"
 | 
			
		||||
#else
 | 
			
		||||
	"	 lw	$2, 0(%0)	\n"
 | 
			
		||||
#endif
 | 
			
		||||
	"	.set	pop		\n"
 | 
			
		||||
	: "+r" (src), "+r" (dst)
 | 
			
		||||
	: "r" (end)
 | 
			
		||||
#ifdef CONFIG_64BIT
 | 
			
		||||
	: "$8", "$9", "$10", "$11", "memory");
 | 
			
		||||
#else
 | 
			
		||||
	: "$2", "$3", "$6", "$7", "$8", "$9", "$10", "$11", "memory");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Pad descriptors to cacheline, since each is exclusively owned by a
 | 
			
		||||
 * particular CPU.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct dmadscr_s {
 | 
			
		||||
	u64 dscr_a;
 | 
			
		||||
	u64 dscr_b;
 | 
			
		||||
	u64 pad_a;
 | 
			
		||||
	u64 pad_b;
 | 
			
		||||
} dmadscr_t;
 | 
			
		||||
 | 
			
		||||
static dmadscr_t page_descr[DM_NUM_CHANNELS]
 | 
			
		||||
	__attribute__((aligned(SMP_CACHE_BYTES)));
 | 
			
		||||
 | 
			
		||||
void sb1_dma_init(void)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < DM_NUM_CHANNELS; i++) {
 | 
			
		||||
		const u64 base_val = CPHYSADDR((unsigned long)&page_descr[i]) |
 | 
			
		||||
				     V_DM_DSCR_BASE_RINGSZ(1);
 | 
			
		||||
		void *base_reg = IOADDR(A_DM_REGISTER(i, R_DM_DSCR_BASE));
 | 
			
		||||
 | 
			
		||||
		__raw_writeq(base_val, base_reg);
 | 
			
		||||
		__raw_writeq(base_val | M_DM_DSCR_BASE_RESET, base_reg);
 | 
			
		||||
		__raw_writeq(base_val | M_DM_DSCR_BASE_ENABL, base_reg);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clear_page(void *page)
 | 
			
		||||
{
 | 
			
		||||
	u64 to_phys = CPHYSADDR((unsigned long)page);
 | 
			
		||||
	unsigned int cpu = smp_processor_id();
 | 
			
		||||
 | 
			
		||||
	/* if the page is not in KSEG0, use old way */
 | 
			
		||||
	if ((long)KSEGX((unsigned long)page) != (long)CKSEG0)
 | 
			
		||||
		return clear_page_cpu(page);
 | 
			
		||||
 | 
			
		||||
	page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_ZERO_MEM |
 | 
			
		||||
				 M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
 | 
			
		||||
	page_descr[cpu].dscr_b = V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
 | 
			
		||||
	__raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Don't really want to do it this way, but there's no
 | 
			
		||||
	 * reliable way to delay completion detection.
 | 
			
		||||
	 */
 | 
			
		||||
	while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
 | 
			
		||||
		 & M_DM_DSCR_BASE_INTERRUPT))
 | 
			
		||||
		;
 | 
			
		||||
	__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void copy_page(void *to, void *from)
 | 
			
		||||
{
 | 
			
		||||
	u64 from_phys = CPHYSADDR((unsigned long)from);
 | 
			
		||||
	u64 to_phys = CPHYSADDR((unsigned long)to);
 | 
			
		||||
	unsigned int cpu = smp_processor_id();
 | 
			
		||||
 | 
			
		||||
	/* if any page is not in KSEG0, use old way */
 | 
			
		||||
	if ((long)KSEGX((unsigned long)to) != (long)CKSEG0
 | 
			
		||||
	    || (long)KSEGX((unsigned long)from) != (long)CKSEG0)
 | 
			
		||||
		return copy_page_cpu(to, from);
 | 
			
		||||
 | 
			
		||||
	page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_L2C_DEST |
 | 
			
		||||
				 M_DM_DSCRA_INTERRUPT;
 | 
			
		||||
	page_descr[cpu].dscr_b = from_phys | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
 | 
			
		||||
	__raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Don't really want to do it this way, but there's no
 | 
			
		||||
	 * reliable way to delay completion detection.
 | 
			
		||||
	 */
 | 
			
		||||
	while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)))
 | 
			
		||||
		 & M_DM_DSCR_BASE_INTERRUPT))
 | 
			
		||||
		;
 | 
			
		||||
	__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else /* !CONFIG_SIBYTE_DMA_PAGEOPS */
 | 
			
		||||
 | 
			
		||||
void clear_page(void *page)
 | 
			
		||||
{
 | 
			
		||||
	return clear_page_cpu(page);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void copy_page(void *to, void *from)
 | 
			
		||||
{
 | 
			
		||||
	return copy_page_cpu(to, from);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* !CONFIG_SIBYTE_DMA_PAGEOPS */
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(clear_page);
 | 
			
		||||
EXPORT_SYMBOL(copy_page);
 | 
			
		||||
 | 
			
		||||
void __cpuinit build_clear_page(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __cpuinit build_copy_page(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
@ -12,7 +12,6 @@ void show_mem(void)
 | 
			
		||||
 | 
			
		||||
	printk("Mem-info:\n");
 | 
			
		||||
	show_free_areas();
 | 
			
		||||
	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 | 
			
		||||
	pfn = max_mapnr;
 | 
			
		||||
	while (pfn-- > 0) {
 | 
			
		||||
		if (!pfn_valid(pfn))
 | 
			
		||||
 | 
			
		||||
@ -299,7 +299,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 | 
			
		||||
	idx = read_c0_index();
 | 
			
		||||
	ptep = pte_offset_map(pmdp, address);
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
 | 
			
		||||
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
 | 
			
		||||
	write_c0_entrylo0(ptep->pte_high);
 | 
			
		||||
	ptep++;
 | 
			
		||||
	write_c0_entrylo1(ptep->pte_high);
 | 
			
		||||
 | 
			
		||||
@ -58,13 +58,13 @@ enum opcode {
 | 
			
		||||
	insn_invalid,
 | 
			
		||||
	insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
 | 
			
		||||
	insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
 | 
			
		||||
	insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
 | 
			
		||||
	insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32,
 | 
			
		||||
	insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
 | 
			
		||||
	insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
 | 
			
		||||
	insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
 | 
			
		||||
	insn_sra, insn_srl, insn_subu, insn_sw, insn_tlbp, insn_tlbwi,
 | 
			
		||||
	insn_tlbwr, insn_xor, insn_xori
 | 
			
		||||
	insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0,
 | 
			
		||||
	insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
 | 
			
		||||
	insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr,
 | 
			
		||||
	insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
 | 
			
		||||
	insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd,
 | 
			
		||||
	insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
 | 
			
		||||
	insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct insn {
 | 
			
		||||
@ -94,6 +94,7 @@ static struct insn insn_table[] __cpuinitdata = {
 | 
			
		||||
	{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
 | 
			
		||||
	{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
 | 
			
		||||
	{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
 | 
			
		||||
	{ insn_cache,  M(cache_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 | 
			
		||||
	{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
 | 
			
		||||
	{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
 | 
			
		||||
	{ insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
 | 
			
		||||
@ -116,6 +117,7 @@ static struct insn insn_table[] __cpuinitdata = {
 | 
			
		||||
	{ insn_mfc0,  M(cop0_op, mfc_op, 0, 0, 0, 0),  RT | RD | SET},
 | 
			
		||||
	{ insn_mtc0,  M(cop0_op, mtc_op, 0, 0, 0, 0),  RT | RD | SET},
 | 
			
		||||
	{ insn_ori,  M(ori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
 | 
			
		||||
	{ insn_pref,  M(pref_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 | 
			
		||||
	{ insn_rfe,  M(cop0_op, cop_op, 0, 0, 0, rfe_op),  0 },
 | 
			
		||||
	{ insn_sc,  M(sc_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 | 
			
		||||
	{ insn_scd,  M(scd_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 | 
			
		||||
@ -337,6 +339,7 @@ I_u1s2(_bgezl)
 | 
			
		||||
I_u1s2(_bltz)
 | 
			
		||||
I_u1s2(_bltzl)
 | 
			
		||||
I_u1u2s3(_bne)
 | 
			
		||||
I_u2s3u1(_cache)
 | 
			
		||||
I_u1u2u3(_dmfc0)
 | 
			
		||||
I_u1u2u3(_dmtc0)
 | 
			
		||||
I_u2u1s3(_daddiu)
 | 
			
		||||
@ -359,6 +362,7 @@ I_u2s3u1(_lw)
 | 
			
		||||
I_u1u2u3(_mfc0)
 | 
			
		||||
I_u1u2u3(_mtc0)
 | 
			
		||||
I_u2u1u3(_ori)
 | 
			
		||||
I_u2s3u1(_pref)
 | 
			
		||||
I_0(_rfe)
 | 
			
		||||
I_u2s3u1(_sc)
 | 
			
		||||
I_u2s3u1(_scd)
 | 
			
		||||
@ -554,6 +558,14 @@ uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
 | 
			
		||||
	uasm_i_beqzl(p, reg, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __cpuinit
 | 
			
		||||
uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
 | 
			
		||||
	unsigned int reg2, int lid)
 | 
			
		||||
{
 | 
			
		||||
	uasm_r_mips_pc16(r, *p, lid);
 | 
			
		||||
	uasm_i_bne(p, reg1, reg2, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __cpuinit
 | 
			
		||||
uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -55,6 +55,7 @@ Ip_u1s2(_bgezl);
 | 
			
		||||
Ip_u1s2(_bltz);
 | 
			
		||||
Ip_u1s2(_bltzl);
 | 
			
		||||
Ip_u1u2s3(_bne);
 | 
			
		||||
Ip_u2s3u1(_cache);
 | 
			
		||||
Ip_u1u2u3(_dmfc0);
 | 
			
		||||
Ip_u1u2u3(_dmtc0);
 | 
			
		||||
Ip_u2u1s3(_daddiu);
 | 
			
		||||
@ -77,6 +78,7 @@ Ip_u2s3u1(_lw);
 | 
			
		||||
Ip_u1u2u3(_mfc0);
 | 
			
		||||
Ip_u1u2u3(_mtc0);
 | 
			
		||||
Ip_u2u1u3(_ori);
 | 
			
		||||
Ip_u2s3u1(_pref);
 | 
			
		||||
Ip_0(_rfe);
 | 
			
		||||
Ip_u2s3u1(_sc);
 | 
			
		||||
Ip_u2s3u1(_scd);
 | 
			
		||||
@ -177,6 +179,8 @@ void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
 | 
			
		||||
void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid);
 | 
			
		||||
void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
 | 
			
		||||
void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
 | 
			
		||||
void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
 | 
			
		||||
		 unsigned int reg2, int lid);
 | 
			
		||||
void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
 | 
			
		||||
void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
 | 
			
		||||
void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Platform device support for Philips PNX8550 SoCs
 | 
			
		||||
 * Platform device support for NXP PNX8550 SoCs
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2005, Embedded Alley Solutions, Inc
 | 
			
		||||
 *
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
 | 
			
		||||
# Makefile for the Philips JBS Board.
 | 
			
		||||
# Makefile for the NXP JBS Board.
 | 
			
		||||
 | 
			
		||||
lib-y := init.o board_setup.o irqmap.o
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user