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:
Linus Torvalds 2008-04-28 10:51:43 -07:00
commit e31a94ed37
157 changed files with 4120 additions and 2239 deletions

View File

@ -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"
#

View File

@ -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

View File

@ -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

View File

@ -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];

View File

@ -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)

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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.
*/

View File

@ -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>

View File

@ -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));
}

View File

@ -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);

View File

@ -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>

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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>

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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 = {

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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[] = {

View File

@ -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>

View File

@ -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>

View File

@ -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[] = {

View File

@ -3,5 +3,6 @@
#
lib-y := init.o board_setup.o irqmap.o
obj-y += platform.o
EXTRA_CFLAGS += -Werror

View File

@ -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);

View File

@ -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>

View File

@ -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

View 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);

View File

@ -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>

View File

@ -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>

View File

@ -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 = {

View File

@ -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>

View File

@ -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>

View File

@ -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 = {

View File

@ -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)

View File

@ -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>

View File

@ -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[] = {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]);
}

View File

@ -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;

View File

@ -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

View 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);
}

View File

@ -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;

View File

@ -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;

View 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);
}

View 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
View 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();
}

View File

@ -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 */

View File

@ -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
View 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 = &current_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,
};

View File

@ -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 = {

View File

@ -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() */

View File

@ -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
View 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 = &current_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
View 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

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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

View 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);
}

View File

@ -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

View File

@ -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;

View File

@ -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
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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();
}

View File

@ -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)

View File

@ -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
View 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 *)&copy_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 */

View File

@ -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 *) &copy_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");
}

View File

@ -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)
{
}

View File

@ -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))

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -1,5 +1,5 @@
/*
* Platform device support for Philips PNX8550 SoCs
* Platform device support for NXP PNX8550 SoCs
*
* Copyright 2005, Embedded Alley Solutions, Inc
*

View File

@ -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