diff options
Diffstat (limited to 'arch/mips/ite-boards/generic')
-rw-r--r-- | arch/mips/ite-boards/generic/Makefile | 15 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/dbg_io.c | 125 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/int-handler.S | 63 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/irq.c | 304 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/it8172_cir.c | 171 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/it8172_setup.c | 309 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/lpc.c | 144 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/pmon_prom.c | 136 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/puts.c | 139 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/reset.c | 60 | ||||
-rw-r--r-- | arch/mips/ite-boards/generic/time.c | 247 |
11 files changed, 1713 insertions, 0 deletions
diff --git a/arch/mips/ite-boards/generic/Makefile b/arch/mips/ite-boards/generic/Makefile new file mode 100644 index 000000000000..0e7853f43983 --- /dev/null +++ b/arch/mips/ite-boards/generic/Makefile @@ -0,0 +1,15 @@ +# +# Copyright 2000 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the ITE 8172 (qed-4n-s01b) board, generic files. +# + +obj-y += it8172_setup.o irq.o int-handler.o pmon_prom.o \ + time.o lpc.o puts.o reset.o + +obj-$(CONFIG_IT8172_CIR)+= it8172_cir.o +obj-$(CONFIG_KGDB) += dbg_io.o + +EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/ite-boards/generic/dbg_io.c b/arch/mips/ite-boards/generic/dbg_io.c new file mode 100644 index 000000000000..c4f8530fd07e --- /dev/null +++ b/arch/mips/ite-boards/generic/dbg_io.c @@ -0,0 +1,125 @@ + +#include <linux/config.h> + +#ifdef CONFIG_KGDB + +/* --- CONFIG --- */ + +/* we need uint32 uint8 */ +/* #include "types.h" */ +typedef unsigned char uint8; +typedef unsigned int uint32; + +/* --- END OF CONFIG --- */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ + +/* [stevel] we use the IT8712 serial port for kgdb */ +#define DEBUG_BASE 0xB40003F8 /* 8712 serial port 1 base address */ +#define MAX_BAUD 115200 + +/* === END OF CONFIG === */ + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE 1 +#define OFS_INTR_ID 2 +#define OFS_DATA_FORMAT 3 +#define OFS_LINE_CONTROL 3 +#define OFS_MODEM_CONTROL 4 +#define OFS_RS232_OUTPUT 4 +#define OFS_LINE_STATUS 5 +#define OFS_MODEM_STATUS 6 +#define OFS_RS232_INPUT 6 +#define OFS_SCRATCH_PAD 7 + +#define OFS_DIVISOR_LSB 0 +#define OFS_DIVISOR_MSB 1 + + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile uint8*)(DEBUG_BASE + y))) +#define UART16550_WRITE(y,z) ((*((volatile uint8*)(DEBUG_BASE + y))) = z) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + +static int remoteDebugInitialized = 0; + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); +} + + +int putDebugChar(uint8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} + +#endif diff --git a/arch/mips/ite-boards/generic/int-handler.S b/arch/mips/ite-boards/generic/int-handler.S new file mode 100644 index 000000000000..d190d8add9cb --- /dev/null +++ b/arch/mips/ite-boards/generic/int-handler.S @@ -0,0 +1,63 @@ +#include <asm/asm.h> +#include <asm/mipsregs.h> +#include <asm/regdef.h> +#include <asm/stackframe.h> + + .text + .set macro + .set noat + .align 5 + +NESTED(it8172_IRQ, PT_SIZE, sp) + SAVE_ALL + CLI # Important: mark KERNEL mode ! + + /* We're working with 'reorder' set at this point. */ + /* + * Get pending interrupts + */ + + mfc0 t0,CP0_CAUSE # get pending interrupts + mfc0 t1,CP0_STATUS # get enabled interrupts + and t0,t1 # isolate allowed ones + + andi t0,0xff00 # isolate pending bits + beqz t0, 3f # spurious interrupt + + andi a0, t0, CAUSEF_IP7 + beq a0, zero, 1f + + li a0, 127 # MIPS_CPU_TIMER_IRQ = (NR_IRQS-1) + move a1, sp + jal ll_timer_interrupt + j ret_from_irq + nop + +1: + andi a0, t0, CAUSEF_IP2 # the only int we expect at this time + beq a0, zero, 3f + move a0,sp + jal it8172_hw0_irqdispatch + + mfc0 t0,CP0_STATUS # disable interrupts + ori t0,1 + xori t0,1 + mtc0 t0,CP0_STATUS + nop + nop + nop + + la a1, ret_from_irq + jr a1 + nop + +3: + move a0, sp + jal mips_spurious_interrupt + nop + la a1, ret_from_irq + jr a1 + nop + +END(it8172_IRQ) + diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c new file mode 100644 index 000000000000..cb71b9024d6f --- /dev/null +++ b/arch/mips/ite-boards/generic/irq.c @@ -0,0 +1,304 @@ +/* + * BRIEF MODULE DESCRIPTION + * ITE 8172G interrupt/setup routines. + * + * Copyright 2000,2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * Part of this file was derived from Carsten Langgaard's + * arch/mips/mips-boards/atlas/atlas_int.c. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * 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/errno.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/kernel_stat.h> +#include <linux/module.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/timex.h> +#include <linux/slab.h> +#include <linux/random.h> +#include <linux/serial_reg.h> +#include <linux/bitops.h> + +#include <asm/bootinfo.h> +#include <asm/io.h> +#include <asm/mipsregs.h> +#include <asm/system.h> +#include <asm/it8172/it8172.h> +#include <asm/it8172/it8172_int.h> +#include <asm/it8172/it8172_dbg.h> + +/* revisit */ +#define EXT_IRQ0_TO_IP 2 /* IP 2 */ +#define EXT_IRQ5_TO_IP 7 /* IP 7 */ + +#define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) + +void disable_it8172_irq(unsigned int irq_nr); +void enable_it8172_irq(unsigned int irq_nr); + +extern void set_debug_traps(void); +extern void mips_timer_interrupt(int irq, struct pt_regs *regs); +extern asmlinkage void it8172_IRQ(void); + +struct it8172_intc_regs volatile *it8172_hw0_icregs = + (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE)); + +static void disable_it8172_irq(unsigned int irq_nr) +{ + if ( (irq_nr >= IT8172_LPC_IRQ_BASE) && (irq_nr <= IT8172_SERIRQ_15)) { + /* LPC interrupt */ + it8172_hw0_icregs->lpc_mask |= + (1 << (irq_nr - IT8172_LPC_IRQ_BASE)); + } else if ( (irq_nr >= IT8172_LB_IRQ_BASE) && (irq_nr <= IT8172_IOCHK_IRQ)) { + /* Local Bus interrupt */ + it8172_hw0_icregs->lb_mask |= + (1 << (irq_nr - IT8172_LB_IRQ_BASE)); + } else if ( (irq_nr >= IT8172_PCI_DEV_IRQ_BASE) && (irq_nr <= IT8172_DMA_IRQ)) { + /* PCI and other interrupts */ + it8172_hw0_icregs->pci_mask |= + (1 << (irq_nr - IT8172_PCI_DEV_IRQ_BASE)); + } else if ( (irq_nr >= IT8172_NMI_IRQ_BASE) && (irq_nr <= IT8172_POWER_NMI_IRQ)) { + /* NMI interrupts */ + it8172_hw0_icregs->nmi_mask |= + (1 << (irq_nr - IT8172_NMI_IRQ_BASE)); + } else { + panic("disable_it8172_irq: bad irq %d", irq_nr); + } +} + +static void enable_it8172_irq(unsigned int irq_nr) +{ + if ( (irq_nr >= IT8172_LPC_IRQ_BASE) && (irq_nr <= IT8172_SERIRQ_15)) { + /* LPC interrupt */ + it8172_hw0_icregs->lpc_mask &= + ~(1 << (irq_nr - IT8172_LPC_IRQ_BASE)); + } + else if ( (irq_nr >= IT8172_LB_IRQ_BASE) && (irq_nr <= IT8172_IOCHK_IRQ)) { + /* Local Bus interrupt */ + it8172_hw0_icregs->lb_mask &= + ~(1 << (irq_nr - IT8172_LB_IRQ_BASE)); + } + else if ( (irq_nr >= IT8172_PCI_DEV_IRQ_BASE) && (irq_nr <= IT8172_DMA_IRQ)) { + /* PCI and other interrupts */ + it8172_hw0_icregs->pci_mask &= + ~(1 << (irq_nr - IT8172_PCI_DEV_IRQ_BASE)); + } + else if ( (irq_nr >= IT8172_NMI_IRQ_BASE) && (irq_nr <= IT8172_POWER_NMI_IRQ)) { + /* NMI interrupts */ + it8172_hw0_icregs->nmi_mask &= + ~(1 << (irq_nr - IT8172_NMI_IRQ_BASE)); + } + else { + panic("enable_it8172_irq: bad irq %d", irq_nr); + } +} + +static unsigned int startup_ite_irq(unsigned int irq) +{ + enable_it8172_irq(irq); + return 0; +} + +#define shutdown_ite_irq disable_it8172_irq +#define mask_and_ack_ite_irq disable_it8172_irq + +static void end_ite_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_it8172_irq(irq); +} + +static struct hw_interrupt_type it8172_irq_type = { + "ITE8172", + startup_ite_irq, + shutdown_ite_irq, + enable_it8172_irq, + disable_it8172_irq, + mask_and_ack_ite_irq, + end_ite_irq, + NULL +}; + + +static void enable_none(unsigned int irq) { } +static unsigned int startup_none(unsigned int irq) { return 0; } +static void disable_none(unsigned int irq) { } +static void ack_none(unsigned int irq) { } + +/* startup is the same as "enable", shutdown is same as "disable" */ +#define shutdown_none disable_none +#define end_none enable_none + +static struct hw_interrupt_type cp0_irq_type = { + "CP0 Count", + startup_none, + shutdown_none, + enable_none, + disable_none, + ack_none, + end_none +}; + +void enable_cpu_timer(void) +{ + unsigned long flags; + + local_irq_save(flags); + set_c0_status(0x100 << EXT_IRQ5_TO_IP); + local_irq_restore(flags); +} + +void __init arch_init_irq(void) +{ + int i; + unsigned long flags; + + memset(irq_desc, 0, sizeof(irq_desc)); + set_except_vector(0, it8172_IRQ); + + /* mask all interrupts */ + it8172_hw0_icregs->lb_mask = 0xffff; + it8172_hw0_icregs->lpc_mask = 0xffff; + it8172_hw0_icregs->pci_mask = 0xffff; + it8172_hw0_icregs->nmi_mask = 0xffff; + + /* make all interrupts level triggered */ + it8172_hw0_icregs->lb_trigger = 0; + it8172_hw0_icregs->lpc_trigger = 0; + it8172_hw0_icregs->pci_trigger = 0; + it8172_hw0_icregs->nmi_trigger = 0; + + /* active level setting */ + /* uart, keyboard, and mouse are active high */ + it8172_hw0_icregs->lpc_level = (0x10 | 0x2 | 0x1000); + it8172_hw0_icregs->lb_level |= 0x20; + + /* keyboard and mouse are edge triggered */ + it8172_hw0_icregs->lpc_trigger |= (0x2 | 0x1000); + + +#if 0 + // Enable this piece of code to make internal USB interrupt + // edge triggered. + it8172_hw0_icregs->pci_trigger |= + (1 << (IT8172_USB_IRQ - IT8172_PCI_DEV_IRQ_BASE)); + it8172_hw0_icregs->pci_level &= + ~(1 << (IT8172_USB_IRQ - IT8172_PCI_DEV_IRQ_BASE)); +#endif + + for (i = 0; i <= IT8172_LAST_IRQ; i++) { + irq_desc[i].handler = &it8172_irq_type; + spin_lock_init(&irq_desc[i].lock); + } + irq_desc[MIPS_CPU_TIMER_IRQ].handler = &cp0_irq_type; + set_c0_status(ALLINTS_NOTIMER); +} + +void mips_spurious_interrupt(struct pt_regs *regs) +{ +#if 1 + return; +#else + unsigned long status, cause; + + printk("got spurious interrupt\n"); + status = read_c0_status(); + cause = read_c0_cause(); + printk("status %x cause %x\n", status, cause); + printk("epc %x badvaddr %x \n", regs->cp0_epc, regs->cp0_badvaddr); +#endif +} + +void it8172_hw0_irqdispatch(struct pt_regs *regs) +{ + int irq; + unsigned short intstatus = 0, status = 0; + + intstatus = it8172_hw0_icregs->intstatus; + if (intstatus & 0x8) { + panic("Got NMI interrupt"); + } else if (intstatus & 0x4) { + /* PCI interrupt */ + irq = 0; + status |= it8172_hw0_icregs->pci_req; + while (!(status & 0x1)) { + irq++; + status >>= 1; + } + irq += IT8172_PCI_DEV_IRQ_BASE; + } else if (intstatus & 0x1) { + /* Local Bus interrupt */ + irq = 0; + status |= it8172_hw0_icregs->lb_req; + while (!(status & 0x1)) { + irq++; + status >>= 1; + } + irq += IT8172_LB_IRQ_BASE; + } else if (intstatus & 0x2) { + /* LPC interrupt */ + /* Since some lpc interrupts are edge triggered, + * we could lose an interrupt this way because + * we acknowledge all ints at onces. Revisit. + */ + status |= it8172_hw0_icregs->lpc_req; + it8172_hw0_icregs->lpc_req = 0; /* acknowledge ints */ + irq = 0; + while (!(status & 0x1)) { + irq++; + status >>= 1; + } + irq += IT8172_LPC_IRQ_BASE; + } else + return; + + do_IRQ(irq, regs); +} + +void show_pending_irqs(void) +{ + fputs("intstatus: "); + put32(it8172_hw0_icregs->intstatus); + puts(""); + + fputs("pci_req: "); + put32(it8172_hw0_icregs->pci_req); + puts(""); + + fputs("lb_req: "); + put32(it8172_hw0_icregs->lb_req); + puts(""); + + fputs("lpc_req: "); + put32(it8172_hw0_icregs->lpc_req); + puts(""); +} diff --git a/arch/mips/ite-boards/generic/it8172_cir.c b/arch/mips/ite-boards/generic/it8172_cir.c new file mode 100644 index 000000000000..19deb153d005 --- /dev/null +++ b/arch/mips/ite-boards/generic/it8172_cir.c @@ -0,0 +1,171 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * IT8172 Consumer IR port generic routines. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS 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> + +#ifdef CONFIG_IT8172_CIR + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/init.h> + +#include <asm/it8172/it8172.h> +#include <asm/it8172/it8172_cir.h> + + +volatile struct it8172_cir_regs *cir_regs[NUM_CIR_PORTS] = { + (volatile struct it8172_cir_regs *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_CIR0_BASE)), + (volatile struct it8172_cir_regs *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_CIR1_BASE))}; + + +/* + * Initialize Consumer IR Port. + */ +int cir_port_init(struct cir_port *cir) +{ + int port = cir->port; + unsigned char data; + + /* set baud rate */ + cir_regs[port]->bdlr = cir->baud_rate & 0xff; + cir_regs[port]->bdhr = (cir->baud_rate >> 8) & 0xff; + + /* set receiver control register */ + cir_regs[port]->rcr = (CIR_SET_RDWOS(cir->rdwos) | CIR_SET_RXDCR(cir->rxdcr)); + + /* set carrier frequency register */ + cir_regs[port]->cfr = (CIR_SET_CF(cir->cfq) | CIR_SET_HS(cir->hcfs)); + + /* set fifo threshold */ + data = cir_regs[port]->mstcr & 0xf3; + data |= CIR_SET_FIFO_TL(cir->fifo_tl); + cir_regs[port]->mstcr = data; + + clear_fifo(cir); + enable_receiver(cir); + disable_rx_demodulation(cir); + + set_rx_active(cir); + int_enable(cir); + rx_int_enable(cir); + + return 0; +} + + +void clear_fifo(struct cir_port *cir) +{ + cir_regs[cir->port]->mstcr |= CIR_FIFO_CLEAR; +} + +void enable_receiver(struct cir_port *cir) +{ + cir_regs[cir->port]->rcr |= CIR_RXEN; +} + +void disable_receiver(struct cir_port *cir) +{ + cir_regs[cir->port]->rcr &= ~CIR_RXEN; +} + +void enable_rx_demodulation(struct cir_port *cir) +{ + cir_regs[cir->port]->rcr |= CIR_RXEND; +} + +void disable_rx_demodulation(struct cir_port *cir) +{ + cir_regs[cir->port]->rcr &= ~CIR_RXEND; +} + +void set_rx_active(struct cir_port *cir) +{ + cir_regs[cir->port]->rcr |= CIR_RXACT; +} + +void int_enable(struct cir_port *cir) +{ + cir_regs[cir->port]->ier |= CIR_IEC; +} + +void rx_int_enable(struct cir_port *cir) +{ + cir_regs[cir->port]->ier |= CIR_RDAIE; +} + +void dump_regs(struct cir_port *cir) +{ + printk("mstcr %x ier %x iir %x cfr %x rcr %x tcr %x tfsr %x rfsr %x\n", + cir_regs[cir->port]->mstcr, + cir_regs[cir->port]->ier, + cir_regs[cir->port]->iir, + cir_regs[cir->port]->cfr, + cir_regs[cir->port]->rcr, + cir_regs[cir->port]->tcr, + cir_regs[cir->port]->tfsr, + cir_regs[cir->port]->rfsr); + + while (cir_regs[cir->port]->iir & CIR_RDAI) { + printk("data %x\n", cir_regs[cir->port]->dr); + } +} + +void dump_reg_addr(struct cir_port *cir) +{ + printk("dr %x mstcr %x ier %x iir %x cfr %x rcr %x tcr %x bdlr %x bdhr %x tfsr %x rfsr %x\n", + (unsigned)&cir_regs[cir->port]->dr, + (unsigned)&cir_regs[cir->port]->mstcr, + (unsigned)&cir_regs[cir->port]->ier, + (unsigned)&cir_regs[cir->port]->iir, + (unsigned)&cir_regs[cir->port]->cfr, + (unsigned)&cir_regs[cir->port]->rcr, + (unsigned)&cir_regs[cir->port]->tcr, + (unsigned)&cir_regs[cir->port]->bdlr, + (unsigned)&cir_regs[cir->port]->bdhr, + (unsigned)&cir_regs[cir->port]->tfsr, + (unsigned)&cir_regs[cir->port]->rfsr); +} + +int cir_get_rx_count(struct cir_port *cir) +{ + return cir_regs[cir->port]->rfsr & CIR_RXFBC_MASK; +} + +char cir_read_data(struct cir_port *cir) +{ + return cir_regs[cir->port]->dr; +} + +char get_int_status(struct cir_port *cir) +{ + return cir_regs[cir->port]->iir; +} +#endif diff --git a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c new file mode 100644 index 000000000000..d808a67294b8 --- /dev/null +++ b/arch/mips/ite-boards/generic/it8172_setup.c @@ -0,0 +1,309 @@ +/* + * BRIEF MODULE DESCRIPTION + * IT8172/QED5231 board setup. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS 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/init.h> +#include <linux/sched.h> +#include <linux/ioport.h> +#include <linux/serial_reg.h> +#include <linux/major.h> +#include <linux/kdev_t.h> +#include <linux/root_dev.h> + +#include <asm/cpu.h> +#include <asm/time.h> +#include <asm/io.h> +#include <asm/bootinfo.h> +#include <asm/irq.h> +#include <asm/mipsregs.h> +#include <asm/reboot.h> +#include <asm/traps.h> +#include <asm/it8172/it8172.h> +#include <asm/it8712.h> + +extern struct resource ioport_resource; +#ifdef CONFIG_SERIO_I8042 +int init_8712_keyboard(void); +#endif + +extern int SearchIT8712(void); +extern void InitLPCInterface(void); +extern char * __init prom_getcmdline(void); +extern void it8172_restart(char *command); +extern void it8172_halt(void); +extern void it8172_power_off(void); + +extern void (*board_time_init)(void); +extern void (*board_timer_setup)(struct irqaction *irq); +extern void it8172_time_init(void); +extern void it8172_timer_setup(struct irqaction *irq); + +#ifdef CONFIG_IT8172_REVC +struct { + struct resource ram; + struct resource pci_mem; + struct resource pci_io; + struct resource flash; + struct resource boot; +} it8172_resources = { + { "RAM", 0, 0, IORESOURCE_MEM }, /* to be initted */ + { "PCI Mem", 0x10000000, 0x13FFFFFF, IORESOURCE_MEM }, + { "PCI I/O", 0x14000000, 0x17FFFFFF }, + { "Flash", 0x08000000, 0x0CFFFFFF }, + { "Boot ROM", 0x1FC00000, 0x1FFFFFFF } +}; +#else +struct { + struct resource ram; + struct resource pci_mem0; + struct resource pci_mem1; + struct resource pci_io; + struct resource pci_mem2; + struct resource pci_mem3; + struct resource flash; + struct resource boot; +} it8172_resources = { + { "RAM", 0, 0, IORESOURCE_MEM }, /* to be initted */ + { "PCI Mem0", 0x0C000000, 0x0FFFFFFF, IORESOURCE_MEM }, + { "PCI Mem1", 0x10000000, 0x13FFFFFF, IORESOURCE_MEM }, + { "PCI I/O", 0x14000000, 0x17FFFFFF }, + { "PCI Mem2", 0x1A000000, 0x1BFFFFFF, IORESOURCE_MEM }, + { "PCI Mem3", 0x1C000000, 0x1FBFFFFF, IORESOURCE_MEM }, + { "Flash", 0x08000000, 0x0CFFFFFF }, + { "Boot ROM", 0x1FC00000, 0x1FFFFFFF } +}; +#endif + + +void __init it8172_init_ram_resource(unsigned long memsize) +{ + it8172_resources.ram.end = memsize; +} + +static void __init it8172_setup(void) +{ + unsigned short dsr; + char *argptr; + + argptr = prom_getcmdline(); +#ifdef CONFIG_SERIAL_CONSOLE + if ((argptr = strstr(argptr, "console=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS0,115200"); + } +#endif + + clear_c0_status(ST0_FR); + + board_time_init = it8172_time_init; + board_timer_setup = it8172_timer_setup; + + _machine_restart = it8172_restart; + _machine_halt = it8172_halt; + _machine_power_off = it8172_power_off; + + /* + * IO/MEM resources. + * + * revisit this area. + */ + set_io_port_base(KSEG1); + ioport_resource.start = it8172_resources.pci_io.start; + ioport_resource.end = it8172_resources.pci_io.end; +#ifdef CONFIG_IT8172_REVC + iomem_resource.start = it8172_resources.pci_mem.start; + iomem_resource.end = it8172_resources.pci_mem.end; +#else + iomem_resource.start = it8172_resources.pci_mem0.start; + iomem_resource.end = it8172_resources.pci_mem3.end; +#endif + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; +#endif + + /* + * Pull enabled devices out of standby + */ + IT_IO_READ16(IT_PM_DSR, dsr); + + /* + * Fixme: This breaks when these drivers are modules!!! + */ +#ifdef CONFIG_SOUND_IT8172 + dsr &= ~IT_PM_DSR_ACSB; +#else + dsr |= IT_PM_DSR_ACSB; +#endif +#ifdef CONFIG_BLK_DEV_IT8172 + dsr &= ~IT_PM_DSR_IDESB; +#else + dsr |= IT_PM_DSR_IDESB; +#endif + IT_IO_WRITE16(IT_PM_DSR, dsr); + + InitLPCInterface(); + +#ifdef CONFIG_MIPS_ITE8172 + if (SearchIT8712()) { + printk("Found IT8712 Super IO\n"); + /* enable IT8712 serial port */ + LPCSetConfig(LDN_SERIAL1, 0x30, 0x01); /* enable */ + LPCSetConfig(LDN_SERIAL1, 0x23, 0x01); /* clock selection */ +#ifdef CONFIG_SERIO_I8042 + if (init_8712_keyboard()) { + printk("Unable to initialize keyboard\n"); + LPCSetConfig(LDN_KEYBOARD, 0x30, 0x0); /* disable keyboard */ + } else { + LPCSetConfig(LDN_KEYBOARD, 0x30, 0x1); /* enable keyboard */ + LPCSetConfig(LDN_KEYBOARD, 0xf0, 0x2); + LPCSetConfig(LDN_KEYBOARD, 0x71, 0x3); + + LPCSetConfig(LDN_MOUSE, 0x30, 0x1); /* enable mouse */ + + LPCSetConfig(0x4, 0x30, 0x1); + LPCSetConfig(0x4, 0xf4, LPCGetConfig(0x4, 0xf4) | 0x80); + + if ((LPCGetConfig(LDN_KEYBOARD, 0x30) == 0) || + (LPCGetConfig(LDN_MOUSE, 0x30) == 0)) + printk("Error: keyboard or mouse not enabled\n"); + + } +#endif + } + else { + printk("IT8712 Super IO not found\n"); + } +#endif + +#ifdef CONFIG_IT8172_CIR + { + unsigned long data; + //printk("Enabling CIR0\n"); + IT_IO_READ16(IT_PM_DSR, data); + data &= ~IT_PM_DSR_CIR0SB; + IT_IO_WRITE16(IT_PM_DSR, data); + //printk("DSR register: %x\n", (unsigned)IT_IO_READ16(IT_PM_DSR, data)); + } +#endif +#ifdef CONFIG_IT8172_SCR0 + { + unsigned i; + /* Enable Smart Card Reader 0 */ + /* First power it up */ + IT_IO_READ16(IT_PM_DSR, i); + i &= ~IT_PM_DSR_SCR0SB; + IT_IO_WRITE16(IT_PM_DSR, i); + /* Then initialize its registers */ + outb(( IT_SCR_SFR_GATE_UART_OFF << IT_SCR_SFR_GATE_UART_BIT + |IT_SCR_SFR_FET_CHARGE_213_US << IT_SCR_SFR_FET_CHARGE_BIT + |IT_SCR_SFR_CARD_FREQ_3_5_MHZ << IT_SCR_SFR_CARD_FREQ_BIT + |IT_SCR_SFR_FET_ACTIVE_INVERT << IT_SCR_SFR_FET_ACTIVE_BIT + |IT_SCR_SFR_ENABLE_ON << IT_SCR_SFR_ENABLE_BIT), + IT8172_PCI_IO_BASE + IT_SCR0_BASE + IT_SCR_SFR); + outb(IT_SCR_SCDR_RESET_MODE_ASYNC << IT_SCR_SCDR_RESET_MODE_BIT, + IT8172_PCI_IO_BASE + IT_SCR0_BASE + IT_SCR_SCDR); + } +#endif /* CONFIG_IT8172_SCR0 */ +#ifdef CONFIG_IT8172_SCR1 + { + unsigned i; + /* Enable Smart Card Reader 1 */ + /* First power it up */ + IT_IO_READ16(IT_PM_DSR, i); + i &= ~IT_PM_DSR_SCR1SB; + IT_IO_WRITE16(IT_PM_DSR, i); + /* Then initialize its registers */ + outb(( IT_SCR_SFR_GATE_UART_OFF << IT_SCR_SFR_GATE_UART_BIT + |IT_SCR_SFR_FET_CHARGE_213_US << IT_SCR_SFR_FET_CHARGE_BIT + |IT_SCR_SFR_CARD_FREQ_3_5_MHZ << IT_SCR_SFR_CARD_FREQ_BIT + |IT_SCR_SFR_FET_ACTIVE_INVERT << IT_SCR_SFR_FET_ACTIVE_BIT + |IT_SCR_SFR_ENABLE_ON << IT_SCR_SFR_ENABLE_BIT), + IT8172_PCI_IO_BASE + IT_SCR1_BASE + IT_SCR_SFR); + outb(IT_SCR_SCDR_RESET_MODE_ASYNC << IT_SCR_SCDR_RESET_MODE_BIT, + IT8172_PCI_IO_BASE + IT_SCR1_BASE + IT_SCR_SCDR); + } +#endif /* CONFIG_IT8172_SCR1 */ +} + +early_initcall(it8172_setup); + +#ifdef CONFIG_SERIO_I8042 +/* + * According to the ITE Special BIOS Note for waking up the + * keyboard controller... + */ +static int init_8712_keyboard(void) +{ + unsigned int cmd_port = 0x14000064; + unsigned int data_port = 0x14000060; + ^^^^^^^^^^^ + Somebody here doesn't grok the concept of io ports. + + unsigned char data; + int i; + + outb(0xaa, cmd_port); /* send self-test cmd */ + i = 0; + while (!(inb(cmd_port) & 0x1)) { /* wait output buffer full */ + i++; + if (i > 0xffffff) + return 1; + } + + data = inb(data_port); + outb(0xcb, cmd_port); /* set ps2 mode */ + while (inb(cmd_port) & 0x2) { /* wait while input buffer full */ + i++; + if (i > 0xffffff) + return 1; + } + outb(0x01, data_port); + while (inb(cmd_port) & 0x2) { /* wait while input buffer full */ + i++; + if (i > 0xffffff) + return 1; + } + + outb(0x60, cmd_port); /* write 8042 command byte */ + while (inb(cmd_port) & 0x2) { /* wait while input buffer full */ + i++; + if (i > 0xffffff) + return 1; + } + outb(0x45, data_port); /* at interface, keyboard enabled, system flag */ + while (inb(cmd_port) & 0x2) { /* wait while input buffer full */ + i++; + if (i > 0xffffff) + return 1; + } + + outb(0xae, cmd_port); /* enable interface */ + return 0; +} +#endif diff --git a/arch/mips/ite-boards/generic/lpc.c b/arch/mips/ite-boards/generic/lpc.c new file mode 100644 index 000000000000..cc7584fbef8a --- /dev/null +++ b/arch/mips/ite-boards/generic/lpc.c @@ -0,0 +1,144 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * ITE Semi IT8712 Super I/O functions. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS 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/io.h> +#include <asm/types.h> +#include <asm/it8712.h> +#include <asm/it8172/it8172.h> + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +void LPCEnterMBPnP(void) +{ + int i; + unsigned char key[4] = {0x87, 0x01, 0x55, 0x55}; + + for (i = 0; i<4; i++) + outb(key[i], LPC_KEY_ADDR); + +} + +void LPCExitMBPnP(void) +{ + outb(0x02, LPC_KEY_ADDR); + outb(0x02, LPC_DATA_ADDR); +} + +void LPCSetConfig(char LdnNumber, char Index, char data) +{ + LPCEnterMBPnP(); // Enter IT8712 MB PnP mode + outb(0x07, LPC_KEY_ADDR); + outb(LdnNumber, LPC_DATA_ADDR); + outb(Index, LPC_KEY_ADDR); + outb(data, LPC_DATA_ADDR); + LPCExitMBPnP(); +} + +char LPCGetConfig(char LdnNumber, char Index) +{ + char rtn; + + LPCEnterMBPnP(); // Enter IT8712 MB PnP mode + outb(0x07, LPC_KEY_ADDR); + outb(LdnNumber, LPC_DATA_ADDR); + outb(Index, LPC_KEY_ADDR); + rtn = inb(LPC_DATA_ADDR); + LPCExitMBPnP(); + return rtn; +} + +int SearchIT8712(void) +{ + unsigned char Id1, Id2; + unsigned short Id; + + LPCEnterMBPnP(); + outb(0x20, LPC_KEY_ADDR); /* chip id byte 1 */ + Id1 = inb(LPC_DATA_ADDR); + outb(0x21, LPC_KEY_ADDR); /* chip id byte 2 */ + Id2 = inb(LPC_DATA_ADDR); + Id = (Id1 << 8) | Id2; + LPCExitMBPnP(); + if (Id == 0x8712) + return TRUE; + else + return FALSE; +} + +void InitLPCInterface(void) +{ + unsigned char bus, dev_fn; + unsigned long data; + + bus = 0; + dev_fn = 1<<3 | 4; + + + /* pci cmd, SERR# Enable */ + IT_WRITE(IT_CONFADDR, + (bus << IT_BUSNUM_SHF) | + (dev_fn << IT_FUNCNUM_SHF) | + ((0x4 / 4) << IT_REGNUM_SHF)); + IT_READ(IT_CONFDATA, data); + data |= 0x0100; + IT_WRITE(IT_CONFADDR, + (bus << IT_BUSNUM_SHF) | + (dev_fn << IT_FUNCNUM_SHF) | + ((0x4 / 4) << IT_REGNUM_SHF)); + IT_WRITE(IT_CONFDATA, data); + + /* setup serial irq control register */ + IT_WRITE(IT_CONFADDR, + (bus << IT_BUSNUM_SHF) | + (dev_fn << IT_FUNCNUM_SHF) | + ((0x48 / 4) << IT_REGNUM_SHF)); + IT_READ(IT_CONFDATA, data); + data = (data & 0xffff00ff) | 0xc400; + IT_WRITE(IT_CONFADDR, + (bus << IT_BUSNUM_SHF) | + (dev_fn << IT_FUNCNUM_SHF) | + ((0x48 / 4) << IT_REGNUM_SHF)); + IT_WRITE(IT_CONFDATA, data); + + + /* Enable I/O Space Subtractive Decode */ + /* default 0x4C is 0x3f220000 */ + IT_WRITE(IT_CONFADDR, + (bus << IT_BUSNUM_SHF) | + (dev_fn << IT_FUNCNUM_SHF) | + ((0x4C / 4) << IT_REGNUM_SHF)); + IT_WRITE(IT_CONFDATA, 0x3f2200f3); +} diff --git a/arch/mips/ite-boards/generic/pmon_prom.c b/arch/mips/ite-boards/generic/pmon_prom.c new file mode 100644 index 000000000000..6e505af0cc08 --- /dev/null +++ b/arch/mips/ite-boards/generic/pmon_prom.c @@ -0,0 +1,136 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PROM library initialisation code, assuming a version of + * pmon is the boot code. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/xx files. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/string.h> + +#include <asm/bootinfo.h> + +extern int prom_argc; +extern char **prom_argv, **prom_envp; + +typedef struct +{ + char *name; +/* char *val; */ +}t_env_var; + + +char * __init prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +void __init prom_init_cmdline(void) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while(actr < prom_argc) { + strcpy(cp, prom_argv[actr]); + cp += strlen(prom_argv[actr]); + *cp++ = ' '; + actr++; + } + if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + --cp; + *cp = '\0'; + +} + + +char *prom_getenv(char *envname) +{ + /* + * Return a pointer to the given environment variable. + * Environment variables are stored in the form of "memsize=64". + */ + + t_env_var *env = (t_env_var *)prom_envp; + int i; + + i = strlen(envname); + + while(env->name) { + if(strncmp(envname, env->name, i) == 0) { + return(env->name + strlen(envname) + 1); + } + env++; + } + return(NULL); +} + +static inline unsigned char str2hexnum(unsigned char c) +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'a' && c <= 'f') + return c - 'a' + 10; + return 0; /* foo */ +} + +unsigned long __init prom_free_prom_memory(void) +{ + return 0; +} + +unsigned long __init prom_get_memsize(void) +{ + char *memsize_str; + unsigned int memsize; + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { +#ifdef CONFIG_MIPS_ITE8172 + memsize = 32; +#elif defined(CONFIG_MIPS_IVR) + memsize = 64; +#else + memsize = 8; +#endif + printk("memsize unknown: setting to %dMB\n", memsize); + } else { + printk("memsize: %s\n", memsize_str); + memsize = simple_strtol(memsize_str, NULL, 0); + } + return memsize; +} diff --git a/arch/mips/ite-boards/generic/puts.c b/arch/mips/ite-boards/generic/puts.c new file mode 100644 index 000000000000..20b02df6b414 --- /dev/null +++ b/arch/mips/ite-boards/generic/puts.c @@ -0,0 +1,139 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Low level uart routines to directly access a 16550 uart. + * + * Copyright 2000,2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS 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/types.h> + +#define SERIAL_BASE 0xB4011800 /* it8172 */ +#define SER_CMD 5 +#define SER_DATA 0x00 +#define TX_BUSY 0x20 + +#define TIMEOUT 0xffff +#undef SLOW_DOWN + +static const char digits[16] = "0123456789abcdef"; +static volatile unsigned char *const com1 = (unsigned char *) SERIAL_BASE; + + +#ifdef SLOW_DOWN +static inline void slow_down() +{ + int k; + for (k = 0; k < 10000; k++); +} +#else +#define slow_down() +#endif + +void putch(const unsigned char c) +{ + unsigned char ch; + int i = 0; + + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SER_DATA] = c; +} + +void puts(unsigned char *cp) +{ + unsigned char ch; + int i = 0; + + while (*cp) { + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SER_DATA] = *cp++; + } + putch('\r'); + putch('\n'); +} + +void fputs(unsigned char *cp) +{ + unsigned char ch; + int i = 0; + + while (*cp) { + + do { + ch = com1[SER_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SER_DATA] = *cp++; + } +} + + +void put64(uint64_t ul) +{ + int cnt; + unsigned ch; + + cnt = 16; /* 16 nibbles in a 64 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char) (ul >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); +} + +void put32(unsigned u) +{ + int cnt; + unsigned ch; + + cnt = 8; /* 8 nibbles in a 32 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char) (u >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); +} diff --git a/arch/mips/ite-boards/generic/reset.c b/arch/mips/ite-boards/generic/reset.c new file mode 100644 index 000000000000..03bd5ba8c913 --- /dev/null +++ b/arch/mips/ite-boards/generic/reset.c @@ -0,0 +1,60 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * ITE 8172 reset routines. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS 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/sched.h> +#include <linux/mm.h> +#include <asm/cacheflush.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/reboot.h> +#include <asm/system.h> + +void it8172_restart() +{ + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void it8172_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void it8172_power_off(void) +{ + it8172_halt(); +} diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c new file mode 100644 index 000000000000..30a6c0d5fc50 --- /dev/null +++ b/arch/mips/ite-boards/generic/time.c @@ -0,0 +1,247 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * Copyright (C) 2003 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Setting up the clock on the MIPS boards. + */ +#include <linux/init.h> +#include <linux/kernel_stat.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/spinlock.h> + +#include <asm/time.h> +#include <asm/mipsregs.h> +#include <asm/ptrace.h> +#include <asm/it8172/it8172.h> +#include <asm/it8172/it8172_int.h> +#include <asm/debug.h> + +#define IT8172_RTC_ADR_REG (IT8172_PCI_IO_BASE + IT_RTC_BASE) +#define IT8172_RTC_DAT_REG (IT8172_RTC_ADR_REG + 1) +#define IT8172_RTC_CENTURY_REG (IT8172_PCI_IO_BASE + IT_RTC_CENTURY) + +static volatile char *rtc_adr_reg = (char*)KSEG1ADDR(IT8172_RTC_ADR_REG); +static volatile char *rtc_dat_reg = (char*)KSEG1ADDR(IT8172_RTC_DAT_REG); +static volatile char *rtc_century_reg = (char*)KSEG1ADDR(IT8172_RTC_CENTURY_REG); + +unsigned char it8172_rtc_read_data(unsigned long addr) +{ + unsigned char retval; + + *rtc_adr_reg = addr; + retval = *rtc_dat_reg; + return retval; +} + +void it8172_rtc_write_data(unsigned char data, unsigned long addr) +{ + *rtc_adr_reg = addr; + *rtc_dat_reg = data; +} + +#undef CMOS_READ +#undef CMOS_WRITE +#define CMOS_READ(addr) it8172_rtc_read_data(addr) +#define CMOS_WRITE(data, addr) it8172_rtc_write_data(data, addr) + +static unsigned char saved_control; /* remember rtc control reg */ +static inline int rtc_24h(void) { return saved_control & RTC_24H; } +static inline int rtc_dm_binary(void) { return saved_control & RTC_DM_BINARY; } + +static inline unsigned char +bin_to_hw(unsigned char c) +{ + if (rtc_dm_binary()) + return c; + else + return ((c/10) << 4) + (c%10); +} + +static inline unsigned char +hw_to_bin(unsigned char c) +{ + if (rtc_dm_binary()) + return c; + else + return (c>>4)*10 + (c &0xf); +} + +/* 0x80 bit indicates pm in 12-hour format */ +static inline unsigned char +hour_bin_to_hw(unsigned char c) +{ + if (rtc_24h()) + return bin_to_hw(c); + if (c >= 12) + return 0x80 | bin_to_hw((c==12)?12:c-12); /* 12 is 12pm */ + else + return bin_to_hw((c==0)?12:c); /* 0 is 12 AM, not 0 am */ +} + +static inline unsigned char +hour_hw_to_bin(unsigned char c) +{ + unsigned char tmp = hw_to_bin(c&0x3f); + if (rtc_24h()) + return tmp; + if (c & 0x80) + return (tmp==12)?12:tmp+12; /* 12pm is 12, not 24 */ + else + return (tmp==12)?0:tmp; /* 12am is 0 */ +} + +static unsigned long r4k_offset; /* Amount to increment compare reg each time */ +static unsigned long r4k_cur; /* What counter should be at next timer irq */ +extern unsigned int mips_hpt_frequency; + +/* + * Figure out the r4k offset, the amount to increment the compare + * register for each time tick. + * Use the RTC to calculate offset. + */ +static unsigned long __init cal_r4koff(void) +{ + unsigned int flags; + + local_irq_save(flags); + + /* Start counter exactly on falling edge of update flag */ + while (CMOS_READ(RTC_REG_A) & RTC_UIP); + while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); + + /* Start r4k counter. */ + write_c0_count(0); + + /* Read counter exactly on falling edge of update flag */ + while (CMOS_READ(RTC_REG_A) & RTC_UIP); + while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); + + mips_hpt_frequency = read_c0_count(); + + /* restore interrupts */ + local_irq_restore(flags); + + return (mips_hpt_frequency / HZ); +} + +static unsigned long +it8172_rtc_get_time(void) +{ + unsigned int year, mon, day, hour, min, sec; + unsigned int flags; + + /* avoid update-in-progress. */ + for (;;) { + local_irq_save(flags); + if (! (CMOS_READ(RTC_REG_A) & RTC_UIP)) + break; + /* don't hold intr closed all the time */ + local_irq_restore(flags); + } + + /* Read regs. */ + sec = hw_to_bin(CMOS_READ(RTC_SECONDS)); + min = hw_to_bin(CMOS_READ(RTC_MINUTES)); + hour = hour_hw_to_bin(CMOS_READ(RTC_HOURS)); + day = hw_to_bin(CMOS_READ(RTC_DAY_OF_MONTH)); + mon = hw_to_bin(CMOS_READ(RTC_MONTH)); + year = hw_to_bin(CMOS_READ(RTC_YEAR)) + + hw_to_bin(*rtc_century_reg) * 100; + + /* restore interrupts */ + local_irq_restore(flags); + + return mktime(year, mon, day, hour, min, sec); +} + +static int +it8172_rtc_set_time(unsigned long t) +{ + struct rtc_time tm; + unsigned int flags; + + /* convert */ + to_tm(t, &tm); + + /* avoid update-in-progress. */ + for (;;) { + local_irq_save(flags); + if (! (CMOS_READ(RTC_REG_A) & RTC_UIP)) + break; + /* don't hold intr closed all the time */ + local_irq_restore(flags); + } + + *rtc_century_reg = bin_to_hw(tm.tm_year/100); + CMOS_WRITE(bin_to_hw(tm.tm_sec), RTC_SECONDS); + CMOS_WRITE(bin_to_hw(tm.tm_min), RTC_MINUTES); + CMOS_WRITE(hour_bin_to_hw(tm.tm_hour), RTC_HOURS); + CMOS_WRITE(bin_to_hw(tm.tm_mday), RTC_DAY_OF_MONTH); + CMOS_WRITE(bin_to_hw(tm.tm_mon+1), RTC_MONTH); /* tm_mon starts from 0 */ + CMOS_WRITE(bin_to_hw(tm.tm_year%100), RTC_YEAR); + + /* restore interrupts */ + local_irq_restore(flags); + + return 0; +} + +void __init it8172_time_init(void) +{ + unsigned int est_freq, flags; + + local_irq_save(flags); + + saved_control = CMOS_READ(RTC_CONTROL); + + printk("calculating r4koff... "); + r4k_offset = cal_r4koff(); + printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + + est_freq = 2*r4k_offset*HZ; + est_freq += 5000; /* round */ + est_freq -= est_freq%10000; + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + (est_freq%1000000)*100/1000000); + + local_irq_restore(flags); + + rtc_get_time = it8172_rtc_get_time; + rtc_set_time = it8172_rtc_set_time; +} + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) +void __init it8172_timer_setup(struct irqaction *irq) +{ + puts("timer_setup\n"); + put32(NR_IRQS); + puts(""); + /* we are using the cpu counter for timer interrupts */ + setup_irq(MIPS_CPU_TIMER_IRQ, irq); + + /* to generate the first timer interrupt */ + r4k_cur = (read_c0_count() + r4k_offset); + write_c0_compare(r4k_cur); + set_c0_status(ALLINTS); +} |