diff options
Diffstat (limited to 'arch/mips/tx4927/common')
-rw-r--r-- | arch/mips/tx4927/common/Makefile | 12 | ||||
-rw-r--r-- | arch/mips/tx4927/common/tx4927_dbgio.c | 47 | ||||
-rw-r--r-- | arch/mips/tx4927/common/tx4927_irq.c | 584 | ||||
-rw-r--r-- | arch/mips/tx4927/common/tx4927_irq_handler.S | 103 | ||||
-rw-r--r-- | arch/mips/tx4927/common/tx4927_prom.c | 146 | ||||
-rw-r--r-- | arch/mips/tx4927/common/tx4927_setup.c | 237 |
6 files changed, 1129 insertions, 0 deletions
diff --git a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile new file mode 100644 index 00000000000..8fa126b296e --- /dev/null +++ b/arch/mips/tx4927/common/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for common code for Toshiba TX4927 based systems +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o tx4927_irq_handler.o + +obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o +obj-$(CONFIG_KGDB) += tx4927_dbgio.o diff --git a/arch/mips/tx4927/common/tx4927_dbgio.c b/arch/mips/tx4927/common/tx4927_dbgio.c new file mode 100644 index 00000000000..09bdf2baa83 --- /dev/null +++ b/arch/mips/tx4927/common/tx4927_dbgio.c @@ -0,0 +1,47 @@ +/* + * linux/arch/mips/tx4927/common/tx4927_dbgio.c + * + * kgdb interface for gdb + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <asm/mipsregs.h> +#include <asm/system.h> +#include <asm/tx4927/tx4927_mips.h> + +u8 getDebugChar(void) +{ + extern u8 txx9_sio_kdbg_rd(void); + return (txx9_sio_kdbg_rd()); +} + + +int putDebugChar(u8 byte) +{ + extern int txx9_sio_kdbg_wr( u8 ch ); + return (txx9_sio_kdbg_wr(byte)); +} diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c new file mode 100644 index 00000000000..5ab2e2b7601 --- /dev/null +++ b/arch/mips/tx4927/common/tx4927_irq.c @@ -0,0 +1,584 @@ +/* + * Common tx4927 irq handler + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/config.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel_stat.h> +#include <linux/module.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/timex.h> +#include <linux/slab.h> +#include <linux/random.h> +#include <linux/irq.h> +#include <linux/bitops.h> +#include <asm/bootinfo.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/mipsregs.h> +#include <asm/system.h> +#include <asm/tx4927/tx4927.h> + +/* + * DEBUG + */ + +#undef TX4927_IRQ_DEBUG + +#ifdef TX4927_IRQ_DEBUG +#define TX4927_IRQ_NONE 0x00000000 + +#define TX4927_IRQ_INFO ( 1 << 0 ) +#define TX4927_IRQ_WARN ( 1 << 1 ) +#define TX4927_IRQ_EROR ( 1 << 2 ) + +#define TX4927_IRQ_INIT ( 1 << 5 ) +#define TX4927_IRQ_NEST1 ( 1 << 6 ) +#define TX4927_IRQ_NEST2 ( 1 << 7 ) +#define TX4927_IRQ_NEST3 ( 1 << 8 ) +#define TX4927_IRQ_NEST4 ( 1 << 9 ) + +#define TX4927_IRQ_CP0_INIT ( 1 << 10 ) +#define TX4927_IRQ_CP0_STARTUP ( 1 << 11 ) +#define TX4927_IRQ_CP0_SHUTDOWN ( 1 << 12 ) +#define TX4927_IRQ_CP0_ENABLE ( 1 << 13 ) +#define TX4927_IRQ_CP0_DISABLE ( 1 << 14 ) +#define TX4927_IRQ_CP0_MASK ( 1 << 15 ) +#define TX4927_IRQ_CP0_ENDIRQ ( 1 << 16 ) + +#define TX4927_IRQ_PIC_INIT ( 1 << 20 ) +#define TX4927_IRQ_PIC_STARTUP ( 1 << 21 ) +#define TX4927_IRQ_PIC_SHUTDOWN ( 1 << 22 ) +#define TX4927_IRQ_PIC_ENABLE ( 1 << 23 ) +#define TX4927_IRQ_PIC_DISABLE ( 1 << 24 ) +#define TX4927_IRQ_PIC_MASK ( 1 << 25 ) +#define TX4927_IRQ_PIC_ENDIRQ ( 1 << 26 ) + +#define TX4927_IRQ_ALL 0xffffffff +#endif + +#ifdef TX4927_IRQ_DEBUG +static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE + | TX4927_IRQ_INFO + | TX4927_IRQ_WARN | TX4927_IRQ_EROR +// | TX4927_IRQ_CP0_INIT +// | TX4927_IRQ_CP0_STARTUP +// | TX4927_IRQ_CP0_SHUTDOWN +// | TX4927_IRQ_CP0_ENABLE +// | TX4927_IRQ_CP0_DISABLE +// | TX4927_IRQ_CP0_MASK +// | TX4927_IRQ_CP0_ENDIRQ +// | TX4927_IRQ_PIC_INIT +// | TX4927_IRQ_PIC_STARTUP +// | TX4927_IRQ_PIC_SHUTDOWN +// | TX4927_IRQ_PIC_ENABLE +// | TX4927_IRQ_PIC_DISABLE +// | TX4927_IRQ_PIC_MASK +// | TX4927_IRQ_PIC_ENDIRQ +// | TX4927_IRQ_INIT +// | TX4927_IRQ_NEST1 +// | TX4927_IRQ_NEST2 +// | TX4927_IRQ_NEST3 +// | TX4927_IRQ_NEST4 + ); +#endif + +#ifdef TX4927_IRQ_DEBUG +#define TX4927_IRQ_DPRINTK(flag,str...) \ + if ( (tx4927_irq_debug_flag) & (flag) ) \ + { \ + char tmp[100]; \ + sprintf( tmp, str ); \ + printk( "%s(%s:%u)::%s", __FUNCTION__, __FILE__, __LINE__, tmp ); \ + } +#else +#define TX4927_IRQ_DPRINTK(flag,str...) +#endif + +/* + * Forwad definitions for all pic's + */ + +static unsigned int tx4927_irq_cp0_startup(unsigned int irq); +static void tx4927_irq_cp0_shutdown(unsigned int irq); +static void tx4927_irq_cp0_enable(unsigned int irq); +static void tx4927_irq_cp0_disable(unsigned int irq); +static void tx4927_irq_cp0_mask_and_ack(unsigned int irq); +static void tx4927_irq_cp0_end(unsigned int irq); + +static unsigned int tx4927_irq_pic_startup(unsigned int irq); +static void tx4927_irq_pic_shutdown(unsigned int irq); +static void tx4927_irq_pic_enable(unsigned int irq); +static void tx4927_irq_pic_disable(unsigned int irq); +static void tx4927_irq_pic_mask_and_ack(unsigned int irq); +static void tx4927_irq_pic_end(unsigned int irq); + +/* + * Kernel structs for all pic's + */ + +static DEFINE_SPINLOCK(tx4927_cp0_lock); +static DEFINE_SPINLOCK(tx4927_pic_lock); + +#define TX4927_CP0_NAME "TX4927-CP0" +static struct hw_interrupt_type tx4927_irq_cp0_type = { + .typename = TX4927_CP0_NAME, + .startup = tx4927_irq_cp0_startup, + .shutdown = tx4927_irq_cp0_shutdown, + .enable = tx4927_irq_cp0_enable, + .disable = tx4927_irq_cp0_disable, + .ack = tx4927_irq_cp0_mask_and_ack, + .end = tx4927_irq_cp0_end, + .set_affinity = NULL +}; + +#define TX4927_PIC_NAME "TX4927-PIC" +static struct hw_interrupt_type tx4927_irq_pic_type = { + .typename = TX4927_PIC_NAME, + .startup = tx4927_irq_pic_startup, + .shutdown = tx4927_irq_pic_shutdown, + .enable = tx4927_irq_pic_enable, + .disable = tx4927_irq_pic_disable, + .ack = tx4927_irq_pic_mask_and_ack, + .end = tx4927_irq_pic_end, + .set_affinity = NULL +}; + +#define TX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL } +static struct irqaction tx4927_irq_pic_action = +TX4927_PIC_ACTION(TX4927_PIC_NAME); + +#define CCP0_STATUS 12 +#define CCP0_CAUSE 13 + +/* + * Functions for cp0 + */ + +#define tx4927_irq_cp0_mask(irq) ( 1 << ( irq-TX4927_IRQ_CP0_BEG+8 ) ) + +static void +tx4927_irq_cp0_modify(unsigned cp0_reg, unsigned clr_bits, unsigned set_bits) +{ + unsigned long val = 0; + + switch (cp0_reg) { + case CCP0_STATUS: + val = read_c0_status(); + break; + + case CCP0_CAUSE: + val = read_c0_cause(); + break; + + } + + val &= (~clr_bits); + val |= (set_bits); + + switch (cp0_reg) { + case CCP0_STATUS:{ + write_c0_status(val); + break; + } + case CCP0_CAUSE:{ + write_c0_cause(val); + break; + } + } + + return; +} + +static void __init tx4927_irq_cp0_init(void) +{ + int i; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_INIT, "beg=%d end=%d\n", + TX4927_IRQ_CP0_BEG, TX4927_IRQ_CP0_END); + + for (i = TX4927_IRQ_CP0_BEG; i <= TX4927_IRQ_CP0_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &tx4927_irq_cp0_type; + } + + return; +} + +static unsigned int tx4927_irq_cp0_startup(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_STARTUP, "irq=%d \n", irq); + + tx4927_irq_cp0_enable(irq); + + return (0); +} + +static void tx4927_irq_cp0_shutdown(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_SHUTDOWN, "irq=%d \n", irq); + + tx4927_irq_cp0_disable(irq); + + return; +} + +static void tx4927_irq_cp0_enable(unsigned int irq) +{ + unsigned long flags; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENABLE, "irq=%d \n", irq); + + spin_lock_irqsave(&tx4927_cp0_lock, flags); + + tx4927_irq_cp0_modify(CCP0_STATUS, 0, tx4927_irq_cp0_mask(irq)); + + spin_unlock_irqrestore(&tx4927_cp0_lock, flags); + + return; +} + +static void tx4927_irq_cp0_disable(unsigned int irq) +{ + unsigned long flags; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_DISABLE, "irq=%d \n", irq); + + spin_lock_irqsave(&tx4927_cp0_lock, flags); + + tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0); + + spin_unlock_irqrestore(&tx4927_cp0_lock, flags); + + return; +} + +static void tx4927_irq_cp0_mask_and_ack(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_MASK, "irq=%d \n", irq); + + tx4927_irq_cp0_disable(irq); + + return; +} + +static void tx4927_irq_cp0_end(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENDIRQ, "irq=%d \n", irq); + + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + tx4927_irq_cp0_enable(irq); + } + + return; +} + +/* + * Functions for pic + */ +u32 tx4927_irq_pic_addr(int irq) +{ + /* MVMCP -- need to formulize this */ + irq -= TX4927_IRQ_PIC_BEG; + switch (irq) { + case 17: + case 16: + case 1: + case 0: + return (0xff1ff610); + + case 19: + case 18: + case 3: + case 2: + return (0xff1ff614); + + case 21: + case 20: + case 5: + case 4: + return (0xff1ff618); + + case 23: + case 22: + case 7: + case 6: + return (0xff1ff61c); + + case 25: + case 24: + case 9: + case 8: + return (0xff1ff620); + + case 27: + case 26: + case 11: + case 10: + return (0xff1ff624); + + case 29: + case 28: + case 13: + case 12: + return (0xff1ff628); + + case 31: + case 30: + case 15: + case 14: + return (0xff1ff62c); + + } + return (0); +} + +u32 tx4927_irq_pic_mask(int irq) +{ + /* MVMCP -- need to formulize this */ + irq -= TX4927_IRQ_PIC_BEG; + switch (irq) { + case 31: + case 29: + case 27: + case 25: + case 23: + case 21: + case 19: + case 17:{ + return (0x07000000); + } + case 30: + case 28: + case 26: + case 24: + case 22: + case 20: + case 18: + case 16:{ + return (0x00070000); + } + case 15: + case 13: + case 11: + case 9: + case 7: + case 5: + case 3: + case 1:{ + return (0x00000700); + } + case 14: + case 12: + case 10: + case 8: + case 6: + case 4: + case 2: + case 0:{ + return (0x00000007); + } + } + return (0x00000000); +} + +static void tx4927_irq_pic_modify(unsigned pic_reg, unsigned clr_bits, + unsigned set_bits) +{ + unsigned long val = 0; + + val = TX4927_RD(pic_reg); + val &= (~clr_bits); + val |= (set_bits); + TX4927_WR(pic_reg, val); + + return; +} + +static void __init tx4927_irq_pic_init(void) +{ + unsigned long flags; + int i; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_INIT, "beg=%d end=%d\n", + TX4927_IRQ_PIC_BEG, TX4927_IRQ_PIC_END); + + for (i = TX4927_IRQ_PIC_BEG; i <= TX4927_IRQ_PIC_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 2; + irq_desc[i].handler = &tx4927_irq_pic_type; + } + + setup_irq(TX4927_IRQ_NEST_PIC_ON_CP0, &tx4927_irq_pic_action); + + spin_lock_irqsave(&tx4927_pic_lock, flags); + + TX4927_WR(0xff1ff640, 0x6); /* irq level mask -- only accept hightest */ + TX4927_WR(0xff1ff600, TX4927_RD(0xff1ff600) | 0x1); /* irq enable */ + + spin_unlock_irqrestore(&tx4927_pic_lock, flags); + + return; +} + +static unsigned int tx4927_irq_pic_startup(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_STARTUP, "irq=%d\n", irq); + + tx4927_irq_pic_enable(irq); + + return (0); +} + +static void tx4927_irq_pic_shutdown(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_SHUTDOWN, "irq=%d\n", irq); + + tx4927_irq_pic_disable(irq); + + return; +} + +static void tx4927_irq_pic_enable(unsigned int irq) +{ + unsigned long flags; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENABLE, "irq=%d\n", irq); + + spin_lock_irqsave(&tx4927_pic_lock, flags); + + tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), 0, + tx4927_irq_pic_mask(irq)); + + spin_unlock_irqrestore(&tx4927_pic_lock, flags); + + return; +} + +static void tx4927_irq_pic_disable(unsigned int irq) +{ + unsigned long flags; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_DISABLE, "irq=%d\n", irq); + + spin_lock_irqsave(&tx4927_pic_lock, flags); + + tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), + tx4927_irq_pic_mask(irq), 0); + + spin_unlock_irqrestore(&tx4927_pic_lock, flags); + + return; +} + +static void tx4927_irq_pic_mask_and_ack(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_MASK, "irq=%d\n", irq); + + tx4927_irq_pic_disable(irq); + + return; +} + +static void tx4927_irq_pic_end(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENDIRQ, "irq=%d\n", irq); + + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + tx4927_irq_pic_enable(irq); + } + + return; +} + +/* + * Main init functions + */ +void __init tx4927_irq_init(void) +{ + extern asmlinkage void tx4927_irq_handler(void); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "-\n"); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_cp0_init()\n"); + tx4927_irq_cp0_init(); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_pic_init()\n"); + tx4927_irq_pic_init(); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, + "=Calling set_except_vector(tx4927_irq_handler)\n"); + set_except_vector(0, tx4927_irq_handler); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n"); + + return; +} + +int tx4927_irq_nested(void) +{ + int sw_irq = 0; + u32 level2; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST1, "-\n"); + + level2 = TX4927_RD(0xff1ff6a0); + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST2, "=level2a=0x%x\n", level2); + + if ((level2 & 0x10000) == 0) { + level2 &= 0x1f; + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST3, "=level2b=0x%x\n", level2); + + sw_irq = TX4927_IRQ_PIC_BEG + level2; + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST3, "=sw_irq=%d\n", sw_irq); + + if (sw_irq == 27) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST4, "=irq-%d\n", + sw_irq); + +#ifdef CONFIG_TOSHIBA_RBTX4927 + { + sw_irq = toshiba_rbtx4927_irq_nested(sw_irq); + } +#endif + + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST4, "=irq+%d\n", + sw_irq); + } + } + + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST2, "=sw_irq=%d\n", sw_irq); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST1, "+\n"); + + return (sw_irq); +} diff --git a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S new file mode 100644 index 00000000000..ca123e28d1e --- /dev/null +++ b/arch/mips/tx4927/common/tx4927_irq_handler.S @@ -0,0 +1,103 @@ +/* + * linux/arch/mips/tx4927/common/tx4927_irq_handler.S + * + * Primary interrupt handler for tx4927 based systems + * + * Author: MontaVista Software, Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <asm/asm.h> +#include <asm/mipsregs.h> +#include <asm/addrspace.h> +#include <asm/regdef.h> +#include <asm/stackframe.h> +#include <asm/tx4927/tx4927.h> + + .align 5 + NESTED(tx4927_irq_handler, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + + mfc0 t0, CP0_CAUSE + mfc0 t1, CP0_STATUS + and t0, t1 + + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_ip7 + + /* IP6..IP3 multiplexed -- do not use */ + + andi t1, t0, STATUSF_IP2 /* tx4927 pic */ + bnez t1, ll_ip2 + + andi t1, t0, STATUSF_IP0 /* user line 0 */ + bnez t1, ll_ip0 + + andi t1, t0, STATUSF_IP1 /* user line 1 */ + bnez t1, ll_ip1 + + .set reorder + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(tx4927_irq_handler) + + .align 5 + + +ll_ip7: + li a0, TX4927_IRQ_CPU_TIMER + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_ip2: + jal tx4927_irq_nested + nop + beqz v0, goto_spurious_interrupt + nop + move a0, v0 + move a1, sp + jal do_IRQ + j ret_from_irq + +goto_spurious_interrupt: + j spurious_interrupt + nop + +ll_ip1: + li a0, TX4927_IRQ_USER1 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_ip0: + li a0, TX4927_IRQ_USER0 + move a1, sp + jal do_IRQ + j ret_from_irq diff --git a/arch/mips/tx4927/common/tx4927_prom.c b/arch/mips/tx4927/common/tx4927_prom.c new file mode 100644 index 00000000000..7d4cbf512d8 --- /dev/null +++ b/arch/mips/tx4927/common/tx4927_prom.c @@ -0,0 +1,146 @@ +/* + * linux/arch/mips/tx4927/common/tx4927_prom.c + * + * common tx4927 memory interface + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/bootmem.h> + +#include <asm/addrspace.h> +#include <asm/bootinfo.h> +#include <asm/tx4927/tx4927.h> + +static unsigned int __init tx4927_process_sdccr(u64 * addr) +{ + u64 val; + unsigned int sdccr_ce; + unsigned int sdccr_bs; + unsigned int sdccr_rs; + unsigned int sdccr_cs; + unsigned int sdccr_mw; + unsigned int bs = 0; + unsigned int rs = 0; + unsigned int cs = 0; + unsigned int mw = 0; + unsigned int msize = 0; + + val = (*((vu64 *) (addr))); + + /* MVMCP -- need #defs for these bits masks */ + sdccr_ce = ((val & (1 << 10)) >> 10); + sdccr_bs = ((val & (1 << 8)) >> 8); + sdccr_rs = ((val & (3 << 5)) >> 5); + sdccr_cs = ((val & (3 << 2)) >> 2); + sdccr_mw = ((val & (1 << 0)) >> 0); + + if (sdccr_ce) { + switch (sdccr_bs) { + case 0:{ + bs = 2; + break; + } + case 1:{ + bs = 4; + break; + } + } + switch (sdccr_rs) { + case 0:{ + rs = 2048; + break; + } + case 1:{ + rs = 4096; + break; + } + case 2:{ + rs = 8192; + break; + } + case 3:{ + rs = 0; + break; + } + } + switch (sdccr_cs) { + case 0:{ + cs = 256; + break; + } + case 1:{ + cs = 512; + break; + } + case 2:{ + cs = 1024; + break; + } + case 3:{ + cs = 2048; + break; + } + } + switch (sdccr_mw) { + case 0:{ + mw = 8; + break; + } /* 8 bytes = 64 bits */ + case 1:{ + mw = 4; + break; + } /* 4 bytes = 32 bits */ + } + } + + /* bytes per chip MB per chip num chips */ + msize = (((rs * cs * mw) / (1024 * 1024)) * bs); + + return (msize); +} + + +unsigned int __init tx4927_get_mem_size(void) +{ + unsigned int c0; + unsigned int c1; + unsigned int c2; + unsigned int c3; + unsigned int total; + + /* MVMCP -- need #defs for these registers */ + c0 = tx4927_process_sdccr((u64 *) 0xff1f8000); + c1 = tx4927_process_sdccr((u64 *) 0xff1f8008); + c2 = tx4927_process_sdccr((u64 *) 0xff1f8010); + c3 = tx4927_process_sdccr((u64 *) 0xff1f8018); + total = c0 + c1 + c2 + c3; + + return (total); +} diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c new file mode 100644 index 00000000000..16bcbdc6d1c --- /dev/null +++ b/arch/mips/tx4927/common/tx4927_setup.c @@ -0,0 +1,237 @@ +/* + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/config.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel_stat.h> +#include <linux/module.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/timex.h> +#include <linux/slab.h> +#include <linux/random.h> +#include <linux/irq.h> +#include <linux/bitops.h> +#include <asm/bootinfo.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/mipsregs.h> +#include <asm/system.h> +#include <asm/time.h> +#include <asm/tx4927/tx4927.h> + + +#undef DEBUG + +void __init tx4927_time_init(void); +void __init tx4927_timer_setup(struct irqaction *irq); +void dump_cp0(char *key); + + +void (*__wbflush) (void); + +static void tx4927_write_buffer_flush(void) +{ + __asm__ __volatile__ + ("sync\n\t" "nop\n\t" "loop: bc0f loop\n\t" "nop\n\t"); +} + + +static void __init tx4927_setup(void) +{ + board_time_init = tx4927_time_init; + board_timer_setup = tx4927_timer_setup; + __wbflush = tx4927_write_buffer_flush; + +#ifdef CONFIG_TOSHIBA_RBTX4927 + { + extern void toshiba_rbtx4927_setup(void); + toshiba_rbtx4927_setup(); + } +#endif + + return; +} + +early_initcall(tx4927_setup); + +void __init tx4927_time_init(void) +{ + +#ifdef CONFIG_TOSHIBA_RBTX4927 + { + extern void toshiba_rbtx4927_time_init(void); + toshiba_rbtx4927_time_init(); + } +#endif + + return; +} + + +void __init tx4927_timer_setup(struct irqaction *irq) +{ + u32 count; + u32 c1; + u32 c2; + + setup_irq(TX4927_IRQ_CPU_TIMER, irq); + + /* to generate the first timer interrupt */ + c1 = read_c0_count(); + count = c1 + (mips_hpt_frequency / HZ); + write_c0_compare(count); + c2 = read_c0_count(); + +#ifdef CONFIG_TOSHIBA_RBTX4927 + { + extern void toshiba_rbtx4927_timer_setup(struct irqaction + *irq); + toshiba_rbtx4927_timer_setup(irq); + } +#endif + + return; +} + + +#ifdef DEBUG +void print_cp0(char *key, int num, char *name, u32 val) +{ + printk("%s cp0:%02d:%s=0x%08x\n", key, num, name, val); + return; +} + +indent: Standard input:25: Error:Unexpected end of file + +void +dump_cp0(char *key) +{ + if (key == NULL) + key = ""; + + print_cp0(key, 0, "INDEX ", read_c0_index()); + print_cp0(key, 2, "ENTRYLO1", read_c0_entrylo0()); + print_cp0(key, 3, "ENTRYLO2", read_c0_entrylo1()); + print_cp0(key, 4, "CONTEXT ", read_c0_context()); + print_cp0(key, 5, "PAGEMASK", read_c0_pagemask()); + print_cp0(key, 6, "WIRED ", read_c0_wired()); + //print_cp0(key, 8, "BADVADDR", read_c0_badvaddr()); + print_cp0(key, 9, "COUNT ", read_c0_count()); + print_cp0(key, 10, "ENTRYHI ", read_c0_entryhi()); + print_cp0(key, 11, "COMPARE ", read_c0_compare()); + print_cp0(key, 12, "STATUS ", read_c0_status()); + print_cp0(key, 13, "CAUSE ", read_c0_cause() & 0xffff87ff); + print_cp0(key, 16, "CONFIG ", read_c0_config()); + return; +} + +void print_pic(char *key, u32 reg, char *name) +{ + printk("%s pic:0x%08x:%s=0x%08x\n", key, reg, name, + TX4927_RD(reg)); + return; +} + + +void dump_pic(char *key) +{ + if (key == NULL) + key = ""; + + print_pic(key, 0xff1ff600, "IRDEN "); + print_pic(key, 0xff1ff604, "IRDM0 "); + print_pic(key, 0xff1ff608, "IRDM1 "); + + print_pic(key, 0xff1ff610, "IRLVL0 "); + print_pic(key, 0xff1ff614, "IRLVL1 "); + print_pic(key, 0xff1ff618, "IRLVL2 "); + print_pic(key, 0xff1ff61c, "IRLVL3 "); + print_pic(key, 0xff1ff620, "IRLVL4 "); + print_pic(key, 0xff1ff624, "IRLVL5 "); + print_pic(key, 0xff1ff628, "IRLVL6 "); + print_pic(key, 0xff1ff62c, "IRLVL7 "); + + print_pic(key, 0xff1ff640, "IRMSK "); + print_pic(key, 0xff1ff660, "IREDC "); + print_pic(key, 0xff1ff680, "IRPND "); + print_pic(key, 0xff1ff6a0, "IRCS "); + + print_pic(key, 0xff1ff514, "IRFLAG1 "); /* don't read IRLAG0 -- it hangs system */ + + print_pic(key, 0xff1ff518, "IRPOL "); + print_pic(key, 0xff1ff51c, "IRRCNT "); + print_pic(key, 0xff1ff520, "IRMASKINT"); + print_pic(key, 0xff1ff524, "IRMASKEXT"); + + return; +} + + +void print_addr(char *hdr, char *key, u32 addr) +{ + printk("%s %s:0x%08x=0x%08x\n", hdr, key, addr, TX4927_RD(addr)); + return; +} + + +void dump_180(char *key) +{ + u32 i; + + for (i = 0x80000180; i < 0x80000180 + 0x80; i += 4) { + print_addr("180", key, i); + } + return; +} + + +void dump_eh0(char *key) +{ + int i; + extern unsigned long exception_handlers[]; + + for (i = (int) exception_handlers; + i < (int) (exception_handlers + 20); i += 4) { + print_addr("eh0", key, i); + } + + return; +} + +void pk0(void) +{ + volatile u32 val; + + __asm__ __volatile__("ori %0, $26, 0":"=r"(val) + ); + printk("k0=[0x%08x]\n", val); +} +#endif |