You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(165) |
Sep
(240) |
Oct
(424) |
Nov
(526) |
Dec
(293) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(242) |
Feb
(149) |
Mar
(143) |
Apr
(143) |
May
(76) |
Jun
(59) |
Jul
(20) |
Aug
(2) |
Sep
(49) |
Oct
(1) |
Nov
(4) |
Dec
|
2003 |
Jan
(1) |
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2004 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(3) |
Nov
|
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
(72) |
Jul
(36) |
Aug
(9) |
Sep
(16) |
Oct
(23) |
Nov
(9) |
Dec
(3) |
2010 |
Jan
|
Feb
(1) |
Mar
(35) |
Apr
(44) |
May
(56) |
Jun
(71) |
Jul
(41) |
Aug
(41) |
Sep
(22) |
Oct
(3) |
Nov
(1) |
Dec
(1) |
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2012 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2013 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2014 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
(1) |
Nov
(1) |
Dec
|
2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2017 |
Jan
|
Feb
|
Mar
(1) |
Apr
(1) |
May
(1) |
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
(25) |
Oct
(105) |
Nov
(15) |
Dec
|
2025 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
(4) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: James S. <jsi...@us...> - 2001-10-25 23:58:44
|
Update of /cvsroot/linux-mips/linux/arch/mips/cobalt In directory usw-pr-cvs1:/tmp/cvs-serv26899 Added Files: rtc_dallas.c Log Message: Migrated to new time. I even made a generic dallas PC sytle driver which also works with the old style drivers. --- NEW FILE: rtc_dallas.c --- /* * Copyright 2001 James Simmons. jsi...@tr... * * arch/mips/kernel/rtc_dallas.c * low-level RTC hookups for Dallas PC style chip. * * 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 file exports a function, rtc_dallas_init(), which expects an * uncached base address as the argument. It will set the two function * pointers expected by the MIPS generic timer code. */ #include <linux/types.h> #include <linux/time.h> #include <asm/time.h> #include <asm/addrspace.h> #include <asm/debug.h> #include <linux/mc146818rtc.h> #define EPOCH 2000 #undef BCD_TO_BIN #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) #undef BIN_TO_BCD #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) static unsigned long rtc_base; #define READ_RTC(x) rtc_ops->rtc_read_data(x) #define WRITE_RTC(x, y) rtc_ops->rtc_write_data(y, x) static unsigned long rtc_dallas_get_time(void) { unsigned int year, month, day, hour, minute, second; u8 byte, temp; /* let us freeze external registers */ byte = READ_RTC(0xB); byte &= 0x3f; WRITE_RTC(0xB, byte); /* read time data */ year = BCD_TO_BIN(READ_RTC(0xA)) + EPOCH; month = BCD_TO_BIN(READ_RTC(0x9) & 0x1f); day = BCD_TO_BIN(READ_RTC(0x8)); minute = BCD_TO_BIN(READ_RTC(0x2)); second = BCD_TO_BIN(READ_RTC(0x1)); /* hour is special - deal with it later */ temp = READ_RTC(0x4); /* enable time transfer */ byte |= 0x80; WRITE_RTC(0xB, byte); /* calc hour */ if (temp & 0x40) { /* 12 hour format */ hour = BCD_TO_BIN(temp & 0x1f); if (temp & 0x20) hour += 12; /* PM */ } else { /* 24 hour format */ hour = BCD_TO_BIN(temp & 0x3f); } return mktime(year, month, day, hour, minute, second); } static int rtc_dallas_set_time(unsigned long t) { struct rtc_time tm; u8 year, month, day, hour, minute, second; u8 byte, temp; /* let us freeze external registers */ byte = READ_RTC(0xB); byte &= 0x3f; WRITE_RTC(0xB, byte); /* convert */ to_tm(t, &tm); /* check each field one by one */ year = BIN_TO_BCD(tm.tm_year - EPOCH); if (year != READ_RTC(0xA)) { WRITE_RTC(0xA, year); } temp = READ_RTC(0x9); month = BIN_TO_BCD(tm.tm_mon); if (month != (temp & 0x1f)) { WRITE_RTC( 0x9, (month & 0x1f) | (temp & ~0x1f) ); } day = BIN_TO_BCD(tm.tm_mday); if (day != READ_RTC(0x8)) { WRITE_RTC(0x8, day); } temp = READ_RTC(0x4); if (temp & 0x40) { /* 12 hour format */ hour = 0x40; if (tm.tm_hour > 12) { hour |= 0x20 | (BIN_TO_BCD(hour-12) & 0x1f); } else { hour |= BIN_TO_BCD(tm.tm_hour); } } else { /* 24 hour format */ hour = BIN_TO_BCD(tm.tm_hour) & 0x3f; } if (hour != temp) WRITE_RTC(0x4, hour); minute = BIN_TO_BCD(tm.tm_min); if (minute != READ_RTC(0x2)) { WRITE_RTC(0x2, minute); } second = BIN_TO_BCD(tm.tm_sec); if (second != READ_RTC(0x1)) { WRITE_RTC(0x1, second); } return 0; } void rtc_dallas_init(unsigned long base) { unsigned char byte; /* remember the base */ rtc_base = base; db_assert((rtc_base & 0xe0000000) == KSEG1); /* turn on RTC if it is not on */ byte = READ_RTC(0x9); if (byte & 0x80) { byte &= 0x7f; WRITE_RTC(0x9, byte); } /* enable time transfer */ byte = READ_RTC(0xB); byte |= 0x80; WRITE_RTC(0xB, byte); /* set the function pointers */ rtc_get_time = rtc_dallas_get_time; rtc_set_time = rtc_dallas_set_time; } |
From: James S. <jsi...@us...> - 2001-10-25 23:58:14
|
Update of /cvsroot/linux-mips/linux/arch/mips/cobalt In directory usw-pr-cvs1:/tmp/cvs-serv26823 Modified Files: Makefile setup.c Log Message: Migrated to new time. I even made a generic dallas PC sytle driver which also works with the old style drivers. Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/Makefile,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- Makefile 2001/10/24 18:53:29 1.6 +++ Makefile 2001/10/25 23:58:08 1.7 @@ -16,7 +16,7 @@ O_TARGET := cobalt.o -obj-y += rtc_qube.o irq.o int-handler.o pci_fixups.o pci_ops.o \ +obj-y += rtc_dallas.o rtc_qube.o irq.o int-handler.o pci_fixups.o pci_ops.o \ reset.o setup.o via.o promcon.o ide.o include $(TOPDIR)/Rules.make Index: setup.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/setup.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- setup.c 2001/10/25 21:39:48 1.6 +++ setup.c 2001/10/25 23:58:08 1.7 @@ -18,6 +18,7 @@ #include <linux/ide.h> #include <asm/bootinfo.h> +#include <asm/time.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/cobalt/cobalt.h> @@ -30,6 +31,8 @@ extern void cobalt_machine_halt(void); extern void cobalt_machine_power_off(void); +extern void rtc_dallas_init(unsigned long base); + extern struct rtc_ops cobalt_rtc_ops; extern struct ide_ops cobalt_ide_ops; @@ -84,8 +87,6 @@ VIA_PORT_WRITE(0xa1, 0x00); } -extern void (*board_time_init)(struct irqaction *irq); - #define GALILEO_T0_VAL 0xb4000850 #define GALILEO_TIMER_CTRL 0xb4000864 #define GALILEO_CPU_MASK 0xb4000c1c @@ -117,6 +118,20 @@ *((volatile unsigned long *) GALILEO_CPU_MASK) = (unsigned long) 0x00000100; } +static void __init cobalt_time_init(void) +{ + //mips_counter_frequency = 83000000; + + /* we have ds1396 RTC chip */ + rtc_dallas_init(0x70); + + /* optional: we don't have a good way to set RTC time, + * so we will hack here to set a time. In normal running. + * it should *not* be called becaues RTC will keep the correct time. + */ + /* rtc_set_time(mktime(2001, 10, 05, 17, 20, 0)); */ +} + int cobalt_serial_present; int cobalt_serial_type; int cobalt_is_raq; @@ -136,8 +151,10 @@ _machine_halt = cobalt_machine_halt; _machine_power_off = cobalt_machine_power_off; - board_time_init = cobalt_timer_setup; - rtc_ops = &cobalt_rtc_ops; + board_time_init = cobalt_time_init; + board_timer_setup = cobalt_timer_setup; + + rtc_ops = &cobalt_rtc_ops; #ifdef CONFIG_BLK_DEV_IDE ide_ops = &cobalt_ide_ops; #endif |
From: James S. <jsi...@us...> - 2001-10-25 21:39:50
|
Update of /cvsroot/linux-mips/linux/arch/mips/cobalt In directory usw-pr-cvs1:/tmp/cvs-serv28647/cobalt Modified Files: pci_fixups.c pci_ops.c setup.c Log Message: Fixed the problem with the new pci code with the qube. Now just to fix the issues with pci_auto. Index: pci_fixups.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/pci_fixups.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- pci_fixups.c 2001/10/24 18:53:29 1.2 +++ pci_fixups.c 2001/10/25 21:39:48 1.3 @@ -334,24 +334,6 @@ struct pci_dev *dev; pci_for_each_dev(dev) { -/* - switch (dev->vendor) { - case PCI_VENDOR_ID_NEC: - switch (dev->device) { - case PCI_DEVICE_ID_NEC_VRC4173_BCU: - case PCI_DEVICE_ID_NEC_VRC4173_AC97: - case PCI_DEVICE_ID_NEC_VRC4173_CARDU: - case PCI_DEVICE_ID_NEC_VRC4173_USB: - dev->irq = VR4122_IRQ_VRC4173; - break; - } - break; - case PCI_VENDOR_ID_MEDIAQ: - if (dev->device == PCI_DEVICE_ID_MEDIAQ_MQ200) - dev->irq = VR4122_IRQ_MQ200; - break; - } -*/ } } Index: pci_ops.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/pci_ops.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- pci_ops.c 2001/10/24 21:41:32 1.4 +++ pci_ops.c 2001/10/25 21:39:48 1.5 @@ -48,6 +48,8 @@ #define IO_BASE 0x00000000 #define IO_SIZE 0x1CFFFFFF +#define MEM_BASE 0x00000000 +#define MEM_SIZE 0x1CFFFFFF static struct resource pci_io_resource = { "pci IO space", @@ -58,8 +60,8 @@ static struct resource pci_mem_resource = { "pci memory space", - 0, - 0, + MEM_BASE, + MEM_BASE + MEM_SIZE, IORESOURCE_MEM }; @@ -76,7 +78,8 @@ */ struct pci_channel mips_pci_channels[] = { { &qube_pci_ops, &pci_io_resource, &pci_mem_resource, 0, 0xFF }, - { NULL, NULL, NULL, NULL, NULL} + {(struct pci_ops *) NULL, (struct resource *) NULL, + (struct resource *) NULL, (int) NULL, (int) NULL} }; #define PCI_CFG_DATA ((volatile unsigned long *)0xb4000cfc) Index: setup.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/setup.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- setup.c 2001/09/26 20:16:04 1.5 +++ setup.c 2001/10/25 21:39:48 1.6 @@ -54,8 +54,6 @@ static struct resource res_pic2 = { "pic2", 0xb00000A0, 0xb00000BF, IORESOURCE_IO }; - - void __init cobalt_irq_setup(void) { /* @@ -103,7 +101,7 @@ *timer_reg = 500000; } -static void __init cobalt_time_init(struct irqaction *irq) +static void __init cobalt_timer_setup(struct irqaction *irq) { /* Load timer value for 150 Hz */ cobalt_calibrate_timer(); @@ -125,18 +123,24 @@ void __init cobalt_setup(void) { + /* + * IO/MEM resources. + */ + mips_io_port_base = COBALT_LOCAL_IO_SPACE; + ioport_resource.start = 0; + ioport_resource.end = 0xffffffff; + iomem_resource.start = 0; + ioport_resource.end = 0xffffffff; _machine_restart = cobalt_machine_restart; _machine_halt = cobalt_machine_halt; _machine_power_off = cobalt_machine_power_off; - board_time_init = cobalt_time_init; + board_time_init = cobalt_timer_setup; rtc_ops = &cobalt_rtc_ops; #ifdef CONFIG_BLK_DEV_IDE ide_ops = &cobalt_ide_ops; #endif - mips_io_port_base = COBALT_LOCAL_IO_SPACE; - /*ns16550_setup_console();*/ /* We have to do this early, here, before the value could |
From: James S. <jsi...@us...> - 2001-10-25 21:39:50
|
Update of /cvsroot/linux-mips/linux/arch/mips In directory usw-pr-cvs1:/tmp/cvs-serv28647 Modified Files: config.in Log Message: Fixed the problem with the new pci code with the qube. Now just to fix the issues with pci_auto. Index: config.in =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/config.in,v retrieving revision 1.36 retrieving revision 1.37 diff -u -d -r1.36 -r1.37 --- config.in 2001/10/25 08:10:20 1.36 +++ config.in 2001/10/25 21:39:47 1.37 @@ -245,6 +245,7 @@ define_bool CONFIG_NO_VIDEO_CONSOLE y define_bool CONFIG_COBALT_LCD y define_bool CONFIG_PCI y + define_bool CONFIG_NEW_PCI y define_bool CONFIG_OLD_TIME_C y fi if [ "$CONFIG_NINO" = "y" ]; then |
From: James S. <jsi...@us...> - 2001-10-25 17:27:58
|
Update of /cvsroot/linux-mips/linux/drivers/char In directory usw-pr-cvs1:/tmp/cvs-serv30696 Modified Files: Config.in Log Message: Removed the repeated ITE slections. Especially the one underneath CONFIG_FOOTBRIDGE. Just dumb. Fixed now. Index: Config.in =================================================================== RCS file: /cvsroot/linux-mips/linux/drivers/char/Config.in,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- Config.in 2001/10/24 16:39:35 1.13 +++ Config.in 2001/10/25 17:27:56 1.14 @@ -68,6 +68,11 @@ fi if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then bool 'Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD + if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then + define_bool CONFIG_IT8172_CIR y + else + bool ' Enable PS2 Keyboard Support' CONFIG_PC_KEYB + fi bool 'Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0 bool 'Enable Smart Card Reader 1 Support ' CONFIG_IT8172_SCR1 fi @@ -82,24 +87,6 @@ fi bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE fi - if [ "$CONFIG_MIPS" = "y" ]; then - bool ' TMPTX3912/PR31700 serial port support' CONFIG_SERIAL_TX3912 - dep_bool ' Console on TMPTX3912/PR31700 serial port' CONFIG_SERIAL_TX3912_CONSOLE $CONFIG_SERIAL_TX3912 - bool ' Enable Au1000 UART Support' CONFIG_AU1000_UART - if [ "$CONFIG_AU1000_UART" = "y" ]; then - bool ' Enable Au1000 serial console' CONFIG_AU1000_SERIAL_CONSOLE - fi - fi -fi -if [ "$CONFIG_IT8712" = "y" ]; then - bool 'Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD - if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then - define_bool CONFIG_IT8172_CIR y - else - bool ' Enable PS2 Keyboard Support' CONFIG_PC_KEYB - fi - bool 'Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0 - bool 'Enable Smart Card Reader 1 Support ' CONFIG_IT8172_SCR1 fi bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then |
From: James S. <jsi...@us...> - 2001-10-25 17:17:47
|
Update of /cvsroot/linux-mips/linux/include/asm-mips In directory usw-pr-cvs1:/tmp/cvs-serv27721 Modified Files: processor.h bugs.h Log Message: Fixed missing declarations for rx39xx_wait. Index: processor.h =================================================================== RCS file: /cvsroot/linux-mips/linux/include/asm-mips/processor.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- processor.h 2001/10/19 21:19:40 1.5 +++ processor.h 2001/10/25 17:17:45 1.6 @@ -40,6 +40,7 @@ * System setup and hardware flags.. */ extern void (*cpu_wait)(void); /* only available on R4[26]00 and R3081 */ +extern void r39xx_wait(void); extern void r3081_wait(void); extern void r4k_wait(void); extern char cyclecounter_available; /* only available from R4000 upwards. */ Index: bugs.h =================================================================== RCS file: /cvsroot/linux-mips/linux/include/asm-mips/bugs.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- bugs.h 2001/10/24 23:32:54 1.3 +++ bugs.h 2001/10/25 17:17:45 1.4 @@ -3,6 +3,7 @@ * Copyright (C) 1997, 1999 Ralf Baechle */ #include <asm/bootinfo.h> +#include <asm/processor.h> #include <asm/cpu.h> /* |
From: James S. <jsi...@us...> - 2001-10-25 16:43:29
|
Update of /cvsroot/linux-mips/linux/arch/mips/mm In directory usw-pr-cvs1:/tmp/cvs-serv18416/mm Modified Files: Makefile Log Message: Makefile changes to go along with the TX39/TX49 changes. Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/mm/Makefile,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- Makefile 2001/10/25 08:10:21 1.7 +++ Makefile 2001/10/25 16:43:24 1.8 @@ -18,6 +18,8 @@ obj-$(CONFIG_CPU_R3000) += pg-r3k.o c-r3k.o c-tx39.o tlb-r3k.o \ tlbex-r3k.o +obj-$(CONFIG_CPU_TX39XX) += pg-r3k.o c-tx39.o tlb-r3k.o tlbex-r3k.o +obj-$(CONFIG_CPU_TX49XX) += pg-r4k.o c-tx49.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_R4300) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_R4X00) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_VR41XX) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o |
From: James S. <jsi...@us...> - 2001-10-25 16:43:28
|
Update of /cvsroot/linux-mips/linux/arch/mips/kernel In directory usw-pr-cvs1:/tmp/cvs-serv18416/kernel Modified Files: Makefile Log Message: Makefile changes to go along with the TX39/TX49 changes. Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/kernel/Makefile,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- Makefile 2001/10/24 21:43:33 1.10 +++ Makefile 2001/10/25 16:43:24 1.11 @@ -22,6 +22,8 @@ obj-$(CONFIG_MODULES) += mips_ksyms.o obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o +obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o +obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R4000) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4k_switch.o |
From: Paul M. <le...@us...> - 2001-10-25 08:10:24
|
Update of /cvsroot/linux-mips/linux/arch/mips/mm In directory usw-pr-cvs1:/tmp/cvs-serv31689/arch/mips/mm Modified Files: Makefile Added Files: pg-r5900.c Log Message: Started reworking R5900 mm stuff to new API. Incomplete for now, more to follow.. --- NEW FILE: pg-r5900.c --- /* * $Id: pg-r5900.c,v 1.1 2001/10/25 08:10:21 lethal Exp $ * * 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. * * r5900.c: R5900 processor specific MMU/Cache routines. * * Copyright (C) 2000 Sony Computer Entertainment Inc. * Copyright (C) 2001 Paul Mundt (le...@ch...) * * This file is based on r4xx0.c: * * Copyright (C) 1996 David S. Miller (dm...@en...) * Copyright (C) 1997, 1998 Ralf Baechle ra...@gn... * * To do: * * - this code is a overbloated pig * - many of the bug workarounds are not efficient at all, but at * least they are functional ... */ #include <linux/sched.h> #include <linux/mm.h> #include <asm/r5900_cacheops.h> /* * Zero an entire page. Basically a simple unrolled loop should do the * job but we want more performance by saving memory bus bandwidth. We * have five flavours of the routine available for: * * - 16byte cachelines and no second level cache * - 32byte cachelines second level cache * - a version which handles the buggy R4600 v1.x * - a version which handles the buggy R4600 v2.0 * - Finally a last version without fancy cache games for the SC and MC * versions of R4000 and R4400. */ static void r5900_clear_page_d16(void* page) { __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" ".set\tmips3\n\t" "daddiu\t$1,%0,%2\n" "1:\tsq\t$0,(%0)\n\t" "sq\t$0,16(%0)\n\t" "daddiu\t%0,64\n\t" "sq\t$0,-32(%0)\n\t" "sq\t$0,-16(%0)\n\t" "bne\t$1,%0,1b\n\t" "nop\n\t" /* inhibit short loop */ ".set\tmips0\n\t" ".set\tat\n\t" ".set\treorder" :"=r" (page) :"0" (page), "I" (PAGE_SIZE)); } /* * This is still inefficient. We only can do better if we know the * virtual address where the copy will be accessed. */ #ifdef CONFIG_CPU_R5900_CONTEXT static void r5900_copy_page_d16(unsigned long to, unsigned long from) { unsigned long dummy1, dummy2; unsigned long reg1, reg2, reg3, reg4; __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" ".set\tmips3\n\t" "daddiu\t$1,%0,%8\n" "1:\tlq\t%2,(%1)\n\t" "lq\t%3,16(%1)\n\t" "sq\t%2,(%0)\n\t" "sq\t%3,16(%0)\n\t" "daddiu\t%0,64\n\t" "daddiu\t%1,64\n\t" "lq\t%2,-32(%1)\n\t" "lq\t%3,-16(%1)\n\t" "sq\t%2,-32(%0)\n\t" "bne\t$1,%0,1b\n\t" "sq\t%3,-16(%0)\n\t" ".set\tmips0\n\t" ".set\tat\n\t" ".set\treorder" :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) :"0" (to), "1" (from), "I" (PAGE_SIZE)); } #else static void r5900_copy_page_d16(void *to, void *from) { unsigned long dummy1, dummy2; unsigned long reg1, reg2, reg3, reg4; __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" ".set\tmips3\n\t" "daddiu\t$1,%0,%8\n" "1:\tlw\t%2,(%1)\n\t" "lw\t%3,4(%1)\n\t" "lw\t%4,8(%1)\n\t" "lw\t%5,12(%1)\n\t" "sw\t%2,(%0)\n\t" "sw\t%3,4(%0)\n\t" "sw\t%4,8(%0)\n\t" "sw\t%5,12(%0)\n\t" "lw\t%2,16(%1)\n\t" "lw\t%3,20(%1)\n\t" "lw\t%4,24(%1)\n\t" "lw\t%5,28(%1)\n\t" "sw\t%2,16(%0)\n\t" "sw\t%3,20(%0)\n\t" "sw\t%4,24(%0)\n\t" "sw\t%5,28(%0)\n\t" "daddiu\t%0,64\n\t" "daddiu\t%1,64\n\t" "lw\t%2,-32(%1)\n\t" "lw\t%3,-28(%1)\n\t" "lw\t%4,-24(%1)\n\t" "lw\t%5,-20(%1)\n\t" "sw\t%2,-32(%0)\n\t" "sw\t%3,-28(%0)\n\t" "sw\t%4,-24(%0)\n\t" "sw\t%5,-20(%0)\n\t" "lw\t%2,-16(%1)\n\t" "lw\t%3,-12(%1)\n\t" "lw\t%4,-8(%1)\n\t" "lw\t%5,-4(%1)\n\t" "sw\t%2,-16(%0)\n\t" "sw\t%3,-12(%0)\n\t" "sw\t%4,-8(%0)\n\t" "bne\t$1,%0,1b\n\t" "sw\t%5,-4(%0)\n\t" ".set\tmips0\n\t" ".set\tat\n\t" ".set\treorder" :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) :"0" (to), "1" (from), "I" (PAGE_SIZE)); } #endif void pgd_init(unsigned long page) { unsigned long *p = (unsigned long *) page; int i; for(i = 0; i < USER_PTRS_PER_PGD; i+=8) { p[i + 0] = (unsigned long) invalid_pte_table; p[i + 1] = (unsigned long) invalid_pte_table; p[i + 2] = (unsigned long) invalid_pte_table; p[i + 3] = (unsigned long) invalid_pte_table; p[i + 4] = (unsigned long) invalid_pte_table; p[i + 5] = (unsigned long) invalid_pte_table; p[i + 6] = (unsigned long) invalid_pte_table; p[i + 7] = (unsigned long) invalid_pte_table; } } Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/mm/Makefile,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- Makefile 2001/10/23 17:20:14 1.6 +++ Makefile 2001/10/25 08:10:21 1.7 @@ -24,6 +24,7 @@ obj-$(CONFIG_CPU_R5000) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_NEVADA) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_R5432) += pg-r5432.o c-r5432.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_R5900) += pg-r5900.o c-r5900.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_RM7000) += pg-rm7k.o c-rm7k.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_R10000) += pg-andes.o c-andes.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_MIPS32) += pg-mips32.o c-mips32.o tlb-r4k.o tlbex-r4k.o |
From: Paul M. <le...@us...> - 2001-10-25 08:10:24
|
Update of /cvsroot/linux-mips/linux/arch/mips In directory usw-pr-cvs1:/tmp/cvs-serv31689/arch/mips Modified Files: config.in Log Message: Started reworking R5900 mm stuff to new API. Incomplete for now, more to follow.. Index: config.in =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/config.in,v retrieving revision 1.35 retrieving revision 1.36 diff -u -d -r1.35 -r1.36 --- config.in 2001/10/24 23:32:54 1.35 +++ config.in 2001/10/25 08:10:20 1.36 @@ -252,6 +252,7 @@ fi if [ "$CONFIG_PS2" = "y" ]; then define_bool CONFIG_PC_KEYB y + define_bool CONFIG_BOARD_SCACHE y fi if [ "$CONFIG_CASIO_BE300" = "y" ]; then define_bool CONFIG_CPU_VR41XX y @@ -568,6 +569,10 @@ if [ "$CONFIG_SGI_IP22" = "y" ]; then source drivers/sgi/Config.in +fi + +if [ "$CONFIG_PS2" = "y" ]; then + bool ' Enable R5900 specific context' CONFIG_CPU_R5900_CONTEXT fi source drivers/usb/Config.in |
From: Paul M. <le...@us...> - 2001-10-25 08:10:24
|
Update of /cvsroot/linux-mips/linux/include/asm-mips In directory usw-pr-cvs1:/tmp/cvs-serv31689/include/asm-mips Added Files: r5900_cacheops.h Log Message: Started reworking R5900 mm stuff to new API. Incomplete for now, more to follow.. --- NEW FILE: r5900_cacheops.h --- /* * Cache operations for the cache instruction. * * 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. * * (C) Copyright 1996, 1997 by Ralf Baechle */ #ifndef __ASM_MIPS_CACHEOPS_H #define __ASM_MIPS_CACHEOPS_H /* * Cache Operations */ #define Index_Invalidate_I 0x07 #define Index_Load_Tag_I 0x00 #define Index_Store_Tag_I 0x04 #define Hit_Invalidate_I 0x0b #define Fill 0x0e #define Index_Writeback_Inv_D 0x14 #define Index_Load_Tag_D 0x10 #define Index_Store_Tag_D 0x12 #define Hit_Invalidate_D 0x1a #define Hit_Writeback_Inv_D 0x18 #define Hit_Writeback_D 0x1c #endif /* __ASM_MIPS_CACHEOPS_H */ |
Update of /cvsroot/linux-mips/linux/include/asm-mips In directory usw-pr-cvs1:/tmp/cvs-serv28848/include/asm-mips Modified Files: bootinfo.h mipsregs.h mmu_context.h Added Files: bugs.h cache.h isadep.h pgtable.h r4kcache.h stackframe.h Log Message: Improved support for Toshiba TX39/TX49 series. --- NEW FILE: isadep.h --- /* * Various ISA level dependant constants. * Most of the following constants reflect the different layout * of Coprocessor 0 registers. * * Copyright (c) 1998 Harald Koerfgen */ #include <linux/config.h> #ifndef __ASM_ISADEP_H #define __ASM_ISADEP_H #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) /* * R2000 or R3000 */ /* * kernel or user mode? (CP0_STATUS) */ #define KU_MASK 0x08 #define KU_USER 0x08 #define KU_KERN 0x00 #else /* * kernel or user mode? */ #define KU_MASK 0x18 #define KU_USER 0x10 #define KU_KERN 0x00 #endif #endif /* __ASM_ISADEP_H */ --- NEW FILE: r4kcache.h --- /* * r4kcache.h: Inline assembly cache operations. * * Copyright (C) 1996 David S. Miller (dm...@en...) * * FIXME: Handle split L2 caches. */ #ifndef _MIPS_R4KCACHE_H #define _MIPS_R4KCACHE_H #include <asm/asm.h> #include <asm/cacheops.h> extern inline void flush_icache_line_indexed(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n\t" "cache %1, (%0)\n\t" ".set mips0\n\t" ".set reorder" : : "r" (addr), "i" (Index_Invalidate_I)); } extern inline void flush_dcache_line_indexed(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n\t" "cache %1, (%0)\n\t" ".set mips0\n\t" ".set reorder" : : "r" (addr), "i" (Index_Writeback_Inv_D)); } extern inline void flush_scache_line_indexed(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n\t" "cache %1, (%0)\n\t" ".set mips0\n\t" ".set reorder" : : "r" (addr), "i" (Index_Writeback_Inv_SD)); } extern inline void flush_icache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n\t" "cache %1, (%0)\n\t" ".set mips0\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Invalidate_I)); } extern inline void flush_dcache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n\t" "cache %1, (%0)\n\t" ".set mips0\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Writeback_Inv_D)); } extern inline void invalidate_dcache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n\t" "cache %1, (%0)\n\t" ".set mips0\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Invalidate_D)); } extern inline void invalidate_scache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n\t" "cache %1, (%0)\n\t" ".set mips0\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Invalidate_SD)); } extern inline void flush_scache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n\t" "cache %1, (%0)\n\t" ".set mips0\n\t" ".set reorder" : : "r" (addr), "i" (Hit_Writeback_Inv_SD)); } /* * The next two are for badland addresses like signal trampolines. */ extern inline void protected_flush_icache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n" "1:\tcache %1,(%0)\n" "2:\t.set mips0\n\t" ".set reorder\n\t" ".section\t__ex_table,\"a\"\n\t" STR(PTR)"\t1b,2b\n\t" ".previous" : : "r" (addr), "i" (Hit_Invalidate_I)); } extern inline void protected_writeback_dcache_line(unsigned long addr) { __asm__ __volatile__( ".set noreorder\n\t" ".set mips3\n" "1:\tcache %1,(%0)\n" "2:\t.set mips0\n\t" ".set reorder\n\t" ".section\t__ex_table,\"a\"\n\t" STR(PTR)"\t1b,2b\n\t" ".previous" : : "r" (addr), "i" (Hit_Writeback_D)); } #define cache16_unroll32(base,op) \ __asm__ __volatile__(" \ .set noreorder; \ .set mips3; \ cache %1, 0x000(%0); cache %1, 0x010(%0); \ cache %1, 0x020(%0); cache %1, 0x030(%0); \ cache %1, 0x040(%0); cache %1, 0x050(%0); \ cache %1, 0x060(%0); cache %1, 0x070(%0); \ cache %1, 0x080(%0); cache %1, 0x090(%0); \ cache %1, 0x0a0(%0); cache %1, 0x0b0(%0); \ cache %1, 0x0c0(%0); cache %1, 0x0d0(%0); \ cache %1, 0x0e0(%0); cache %1, 0x0f0(%0); \ cache %1, 0x100(%0); cache %1, 0x110(%0); \ cache %1, 0x120(%0); cache %1, 0x130(%0); \ cache %1, 0x140(%0); cache %1, 0x150(%0); \ cache %1, 0x160(%0); cache %1, 0x170(%0); \ cache %1, 0x180(%0); cache %1, 0x190(%0); \ cache %1, 0x1a0(%0); cache %1, 0x1b0(%0); \ cache %1, 0x1c0(%0); cache %1, 0x1d0(%0); \ cache %1, 0x1e0(%0); cache %1, 0x1f0(%0); \ .set mips0; \ .set reorder" \ : \ : "r" (base), \ "i" (op)); extern inline void blast_dcache16(void) { unsigned long start = KSEG0; unsigned long end = (start + dcache_size); while(start < end) { cache16_unroll32(start,Index_Writeback_Inv_D); start += 0x200; } } extern inline void blast_dcache16_wayLSB(void) { unsigned long start = KSEG0; unsigned long end = (start + mips_cpu.dcache.sets * mips_cpu.dcache.linesz); int way; while(start < end) { /* LSB of VA select the way */ for (way = 0; way < mips_cpu.dcache.ways; way++) cache16_unroll32(start|way,Index_Writeback_Inv_D); start += 0x200; } } extern inline void blast_dcache16_page(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache16_unroll32(start,Hit_Writeback_Inv_D); start += 0x200; } } extern inline void blast_dcache16_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache16_unroll32(start,Index_Writeback_Inv_D); start += 0x200; } } extern inline void blast_dcache16_page_indexed_wayLSB(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); int way; while(start < end) { /* LSB of VA select the way */ for (way = 0; way < mips_cpu.dcache.ways; way++) cache16_unroll32(start|way,Index_Writeback_Inv_D); start += 0x200; } } extern inline void blast_icache16(void) { unsigned long start = KSEG0; unsigned long end = (start + icache_size); while(start < end) { cache16_unroll32(start,Index_Invalidate_I); start += 0x200; } } extern inline void blast_icache16_wayLSB(void) { unsigned long start = KSEG0; unsigned long end = (start + mips_cpu.icache.sets * mips_cpu.icache.linesz); int way; while(start < end) { /* LSB of VA select the way */ for (way = 0; way < mips_cpu.icache.ways; way++) cache16_unroll32(start|way,Index_Invalidate_I); start += 0x200; } } extern inline void blast_icache16_page(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache16_unroll32(start,Hit_Invalidate_I); start += 0x200; } } extern inline void blast_icache16_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache16_unroll32(start,Index_Invalidate_I); start += 0x200; } } extern inline void blast_scache16(void) { unsigned long start = KSEG0; unsigned long end = KSEG0 + scache_size; while(start < end) { cache16_unroll32(start,Index_Writeback_Inv_SD); start += 0x200; } } extern inline void blast_scache16_page(unsigned long page) { unsigned long start = page; unsigned long end = page + PAGE_SIZE; while(start < end) { cache16_unroll32(start,Hit_Writeback_Inv_SD); start += 0x200; } } extern inline void blast_scache16_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = page + PAGE_SIZE; while(start < end) { cache16_unroll32(start,Index_Writeback_Inv_SD); start += 0x200; } } #define cache32_unroll32(base,op) \ __asm__ __volatile__(" \ .set noreorder; \ .set mips3; \ cache %1, 0x000(%0); cache %1, 0x020(%0); \ cache %1, 0x040(%0); cache %1, 0x060(%0); \ cache %1, 0x080(%0); cache %1, 0x0a0(%0); \ cache %1, 0x0c0(%0); cache %1, 0x0e0(%0); \ cache %1, 0x100(%0); cache %1, 0x120(%0); \ cache %1, 0x140(%0); cache %1, 0x160(%0); \ cache %1, 0x180(%0); cache %1, 0x1a0(%0); \ cache %1, 0x1c0(%0); cache %1, 0x1e0(%0); \ cache %1, 0x200(%0); cache %1, 0x220(%0); \ cache %1, 0x240(%0); cache %1, 0x260(%0); \ cache %1, 0x280(%0); cache %1, 0x2a0(%0); \ cache %1, 0x2c0(%0); cache %1, 0x2e0(%0); \ cache %1, 0x300(%0); cache %1, 0x320(%0); \ cache %1, 0x340(%0); cache %1, 0x360(%0); \ cache %1, 0x380(%0); cache %1, 0x3a0(%0); \ cache %1, 0x3c0(%0); cache %1, 0x3e0(%0); \ .set mips0; \ .set reorder" \ : \ : "r" (base), \ "i" (op)); extern inline void blast_dcache32(void) { unsigned long start = KSEG0; unsigned long end = (start + dcache_size); while(start < end) { cache32_unroll32(start,Index_Writeback_Inv_D); start += 0x400; } } extern inline void blast_dcache32_wayLSB(void) { unsigned long start = KSEG0; unsigned long end = (start + mips_cpu.dcache.sets * mips_cpu.dcache.linesz); int way; while(start < end) { /* LSB of VA select the way */ for (way = 0; way < mips_cpu.dcache.ways; way++) cache32_unroll32(start|way,Index_Writeback_Inv_D); start += 0x400; } } /* * Call this function only with interrupts disabled or R4600 V2.0 may blow * up on you. * * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D, * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Excl_D will only * operate correctly if the internal data cache refill buffer is empty. These * CACHE instructions should be separated from any potential data cache miss * by a load instruction to an uncached address to empty the response buffer." * (Revision 2.0 device errata from IDT available on http://www.idt.com/ * in .pdf format.) */ extern inline void blast_dcache32_page(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); /* * Sigh ... workaround for R4600 v1.7 bug. Explanation see above. */ *(volatile unsigned long *)KSEG1; __asm__ __volatile__("nop;nop;nop;nop"); while(start < end) { cache32_unroll32(start,Hit_Writeback_Inv_D); start += 0x400; } } extern inline void blast_dcache32_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache32_unroll32(start,Index_Writeback_Inv_D); start += 0x400; } } extern inline void blast_dcache32_page_indexed_wayLSB(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); int way; while(start < end) { /* LSB of VA select the way */ for (way = 0; way < mips_cpu.dcache.ways; way++) cache32_unroll32(start|way,Index_Writeback_Inv_D); start += 0x400; } } extern inline void blast_icache32(void) { unsigned long start = KSEG0; unsigned long end = (start + icache_size); while(start < end) { cache32_unroll32(start,Index_Invalidate_I); start += 0x400; } } extern inline void blast_icache32_wayLSB(void) { unsigned long start = KSEG0; unsigned long end = (start + mips_cpu.icache.sets * mips_cpu.icache.linesz); int way; while(start < end) { /* LSB of VA select the way */ for (way = 0; way < mips_cpu.icache.ways; way++) cache32_unroll32(start|way,Index_Invalidate_I); start += 0x400; } } extern inline void blast_icache32_page(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache32_unroll32(start,Hit_Invalidate_I); start += 0x400; } } extern inline void blast_icache32_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = (start + PAGE_SIZE); while(start < end) { cache32_unroll32(start,Index_Invalidate_I); start += 0x400; } } extern inline void blast_scache32(void) { unsigned long start = KSEG0; unsigned long end = KSEG0 + scache_size; while(start < end) { cache32_unroll32(start,Index_Writeback_Inv_SD); start += 0x400; } } extern inline void blast_scache32_page(unsigned long page) { unsigned long start = page; unsigned long end = page + PAGE_SIZE; while(start < end) { cache32_unroll32(start,Hit_Writeback_Inv_SD); start += 0x400; } } extern inline void blast_scache32_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = page + PAGE_SIZE; while(start < end) { cache32_unroll32(start,Index_Writeback_Inv_SD); start += 0x400; } } #define cache64_unroll32(base,op) \ __asm__ __volatile__(" \ .set noreorder; \ .set mips3; \ cache %1, 0x000(%0); cache %1, 0x040(%0); \ cache %1, 0x080(%0); cache %1, 0x0c0(%0); \ cache %1, 0x100(%0); cache %1, 0x140(%0); \ cache %1, 0x180(%0); cache %1, 0x1c0(%0); \ cache %1, 0x200(%0); cache %1, 0x240(%0); \ cache %1, 0x280(%0); cache %1, 0x2c0(%0); \ cache %1, 0x300(%0); cache %1, 0x340(%0); \ cache %1, 0x380(%0); cache %1, 0x3c0(%0); \ cache %1, 0x400(%0); cache %1, 0x440(%0); \ cache %1, 0x480(%0); cache %1, 0x4c0(%0); \ cache %1, 0x500(%0); cache %1, 0x540(%0); \ cache %1, 0x580(%0); cache %1, 0x5c0(%0); \ cache %1, 0x600(%0); cache %1, 0x640(%0); \ cache %1, 0x680(%0); cache %1, 0x6c0(%0); \ cache %1, 0x700(%0); cache %1, 0x740(%0); \ cache %1, 0x780(%0); cache %1, 0x7c0(%0); \ .set mips0; \ .set reorder" \ : \ : "r" (base), \ "i" (op)); extern inline void blast_scache64(void) { unsigned long start = KSEG0; unsigned long end = KSEG0 + scache_size; while(start < end) { cache64_unroll32(start,Index_Writeback_Inv_SD); start += 0x800; } } extern inline void blast_scache64_page(unsigned long page) { unsigned long start = page; unsigned long end = page + PAGE_SIZE; while(start < end) { cache64_unroll32(start,Hit_Writeback_Inv_SD); start += 0x800; } } extern inline void blast_scache64_page_indexed(unsigned long page) { unsigned long start = page; unsigned long end = page + PAGE_SIZE; while(start < end) { cache64_unroll32(start,Index_Writeback_Inv_SD); start += 0x800; } } #define cache128_unroll32(base,op) \ __asm__ __volatile__(" \ .set noreorder; \ .set mips3; \ cache %1, 0x000(%0); cache %1, 0x080(%0); \ cache %1, 0x100(%0); cache %1, 0x180(%0); \ cache %1, 0x200(%0); cache %1, 0x280(%0); \ cache %1, 0x300(%0); cache %1, 0x380(%0); \ cache %1, 0x400(%0); cache %1, 0x480(%0); \ cache %1, 0x500(%0); cache %1, 0x580(%0); \ cache %1, 0x600(%0); cache %1, 0x680(%0); \ cache %1, 0x700(%0); cache %1, 0x780(%0); \ cache %1, 0x800(%0); cache %1, 0x880(%0); \ cache %1, 0x900(%0); cache %1, 0x980(%0); \ cache %1, 0xa00(%0); cache %1, 0xa80(%0); \ cache %1, 0xb00(%0); cache %1, 0xb80(%0); \ cache %1, 0xc00(%0); cache %1, 0xc80(%0); \ cache %1, 0xd00(%0); cache %1, 0xd80(%0); \ cache %1, 0xe00(%0); cache %1, 0xe80(%0); \ cache %1, 0xf00(%0); cache %1, 0xf80(%0); \ .set mips0; \ .set reorder" \ : \ : "r" (base), \ "i" (op)); extern inline void blast_scache128(void) { unsigned long start = KSEG0; unsigned long end = KSEG0 + scache_size; while(start < end) { cache128_unroll32(start,Index_Writeback_Inv_SD); start += 0x1000; } } extern inline void blast_scache128_page(unsigned long page) { cache128_unroll32(page,Hit_Writeback_Inv_SD); } extern inline void blast_scache128_page_indexed(unsigned long page) { cache128_unroll32(page,Index_Writeback_Inv_SD); } #endif /* !(_MIPS_R4KCACHE_H) */ Index: bootinfo.h =================================================================== RCS file: /cvsroot/linux-mips/linux/include/asm-mips/bootinfo.h,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- bootinfo.h 2001/10/12 17:49:17 1.8 +++ bootinfo.h 2001/10/24 23:32:54 1.9 @@ -259,8 +259,10 @@ #define CPU_4KSC 39 #define CPU_VR41XX 40 #define CPU_R5500 41 -#define CPU_R5900 42 -#define CPU_LAST 42 +#define CPU_TX49XX 42 +#define CPU_TX39XX 43 +#define CPU_R5900 44 +#define CPU_LAST 44 #define CPU_NAMES { "unknown", "R2000", "R3000", "R3000A", "R3041", "R3051", \ @@ -269,7 +271,8 @@ "R6000A", "R8000", "R10000", "R4300", "R4650", "R4700", "R5000", \ "R5000A", "R4640", "Nevada", "RM7000", "R5432", "MIPS 4Kc", \ "MIPS 5Kc", "R4310", "SiByte SB1", "TX3912", "TX3922", "TX3927", \ - "Au1000", "MIPS 4KEc", "MIPS 4KSc", "NEC Vr41xx", "R5500", "R5900" } + "Au1000", "MIPS 4KEc", "MIPS 4KSc", "NEC Vr41xx", "R5500", "TX49xx", \ + "TX39xx", "R5900" } #define COMMAND_LINE_SIZE 256 Index: mipsregs.h =================================================================== RCS file: /cvsroot/linux-mips/linux/include/asm-mips/mipsregs.h,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- mipsregs.h 2001/09/04 16:14:10 1.7 +++ mipsregs.h 2001/10/24 23:32:54 1.8 @@ -79,7 +79,13 @@ #define CP0_S1_DERRADDR0 $26 #define CP0_S1_DERRADDR1 $27 #define CP0_S1_INTCONTROL $20 + /* + * TX39 Series + */ +#define CP0_TX39_CACHE $7 + +/* * Coprocessor 1 (FPU) register names */ #define CP1_REVISION $0 @@ -478,6 +484,14 @@ #define CONF_SC (1 << 17) #define CONF_AC (1 << 23) #define CONF_HALT (1 << 25) + +/* + * Bits in the TX49 coprozessor 0 config register. + */ +#define TX49_CONF_DC (1 << 16) +#define TX49_CONF_IC (1 << 17) /* conflict with CONF_SC */ +#define TX49_CONF_HALT (1 << 18) +#define TX49_CONF_CWFON (1 << 27) /* * R10000 performance counter definitions. Index: mmu_context.h =================================================================== RCS file: /cvsroot/linux-mips/linux/include/asm-mips/mmu_context.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- mmu_context.h 2001/10/22 19:16:45 1.4 +++ mmu_context.h 2001/10/24 23:32:54 1.5 @@ -37,7 +37,7 @@ #endif #define ASID_CACHE(cpu) cpu_data[cpu].asid_cache -#if defined(CONFIG_CPU_R3000) +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) #define ASID_INC 0x40 #define ASID_MASK 0xfc0 |
From: James S. <jsi...@us...> - 2001-10-24 23:32:57
|
Update of /cvsroot/linux-mips/linux/arch/mips/mm In directory usw-pr-cvs1:/tmp/cvs-serv28848/arch/mips/mm Modified Files: c-tx39.c loadmmu.c tlb-r3k.c Added Files: c-tx49.c Log Message: Improved support for Toshiba TX39/TX49 series. --- NEW FILE: c-tx49.c --- /* * 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. * * r49xx.c: TX49 processor variant specific MMU/Cache routines. * * Copyright (C) 1996 David S. Miller (dm...@en...) * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ra...@gn... * * Modified for R4300/TX49xx (Jun/2001) * Copyright (C) 1999-2001 Toshiba Corporation * * To do: * * - this code is a overbloated pig * - many of the bug workarounds are not efficient at all, but at * least they are functional ... */ #include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> #include <asm/bootinfo.h> #include <asm/cpu.h> #include <asm/io.h> #include <asm/page.h> #include <asm/pgtable.h> #include <asm/system.h> #include <asm/mmu_context.h> /* Primary cache parameters. */ static int icache_size, dcache_size; /* Size in bytes */ #define ic_lsize mips_cpu.icache.linesz #define dc_lsize mips_cpu.dcache.linesz static unsigned long scache_size; #include <asm/cacheops.h> #include <asm/r4kcache.h> #undef DEBUG_CACHE /* TX49 does can not flush the line contains the CACHE insn itself... */ /* r4k_xxx routines are completely same as those in r4xx0.c */ /* * If you think for one second that this stuff coming up is a lot * of bulky code eating too many kernel cache lines. Think _again_. * * Consider: * 1) Taken branches have a 3 cycle penalty on R4k * 2) The branch itself is a real dead cycle on even R4600/R5000. * 3) Only one of the following variants of each type is even used by * the kernel based upon the cache parameters we detect at boot time. * * QED. */ static inline void r49_flush_cache_all_d16i32(void) { unsigned long flags, config; __save_and_cli(flags); blast_dcache16_wayLSB(); /* disable icache (set ICE#) */ config = read_32bit_cp0_register(CP0_CONFIG); write_32bit_cp0_register(CP0_CONFIG, config|TX49_CONF_IC); blast_icache32_wayLSB(); write_32bit_cp0_register(CP0_CONFIG, config); __restore_flags(flags); } static inline void r49_flush_cache_all_d32i32(void) { unsigned long flags, config; __save_and_cli(flags); blast_dcache32_wayLSB(); /* disable icache (set ICE#) */ config = read_32bit_cp0_register(CP0_CONFIG); write_32bit_cp0_register(CP0_CONFIG, config|TX49_CONF_IC); blast_icache32_wayLSB(); write_32bit_cp0_register(CP0_CONFIG, config); __restore_flags(flags); } static void r49_flush_cache_range_d16i32(struct mm_struct *mm, unsigned long start, unsigned long end) { if (mm->context != 0) { unsigned long flags, config; #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif __save_and_cli(flags); blast_dcache16_wayLSB(); /* disable icache (set ICE#) */ config = read_32bit_cp0_register(CP0_CONFIG); write_32bit_cp0_register(CP0_CONFIG, config|TX49_CONF_IC); blast_icache32_wayLSB(); write_32bit_cp0_register(CP0_CONFIG, config); __restore_flags(flags); } } static void r49_flush_cache_range_d32i32(struct mm_struct *mm, unsigned long start, unsigned long end) { if (mm->context != 0) { unsigned long flags, config; #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif __save_and_cli(flags); blast_dcache32_wayLSB(); /* disable icache (set ICE#) */ config = read_32bit_cp0_register(CP0_CONFIG); write_32bit_cp0_register(CP0_CONFIG, config|TX49_CONF_IC); blast_icache32_wayLSB(); write_32bit_cp0_register(CP0_CONFIG, config); __restore_flags(flags); } } /* * On architectures like the Sparc, we could get rid of lines in * the cache created only by a certain context, but on the MIPS * (and actually certain Sparc's) we cannot. */ static void r49_flush_cache_mm_d16i32(struct mm_struct *mm) { if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif r49_flush_cache_all_d16i32(); } } static void r49_flush_cache_mm_d32i32(struct mm_struct *mm) { if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif r49_flush_cache_all_d32i32(); } } static void r49_flush_cache_page_d16i32(struct vm_area_struct *vma, unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; /* * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ if (mm->context == 0) return; #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); ptep = pte_offset(pmdp, page); /* * If the page isn't marked valid, the page cannot possibly be * in the cache. */ if (!(pte_val(*ptep) & _PAGE_PRESENT)) goto out; /* * Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { blast_dcache16_page(page); } else { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ page = (KSEG0 + (page & (dcache_size - 1))); blast_dcache16_page_indexed_wayLSB(page); } out: __restore_flags(flags); } static void r49_flush_cache_page_d32i32(struct vm_area_struct *vma, unsigned long page) { struct mm_struct *mm = vma->vm_mm; unsigned long flags; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; /* * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ if (mm->context == 0) return; #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); ptep = pte_offset(pmdp, page); /* * If the page isn't marked valid, the page cannot possibly be * in the cache. */ if (!(pte_val(*ptep) & _PAGE_PRESENT)) goto out; /* * Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { blast_dcache32_page(page); } else { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ page = (KSEG0 + (page & (dcache_size - 1))); blast_dcache32_page_indexed_wayLSB(page); } out: __restore_flags(flags); } /* If the addresses passed to these routines are valid, they are * either: * * 1) In KSEG0, so we can do a direct flush of the page. * 2) In KSEG2, and since every process can translate those * addresses all the time in kernel mode we can do a direct * flush. * 3) In KSEG1, no flush necessary. */ static void r4k_flush_page_to_ram_d16(struct page *page) { blast_dcache16_page((unsigned long)page_address(page)); } static void r4k_flush_page_to_ram_d32(struct page *page) { blast_dcache32_page((unsigned long)page_address(page)); } static void r4k_flush_icache_range(unsigned long start, unsigned long end) { flush_cache_all(); } /* * Ok, this seriously sucks. We use them to flush a user page but don't * know the virtual address, so we have to blast away the whole icache * which is significantly more expensive than the real thing. */ static void r4k_flush_icache_page(struct vm_area_struct *vma, struct page *page) { if (!(vma->vm_flags & VM_EXEC)) return; flush_cache_all(); } /* * Writeback and invalidate the primary cache dcache before DMA. */ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) { unsigned long end, a; unsigned int flags; if (size >= dcache_size) { flush_cache_all(); } else { __save_and_cli(flags); a = addr & ~(dc_lsize - 1); end = (addr + size) & ~(dc_lsize - 1); while (1) { flush_dcache_line(a); /* Hit_Writeback_Inv_D */ if (a == end) break; a += dc_lsize; } __restore_flags(flags); } } static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) { unsigned long end, a; unsigned int flags; if (size >= dcache_size) { flush_cache_all(); } else { __save_and_cli(flags); a = addr & ~(dc_lsize - 1); end = (addr + size) & ~(dc_lsize - 1); while (1) { flush_dcache_line(a); /* Hit_Writeback_Inv_D */ if (a == end) break; a += dc_lsize; } __restore_flags(flags); } } static void r4k_dma_cache_wback(unsigned long addr, unsigned long size) { panic("r4k_dma_cache called - should not happen.\n"); } /* * While we're protected against bad userland addresses we don't care * very much about what happens in that case. Usually a segmentation * fault will dump the process later on anyway ... */ static void r4k_flush_cache_sigtramp(unsigned long addr) { protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); protected_flush_icache_line(addr & ~(ic_lsize - 1)); } /* Detect and size the various r4k caches. */ static void __init probe_icache(unsigned long config) { icache_size = 1 << (12 + ((config >> 9) & 7)); ic_lsize = 16 << ((config >> 5) & 1); printk("Primary instruction cache %dkb, linesize %d bytes.\n", icache_size >> 10, ic_lsize); } static void __init probe_dcache(unsigned long config) { dcache_size = 1 << (12 + ((config >> 6) & 7)); dc_lsize = 16 << ((config >> 4) & 1); printk("Primary data cache %dkb, linesize %d bytes.\n", dcache_size >> 10, dc_lsize); } int mips_configk0 = -1; /* board-specific setup routine can override this */ void __init ld_mmu_tx49(void) { unsigned long config = read_32bit_cp0_register(CP0_CONFIG); printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); if (mips_configk0 != -1) change_cp0_config(CONF_CM_CMASK, mips_configk0); else #ifdef CONFIG_MIPS_UNCACHED change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); #else change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT); #endif probe_icache(config); probe_dcache(config); if (mips_cpu.icache.ways == 0) mips_cpu.icache.ways = 1; if (mips_cpu.dcache.ways == 0) mips_cpu.dcache.ways = 1; mips_cpu.icache.sets = icache_size / mips_cpu.icache.ways / mips_cpu.icache.linesz; mips_cpu.dcache.sets = dcache_size / mips_cpu.dcache.ways / mips_cpu.dcache.linesz; switch(dc_lsize) { case 16: _clear_page = r4k_clear_page_d16; _copy_page = r4k_copy_page_d16; _flush_page_to_ram = r4k_flush_page_to_ram_d16; _flush_cache_all = r49_flush_cache_all_d16i32; _flush_cache_mm = r49_flush_cache_mm_d16i32; _flush_cache_range = r49_flush_cache_range_d16i32; _flush_cache_page = r49_flush_cache_page_d16i32; break; case 32: _clear_page = r4k_clear_page_d32; _copy_page = r4k_copy_page_d32; _flush_page_to_ram = r4k_flush_page_to_ram_d32; _flush_cache_all = r49_flush_cache_all_d32i32; _flush_cache_mm = r49_flush_cache_mm_d32i32; _flush_cache_range = r49_flush_cache_range_d32i32; _flush_cache_page = r49_flush_cache_page_d32i32; break; } ___flush_cache_all = _flush_cache_all; _flush_icache_page = r4k_flush_icache_page; _dma_cache_wback_inv = r4k_dma_cache_wback_inv; _dma_cache_wback = r4k_dma_cache_wback; _dma_cache_inv = r4k_dma_cache_inv; _flush_cache_sigtramp = r4k_flush_cache_sigtramp; _flush_icache_range = r4k_flush_icache_range; /* Ouch */ __flush_cache_all(); } Index: c-tx39.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/mm/c-tx39.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- c-tx39.c 2001/10/23 17:20:14 1.1 +++ c-tx39.c 2001/10/24 23:32:54 1.2 @@ -28,31 +28,27 @@ static unsigned long icache_size, dcache_size; /* Size in bytes */ extern long scache_size; -#define icache_lsize 16 /* for all current cpu variants */ -#define dcache_lsize 4 /* for all current cpu variants */ +#define icache_lsize mips_cpu.icache.linesz +#define dcache_lsize mips_cpu.dcache.linesz #include <asm/r4kcache.h> -static void tx39_flush_page_to_ram(struct page * page) +extern int r3k_have_wired_reg; /* in r3k-tlb.c */ + +static void tx39h_flush_page_to_ram(struct page * page) { } -static void tx39_flush_icache_all(void) +/* TX39H-style cache flush routines. */ +static void tx39h_flush_icache_all(void) { unsigned long start = KSEG0; unsigned long end = (start + icache_size); - unsigned long dummy = 0; + unsigned long flags, config; - /* disable icache and stop streaming */ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - "mfc0\t%0, $3\n\t" - "xori\t%0, 32\n\t" - "mtc0\t%0, $3\n\t" - "j\t1f\n\t" - "nop\n\t" - "1:\t.set\treorder\n\t" - : "+r"(dummy)); + /* disable icache (set ICE#) */ + __save_and_cli(flags); + config = read_32bit_cp0_register(CP0_CONF); /* invalidate icache */ while (start < end) { @@ -60,16 +56,196 @@ start += 0x200; } - /* enable icache */ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - "mfc0\t%0, $3\n\t" - "xori\t%0, 32\n\t" - "mtc0\t%0, $3\n\t" - ".set\treorder\n\t" - : "+r"(dummy)); + write_32bit_cp0_register(CP0_CONF, config); + __restore_flags(flags); +} + +static void tx39h_dma_cache_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + wbflush(); + + a = addr & ~(dcache_lsize - 1); + end = (addr + size) & ~(dcache_lsize - 1); + while (1) { + invalidate_dcache_line(a); /* Hit_Invalidate_D */ + if (a == end) break; + a += dcache_lsize; + } +} + + +/* TX39H2,TX39H3 */ +static inline void tx39_flush_cache_all(void) +{ + unsigned long flags, config; + + __save_and_cli(flags); + blast_dcache16_wayLSB(); + /* disable icache (set ICE#) */ + config = read_32bit_cp0_register(CP0_CONF); + write_32bit_cp0_register(CP0_CONF, config&~TX39_CONF_ICE); + blast_icache16_wayLSB(); + write_32bit_cp0_register(CP0_CONF, config); + __restore_flags(flags); +} + +static void tx39_flush_cache_mm(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + tx39_flush_cache_all(); + } +} + +static void tx39_flush_cache_range(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + if(mm->context != 0) { + unsigned long flags, config; + +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + __save_and_cli(flags); + blast_dcache16_wayLSB(); + /* disable icache (set ICE#) */ + config = read_32bit_cp0_register(CP0_CONF); + write_32bit_cp0_register(CP0_CONF, config&~TX39_CONF_ICE); + blast_icache16_wayLSB(); + write_32bit_cp0_register(CP0_CONF, config); + __restore_flags(flags); + } +} + +static void tx39_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if(mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + __save_and_cli(flags); + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if(!(pte_val(*ptep) & _PAGE_PRESENT)) + goto out; + + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { + blast_dcache16_page(page); + } else { + /* + * Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (dcache_size - 1))); + blast_dcache16_page_indexed_wayLSB(page); + } +out: + __restore_flags(flags); +} + +static void tx39_flush_page_to_ram(struct page * page) +{ + blast_dcache16_page((unsigned long)page_address(page)); +} + +static void tx39_flush_icache_range(unsigned long start, unsigned long end) +{ + flush_cache_all(); +} + +static void tx39_flush_icache_page(struct vm_area_struct *vma, struct page *page) +{ + if (!(vma->vm_flags & VM_EXEC)) + return; + + flush_cache_all(); +} + +static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (size >= dcache_size) { + flush_cache_all(); + } else { + a = addr & ~(dcache_lsize - 1); + end = (addr + size) & ~(dcache_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) break; + a += dcache_lsize; + } + } } +static void tx39_dma_cache_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (size >= dcache_size) { + flush_cache_all(); + } else { + a = addr & ~(dcache_lsize - 1); + end = (addr + size) & ~(dcache_lsize - 1); + while (1) { + invalidate_dcache_line(a); /* Hit_Invalidate_D */ + if (a == end) break; + a += dcache_lsize; + } + } +} + +static void tx39_dma_cache_wback(unsigned long addr, unsigned long size) +{ + panic("tx39_dma_cache called - should not happen.\n"); +} + +static void tx39_flush_cache_sigtramp(unsigned long addr) +{ + unsigned long config; + unsigned int flags; + + __save_and_cli(flags); + protected_writeback_dcache_line(addr & ~(dcache_lsize - 1)); + + /* disable icache (set ICE#) */ + config = read_32bit_cp0_register(CP0_CONF); + write_32bit_cp0_register(CP0_CONF, config&~TX39_CONF_ICE); + protected_flush_icache_line(addr & ~(icache_lsize - 1)); + write_32bit_cp0_register(CP0_CONF, config); + __restore_flags(flags); +} + static __init void tx39_probe_cache(void) { unsigned long config; @@ -78,6 +254,19 @@ icache_size = 1 << (10 + ((config >> 19) & 3)); dcache_size = 1 << (10 + ((config >> 16) & 3)); + + icache_lsize = 16; + switch (mips_cpu.cputype) { + case CPU_TX3912: + dcache_lsize = 4; + break; + case CPU_TX3922: + case CPU_TX3927: + case CPU_TX39XX: + default: + dcache_lsize = 16; + break; + } } void __init ld_mmu_tx39(void) @@ -95,18 +284,55 @@ tx39_probe_cache(); - _flush_cache_all = tx39_flush_icache_all; - ___flush_cache_all = tx39_flush_icache_all; - _flush_cache_mm = (void *) tx39_flush_icache_all; - _flush_cache_range = (void *) tx39_flush_icache_all; - _flush_cache_page = (void *) tx39_flush_icache_all; - _flush_cache_sigtramp = (void *) tx39_flush_icache_all; - _flush_page_to_ram = tx39_flush_page_to_ram; - _flush_icache_page = (void *) tx39_flush_icache_all; - _flush_icache_range = (void *) tx39_flush_icache_all; + switch (mips_cpu.cputype) { + case CPU_TX3912: + /* TX39/H core (writethru direct-map cache) */ + _flush_cache_all = tx39h_flush_icache_all; + ___flush_cache_all = tx39h_flush_icache_all; + _flush_cache_mm = (void *) tx39h_flush_icache_all; + _flush_cache_range = (void *) tx39h_flush_icache_all; + _flush_cache_page = (void *) tx39h_flush_icache_all; + _flush_cache_sigtramp = (void *) tx39h_flush_icache_all; + _flush_page_to_ram = tx39h_flush_page_to_ram; + _flush_icache_page = (void *) tx39h_flush_icache_all; + _flush_icache_range = (void *) tx39h_flush_icache_all; - /* This seems to be wrong for a R4k-style caches -- Ralf */ - // _dma_cache_wback_inv = r3k_dma_cache_wback_inv; + _dma_cache_wback_inv = tx39h_dma_cache_wback_inv; + break; + + case CPU_TX3922: + case CPU_TX3927: + default: + /* TX39/H2,H3 core (writeback 2way-set-associative cache) */ + r3k_have_wired_reg = 1; + set_wired (0); /* set 8 on reset... */ + /* board-dependent init code may set WBON */ + + _flush_cache_all = tx39_flush_cache_all; + ___flush_cache_all = tx39_flush_cache_all; + _flush_cache_mm = tx39_flush_cache_mm; + _flush_cache_range = tx39_flush_cache_range; + _flush_cache_page = tx39_flush_cache_page; + _flush_cache_sigtramp = tx39_flush_cache_sigtramp; + _flush_page_to_ram = tx39_flush_page_to_ram; + _flush_icache_page = tx39_flush_icache_page; + _flush_icache_range = tx39_flush_icache_range; + + _dma_cache_wback_inv = tx39_dma_cache_wback_inv; + _dma_cache_wback = tx39_dma_cache_wback; + _dma_cache_inv = tx39_dma_cache_inv; + + break; + } + + if (mips_cpu.icache.ways == 0) + mips_cpu.icache.ways = 1; + if (mips_cpu.dcache.ways == 0) + mips_cpu.dcache.ways = 1; + mips_cpu.icache.sets = + icache_size / mips_cpu.icache.ways / mips_cpu.icache.linesz; + mips_cpu.dcache.sets = + dcache_size / mips_cpu.dcache.ways / mips_cpu.dcache.linesz; printk("Primary instruction cache %dkb, linesize %d bytes\n", (int) (icache_size >> 10), (int) icache_lsize); Index: loadmmu.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/mm/loadmmu.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- loadmmu.c 2001/10/23 17:20:14 1.6 +++ loadmmu.c 2001/10/24 23:32:54 1.7 @@ -40,6 +40,8 @@ extern void ld_mmu_r23000(void); extern void ld_mmu_r4xx0(void); +extern void ld_mmu_tx39(void); +extern void ld_mmu_tx49(void); extern void ld_mmu_r5432(void); extern void ld_mmu_r6000(void); extern void ld_mmu_rm7k(void); @@ -67,6 +69,10 @@ ld_mmu_r5432(); r4k_tlb_init(); #endif +#if defined(CONFIG_CPU_TX49XX) + ld_mmu_tx49(); + r4k_tlb_init(); +#endif #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) ld_mmu_mips32(); @@ -80,10 +86,20 @@ case CPU_R3081E: ld_mmu_r23000(); r3k_tlb_init(); - + break; + case CPU_TX3912: + case CPU_TX3922: + case CPU_TX3927: + case CPU_TX39XX: + ld_mmu_tx39(); + r3k_tlb_init(); + break; +#endif +#ifdef CONFIG_CPU_TX39XX case CPU_TX3912: case CPU_TX3922: case CPU_TX3927: + case CPU_TX39XX: ld_mmu_tx39(); r3k_tlb_init(); break; Index: tlb-r3k.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/mm/tlb-r3k.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- tlb-r3k.c 2001/10/23 17:20:14 1.2 +++ tlb-r3k.c 2001/10/24 23:32:54 1.3 @@ -27,6 +27,10 @@ #undef DEBUG_TLB +#ifdef CONFIG_CPU_TX39XX +int r3k_have_wired_reg = 0; /* should be in mips_cpu? */ +#endif + /* TLB operations. */ void local_flush_tlb_all(void) { @@ -41,7 +45,12 @@ save_and_cli(flags); old_ctx = (get_entryhi() & 0xfc0); write_32bit_cp0_register(CP0_ENTRYLO0, 0); - for (entry = 8; entry < mips_cpu.tlbsize; entry++) { +#ifdef CONFIG_CPU_TX39XX + entry = r3k_have_wired_reg ? get_wired() : 8; +#else + entry = 8; +#endif + for (; entry < mips_cpu.tlbsize; entry++) { write_32bit_cp0_register(CP0_INDEX, entry << 8); write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x80000) << 12)); __asm__ __volatile__("tlbwi"); @@ -193,6 +202,40 @@ unsigned long old_ctx; static unsigned long wired = 0; +#ifdef CONFIG_CPU_TX39XX + if (r3k_have_wired_reg) { + unsigned long old_pagemask; + unsigned long w; + +#ifdef DEBUG_TLB + printk("[tlbwired]"); + printk("ently lo0 %8x, hi %8x\n, pagemask %8x\n", + entrylo0, entryhi, pagemask); +#endif + save_and_cli(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = (get_entryhi() & 0xff); + old_pagemask = get_pagemask(); + w = get_wired(); + set_wired (w + 1); + if (get_wired() != w + 1) { + printk("[tlbwired] No WIRED reg?\n"); + return; + } + set_index (w << 8); + set_pagemask (pagemask); + set_entryhi(entryhi); + set_entrylo0(entrylo0); + tlb_write_indexed(); + + set_entryhi(old_ctx); + set_pagemask (old_pagemask); + local_flush_tlb_all(); + restore_flags(flags); + return; + } +#endif + if (wired < 8) { __save_and_cli(flags); old_ctx = get_entryhi() & 0xfc0; |
From: James S. <jsi...@us...> - 2001-10-24 23:32:57
|
Update of /cvsroot/linux-mips/linux/arch/mips/kernel In directory usw-pr-cvs1:/tmp/cvs-serv28848/arch/mips/kernel Modified Files: gdb-low.S setup.c traps.c Log Message: Improved support for Toshiba TX39/TX49 series. Index: gdb-low.S =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/kernel/gdb-low.S,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- gdb-low.S 2001/07/19 17:14:54 1.1 +++ gdb-low.S 2001/10/24 23:32:54 1.2 @@ -304,7 +304,7 @@ lw v1,GDB_FR_REG3(sp) lw v0,GDB_FR_REG2(sp) lw $1,GDB_FR_REG1(sp) -#ifdef CONFIG_CPU_R3000 +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) lw k0, GDB_FR_EPC(sp) lw sp, GDB_FR_REG29(sp) /* Deallocate stack */ jr k0 Index: setup.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/kernel/setup.c,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- setup.c 2001/10/22 19:16:44 1.22 +++ setup.c 2001/10/24 23:32:54 1.23 @@ -203,6 +203,12 @@ mips_cpu.dcache.ways = 2; #endif break; + case PRID_IMP_R4300: + mips_cpu.cputype = CPU_R4300; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; + mips_cpu.tlbsize = 32; + break; case PRID_IMP_R4600: mips_cpu.cputype = CPU_R4600; mips_cpu.isa_level = MIPS_CPU_ISA_III; @@ -237,9 +243,23 @@ mips_cpu.tlbsize = 64; break; case PRID_REV_TX3927: - mips_cpu.cputype = CPU_TX3927; + case PRID_REV_TX3927B: + /* check core-mode */ + if ((*(volatile u32 *)0xfffee004 >> 16) == 0x3927) + mips_cpu.cputype = CPU_TX3927; + else + mips_cpu.cputype = CPU_TX39XX; mips_cpu.tlbsize = 64; + mips_cpu.icache.ways = 2; + mips_cpu.dcache.ways = 2; break; + case PRID_REV_TX39H3TEG: + /* support core-mode only */ + mips_cpu.cputype = CPU_TX39XX; + mips_cpu.tlbsize = 32; + mips_cpu.icache.ways = 2; + mips_cpu.dcache.ways = 2; + break; default: mips_cpu.cputype = CPU_UNKNOWN; break; @@ -252,6 +272,15 @@ MIPS_CPU_32FPR; mips_cpu.tlbsize = 48; break; + case PRID_IMP_TX49: + mips_cpu.cputype = CPU_TX49XX; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | + MIPS_CPU_32FPR; + mips_cpu.tlbsize = 48; + mips_cpu.icache.ways = 4; + mips_cpu.dcache.ways = 4; + break; case PRID_IMP_R5000: mips_cpu.cputype = CPU_R5000; mips_cpu.isa_level = MIPS_CPU_ISA_IV; @@ -872,6 +901,12 @@ { unsigned long cfg = read_32bit_cp0_register(CP0_CONF); write_32bit_cp0_register(CP0_CONF, cfg|CONF_HALT); +} + +void r39xx_wait(void) +{ + unsigned long cfg = read_32bit_cp0_register(CP0_CONF); + write_32bit_cp0_register(CP0_CONF, cfg|TX39_CONF_HALT); } void r4k_wait(void) Index: traps.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/kernel/traps.c,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- traps.c 2001/10/23 17:20:14 1.21 +++ traps.c 2001/10/24 23:32:54 1.22 @@ -695,6 +695,14 @@ return; bad_cid: +#ifndef CONFIG_CPU_HAS_LLSC + switch (mips_cpu.cputype) { + case CPU_TX3927: + case CPU_TX39XX: + do_ri(regs); + return; + } +#endif compute_return_epc(regs); force_sig(SIGILL, current); } @@ -956,6 +964,7 @@ case CPU_TX3912: case CPU_TX3922: case CPU_TX3927: + case CPU_TX39XX: save_fp_context = _save_fp_context; restore_fp_context = _restore_fp_context; memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); @@ -964,6 +973,10 @@ case CPU_UNKNOWN: default: panic("Unknown CPU type"); + } + if (!(mips_cpu.options & MIPS_CPU_FPU)) { + save_fp_context = fpu_emulator_save_context; + restore_fp_context = fpu_emulator_restore_context; } flush_icache_range(KSEG0, KSEG0 + 0x200); |
From: James S. <jsi...@us...> - 2001-10-24 23:32:57
|
Update of /cvsroot/linux-mips/linux/arch/mips In directory usw-pr-cvs1:/tmp/cvs-serv28848/arch/mips Modified Files: Makefile config.in Log Message: Improved support for Toshiba TX39/TX49 series. Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/Makefile,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- Makefile 2001/10/10 17:46:56 1.22 +++ Makefile 2001/10/24 23:32:54 1.23 @@ -52,6 +52,9 @@ ifdef CONFIG_CPU_R3000 GCCFLAGS += -mcpu=r3000 -mips1 endif +ifdef CONFIG_CPU_TX39XX +GCCFLAGS += -mcpu=r3000 -mips1 +endif ifdef CONFIG_CPU_R6000 GCCFLAGS += -mcpu=r6000 -mips2 -Wa,--trap endif @@ -62,6 +65,9 @@ GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_R4X00 +GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap +endif +ifdef CONFIG_CPU_TX49XX GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_MIPS32 Index: config.in =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/config.in,v retrieving revision 1.34 retrieving revision 1.35 diff -u -d -r1.34 -r1.35 --- config.in 2001/10/17 06:33:14 1.34 +++ config.in 2001/10/24 23:32:54 1.35 @@ -299,10 +299,12 @@ choice 'CPU type' \ "R3000 CONFIG_CPU_R3000 \ + R39XX CONFIG_CPU_TX39XX \ R6000 CONFIG_CPU_R6000 \ R41xx CONFIG_CPU_VR41XX \ R4300 CONFIG_CPU_R4300 \ R4x00 CONFIG_CPU_R4X00 \ + R49XX CONFIG_CPU_TX49XX \ R5000 CONFIG_CPU_R5000 \ R5432 CONFIG_CPU_R5432 \ R5900 CONFIG_CPU_R5900 \ |
From: James S. <jsi...@us...> - 2001-10-24 22:16:12
|
Update of /cvsroot/linux-mips/linux/arch/mips/cobalt In directory usw-pr-cvs1:/tmp/cvs-serv11010 Modified Files: pci.c Log Message: Brought back old code as a reference. No longer used. Index: pci.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/pci.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- pci.c 2001/10/23 23:01:44 1.5 +++ pci.c 2001/10/24 22:16:10 1.6 @@ -17,8 +17,389 @@ #ifdef CONFIG_PCI -extern struct pci_ops qube_pci_ops; +#define SELF 0 + +static void qube_expansion_slot_bist(void) +{ + unsigned char ctrl; + int timeout = 100000; + + pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl); + if(!(ctrl & PCI_BIST_CAPABLE)) + return; + + pcibios_write_config_byte(0, (0x0a<<3), PCI_BIST, ctrl|PCI_BIST_START); + do { + pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl); + if(!(ctrl & PCI_BIST_START)) + break; + } while(--timeout > 0); + if((timeout <= 0) || (ctrl & PCI_BIST_CODE_MASK)) + printk("PCI: Expansion slot card failed BIST with code %x\n", + (ctrl & PCI_BIST_CODE_MASK)); +} + +static void qube_expansion_slot_fixup(void) +{ + unsigned short pci_cmd; + unsigned long ioaddr_base = 0x10108000; /* It's magic, ask Doug. */ + unsigned long memaddr_base = 0x12000000; + int i; + + /* Enable bits in COMMAND so driver can talk to it. */ + pcibios_read_config_word(0, (0x0a<<3), PCI_COMMAND, &pci_cmd); + pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pcibios_write_config_word(0, (0x0a<<3), PCI_COMMAND, pci_cmd); + + /* Give it a working IRQ. */ + pcibios_write_config_byte(0, (0x0a<<3), PCI_INTERRUPT_LINE, 9); + + /* Fixup base addresses, we only support I/O at the moment. */ + for(i = 0; i <= 5; i++) { + unsigned int regaddr = (PCI_BASE_ADDRESS_0 + (i * 4)); + unsigned int rval, mask, size, alignme, aspace; + unsigned long *basep = &ioaddr_base; + + /* Check type first, punt if non-IO. */ + pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval); + aspace = (rval & PCI_BASE_ADDRESS_SPACE); + if(aspace != PCI_BASE_ADDRESS_SPACE_IO) + basep = &memaddr_base; + + /* Figure out how much it wants, if anything. */ + pcibios_write_config_dword(0, (0x0a<<3), regaddr, 0xffffffff); + pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval); + + /* Unused? */ + if(rval == 0) + continue; + + rval &= PCI_BASE_ADDRESS_IO_MASK; + mask = (~rval << 1) | 0x1; + size = (mask & rval) & 0xffffffff; + alignme = size; + if(alignme < 0x400) + alignme = 0x400; + rval = ((*basep + (alignme - 1)) & ~(alignme - 1)); + *basep = (rval + size); + pcibios_write_config_dword(0,(0x0a<<3), regaddr, rval | aspace); + } + qube_expansion_slot_bist(); +} + +#define DEFAULT_BMIBA 0xcc00 /* in case ROM did not init it */ + +static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) +{ + unsigned short cfgword; + unsigned char lt; + unsigned int bmiba; + int try_again = 1; + + /* Enable Bus Mastering and fast back to back. */ + pci_read_config_word(dev, PCI_COMMAND, &cfgword); + cfgword |= (PCI_COMMAND_FAST_BACK | PCI_COMMAND_MASTER); + pci_write_config_word(dev, PCI_COMMAND, cfgword); + + /* Enable interfaces. ROM only enables primary one. */ + { +#ifdef CONFIG_BLK_DEV_COBALT_SECONDARY + unsigned char iface_enable = 0xb; +#else + unsigned char iface_enable = 0xa; +#endif + pci_write_config_byte(dev, 0x40, iface_enable); + } + + /* Set latency timer to reasonable value. */ + pci_read_config_byte(dev, PCI_LATENCY_TIMER, <); + if (lt < 64) + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); + + /* Get the bmiba base address. */ + do { + pci_read_config_dword(dev, 0x20, &bmiba); + bmiba &= 0xfff0; /* extract port base address */ + if (bmiba) { + break; + } else { + printk("ide: BM-DMA base register is invalid (0x%08x)\n",bmiba); + if (inb(DEFAULT_BMIBA) != 0xff || !try_again) + break; + printk("ide: setting BM-DMA base register to 0x%08x\n",DEFAULT_BMIBA); + pci_write_config_dword(dev, 0x20, DEFAULT_BMIBA|1); + } + } while (try_again--); + + bmiba += 0x10000000; + + dev->resource[4].start = bmiba; +} + +static void qube_raq_tulip_fixup(struct pci_dev *dev) +{ + unsigned short pci_cmd; + extern int cobalt_is_raq; + unsigned int tmp; + + /* Fixup the first tulip located at device PCICONF_ETH0 */ + if (dev->devfn == PCI_DEVSHFT(COBALT_PCICONF_ETH0)) { + /* + * Now tell the Ethernet device that we expect an interrupt at + * IRQ 13 and not the default 189. + * + * The IRQ of the first Tulip is different on Qube and RaQ + * hardware except for the weird first RaQ bringup board, + */ + if (! cobalt_is_raq) { + /* All Qube's route this the same way. */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + COBALT_ETHERNET_IRQ); + } else { + /* Setup the first Tulip on the RAQ */ +#ifndef RAQ_BOARD_1_WITH_HWHACKS + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 4); +#else + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 13); +#endif + } + /* Fixup the second tulip located at device PCICONF_ETH1 */ + } else if (dev->devfn == PCI_DEVSHFT(COBALT_PCICONF_ETH1)) { + /* XXX Check for the second Tulip on the RAQ(Already got it!) */ + pci_read_config_dword(dev, PCI_VENDOR_ID, &tmp); + if(tmp == 0xffffffff || tmp == 0x00000000) + return; + + /* Enable the second Tulip device. */ + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); + pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER); + pci_write_config_word(dev, PCI_COMMAND, pci_cmd); + + /* Give it it's IRQ. */ + /* NOTE: RaQ board #1 has a bunch of green wires which swapped + * the IRQ line values of Tulip 0 and Tulip 1. All other + * boards have eth0=4,eth1=13. -DaveM + */ +#ifndef RAQ_BOARD_1_WITH_HWHACKS + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 13); +#else + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 4); +#endif + /* And finally, a usable I/O space allocation, right after what + * the first Tulip uses. + */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x10101001); + } +} + +static void qube_raq_scsi_fixup(struct pci_dev *dev) +{ + unsigned short pci_cmd; + extern int cobalt_is_raq; + unsigned int tmp; + + /* + * Tell the SCSI device that we expect an interrupt at + * IRQ 7 and not the default 0. + */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, COBALT_SCSI_IRQ); + + if (cobalt_is_raq) { + /* Check for the SCSI on the RAQ */ + pci_read_config_dword(dev, PCI_VENDOR_ID, &tmp); + if(tmp == 0xffffffff || tmp == 0x00000000) + return; + /* Enable the device. */ + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); + + pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_INVALIDATE); + pci_write_config_word(dev, PCI_COMMAND, pci_cmd); + + /* Give it it's IRQ. */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 4); + + /* And finally, a usable I/O space allocation, right after what + * the second Tulip uses. + */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x10102001); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0x00002000); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, 0x00100000); + } +} + +static void qube_raq_galileo_fixup(struct pci_dev *dev) +{ + unsigned short galileo_id; + + /* Fix PCI latency-timer and cache-line-size values in Galileo + * host bridge. + */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); + + /* On all machines prior to Q2, we had the STOP line disconnected + * from Galileo to VIA on PCI. The new Galileo does not function + * correctly unless we have it connected. + * + * Therefore we must set the disconnect/retry cycle values to + * something sensible when using the new Galileo. + */ + pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id); + galileo_id &= 0xff; /* mask off class info */ + if (galileo_id == 0x10) { + /* New Galileo, assumes PCI stop line to VIA is connected. */ + *((volatile unsigned int *)0xb4000c04) = 0x00004020; + } else if (galileo_id == 0x1 || galileo_id == 0x2) { + unsigned int timeo; + /* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */ + timeo = *((volatile unsigned int *)0xb4000c04); + /* Old Galileo, assumes PCI STOP line to VIA is disconnected. */ + *((volatile unsigned int *)0xb4000c04) = 0x0000ffff; + } +} + +static void +qube_pcibios_fixup(struct pci_dev *dev) +{ + extern int cobalt_is_raq; + unsigned int tmp; + + + if (! cobalt_is_raq) { + /* See if there is a device in the expansion slot, if so + * fixup IRQ, fix base addresses, and enable master + + * I/O + memory accesses in config space. + */ + pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp); + if(tmp != 0xffffffff && tmp != 0x00000000) + qube_expansion_slot_fixup(); + } else { + /* And if we are a 2800 we have to setup the expansion slot + * too. + */ + pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp); + if(tmp != 0xffffffff && tmp != 0x00000000) + qube_expansion_slot_fixup(); + } +} + +struct pci_fixup pcibios_fixups[] = { + /* TBD:: Add each device here and divvy up pcibios_fixup */ + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, qube_raq_via_bmIDE_fixup }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, qube_raq_tulip_fixup }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID, qube_raq_galileo_fixup }, + /* Not sure about what scsi chips are available on the RAQ, put an + entry for all */ + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C860, qube_raq_scsi_fixup }, + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, qube_pcibios_fixup } +}; + +static __inline__ int pci_range_ck(struct pci_dev *dev) +{ + if ((dev->bus->number == 0) + && ((PCI_SLOT (dev->devfn) == 0) + || ((PCI_SLOT (dev->devfn) > 6) + && (PCI_SLOT (dev->devfn) <= 12)))) + return 0; /* OK device number */ + return -1; /* NOT ok device number */ +} + +#define PCI_CFG_DATA ((volatile unsigned long *)0xb4000cfc) +#define PCI_CFG_CTRL ((volatile unsigned long *)0xb4000cf8) + +#define PCI_CFG_SET(dev,where) \ + ((*PCI_CFG_CTRL) = (0x80000000 | (PCI_SLOT ((dev)->devfn) << 11) | \ + (PCI_FUNC ((dev)->devfn) << 8) | (where))) + +static int qube_pci_read_config_dword(struct pci_dev *dev, int where, u32 *val) +{ + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck (dev)) { + *val = 0xFFFFFFFF; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(dev, where); + *val = *PCI_CFG_DATA; + return PCIBIOS_SUCCESSFUL; +} + +static int qube_pci_read_config_word(struct pci_dev *dev, int where, u16 *val) +{ + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck (dev)) { + *val = 0xffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(dev, (where & ~0x3)); + *val = *PCI_CFG_DATA >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +static int qube_pci_read_config_byte(struct pci_dev *dev, int where, u8 *val) +{ + if (pci_range_ck (dev)) { + *val = 0xff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(dev, (where & ~0x3)); + *val = *PCI_CFG_DATA >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +static int qube_pci_write_config_dword(struct pci_dev *dev, int where, u32 val) +{ + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck (dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(dev, where); + *PCI_CFG_DATA = val; + return PCIBIOS_SUCCESSFUL; +} + +static int qube_pci_write_config_word(struct pci_dev *dev, int where, u16 val) +{ + unsigned long tmp; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck (dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(dev, (where & ~0x3)); + tmp = *PCI_CFG_DATA; + tmp &= ~(0xffff << ((where & 0x3) * 8)); + tmp |= (val << ((where & 0x3) * 8)); + *PCI_CFG_DATA = tmp; + return PCIBIOS_SUCCESSFUL; +} + +static int qube_pci_write_config_byte(struct pci_dev *dev, int where, u8 val) +{ + unsigned long tmp; + + if (pci_range_ck (dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(dev, (where & ~0x3)); + tmp = *PCI_CFG_DATA; + tmp &= ~(0xff << ((where & 0x3) * 8)); + tmp |= (val << ((where & 0x3) * 8)); + *PCI_CFG_DATA = tmp; + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops qube_pci_ops = { + qube_pci_read_config_byte, + qube_pci_read_config_word, + qube_pci_read_config_dword, + qube_pci_write_config_byte, + qube_pci_write_config_word, + qube_pci_write_config_dword +}; + void __init pcibios_init(void) { printk("PCI: Probing PCI hardware\n"); @@ -60,5 +441,10 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) { /* We don't appear to have sub-busses to fixup here */ +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; } #endif /* CONFIG_PCI */ |
From: James S. <jsi...@us...> - 2001-10-24 21:43:36
|
Update of /cvsroot/linux-mips/linux/arch/mips/kernel In directory usw-pr-cvs1:/tmp/cvs-serv1201 Modified Files: Makefile entry.S Log Message: Fix assembler flags and .set mipsX statements. Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/kernel/Makefile,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- Makefile 2001/10/22 19:16:44 1.9 +++ Makefile 2001/10/24 21:43:33 1.10 @@ -11,8 +11,6 @@ .S.o: $(CC) $(AFLAGS) -c $< -o $@ -EXTRA_AFLAGS = -mips3 -mcpu=r4000 - all: kernel.o head.o init_task.o O_TARGET := kernel.o Index: entry.S =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/kernel/entry.S,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- entry.S 2001/10/22 19:16:44 1.7 +++ entry.S 2001/10/24 21:43:33 1.8 @@ -118,7 +118,6 @@ END(except_vec1_generic) NESTED(except_vec3_generic, 0, sp) - .set mips0 mfc0 k1, CP0_CAUSE la k0, exception_handlers andi k1, k1, 0x7c @@ -130,6 +129,7 @@ /* General exception vector R4000 version. */ NESTED(except_vec3_r4000, 0, sp) + .set mips3 .set noat mfc0 k1, CP0_CAUSE andi k1, k1, 0x7c @@ -150,7 +150,6 @@ * line pointed to by c0_badvaddr because after return from * this exception handler the load / store will be re-executed. */ - .set mips3 handle_vced: mfc0 k0, CP0_BADVADDR li k1, -4 @@ -176,7 +175,7 @@ sw k1, %lo(vcei_count)(k0) #endif eret - + .set mips0 END(except_vec3_r4000) __FINIT |
From: James S. <jsi...@us...> - 2001-10-24 21:41:35
|
Update of /cvsroot/linux-mips/linux/arch/mips/cobalt In directory usw-pr-cvs1:/tmp/cvs-serv715 Modified Files: pci_ops.c Log Message: Fixed a Oops. The new pci code expects a IO and MEM PCI spcae. The Qube at present only supports IO space :-(. So I had to add in a dummy MEM space to prevent it from crashing. WARNING: The code is at present broken with the new pci stuff Index: pci_ops.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/pci_ops.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- pci_ops.c 2001/10/24 16:32:36 1.3 +++ pci_ops.c 2001/10/24 21:41:32 1.4 @@ -56,6 +56,13 @@ IORESOURCE_IO }; +static struct resource pci_mem_resource = { + "pci memory space", + 0, + 0, + IORESOURCE_MEM +}; + extern struct pci_ops qube_pci_ops; /* @@ -68,7 +75,7 @@ * to limit the scan. */ struct pci_channel mips_pci_channels[] = { - { &qube_pci_ops, &pci_io_resource, NULL, 0, 0xFF }, + { &qube_pci_ops, &pci_io_resource, &pci_mem_resource, 0, 0xFF }, { NULL, NULL, NULL, NULL, NULL} }; |
From: James S. <jsi...@us...> - 2001-10-24 18:53:32
|
Update of /cvsroot/linux-mips/linux/arch/mips/cobalt In directory usw-pr-cvs1:/tmp/cvs-serv22960 Modified Files: Makefile pci_fixups.c Log Message: Further approach to new pci code. Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/Makefile,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- Makefile 2001/10/23 23:01:44 1.5 +++ Makefile 2001/10/24 18:53:29 1.6 @@ -16,7 +16,7 @@ O_TARGET := cobalt.o -obj-y += rtc_qube.o irq.o int-handler.o pci.o pci_fixups.o pci_ops.o \ +obj-y += rtc_qube.o irq.o int-handler.o pci_fixups.o pci_ops.o \ reset.o setup.o via.o promcon.o ide.o include $(TOPDIR)/Rules.make Index: pci_fixups.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/pci_fixups.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- pci_fixups.c 2001/10/23 23:01:44 1.1 +++ pci_fixups.c 2001/10/24 18:53:29 1.2 @@ -309,17 +309,6 @@ } } -struct pci_fixup pcibios_fixups[] = { - /* TBD:: Add each device here and divvy up pcibios_fixup */ - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, qube_raq_via_bmIDE_fixup }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, qube_raq_tulip_fixup }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID, qube_raq_galileo_fixup }, - /* Not sure about what scsi chips are available on the RAQ, put an - entry for all */ - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C860, qube_raq_scsi_fixup }, - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, qube_pcibios_fixup } -}; - /* * Fixup your resources here, if necessary. *Usually* you * don't have to do anything here. @@ -328,6 +317,11 @@ void __init pcibios_fixup_resources(struct pci_dev *dev) { /* will need to fixup IO resources */ + qube_raq_via_bmIDE_fixup(dev); + qube_raq_tulip_fixup(dev); + qube_raq_galileo_fixup(dev); + qube_raq_scsi_fixup(dev); + qube_pcibios_fixup(dev); } /* @@ -375,6 +369,6 @@ unsigned int pcibios_assign_all_busses(void) { - return 0; + return 1; } #endif |
From: Paul M. <le...@us...> - 2001-10-24 16:39:38
|
Update of /cvsroot/linux-mips/linux/drivers/char In directory usw-pr-cvs1:/tmp/cvs-serv17679 Modified Files: Config.in Log Message: Make the description consistent with the Configure.help entry. Index: Config.in =================================================================== RCS file: /cvsroot/linux-mips/linux/drivers/char/Config.in,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- Config.in 2001/10/24 05:28:03 1.12 +++ Config.in 2001/10/24 16:39:35 1.13 @@ -177,7 +177,7 @@ fi fi tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT - dep_tristate ' VR41xx Watchdog (DSU)' CONFIG_VR41XX_WDT $CONFIG_CPU_VR41XX + dep_tristate ' NEC VR41xx Watchdog (DSU)' CONFIG_VR41XX_WDT $CONFIG_CPU_VR41XX fi endmenu |
From: James S. <jsi...@us...> - 2001-10-24 16:32:42
|
Update of /cvsroot/linux-mips/linux/arch/mips/cobalt In directory usw-pr-cvs1:/tmp/cvs-serv15236 Modified Files: pci_ops.c Log Message: Cobalt only uses PCI IO space, not MEM space. Index: pci_ops.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/cobalt/pci_ops.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- pci_ops.c 2001/10/23 21:52:05 1.2 +++ pci_ops.c 2001/10/24 16:32:36 1.3 @@ -46,22 +46,14 @@ #define DBG(x...) #endif -#define MEM_BASE 0x12000000 -#define MEM_SIZE 0x02000000 -#define IO_BASE 0x10000000 -#define IO_SIZE 0x02000000 +#define IO_BASE 0x00000000 +#define IO_SIZE 0x1CFFFFFF static struct resource pci_io_resource = { "pci IO space", IO_BASE, IO_BASE + IO_SIZE, - IORESOURCE_IO}; - -static struct resource pci_mem_resource = { - "pci memory space", - MEM_BASE, - MEM_BASE + MEM_SIZE, - IORESOURCE_MEM + IORESOURCE_IO }; extern struct pci_ops qube_pci_ops; @@ -76,7 +68,7 @@ * to limit the scan. */ struct pci_channel mips_pci_channels[] = { - { &qube_pci_ops, &pci_io_resource, &pci_mem_resource, 0, 0xff }, + { &qube_pci_ops, &pci_io_resource, NULL, 0, 0xFF }, { NULL, NULL, NULL, NULL, NULL} }; |
From: Paul M. <le...@us...> - 2001-10-24 05:40:47
|
Update of /cvsroot/linux-mips/linux/Documentation In directory usw-pr-cvs1:/tmp/cvs-serv24847 Modified Files: Configure.help Log Message: Add CONFIG_VR41XX_WDT documentation. Index: Configure.help =================================================================== RCS file: /cvsroot/linux-mips/linux/Documentation/Configure.help,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- Configure.help 2001/10/24 05:34:58 1.1 +++ Configure.help 2001/10/24 05:40:44 1.2 @@ -14777,6 +14777,20 @@ The module is called machzwd.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +NEC VR41xx Watchdog (DSU) +CONFIG_VR41XX_WDT + This is a driver for the hardware watchdog integrated in the NEC VR41xx + family of microprocessors. (Also referred to as a DSU, or "Deadman's + Switch Unit" in NEC literature). If you want your processor to be reset + when it becomes unresponsive for a duration of time, say Y here, + otherwise N. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called vr41xxwdt.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Most people + will say N. + Toshiba Laptop support CONFIG_TOSHIBA This adds a driver to safely access the System Management Mode |
From: Paul M. <le...@us...> - 2001-10-24 05:35:00
|
Update of /cvsroot/linux-mips/linux/Documentation In directory usw-pr-cvs1:/tmp/cvs-serv23122 Added Files: Configure.help Log Message: Initial import of Configure.help. --- NEW FILE: Configure.help --- # Maintained by Axel Boldt (ax...@un...) # # This version of the Linux kernel configuration help texts # corresponds to the kernel versions 2.4.x. # # Translations of this file available on the WWW: # # - Japanese, maintained by the JF Project (JF...@li...), at # http://www.linux.or.jp/JF/JFdocs/Configure.help/ # - Russian, by ka...@li..., at # http://nevod.perm.su/service/linux/doc/kernel/Configure.help # - French, by Pierre Tane (ta...@bi...), at # http://www.traduc.org/kernelfr # - Spanish, by Carlos Perelló Marín (fp...@eh...), at # http://visar.csustan.edu/~carlos/ # XXX: Site has moved, new location has no Configure.help trans. # - Italian, by Alessandro Rubini (ru...@li...), at # ftp://ftp-pavia1.linux.it/pub/linux/Configure.help # XXX: ftp-pavia1.linux.it: Non-existent host/domain [...19055 lines suppressed...] # LocalWords: CHDLC UPS's usbmouse wacom wmforce keybdev joydev fibre Trunking # LocalWords: Etherchannel IOC Moxa Intellio moxa SmartIO mxser Mixcom EFI ir # LocalWords: MIXCOMWD mixcomwd SENDCOMPLETE GMAC iBook gmac OAKNET oaknet PCG # LocalWords: diffserv irlan irtty toshoboe IrCC Lifebook idex AUTODMA FIP Cxx # LocalWords: Yenta Databook TCIC FMVJ fmvj NMCLAN LiveWire nmclan XIRC xirc # LocalWords: loadkeys setfont shm SuperIO soc SOCAL socal FCAL fc fcal COMX # LocalWords: MultiGate ITConsult comx CMX HiCOMX downloadable hw LoCOMX PROTO # LocalWords: locomx MixCOM mixcom proto MyriCOM MYRI Sbus myri sbus IBMLS hme # LocalWords: lanstreamer baseT HAPPYMEAL qfe sunhme SUNLANCE sunlance BigMAC # LocalWords: SUNBMAC sunbmac QuadEthernet SUNQE qe FastEthernet sunqe DSB PTI # LocalWords: DSBR dsbr procinfo QLOGICPTI qpti ptisp QLGC qlogicpti se LBA NF # LocalWords: OPENPROMFS OpenPROM openpromfs OBP OpenBoot flashable Multiboard # LocalWords: SPARCAUDIO SparcClassic Ultras DBRI Sparcbook sparcaudio SUNBPP # LocalWords: UltraDMA WDC CRC CONNTRACK IPTABLES iptables nfmark interface's # LocalWords: tdfxfb TNTx HGA hgafb VERBOSEDEBUG SunTrunking SunSoft XIRTULIP # LocalWords: ethercards PNIC Macronix MXIC ASIX xircom Mustek MDC gphoto mdc # LocalWords: CramFs Cramfs uid cramfs AVM's kernelcapi PCIV cdrdao Cdparanoia # LocalWords: DMX Domex dmx wellington ftdi sio Accton Billington Corega FEter # LocalWords: MELCO LUA PNA Linksys SNC chkdsk AWACS Webcam RAMFS Ramfs ramfs # LocalWords: ramfiles MAKEDEV pty WDTPCI APA apa |
From: Paul M. <le...@us...> - 2001-10-24 05:30:41
|
Update of /cvsroot/linux-mips/linux In directory usw-pr-cvs1:/tmp/cvs-serv21871 Modified Files: Makefile Log Message: Oops.. wasn't supposed to commit that. Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/Makefile,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- Makefile 2001/10/24 05:28:03 1.7 +++ Makefile 2001/10/24 05:30:37 1.8 @@ -18,7 +18,7 @@ HOSTCC = gcc HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -CROSS_COMPILE = /opt/hardhat/devkit/mips/fp_le/bin/mips_fp_le- +CROSS_COMPILE = # # Include the make variables (CC, etc...) |
From: Paul M. <le...@us...> - 2001-10-24 05:28:06
|
Update of /cvsroot/linux-mips/linux/drivers/char In directory usw-pr-cvs1:/tmp/cvs-serv20456/drivers/char Modified Files: Config.in Makefile Added Files: vr41xxwdt.c Log Message: Added a watchdog driver for the vr41xx family. --- NEW FILE: vr41xxwdt.c --- /* * drivers/char/vr41xxwdt.c * * Watchdog driver for integrated watchdog in the NEC VR41xx processors. * * Copyright (C) 2001 Paul Mundt <le...@ch...> * * 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. */ #include <linux/config.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/reboot.h> #include <linux/notifier.h> #include <linux/smp_lock.h> #include <linux/ioport.h> #include <linux/fs.h> #include <asm/io.h> #include <asm/uaccess.h> #define __preg16(addr) (volatile unsigned short *)(KSEG1 + addr) #if defined(CONFIG_VR4111) || defined(CONFIG_VR4121) || defined(CONFIG_VR4181) #define DSUCNTREG __preg16(0x0b0000e0) /* DSU Control Register */ #define DSUSETREG __preg16(0x0b0000e2) /* DSU Dead Time Set Register */ #define DSUCLRREG __preg16(0x0b0000e4) /* DSU Clear Register */ #define DSUTIMREG __preg16(0x0b0000e6) /* DSU Elapsed Time Register */ #elif defined(CONFIG_VR4122) #define DSUCNTREG __preg16(0x0f0000e0) /* DSU Control Register */ #define DSUSETREG __preg16(0x0f0000e2) /* DSU Dead Time Set Register */ #define DSUCLRREG __preg16(0x0f0000e4) /* DSU Clear Register */ #define DSUTIMREG __preg16(0x0f0000e6) /* DSU Elapsed Time Register */ #else #error "Can't use VR41xx watchdog on non-VR41xx processor." #endif #define DSUMINOVRFLW 0x01 /* DSU Min Overflow Interval */ #define DSUMAXOVRFLW 0x0f /* DSU Max Overflow Interval */ /* * Allow the next heartbeat a little bit of time, since the request comes from * the userspace daemon. A heartbeat value 2x that of the timer overflow * period should be suffecient. */ #define DSUTMRINTRVL (jiffies + (HZ * nsecs))/* DSU Timer Interval */ #define DSUHEARTBEAT (DSUTMRINTRVL * 2) /* Next Heartbeat */ static int vr41xx_wdt_is_open = 0; static struct watchdog_info vr41xx_wdt_info; static struct timer_list timer; static unsigned long next_heartbeat; static unsigned int nsecs = 7; /* Default overflow period */ /** * vr41xx_wdt_start - Start the Watchdog * * Starts the watchdog. */ static void vr41xx_wdt_start(void) { /* Sanity checks */ if (nsecs < DSUMINOVRFLW) nsecs = DSUMINOVRFLW; if (nsecs > DSUMAXOVRFLW) nsecs = DSUMAXOVRFLW; timer.expires = DSUTMRINTRVL; next_heartbeat = DSUHEARTBEAT; add_timer(&timer); /* Clear the counter */ writew(0x01, DSUCLRREG); /* Set the overflow period (in seconds) */ writew(nsecs, DSUSETREG); /* Turn on the watchdog */ writew(0x01, DSUCNTREG); } /** * vr41xx_wdt_stop - Stop the Watchdog * * Stops the watchdog. */ static void vr41xx_wdt_stop(void) { del_timer(&timer); /* Clear the counter */ writew(0x01, DSUCLRREG); /* Turn off the watchdog */ writew(0x00, DSUCNTREG); } /** * vr41xx_wdt_ping - Ping the Watchdog * * @data: Unused * * Clears DSU counter and updates timer. */ static void vr41xx_wdt_ping(unsigned long data) { if (time_before(jiffies, next_heartbeat)) { /* Clear overflow counter */ writew(0x01, DSUCLRREG); /* Update timer */ timer.expires = DSUTMRINTRVL; add_timer(&timer); } } /** * vr41xx_wdt_open - Open the Device * * @inode: inode of device * @file: file handle of device * * Watchdog device is opened and started. */ static int vr41xx_wdt_open(struct inode *inode, struct file *file) { switch (MINOR(inode->i_rdev)) { case WATCHDOG_MINOR: if (vr41xx_wdt_is_open) return -EBUSY; vr41xx_wdt_is_open = 1; vr41xx_wdt_start(); break; default: return -ENODEV; } return 0; } /** * vr41xx_wdt_close - Close the Device * * @inode: inode of device * @file: file handle of device * * Watchdog is closed and stopped. */ static int vr41xx_wdt_close(struct inode *inode, struct file *file) { lock_kernel(); if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { #ifndef CONFIG_WATCHDOG_NOWAYOUT vr41xx_wdt_stop(); #endif vr41xx_wdt_is_open = 0; } unlock_kernel(); return 0; } /** * vr41xx_wdt_read - Read from Device * * @file: file handle of device * @buf: buffer to write to * @count: length of buffer * @ppos: offset * * Unsupported. */ static ssize_t vr41xx_wdt_read(struct file *file, char *buf, size_t count, loff_t *ppos) { return -EINVAL; } /** * vr41xx_wdt_write - Write to Device * * @file: file handle of device * @buf: buffer to write * @count: length of buffer * @ppos: offset * * Updates next heartbeat interval on write. */ static ssize_t vr41xx_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { /* Can't seek (pwrite) on this device */ if (ppos != &file->f_pos) return -ESPIPE; if (count) { next_heartbeat = DSUHEARTBEAT; return 1; } return 0; } /** * vr41xx_wdt_ioctl - Query Device * * @inode: inode of device * @file: file handle of device * @cmd: watchdog command * @arg: argument * * Query basic information from the device or ping it, as outlined by the * watchdog API. */ static int vr41xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user((struct watchdog_info *)arg, &vr41xx_wdt_info, sizeof(vr41xx_wdt_info)) ? -EFAULT : 0; case WDIOC_GETSTATUS: return copy_to_user((int *)arg, &vr41xx_wdt_is_open, sizeof(int)) ? -EFAULT : 0; case WDIOC_KEEPALIVE: next_heartbeat = DSUHEARTBEAT; break; default: return -ENOTTY; } return 0; } /** * vr41xx_wdt_notify_sys - Notifier Handler * * @this: notifier block * @code: notifier event * @unused: unused. * * Handles specific events, such as turning off the watchdog during a * shutdown event. */ static int vr41xx_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) vr41xx_wdt_stop(); return NOTIFY_DONE; } static struct file_operations vr41xx_wdt_fops = { owner: THIS_MODULE, read: vr41xx_wdt_read, write: vr41xx_wdt_write, ioctl: vr41xx_wdt_ioctl, open: vr41xx_wdt_open, release: vr41xx_wdt_close, }; static struct watchdog_info vr41xx_wdt_info = { WDIOF_KEEPALIVEPING, 1, "VR41xx WDT", }; static struct notifier_block vr41xx_wdt_notifier = { vr41xx_wdt_notify_sys, NULL, 0 }; static struct miscdevice vr41xx_wdt_miscdev = { WATCHDOG_MINOR, "watchdog", &vr41xx_wdt_fops, }; /** * vr41xx_wdt_init - Initialize module * * Registers the device, reserves register region, and registers the * notifier handler. Actual device initialization is handled by * vr41xx_wdt_open(). */ static int __init vr41xx_wdt_init(void) { if (misc_register(&vr41xx_wdt_miscdev)) { printk(KERN_ERR "vr41xx wdt: Can't register misc device\n"); return -EINVAL; } if (!request_region((unsigned long)DSUCNTREG, 8, "vr41xxwdt")) { printk(KERN_ERR "vr41xx wdt: Can't request DSU register region\n"); misc_deregister(&vr41xx_wdt_miscdev); return -ENXIO; } if (register_reboot_notifier(&vr41xx_wdt_notifier)) { printk(KERN_ERR "vr41xx wdt: Can't register reboot notifier\n"); release_region((unsigned long)DSUCNTREG, 8); misc_deregister(&vr41xx_wdt_miscdev); return -EINVAL; } init_timer(&timer); timer.function = vr41xx_wdt_ping; timer.data = 0; return 0; } /** * vr41xx_wdt_exit - Deinitialize module * * Unregisters the device, releases reserved register region, and * deregisters the notifier handler. Actual device deinitialization is * handled by vr41xx_wdt_close(). */ static void __exit vr41xx_wdt_exit(void) { unregister_reboot_notifier(&vr41xx_wdt_notifier); release_region((unsigned long)DSUCNTREG, 8); misc_deregister(&vr41xx_wdt_miscdev); } EXPORT_NO_SYMBOLS; MODULE_AUTHOR("Paul Mundt <le...@ch...>"); MODULE_DESCRIPTION("NEC VR41xx watchdog driver"); MODULE_PARM(nsecs, "i"); MODULE_PARM_DESC(nsecs, "Number of seconds for overflow period. (1 - 15 seconds)."); MODULE_LICENSE("GPL"); module_init(vr41xx_wdt_init); module_exit(vr41xx_wdt_exit); Index: Config.in =================================================================== RCS file: /cvsroot/linux-mips/linux/drivers/char/Config.in,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- Config.in 2001/10/22 19:16:45 1.11 +++ Config.in 2001/10/24 05:28:03 1.12 @@ -177,6 +177,7 @@ fi fi tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT + dep_tristate ' VR41xx Watchdog (DSU)' CONFIG_VR41XX_WDT $CONFIG_CPU_VR41XX fi endmenu Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/drivers/char/Makefile,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- Makefile 2001/10/19 21:19:38 1.11 +++ Makefile 2001/10/24 05:28:03 1.12 @@ -237,7 +237,7 @@ obj-$(CONFIG_I810_TCO) += i810-tco.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o - +obj-$(CONFIG_VR41XX_WDT) += vr41xxwdt.c include $(TOPDIR)/Rules.make |