diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/lasat |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/mips/lasat')
-rw-r--r-- | arch/mips/lasat/Makefile | 14 | ||||
-rw-r--r-- | arch/mips/lasat/at93c.c | 148 | ||||
-rw-r--r-- | arch/mips/lasat/at93c.h | 18 | ||||
-rw-r--r-- | arch/mips/lasat/ds1603.c | 174 | ||||
-rw-r--r-- | arch/mips/lasat/ds1603.h | 33 | ||||
-rw-r--r-- | arch/mips/lasat/image/Makefile | 53 | ||||
-rw-r--r-- | arch/mips/lasat/image/head.S | 31 | ||||
-rw-r--r-- | arch/mips/lasat/image/romscript.normal | 22 | ||||
-rw-r--r-- | arch/mips/lasat/interrupt.c | 160 | ||||
-rw-r--r-- | arch/mips/lasat/lasatIRQ.S | 69 | ||||
-rw-r--r-- | arch/mips/lasat/lasat_board.c | 277 | ||||
-rw-r--r-- | arch/mips/lasat/lasat_models.h | 63 | ||||
-rw-r--r-- | arch/mips/lasat/picvue.c | 240 | ||||
-rw-r--r-- | arch/mips/lasat/picvue.h | 48 | ||||
-rw-r--r-- | arch/mips/lasat/picvue_proc.c | 186 | ||||
-rw-r--r-- | arch/mips/lasat/prom.c | 143 | ||||
-rw-r--r-- | arch/mips/lasat/prom.h | 6 | ||||
-rw-r--r-- | arch/mips/lasat/reset.c | 67 | ||||
-rw-r--r-- | arch/mips/lasat/setup.c | 192 | ||||
-rw-r--r-- | arch/mips/lasat/sysctl.c | 355 | ||||
-rw-r--r-- | arch/mips/lasat/sysctl.h | 24 |
21 files changed, 2323 insertions, 0 deletions
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile new file mode 100644 index 00000000000..0d5aec43672 --- /dev/null +++ b/arch/mips/lasat/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for the LASAT specific kernel interface routines under Linux. +# + +obj-y += reset.o setup.o prom.o lasat_board.o \ + at93c.o interrupt.o lasatIRQ.o + +obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o +obj-$(CONFIG_DS1603) += ds1603.o +obj-$(CONFIG_PICVUE) += picvue.o +obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o + +clean: + make -C image clean diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c new file mode 100644 index 00000000000..f6add041ebe --- /dev/null +++ b/arch/mips/lasat/at93c.c @@ -0,0 +1,148 @@ +/* + * Atmel AT93C46 serial eeprom driver + * + * Brian Murphy <brian.murphy@eicon.com> + * + */ +#include <linux/kernel.h> +#include <linux/delay.h> +#include <asm/lasat/lasat.h> +#include <linux/module.h> +#include <linux/init.h> + +#include "at93c.h" + +#define AT93C_ADDR_SHIFT 7 +#define AT93C_ADDR_MAX ((1 << AT93C_ADDR_SHIFT) - 1) +#define AT93C_RCMD (0x6 << AT93C_ADDR_SHIFT) +#define AT93C_WCMD (0x5 << AT93C_ADDR_SHIFT) +#define AT93C_WENCMD 0x260 +#define AT93C_WDSCMD 0x200 + +struct at93c_defs *at93c; + +static void at93c_reg_write(u32 val) +{ + *at93c->reg = val; +} + +static u32 at93c_reg_read(void) +{ + u32 tmp = *at93c->reg; + return tmp; +} + +static u32 at93c_datareg_read(void) +{ + u32 tmp = *at93c->rdata_reg; + return tmp; +} + +static void at93c_cycle_clk(u32 data) +{ + at93c_reg_write(data | at93c->clk); + lasat_ndelay(250); + at93c_reg_write(data & ~at93c->clk); + lasat_ndelay(250); +} + +static void at93c_write_databit(u8 bit) +{ + u32 data = at93c_reg_read(); + if (bit) + data |= 1 << at93c->wdata_shift; + else + data &= ~(1 << at93c->wdata_shift); + + at93c_reg_write(data); + lasat_ndelay(100); + at93c_cycle_clk(data); +} + +static unsigned int at93c_read_databit(void) +{ + u32 data; + + at93c_cycle_clk(at93c_reg_read()); + data = (at93c_datareg_read() >> at93c->rdata_shift) & 1; + return data; +} + +static u8 at93c_read_byte(void) +{ + int i; + u8 data = 0; + + for (i = 0; i<=7; i++) { + data <<= 1; + data |= at93c_read_databit(); + } + return data; +} + +static void at93c_write_bits(u32 data, int size) +{ + int i; + int shift = size - 1; + u32 mask = (1 << shift); + + for (i = 0; i < size; i++) { + at93c_write_databit((data & mask) >> shift); + data <<= 1; + } +} + +static void at93c_init_op(void) +{ + at93c_reg_write((at93c_reg_read() | at93c->cs) & ~at93c->clk & ~(1 << at93c->rdata_shift)); + lasat_ndelay(50); +} + +static void at93c_end_op(void) +{ + at93c_reg_write(at93c_reg_read() & ~at93c->cs); + lasat_ndelay(250); +} + +static void at93c_wait(void) +{ + at93c_init_op(); + while (!at93c_read_databit()) + ; + at93c_end_op(); +}; + +static void at93c_disable_wp(void) +{ + at93c_init_op(); + at93c_write_bits(AT93C_WENCMD, 10); + at93c_end_op(); +} + +static void at93c_enable_wp(void) +{ + at93c_init_op(); + at93c_write_bits(AT93C_WDSCMD, 10); + at93c_end_op(); +} + +u8 at93c_read(u8 addr) +{ + u8 byte; + at93c_init_op(); + at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_RCMD, 10); + byte = at93c_read_byte(); + at93c_end_op(); + return byte; +} + +void at93c_write(u8 addr, u8 data) +{ + at93c_disable_wp(); + at93c_init_op(); + at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_WCMD, 10); + at93c_write_bits(data, 8); + at93c_end_op(); + at93c_wait(); + at93c_enable_wp(); +} diff --git a/arch/mips/lasat/at93c.h b/arch/mips/lasat/at93c.h new file mode 100644 index 00000000000..a912ac2171b --- /dev/null +++ b/arch/mips/lasat/at93c.h @@ -0,0 +1,18 @@ +/* + * Atmel AT93C46 serial eeprom driver + * + * Brian Murphy <brian.murphy@eicon.com> + * + */ + +extern struct at93c_defs { + volatile u32 *reg; + volatile u32 *rdata_reg; + int rdata_shift; + int wdata_shift; + u32 cs; + u32 clk; +} *at93c; + +u8 at93c_read(u8 addr); +void at93c_write(u8 addr, u8 data); diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c new file mode 100644 index 00000000000..7bbf6cf923c --- /dev/null +++ b/arch/mips/lasat/ds1603.c @@ -0,0 +1,174 @@ +/* + * Dallas Semiconductors 1603 RTC driver + * + * Brian Murphy <brian@murphy.dk> + * + */ +#include <linux/kernel.h> +#include <asm/lasat/lasat.h> +#include <linux/delay.h> +#include <asm/lasat/ds1603.h> + +#include "ds1603.h" + +#define READ_TIME_CMD 0x81 +#define SET_TIME_CMD 0x80 +#define TRIMMER_SET_CMD 0xC0 +#define TRIMMER_VALUE_MASK 0x38 +#define TRIMMER_SHIFT 3 + +struct ds_defs *ds1603 = NULL; + +/* HW specific register functions */ +static void rtc_reg_write(unsigned long val) +{ + *ds1603->reg = val; +} + +static unsigned long rtc_reg_read(void) +{ + unsigned long tmp = *ds1603->reg; + return tmp; +} + +static unsigned long rtc_datareg_read(void) +{ + unsigned long tmp = *ds1603->data_reg; + return tmp; +} + +static void rtc_nrst_high(void) +{ + rtc_reg_write(rtc_reg_read() | ds1603->rst); +} + +static void rtc_nrst_low(void) +{ + rtc_reg_write(rtc_reg_read() & ~ds1603->rst); +} + +static void rtc_cycle_clock(unsigned long data) +{ + data |= ds1603->clk; + rtc_reg_write(data); + lasat_ndelay(250); + if (ds1603->data_reversed) + data &= ~ds1603->data; + else + data |= ds1603->data; + data &= ~ds1603->clk; + rtc_reg_write(data); + lasat_ndelay(250 + ds1603->huge_delay); +} + +static void rtc_write_databit(unsigned int bit) +{ + unsigned long data = rtc_reg_read(); + if (ds1603->data_reversed) + bit = !bit; + if (bit) + data |= ds1603->data; + else + data &= ~ds1603->data; + + rtc_reg_write(data); + lasat_ndelay(50 + ds1603->huge_delay); + rtc_cycle_clock(data); +} + +static unsigned int rtc_read_databit(void) +{ + unsigned int data; + + data = (rtc_datareg_read() & (1 << ds1603->data_read_shift)) + >> ds1603->data_read_shift; + rtc_cycle_clock(rtc_reg_read()); + return data; +} + +static void rtc_write_byte(unsigned int byte) +{ + int i; + + for (i = 0; i<=7; i++) { + rtc_write_databit(byte & 1L); + byte >>= 1; + } +} + +static void rtc_write_word(unsigned long word) +{ + int i; + + for (i = 0; i<=31; i++) { + rtc_write_databit(word & 1L); + word >>= 1; + } +} + +static unsigned long rtc_read_word(void) +{ + int i; + unsigned long word = 0; + unsigned long shift = 0; + + for (i = 0; i<=31; i++) { + word |= rtc_read_databit() << shift; + shift++; + } + return word; +} + +static void rtc_init_op(void) +{ + rtc_nrst_high(); + + rtc_reg_write(rtc_reg_read() & ~ds1603->clk); + + lasat_ndelay(50); +} + +static void rtc_end_op(void) +{ + rtc_nrst_low(); + lasat_ndelay(1000); +} + +/* interface */ +unsigned long ds1603_read(void) +{ + unsigned long word; + rtc_init_op(); + rtc_write_byte(READ_TIME_CMD); + word = rtc_read_word(); + rtc_end_op(); + return word; +} + +int ds1603_set(unsigned long time) +{ + rtc_init_op(); + rtc_write_byte(SET_TIME_CMD); + rtc_write_word(time); + rtc_end_op(); + + return 0; +} + +void ds1603_set_trimmer(unsigned int trimval) +{ + rtc_init_op(); + rtc_write_byte(((trimval << TRIMMER_SHIFT) & TRIMMER_VALUE_MASK) + | (TRIMMER_SET_CMD)); + rtc_end_op(); +} + +void ds1603_disable(void) +{ + ds1603_set_trimmer(TRIMMER_DISABLE_RTC); +} + +void ds1603_enable(void) +{ + ds1603_set_trimmer(TRIMMER_DEFAULT); +} diff --git a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h new file mode 100644 index 00000000000..55f3b0423c2 --- /dev/null +++ b/arch/mips/lasat/ds1603.h @@ -0,0 +1,33 @@ +/* + * Dallas Semiconductors 1603 RTC driver + * + * Brian Murphy <brian@murphy.dk> + * + */ +#ifndef __DS1603_H +#define __DS1603_H + +struct ds_defs { + volatile u32 *reg; + volatile u32 *data_reg; + u32 rst; + u32 clk; + u32 data; + u32 data_read_shift; + char data_reversed; + u32 huge_delay; +}; + +extern struct ds_defs *ds1603; + +unsigned long ds1603_read(void); +int ds1603_set(unsigned long); +void ds1603_set_trimmer(unsigned int); +void ds1603_enable(void); +void ds1603_disable(void); +void ds1603_init(struct ds_defs *); + +#define TRIMMER_DEFAULT 3 +#define TRIMMER_DISABLE_RTC 0 + +#endif diff --git a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile new file mode 100644 index 00000000000..18b6430f11b --- /dev/null +++ b/arch/mips/lasat/image/Makefile @@ -0,0 +1,53 @@ +# +# MAKEFILE FOR THE MIPS LINUX BOOTLOADER AND ROM DEBUGGER +# +# i-data Networks +# +# Author: Thomas Horsten <thh@i-data.com> +# + +ifndef Version + Version = "$(USER)-test" +endif + +MKLASATIMG = mklasatimg +MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200 +KERNEL_IMAGE = $(TOPDIR)/vmlinux +KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ ) +KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ ) + +LDSCRIPT= -L$(obj) -Tromscript.normal + +HEAD_DEFINES := -D_kernel_start=0x$(KERNEL_START) \ + -D_kernel_entry=0x$(KERNEL_ENTRY) \ + -D VERSION="\"$(Version)\"" \ + -D TIMESTAMP=$(shell date +%s) + +$(obj)/head.o: $(obj)/head.S $(KERNEL_IMAGE) + $(CC) -fno-pic $(HEAD_DEFINES) -I$(TOPDIR)/include -c -o $@ $< + +OBJECTS = head.o kImage.o + +rom.sw: $(obj)/rom.sw + +$(obj)/rom.sw: $(obj)/rom.bin + $(MKLASATIMG) -o $@ -k $^ -m $(MKLASATIMG_ARCH) + +$(obj)/rom.bin: $(obj)/rom + $(OBJCOPY) -O binary -S $^ $@ + +# Rule to make the bootloader +$(obj)/rom: $(addprefix $(obj)/,$(OBJECTS)) + $(LD) $(LDFLAGS) $(LDSCRIPT) -o $@ $^ + +$(obj)/%.o: $(obj)/%.gz + $(LD) -r -o $@ -b binary $< + +$(obj)/%.gz: $(obj)/%.bin + gzip -cf -9 $< > $@ + +$(obj)/kImage.bin: $(KERNEL_IMAGE) + $(OBJCOPY) -O binary -S $^ $@ + +clean: + rm -f rom rom.bin rom.sw kImage.bin kImage.o diff --git a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S new file mode 100644 index 00000000000..426bd7de17b --- /dev/null +++ b/arch/mips/lasat/image/head.S @@ -0,0 +1,31 @@ +#include <asm/lasat/head.h> + + .text + .section .text.start, "ax" + .set noreorder + .set mips3 + + /* Magic words identifying a software image */ + .word LASAT_K_MAGIC0_VAL + .word LASAT_K_MAGIC1_VAL + + /* Image header version */ + .word 0x00000002 + + /* image start and size */ + .word _image_start + .word _image_size + + /* start of kernel and entrypoint in uncompressed image */ + .word _kernel_start + .word _kernel_entry + + /* Here we have room for future flags */ + + .org 0x40 +reldate: + .word TIMESTAMP + + .org 0x50 +release: + .string VERSION diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal new file mode 100644 index 00000000000..ca22336f6c3 --- /dev/null +++ b/arch/mips/lasat/image/romscript.normal @@ -0,0 +1,22 @@ +OUTPUT_ARCH(mips) + +SECTIONS +{ + .text : + { + *(.text.start) + } + + /* Data in ROM */ + + .data ALIGN(0x10) : + { + *(.data) + } + _image_start = ADDR(.data); + _image_size = SIZEOF(.data); + + .other : { + *(.*) + } +} diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c new file mode 100644 index 00000000000..1148a2d20aa --- /dev/null +++ b/arch/mips/lasat/interrupt.c @@ -0,0 +1,160 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Routines for generic manipulation of the interrupts found on the + * Lasat boards. + */ +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/kernel_stat.h> + +#include <asm/bootinfo.h> +#include <asm/irq.h> +#include <asm/lasat/lasatint.h> +#include <asm/gdb-stub.h> + +static volatile int *lasat_int_status = NULL; +static volatile int *lasat_int_mask = NULL; +static volatile int lasat_int_mask_shift; + +extern asmlinkage void lasatIRQ(void); + +void disable_lasat_irq(unsigned int irq_nr) +{ + unsigned long flags; + + local_irq_save(flags); + *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift; + local_irq_restore(flags); +} + +void enable_lasat_irq(unsigned int irq_nr) +{ + unsigned long flags; + + local_irq_save(flags); + *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift; + local_irq_restore(flags); +} + +static unsigned int startup_lasat_irq(unsigned int irq) +{ + enable_lasat_irq(irq); + + return 0; /* never anything pending */ +} + +#define shutdown_lasat_irq disable_lasat_irq + +#define mask_and_ack_lasat_irq disable_lasat_irq + +static void end_lasat_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_lasat_irq(irq); +} + +static struct hw_interrupt_type lasat_irq_type = { + "Lasat", + startup_lasat_irq, + shutdown_lasat_irq, + enable_lasat_irq, + disable_lasat_irq, + mask_and_ack_lasat_irq, + end_lasat_irq, + NULL +}; + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +static unsigned long (* get_int_status)(void); + +static unsigned long get_int_status_100(void) +{ + return *lasat_int_status & *lasat_int_mask; +} + +static unsigned long get_int_status_200(void) +{ + unsigned long int_status; + + int_status = *lasat_int_status; + int_status &= (int_status >> LASATINT_MASK_SHIFT_200) & 0xffff; + return int_status; +} + +void lasat_hw0_irqdispatch(struct pt_regs *regs) +{ + unsigned long int_status; + int irq; + + int_status = get_int_status(); + + /* if int_status == 0, then the interrupt has already been cleared */ + if (int_status) { + irq = ls1bit32(int_status); + + do_IRQ(irq, regs); + } +} + +void __init arch_init_irq(void) +{ + int i; + + switch (mips_machtype) { + case MACH_LASAT_100: + lasat_int_status = (void *)LASAT_INT_STATUS_REG_100; + lasat_int_mask = (void *)LASAT_INT_MASK_REG_100; + lasat_int_mask_shift = LASATINT_MASK_SHIFT_100; + get_int_status = get_int_status_100; + *lasat_int_mask = 0; + break; + case MACH_LASAT_200: + lasat_int_status = (void *)LASAT_INT_STATUS_REG_200; + lasat_int_mask = (void *)LASAT_INT_MASK_REG_200; + lasat_int_mask_shift = LASATINT_MASK_SHIFT_200; + get_int_status = get_int_status_200; + *lasat_int_mask &= 0xffff; + break; + default: + panic("arch_init_irq: mips_machtype incorrect"); + } + + /* Now safe to set the exception vector. */ + set_except_vector(0, lasatIRQ); + + for (i = 0; i <= LASATINT_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &lasat_irq_type; + } +} diff --git a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S new file mode 100644 index 00000000000..2a2b0d05656 --- /dev/null +++ b/arch/mips/lasat/lasatIRQ.S @@ -0,0 +1,69 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Interrupt exception dispatch code. + */ +#include <asm/asm.h> +#include <asm/mipsregs.h> +#include <asm/regdef.h> +#include <asm/stackframe.h> + + .text + .set noreorder + .align 5 + NESTED(lasatIRQ, PT_SIZE, sp) + .set noat + SAVE_ALL + CLI + .set at + .set noreorder + + mfc0 s0, CP0_CAUSE # get irq mask + + /* First we check for r4k counter/timer IRQ. */ + andi a0, s0, CAUSEF_IP7 + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt + + /* Wheee, a timer interrupt. */ + li a0, 7 + jal ll_timer_interrupt + move a1, sp + + j ret_from_irq + nop + +1: + /* Wheee, combined hardware level zero interrupt. */ + jal lasat_hw0_irqdispatch + move a0, sp # delay slot + + j ret_from_irq + nop # delay slot + +1: + /* + * Here by mistake? This is possible, what can happen is that by the + * time we take the exception the IRQ pin goes low, so just leave if + * this is the case. + */ + move a1,s0 + mfc0 a1, CP0_EPC + + j ret_from_irq + nop + END(lasatIRQ) diff --git a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c new file mode 100644 index 00000000000..8c784bcf111 --- /dev/null +++ b/arch/mips/lasat/lasat_board.c @@ -0,0 +1,277 @@ +/* + * Thomas Horsten <thh@lasat.com> + * Copyright (C) 2000 LASAT Networks A/S. + * + * 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. + * + * Routines specific to the LASAT boards + */ +#include <linux/config.h> +#include <linux/types.h> +#include <linux/crc32.h> +#include <asm/lasat/lasat.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/ctype.h> +#include <asm/bootinfo.h> +#include <asm/addrspace.h> +#include "at93c.h" +/* New model description table */ +#include "lasat_models.h" + +#define EEPROM_CRC(data, len) (~0 ^ crc32(~0, data, len)) + +struct lasat_info lasat_board_info; + +void update_bcastaddr(void); + +int EEPROMRead(unsigned int pos, unsigned char *data, int len) +{ + int i; + + for (i=0; i<len; i++) + *data++ = at93c_read(pos++); + + return 0; +} +int EEPROMWrite(unsigned int pos, unsigned char *data, int len) +{ + int i; + + for (i=0; i<len; i++) + at93c_write(pos++, *data++); + + return 0; +} + +static void init_flash_sizes(void) +{ + int i; + unsigned long *lb = lasat_board_info.li_flashpart_base; + unsigned long *ls = lasat_board_info.li_flashpart_size; + + ls[LASAT_MTD_BOOTLOADER] = 0x40000; + ls[LASAT_MTD_SERVICE] = 0xC0000; + ls[LASAT_MTD_NORMAL] = 0x100000; + + if (mips_machtype == MACH_LASAT_100) { + lasat_board_info.li_flash_base = 0x1e000000; + + lb[LASAT_MTD_BOOTLOADER] = 0x1e400000; + + if (lasat_board_info.li_flash_size > 0x200000) { + ls[LASAT_MTD_CONFIG] = 0x100000; + ls[LASAT_MTD_FS] = 0x500000; + } + } else { + lasat_board_info.li_flash_base = 0x10000000; + + if (lasat_board_info.li_flash_size < 0x1000000) { + lb[LASAT_MTD_BOOTLOADER] = 0x10000000; + ls[LASAT_MTD_CONFIG] = 0x100000; + if (lasat_board_info.li_flash_size >= 0x400000) { + ls[LASAT_MTD_FS] = lasat_board_info.li_flash_size - 0x300000; + } + } + } + + for (i = 1; i < LASAT_MTD_LAST; i++) + lb[i] = lb[i-1] + ls[i-1]; +} + +int lasat_init_board_info(void) +{ + int c; + unsigned long crc; + unsigned long cfg0, cfg1; + const product_info_t *ppi; + int i_n_base_models = N_BASE_MODELS; + const char * const * i_txt_base_models = txt_base_models; + int i_n_prids = N_PRIDS; + + memset(&lasat_board_info, 0, sizeof(lasat_board_info)); + + /* First read the EEPROM info */ + EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info, + sizeof(struct lasat_eeprom_struct)); + + /* Check the CRC */ + crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info), + sizeof(struct lasat_eeprom_struct) - 4); + + if (crc != lasat_board_info.li_eeprom_info.crc32) { + prom_printf("WARNING...\nWARNING...\nEEPROM CRC does not match calculated, attempting to soldier on...\n"); + } + + if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION) + { + prom_printf("WARNING...\nWARNING...\nEEPROM version %d, wanted version %d, attempting to soldier on...\n", + (unsigned int)lasat_board_info.li_eeprom_info.version, + LASAT_EEPROM_VERSION); + } + + cfg0 = lasat_board_info.li_eeprom_info.cfg[0]; + cfg1 = lasat_board_info.li_eeprom_info.cfg[1]; + + if ( LASAT_W0_DSCTYPE(cfg0) != 1) { + prom_printf("WARNING...\nWARNING...\nInvalid configuration read from EEPROM, attempting to soldier on..."); + } + /* We have a valid configuration */ + + switch (LASAT_W0_SDRAMBANKSZ(cfg0)) { + case 0: + lasat_board_info.li_memsize = 0x0800000; + break; + case 1: + lasat_board_info.li_memsize = 0x1000000; + break; + case 2: + lasat_board_info.li_memsize = 0x2000000; + break; + case 3: + lasat_board_info.li_memsize = 0x4000000; + break; + case 4: + lasat_board_info.li_memsize = 0x8000000; + break; + default: + lasat_board_info.li_memsize = 0; + } + + switch (LASAT_W0_SDRAMBANKS(cfg0)) { + case 0: + break; + case 1: + lasat_board_info.li_memsize *= 2; + break; + default: + break; + } + + switch (LASAT_W0_BUSSPEED(cfg0)) { + case 0x0: + lasat_board_info.li_bus_hz = 60000000; + break; + case 0x1: + lasat_board_info.li_bus_hz = 66000000; + break; + case 0x2: + lasat_board_info.li_bus_hz = 66666667; + break; + case 0x3: + lasat_board_info.li_bus_hz = 80000000; + break; + case 0x4: + lasat_board_info.li_bus_hz = 83333333; + break; + case 0x5: + lasat_board_info.li_bus_hz = 100000000; + break; + } + + switch (LASAT_W0_CPUCLK(cfg0)) { + case 0x0: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz; + break; + case 0x1: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz + + (lasat_board_info.li_bus_hz >> 1); + break; + case 0x2: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz + + lasat_board_info.li_bus_hz; + break; + case 0x3: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz + + lasat_board_info.li_bus_hz + + (lasat_board_info.li_bus_hz >> 1); + break; + case 0x4: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz + + lasat_board_info.li_bus_hz + + lasat_board_info.li_bus_hz; + break; + } + + /* Flash size */ + switch (LASAT_W1_FLASHSIZE(cfg1)) { + case 0: + lasat_board_info.li_flash_size = 0x200000; + break; + case 1: + lasat_board_info.li_flash_size = 0x400000; + break; + case 2: + lasat_board_info.li_flash_size = 0x800000; + break; + case 3: + lasat_board_info.li_flash_size = 0x1000000; + break; + case 4: + lasat_board_info.li_flash_size = 0x2000000; + break; + } + + init_flash_sizes(); + + lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0); + lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid; + if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0) + lasat_board_info.li_prid = lasat_board_info.li_bmid; + + /* Base model stuff */ + if (lasat_board_info.li_bmid > i_n_base_models) + lasat_board_info.li_bmid = i_n_base_models; + strcpy(lasat_board_info.li_bmstr, i_txt_base_models[lasat_board_info.li_bmid]); + + /* Product ID dependent values */ + c = lasat_board_info.li_prid; + if (c >= i_n_prids) { + strcpy(lasat_board_info.li_namestr, "Unknown Model"); + strcpy(lasat_board_info.li_typestr, "Unknown Type"); + } else { + ppi = &vendor_info_table[0].vi_product_info[c]; + strcpy(lasat_board_info.li_namestr, ppi->pi_name); + if (ppi->pi_type) + strcpy(lasat_board_info.li_typestr, ppi->pi_type); + else + sprintf(lasat_board_info.li_typestr, "%d",10*c); + } + +#if defined(CONFIG_INET) && defined(CONFIG_SYSCTL) + update_bcastaddr(); +#endif + + return 0; +} + +void lasat_write_eeprom_info(void) +{ + unsigned long crc; + + /* Generate the CRC */ + crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info), + sizeof(struct lasat_eeprom_struct) - 4); + lasat_board_info.li_eeprom_info.crc32 = crc; + + /* Write the EEPROM info */ + EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info, + sizeof(struct lasat_eeprom_struct)); +} + diff --git a/arch/mips/lasat/lasat_models.h b/arch/mips/lasat/lasat_models.h new file mode 100644 index 00000000000..ae0c5d0bd40 --- /dev/null +++ b/arch/mips/lasat/lasat_models.h @@ -0,0 +1,63 @@ +/* + * Model description tables + */ + +typedef struct product_info_t { + const char *pi_name; + const char *pi_type; +} product_info_t; + +typedef struct vendor_info_t { + const char *vi_name; + const product_info_t *vi_product_info; +} vendor_info_t; + +/* + * Base m |