* [PATCH] ADM5120 for 2.6.10
@ 2005-01-27 20:34 Jeroen Vreeken
2005-01-27 21:01 ` sjhill
0 siblings, 1 reply; 8+ messages in thread
From: Jeroen Vreeken @ 2005-01-27 20:34 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1245 bytes --]
Hi,
I finally succeeded in getting 2.6.10 working on my adm5120 router.
Attached is a patch against 2.6.10 with the needed changes.
First a list of what it does NOT do:
-ethernet
-usb
-pci (my board doesn't have pci)
-anything usefull :)
What it does do:
-Boot
-Serial support (with improved timing compared to the official 2.4.18
kernels)
-Simplified init code (the 2.4.18 code was way to complex)
I also found the most probable reason people had problems porting the
released sources to other kernels: the bootloader jumps to a fixed
address that just happens to be the kernel_entry in 2.4.18
I 'solved' it by adding a jump on this address to the real kernel_entry
(which is at the other end of the kernel in 2.6)
I also had some great fun figuring out how the hell initramfs is
supposed to work.... To finally find out after two days I had one slash
to little in the configured path..... I also found that standard 2.6.10
doesn't support symlinks and my initramfs ended up being 14Mb.
Next I plan to port the ethernet driver and usb. I don't think I will
port the led driver as is, its much easier to just offer a character
device with access to the GPIO port than the 'LED BLINK' stuff used in
the ADMtek led driver.
Jeroen
[-- Attachment #2: linux-2.6.10-adm.1.diff --]
[-- Type: text/x-patch, Size: 132010 bytes --]
diff -ruN linux-2.6.10/Makefile linux-2.6.10-adm.1/Makefile
--- linux-2.6.10/Makefile 2004-12-24 22:35:01.000000000 +0100
+++ linux-2.6.10-adm.1/Makefile 2005-01-27 21:07:04.000000000 +0100
@@ -4,6 +4,8 @@
EXTRAVERSION =
NAME=Woozy Numbat
+ARCH=mips
+
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
# More info can be located in ./README
@@ -722,6 +724,10 @@
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
$(call if_changed_rule,vmlinux__)
+vmlinuz: vmlinux
+ $(OBJCOPY) -O binary vmlinux vmlinux.bin
+ gzip vmlinux.bin -c >vmlinuz
+
# The actual objects are generated when descending,
# make sure no implicit rule kicks in
$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
diff -ruN linux-2.6.10/arch/mips/Kconfig linux-2.6.10-adm.1/arch/mips/Kconfig
--- linux-2.6.10/arch/mips/Kconfig 2004-12-24 22:34:45.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/Kconfig 2005-01-27 21:06:17.000000000 +0100
@@ -46,6 +46,10 @@
the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
<http://www.linux-mips.org/>.
+config MIPS_AM5120
+ bool "Support for ADM5120 board"
+ select DMA_NONCOHERENT
+
config MIPS_MAGNUM_4000
bool "Support for MIPS Magnum 4000"
depends on MACH_JAZZ
diff -ruN linux-2.6.10/arch/mips/Makefile linux-2.6.10-adm.1/arch/mips/Makefile
--- linux-2.6.10/arch/mips/Makefile 2004-12-24 22:33:49.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/Makefile 2005-01-27 21:06:16.000000000 +0100
@@ -49,7 +49,7 @@
endif
ifdef CONFIG_CROSSCOMPILE
-CROSS_COMPILE := $(tool-prefix)
+CROSS_COMPILE := /export/tools/bin/$(tool-prefix)
endif
ifdef CONFIG_BUILD_ELF64
@@ -232,6 +232,13 @@
load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000
#
+# ADMtek 5120
+#
+
+core-$(CONFIG_MIPS_AM5120) += arch/mips/am5120/
+load-$(CONFIG_MIPS_AM5120) += 0xffffffff80002000
+
+#
# Common Alchemy Au1x00 stuff
#
core-$(CONFIG_SOC_AU1X00) += arch/mips/au1000/common/
diff -ruN linux-2.6.10/arch/mips/am5120/5120_rtc.c linux-2.6.10-adm.1/arch/mips/am5120/5120_rtc.c
--- linux-2.6.10/arch/mips/am5120/5120_rtc.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/5120_rtc.c 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,73 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;
+;------------------------------------------------------------------------------
+;
+; Project : ADM5120
+; Creator : daniell@admtek.com.tw
+; File : arch/mips/am5120/5120_rtc.c
+; Date : 2003.3.4
+; Abstract:
+;
+;Modification History:
+;
+;*****************************************************************************/
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/reboot.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+
+#include <linux/mc146818rtc.h>
+#include <asm/am5120/adm5120.h>
+#include <asm-arm/rtc.h>
+
+struct rtc_ops *rtc_ops=NULL;
+/*
+static unsigned char am5120_rtc_read_data(unsigned long addr)
+{
+ //outb(addr, MALTA_RTC_ADR_REG);
+ //return inb(MALTA_RTC_DAT_REG);
+ return 0;
+}
+
+static void am5120_rtc_write_data(unsigned char data, unsigned long addr)
+{
+ //outb(addr, MALTA_RTC_ADR_REG);
+ //outb(data, MALTA_RTC_DAT_REG);
+}
+
+static int am5120_rtc_bcd_mode(void)
+{
+ return 0;
+}
+
+struct rtc_ops am5120_rtc_ops = {
+ &am5120_rtc_read_data,
+ &am5120_rtc_write_data,
+ &am5120_rtc_bcd_mode
+};
+*/
diff -ruN linux-2.6.10/arch/mips/am5120/Makefile linux-2.6.10-adm.1/arch/mips/am5120/Makefile
--- linux-2.6.10/arch/mips/am5120/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/Makefile 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,3 @@
+
+obj-y := setup.o prom.o irq.o serial.o memory.o mipsIRQ.o time.o pci.o
+# 5120_rtc.o led.o
diff -ruN linux-2.6.10/arch/mips/am5120/irq.c linux-2.6.10-adm.1/arch/mips/am5120/irq.c
--- linux-2.6.10/arch/mips/am5120/irq.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/irq.c 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,181 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;
+;------------------------------------------------------------------------------
+;
+; Project : ADM5120
+; Creator : daniell@admtek.com.tw
+; File : arch/mips/am5120/irq.c
+; Date : 2003.3.4
+; Abstract:
+;
+;Modification History:
+;
+; Jeroen Vreeken (pe1rxq@amsat.org)
+; Simplified and merged with 5120_int.c
+;
+; Includes code by:
+; Carsten Langgaard, carstenl@mips.com
+; Copyright (C) 2000, 2001 MIPS Technologies, Inc.
+; Copyright (C) 2001 Ralf Baechle
+;
+;*****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/pm.h>
+
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/gdb-stub.h>
+
+#include <asm/am5120/adm5120.h>
+
+extern void breakpoint(void);
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+extern irq_desc_t irq_desc[];
+extern asmlinkage void mipsIRQ(void);
+
+int mips_int_lock(void);
+void mips_int_unlock(int);
+
+static spinlock_t mips_irq_lock = SPIN_LOCK_UNLOCKED;
+
+void am5120_hw0_irqdispatch(struct pt_regs *regs)
+{
+ unsigned long flags;
+ unsigned long intsrc;
+ int i;
+
+ /* We don't have multiple cpus, is this locking really needed???
+ - Jeroen
+ */
+ spin_lock_irqsave(&mips_irq_lock, flags);
+
+ intsrc = ADM5120_INTC_REG(IRQ_STATUS_REG) & IRQ_MASK;
+
+ for (i = 0; intsrc; intsrc >>= 1, i++)
+ if (intsrc & 0x1)
+ do_IRQ(i, regs);
+
+ spin_unlock_irqrestore(&mips_irq_lock, flags);
+}
+
+
+void enable_am5120_irq(unsigned int irq)
+{
+ int s;
+
+ /* Disable all interrupts (FIQ/IRQ) */
+ s = mips_int_lock();
+
+ if ((irq < 0) || (irq > INT_LVL_MAX))
+ goto err_exit;
+
+ ADM5120_INTC_REG(IRQ_ENABLE_REG) = (1<<irq);
+
+err_exit:
+
+ /* Restore the interrupts states */
+ mips_int_unlock(s);
+}
+
+
+void disable_am5120_irq(unsigned int irq)
+{
+ int s;
+
+ /* Disable all interrupts (FIQ/IRQ) */
+ s = mips_int_lock();
+
+ if ((irq < 0) || (irq > INT_LVL_MAX))
+ goto err_exit;
+
+ ADM5120_INTC_REG(IRQ_DISABLE_REG) = (1<<irq);
+
+err_exit:
+ /* Restore the interrupts states */
+ mips_int_unlock(s);
+}
+
+unsigned int startup_am5120_irq(unsigned int irq)
+{
+ enable_am5120_irq(irq);
+ return 0;
+}
+
+void shutdown_am5120_irq(unsigned int irq)
+{
+ disable_am5120_irq(irq);
+}
+
+static inline void ack_am5120_irq(unsigned int irq_nr)
+{
+ ADM5120_INTC_REG(IRQ_DISABLE_REG) = (1 << irq_nr);
+}
+
+
+static void end_am5120_irq(unsigned int irq_nr)
+{
+ ADM5120_INTC_REG(IRQ_ENABLE_REG) = (1 << irq_nr);
+}
+
+
+void set_affinity_am5120_irq(unsigned int irq, cpumask_t mask)
+{
+ return;
+}
+
+
+static hw_irq_controller am5120_irq_type = {
+ "ADM5120 INTC",
+ startup_am5120_irq,
+ shutdown_am5120_irq,
+ enable_am5120_irq,
+ disable_am5120_irq,
+ ack_am5120_irq,
+ end_am5120_irq,
+ set_affinity_am5120_irq
+};
+
+
+void __init arch_init_irq(void)
+{
+ int i;
+ set_except_vector(0, mipsIRQ);
+
+ for (i=0; i<=INT_LVL_MAX; i++) {
+ irq_desc[i].status=IRQ_DISABLED;
+ irq_desc[i].action=0;
+ irq_desc[i].depth=1;
+ irq_desc[i].handler=&am5120_irq_type;
+ }
+
+#ifdef CONFIG_REMOTE_DEBUG
+ printk("Setting debug traps - please connect the remote debugger.\n");
+
+ set_debug_traps();
+
+ breakpoint();
+#endif
+}
+
diff -ruN linux-2.6.10/arch/mips/am5120/led.c linux-2.6.10-adm.1/arch/mips/am5120/led.c
--- linux-2.6.10/arch/mips/am5120/led.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/led.c 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,493 @@
+/*
+ * LED interface for WP3200
+ *
+ * Copyright (C) 2002, by Allen Hung
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include "led.h"
+
+#define BUF_LEN 30
+
+struct LED_DATA {
+ char sts_buf[BUF_LEN+1];
+ unsigned long sts;
+};
+
+struct LED_DATA led_data[LED_DEV_NUM];
+// sam 01-30-2004 for watchdog
+static struct timer_list watchdog;
+// end sam
+
+static struct timer_list blink_timer[LED_DEV_NUM];
+static char cmd_buf[BUF_LEN+1];
+
+//------------------------------------------------------------
+static long atoh(char *p)
+{
+ long v = 0, c;
+ while ( (c = *p++) ) {
+ if ( c >= '0' && c <= '9' ) v = (v << 4) + c - '0';
+ else if ( c >= 'a' && c <= 'f' ) v = (v << 4) + c - 'a' + 0xA;
+ else if ( c >= 'A' && c <= 'F' ) v = (v << 4) + c - 'A' + 0xA;
+ else break;
+ }
+ return v;
+}
+
+
+#define GPIO_VAL (*(unsigned long *)0xb20000b8)
+#define GPIO_SEL (*(unsigned long *)0xb20000bc)
+#define GPIO_SEL_I_O (*(unsigned long *)0xb20000b8)
+#define GPIO_O_EN (*(unsigned long *)0xb20000b8)
+#define INIT_WATCHDOG_REGISTER 0x20
+
+// sam 1-30-2004 LED status
+// bit map as following
+// BIT 4:0 Link status -->PHY Link ->1 = up, 0 = down
+#define LINK_STATUS (*(unsigned long *)0xb2000014)
+#define WATCHDOG_VAL (*(unsigned long *)0xb20000c0)
+#define WATCHDOG_PERIOD 2000 // unit ms
+#define EXPIRE_TIME 300 // unit 10 ms
+#define CLEAR_TIMEER 0xffffa000l // bit 14:0 -> count up timer, write 0 to clear
+#define ENABLE_WATCHDOG 0x80000000l // bit 31 -> 1 enable , 0 disable watchdog
+#define WATCHDOG_SET_TMR_SHIFT 16 // bit 16:30 -> watchdog timer set
+// end sam
+//------------------------------------------------------------
+static void turn_led(int id, int on)
+{
+ unsigned long led_bit = 1 << (id);
+ unsigned long led_bit_val;
+
+ led_bit_val = led_bit << 24;
+
+ switch ( on ) {
+ case 0: GPIO_VAL |= led_bit_val; break; // LED OFF
+ case 1: GPIO_VAL &= ~led_bit_val; break; // LED ON
+ case 2: GPIO_VAL ^= led_bit_val; break; // LED inverse
+ }
+}
+
+static void blink_wrapper(u_long id)
+{
+ u_long sts = led_data[id].sts;
+ if ( (sts & LED_BLINK_CMD) == LED_BLINK_CMD ) {
+ int period = sts & LED_BLINK_PERIOD;
+ blink_timer[id].expires = jiffies + (period * HZ / 1000);
+ turn_led(id, 2);
+ add_timer(&blink_timer[id]);
+ }
+ else if ( sts == LED_ON || sts == LED_OFF )
+ turn_led(id, sts==LED_ON ? 1 : 0);
+}
+//------------------------------------------------------------
+static void get_token_str(char *str, char token[][21], int token_num)
+{
+ int t, i;
+ for ( t = 0 ; t < token_num ; t++ ) {
+ memset(token[t], 0, 21);
+ while ( *str == ' ' ) str++;
+ for ( i = 0 ; str[i] ; i++ ) {
+ if ( str[i] == '\t' || str[i] == ' ' || str[i] == '\n' ) break;
+ if ( i < 20 ) token[t][i] = str[i];
+ }
+ str += i;
+ }
+}
+
+//------------------------------------------------------------
+static void set_led_status_by_str(int id)
+{
+ char token[3][21], *p;
+
+ get_token_str(led_data[id].sts_buf, token, 3);
+ if ( strcmp(token[0], "LED") )
+ goto set_led_off;
+ if ( !strcmp(token[1], "ON") ) {
+ turn_led(id, 1);
+ led_data[id].sts = LED_ON;
+ }
+ else if ( !strcmp(token[1], "OFF") ) {
+ goto set_led_off;
+ }
+ else if ( !strcmp(token[1], "BLINK") ) {
+ int period = 0;
+ p = token[2];
+ if ( !strcmp(p, "FAST") )
+ period = LED_BLINK_FAST & LED_BLINK_PERIOD;
+ else if ( !strcmp(p, "SLOW") )
+ period = LED_BLINK_SLOW & LED_BLINK_PERIOD;
+ else if ( !strcmp(p, "EXTRA_SLOW") )
+ period = LED_BLINK_EXTRA_SLOW & LED_BLINK_PERIOD;
+ else if ( !strcmp(p, "OFF") )
+ goto set_led_off;
+ else if ( *p >= '0' && *p <= '9' ) {
+ while ( *p >= '0' && *p <= '9' )
+ period = period * 10 + (*p++) - '0';
+ if ( period > 10000 ) period = 10000;
+ }
+ else
+ period = LED_BLINK & LED_BLINK_PERIOD;
+ if ( period == 0 )
+ goto set_led_off;
+ sprintf(led_data[id].sts_buf, "LED BLINK %d\n", period);
+ led_data[id].sts = LED_BLINK_CMD + period;
+ turn_led(id, 2);
+ // Set timer for next blink
+ del_timer(&blink_timer[id]);
+ blink_timer[id].function = blink_wrapper;
+ blink_timer[id].data = id;
+ init_timer(&blink_timer[id]);
+ blink_timer[id].expires = jiffies + (period * HZ / 1000);
+ add_timer(&blink_timer[id]);
+ }
+ else
+ goto set_led_off;
+ return;
+ set_led_off:
+ strcpy(led_data[id].sts_buf, "LED OFF\n");
+ led_data[id].sts = LED_OFF;
+ turn_led(id, 0);
+}
+
+//----------------------------------------------------------------------
+static int led_read_proc(char *buf, char **start, off_t fpos, int length, int *eof, void *data)
+{
+ int len, dev;
+ for ( len = dev = 0 ; dev < LED_DEV_NUM ; dev++ ) {
+ len += sprintf(buf+len, "%d: %s", dev, led_data[dev].sts_buf);
+ }
+ len = strlen(buf) - fpos;
+ if ( len <= 0 ) {
+ *start = buf;
+ *eof = 1;
+ return 0;
+ }
+ *start = buf + fpos;
+ if ( len <= length ) *eof = 1;
+ return len < length ? len : length;
+}
+
+//----------------------------------------------------------------------
+static int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int id = (int)file->private_data;
+
+ switch ( cmd ) {
+ case LED_ON:
+ strcpy(led_data[id].sts_buf, "LED ON\n");
+ set_led_status_by_str(id);
+ break;
+ case LED_OFF:
+ strcpy(led_data[id].sts_buf, "LED OFF\n");
+ set_led_status_by_str(id);
+ break;
+ default:
+ if ( (cmd & LED_BLINK_CMD) != LED_BLINK_CMD )
+ break;
+ case LED_BLINK:
+ case LED_BLINK_FAST:
+ case LED_BLINK_SLOW:
+ case LED_BLINK_EXTRA_SLOW:
+ sprintf(led_data[id].sts_buf, "LED BLINK %d\n", (int)(cmd & LED_BLINK_PERIOD));
+ set_led_status_by_str(id);
+ break;
+ }
+ return 0;
+}
+
+static int led_open(struct inode *inode, struct file *file)
+{
+ int led_id = MINOR(inode->i_rdev);
+ unsigned long led_bit = 1 << (led_id);
+ if ( led_id >= LED_DEV_NUM )
+ return -ENODEV;
+
+ GPIO_SEL_I_O &= ~led_bit; // 0 to GPIO
+ GPIO_O_EN |= (led_bit << 16); // 0 to Output
+
+ file->private_data = (void*)led_id;
+ return 0;
+}
+
+static long led_read(struct file *file, char *buf, size_t count, loff_t *fpos)
+{
+ int rem, len;
+ int id = (int)file->private_data;
+ char *p = led_data[id].sts_buf;
+ len = strlen(p);
+ rem = len - *fpos;
+ if ( rem <= 0 ) {
+ *fpos = len;
+ return 0;
+ }
+ if ( rem > count ) rem = count;
+ memcpy(buf, p+(*fpos), rem);
+ *fpos += rem;
+ return rem;
+}
+
+static long led_write(struct file *file, char *buf, size_t count, loff_t *fpos)
+{
+ int len;
+ int id = (int)file->private_data;
+ char *p = id == REG_MINOR ? cmd_buf : led_data[id].sts_buf;
+ memset(p, 0, BUF_LEN);
+ p += *fpos;
+ len = 0;
+ while ( count > 0 ) {
+ if ( *fpos < BUF_LEN ) {
+ int c = *buf++;
+ p[len] = c>='a' && c<='z' ? c-'a'+'A' : c;
+ }
+ (*fpos)++;
+ len++;
+ count--;
+ }
+ return len;
+}
+
+static int led_flush(struct file *file)
+{
+ int id = (int)file->private_data;
+ if ( file->f_mode & FMODE_WRITE )
+ set_led_status_by_str(id);
+ return 0;
+}
+
+static struct file_operations led_fops = {
+ read: led_read,
+ write: led_write,
+ flush: led_flush,
+ ioctl: led_ioctl,
+ open: led_open,
+};
+
+//----------------------------------------------
+static unsigned long *reg_addr;
+static int dump_len;
+
+static int dump_content(char *buf)
+{
+ int i, j, len;
+ unsigned long *p = reg_addr;
+ j = dump_len/4 + ((dump_len&3) ? 1 : 0);
+ len = sprintf(buf, "Reg Addr = %08lX, Value = \n", (unsigned long)p);
+ for ( i = 0 ; i < j ; i++, p++ )
+ len += sprintf(buf+len,"%08lX%c", *p, (i&7)==7||i==j-1?'\n':' ');
+ return len;
+}
+
+static long gpio_read(struct file *file, char *buf, size_t count, loff_t *fpos)
+{
+ int rem, len;
+ int id = (int)file->private_data;
+ char temp[80*10];
+ if ( id < GPIO_DEV_NUM ) {
+ int gpio_bit = 1 << id;
+ len = sprintf(temp, "%d\n", ((GPIO_VAL >> 8)&gpio_bit) ? 1 : 0);
+ }
+ else // REG device
+ len = dump_content(temp);
+ rem = len - *fpos;
+ if ( rem <= 0 ) {
+ *fpos = len;
+ return 0;
+ }
+ if ( rem > count ) rem = count;
+ memcpy(buf, temp+(*fpos), rem);
+ *fpos += rem;
+ return rem;
+}
+
+static int gpio_flush(struct file *file)
+{
+ long v, addr;
+ int id = (int)file->private_data;
+
+ if ( id == REG_MINOR && (file->f_mode & FMODE_WRITE) ) {
+ char token[3][21], *p;
+ get_token_str(cmd_buf, token, 3);
+ // get reg address
+ p = token[0];
+ if ( *p == 0 ) return 0;
+ addr = atoh(p);
+ //---------------------
+ p = token[1];
+ if ( *p == 'W' ) {
+ int width = 0;
+ if ( !strcmp(p, "W") || !strcmp(p, "WW") )
+ width = 4;
+ else if ( !strcmp(p, "WH") )
+ width = 2;
+ else if ( !strcmp(p, "WB") )
+ width = 1;
+ else
+ return 0;
+ p = token[2];
+ if ( *p == 0 ) return 0;
+ v = atoh(p);
+ switch ( width ) {
+ case 1: *((char *)addr) = (v & 0xFF); break;
+ case 2: *((short*)addr) = (v & 0xFFFF); break;
+ case 4: *((long *)addr) = v; break;
+ }
+ }
+ else { // get dump len
+ char temp[80*10];
+ reg_addr = (unsigned long *)(addr & ~3);
+ dump_len = 4;
+ if ( *p ) {
+ dump_len = atoh(p);
+ dump_len = dump_len < 4 ? 4 : dump_len > 32*10 ? 32*10 : dump_len;
+ }
+ dump_content(temp);
+ printk( KERN_INFO "%s", temp);
+ }
+ cmd_buf[0] = 0;
+ }
+ return 0;
+}
+
+static int gpio_open(struct inode *inode, struct file *file)
+{
+ int id = MINOR(inode->i_rdev);
+ if ( id >= GPIO_DEV_NUM && id != REG_MINOR )
+ return -ENODEV;
+ if ( id < GPIO_DEV_NUM ) {
+ int gpio_bit = 1 << id;
+
+ GPIO_SEL = 0;
+ GPIO_SEL |= gpio_bit; // bit=0 for GPIO
+ }
+ file->private_data = (void*)id;
+ return 0;
+}
+
+static struct file_operations gpio_fops = {
+ read: gpio_read,
+ open: gpio_open,
+ flush: gpio_flush,
+ write: led_write,
+};
+
+//----------------------------------------------
+static void watchdog_wrapper(unsigned int period)
+{
+ // clear timer count
+ WATCHDOG_VAL &= CLEAR_TIMEER;
+ watchdog.expires = jiffies + (period * HZ / 1000);
+ add_timer(&watchdog);
+}
+//----------------------------------------------
+static int init_status;
+
+#define INIT_REGION 0x01
+#define INIT_LED_REGISTER 0x02
+#define INIT_LED_PROC_READ 0x04
+#define INIT_GPIO_REGISTER 0x08
+
+static void led_exit(void)
+{
+ int id;
+ for ( id = 0 ; id < LED_DEV_NUM ; id++ ) {
+ del_timer(&blink_timer[id]);
+ turn_led(id, 0);
+ }
+ if ( init_status & INIT_LED_PROC_READ )
+ remove_proc_entry("driver/led", NULL);
+
+ if ( init_status & INIT_LED_REGISTER )
+ unregister_chrdev(LED_MAJOR, "led");
+
+ if ( init_status & INIT_GPIO_REGISTER )
+ unregister_chrdev(GPIO_MAJOR, "gpio");
+
+ if ( init_status & INIT_REGION )
+ release_region(GPIO_IO_BASE, GPIO_IO_EXTENT);
+}
+
+static int __init led_init(void)
+{
+ int result, id;
+ init_status = 0;
+
+ //---- request region --------------------------
+ /*
+ if ( check_region(GPIO_IO_BASE, GPIO_IO_EXTENT) ) {
+ printk(KERN_ERR "gpio: I/O port %lX is not free.\n", GPIO_IO_BASE);
+ return -EIO;
+ }
+ request_region(GPIO_IO_BASE, GPIO_IO_EXTENT, "gpio");
+ init_status |= INIT_REGION;
+ */
+ //----- register device (LED)-------------------------
+ result = register_chrdev(LED_MAJOR, "led", &led_fops);
+ if ( result < 0 ) {
+ printk(KERN_ERR "led: can't register char device\n" );
+ led_exit();
+ return result;
+ }
+ init_status |= INIT_LED_REGISTER;
+ //----- register device (GPIO)-------------------------
+ result = register_chrdev(GPIO_MAJOR, "gpio", &gpio_fops);
+ if ( result < 0 ) {
+ printk(KERN_ERR "gpio: can't register char device\n" );
+ led_exit();
+ return result;
+ }
+ init_status |= INIT_GPIO_REGISTER;
+ // sam 1-30-2004 LAN Status
+ // ----- register device (LAN_STATUS)-------------------
+/* result = register_chrdev(LAN_STATUS_MAJOR, "lanSt", &lanSt_fops);
+ if ( result < 0 ) {
+ printk(KERN_ERR "lanSt: can't register char device\n" );
+ led_exit();
+ return result;
+ }
+ init_status |= INIT_LAN_STATUS_REGISTER;
+ */
+ // -----------init watchdog timer-------------------------
+ //del_timer(&blink_timer[id]);
+ WATCHDOG_VAL = ENABLE_WATCHDOG | ( EXPIRE_TIME << WATCHDOG_SET_TMR_SHIFT);
+ watchdog.function = watchdog_wrapper;
+ watchdog.data = WATCHDOG_PERIOD;
+ init_timer(&watchdog);
+ watchdog.expires = jiffies + (WATCHDOG_PERIOD * HZ / 1000);
+ add_timer(&watchdog);
+ init_status |= INIT_WATCHDOG_REGISTER;
+
+ // end sam
+ //------ read proc -------------------
+ if ( !create_proc_read_entry("driver/led", 0, 0, led_read_proc, NULL) ) {
+ printk(KERN_ERR "led: can't create /proc/driver/led\n");
+ led_exit();
+ return -ENOMEM;
+ }
+ init_status |= INIT_LED_PROC_READ;
+ //------------------------------
+ reg_addr = (unsigned long *)0xB4000000;
+ dump_len = 4;
+ for ( id = 0 ; id < LED_DEV_NUM ; id++ ) {
+ strcpy(led_data[id].sts_buf, "LED OFF\n" );
+ set_led_status_by_str(id);
+ }
+ printk(KERN_INFO "LED & GPIO Driver " LED_VERSION "\n");
+ return 0;
+}
+
+module_init(led_init);
+module_exit(led_exit);
+EXPORT_NO_SYMBOLS;
diff -ruN linux-2.6.10/arch/mips/am5120/led.h linux-2.6.10-adm.1/arch/mips/am5120/led.h
--- linux-2.6.10/arch/mips/am5120/led.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/led.h 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,26 @@
+#ifndef _LED_H_INCLUDED
+#define _LED_H_INCLUDED
+
+#include <linux/config.h>
+
+#define LED_VERSION "v1.0"
+#define LED_MAJOR 166
+#define LED_DEV_NUM 8
+#define LED_GPIO_START 1
+#define GPIO_MAJOR 167
+#define GPIO_DEV_NUM 16
+#define REG_MINOR 128
+//#define GPIO_IO_BASE 0xB4002480
+#define GPIO_IO_BASE ((unsigned long)0xb20000b8)
+#define GPIO_IO_EXTENT 0x40
+
+#define LED_ON 0x010000
+#define LED_OFF 0x020000
+#define LED_BLINK_CMD 0x030000
+#define LED_BLINK_PERIOD 0x00FFFF
+#define LED_BLINK (LED_BLINK_CMD|1000)
+#define LED_BLINK_FAST (LED_BLINK_CMD|250)
+#define LED_BLINK_SLOW (LED_BLINK_CMD|500)
+#define LED_BLINK_EXTRA_SLOW (LED_BLINK_CMD|2000)
+
+#endif
diff -ruN linux-2.6.10/arch/mips/am5120/memory.c linux-2.6.10-adm.1/arch/mips/am5120/memory.c
--- linux-2.6.10/arch/mips/am5120/memory.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/memory.c 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,84 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;
+;------------------------------------------------------------------------------
+;
+; Project : ADM5120
+; Creator : daniell@admtek.com.tw
+; File : arch/mips/am5120/memory.c
+; Date : 2003.3.4
+; Abstract:
+;
+;Modification History:
+;
+; Jeroen Vreeken (pe1rxq@amsat.org)
+; Simplified by ripping out fake env stuff.
+;
+;*****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/am5120/prom.h>
+#include <asm/am5120/adm5120.h>
+
+
+/* References to section boundaries */
+extern char _end;
+
+#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+#define ADM5120_MEMSIZE 0x1000000 /* 16 Mb */
+
+void __init prom_meminit(void)
+{
+ unsigned long base=CPHYSADDR(PFN_ALIGN(&_end));
+ unsigned long size=ADM5120_MEMSIZE;
+
+ add_memory_region(base, size-base, BOOT_MEM_RAM);
+}
+
+
+void __init prom_free_prom_memory (void)
+{
+ int i;
+ unsigned long freed = 0;
+ unsigned long addr;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++)
+ {
+ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+ continue;
+
+ addr = boot_mem_map.map[i].addr;
+ while (addr < boot_mem_map.map[i].addr
+ + boot_mem_map.map[i].size)
+ {
+ ClearPageReserved(virt_to_page(__va(addr)));
+ set_page_count(virt_to_page(__va(addr)), 1);
+ free_page((unsigned long)__va(addr));
+ addr += PAGE_SIZE;
+ freed += PAGE_SIZE;
+ }
+ }
+
+ printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
+}
+
+
diff -ruN linux-2.6.10/arch/mips/am5120/mipsIRQ.S linux-2.6.10-adm.1/arch/mips/am5120/mipsIRQ.S
--- linux-2.6.10/arch/mips/am5120/mipsIRQ.S 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/mipsIRQ.S 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,135 @@
+/*
+ * 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 <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#define STATUS_IE 0x00000001
+
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ * all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ * common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ * would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ * between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the MIPS board look basically (barring software
+ * IRQs which we don't use at all and all external interrupt sources are
+ * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Combined hardware interrupt (hw0)
+ * 3 Hardware (ignored)
+ * 4 Hardware (ignored)
+ * 5 Hardware (ignored)
+ * 6 Hardware (ignored)
+ * 7 R4k timer (what we use)
+ *
+ * Note: On the SEAD board thing are a little bit different.
+ * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
+ * wired to UART1.
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Lowest ---- Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+ .text
+ .set noreorder
+ .set noat
+ .align 5
+
+NESTED(mipsIRQ, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+
+ mfc0 s0, CP0_CAUSE
+ mfc0 s1, CP0_STATUS
+ and s0, s0, s1
+
+ /* First we check for r4k counter/timer IRQ. */
+ andi a0, s0, CAUSEF_IP7
+ beq a0, zero, 1f
+ nop
+
+ move a0, sp
+ jal mips_timer_interrupt
+ nop
+
+ j ret_from_irq
+ nop
+
+1:
+ andi a0, s0, CAUSEF_IP2
+ beq a0, zero, 1f
+ nop
+
+ move a0, sp
+ jal am5120_hw0_irqdispatch
+ nop
+1:
+ j ret_from_irq
+ nop
+
+END(mipsIRQ)
+
+
+LEAF(mips_int_lock)
+ .set noreorder
+ mfc0 v0, CP0_STATUS
+ li v1, ~STATUS_IE
+ and v1, v1, v0
+ mtc0 v1, CP0_STATUS
+ j ra
+ and v0, v0, STATUS_IE
+ .set reorder
+END(mips_int_lock)
+
+
+LEAF(mips_int_unlock)
+ mfc0 v0, CP0_STATUS
+ and a0, a0, STATUS_IE
+ or v0, v0, a0
+ mtc0 v0, CP0_STATUS
+ j ra
+ nop
+END(mips_int_unlock)
+
diff -ruN linux-2.6.10/arch/mips/am5120/pci.c linux-2.6.10-adm.1/arch/mips/am5120/pci.c
--- linux-2.6.10/arch/mips/am5120/pci.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/pci.c 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,214 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;
+;------------------------------------------------------------------------------
+;
+; Project : ADM5120
+; Creator :
+; File :
+; Abstract:
+;
+;Modification History:
+;
+;
+;*****************************************************************************/
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_PCI
+
+#include <asm/pci_channel.h>
+#include <asm/am5120/adm5120.h>
+
+
+volatile u32* pci_config_address_reg = (volatile u32*)KSEG1ADDR(0x115ffff0);
+volatile u32* pci_config_data_reg = (volatile u32*)KSEG1ADDR(0x115ffff8);
+
+#define PCI_ENABLE 0x80000000
+#define PCI_CMM_IOACC_EN 0x1
+#define PCI_CMM_MEMACC_EN 0x2
+#define PCI_CMM_MASTER_EN 0x4
+#define PCI_CMM_DEF (PCI_CMM_IOACC_EN | PCI_CMM_MEMACC_EN | PCI_CMM_MASTER_EN)
+
+#define PCI_DEF_CACHE_LINE_SZ 4
+#define PCI_DEF_LATENCY_TIMER 0x20
+#define PCI_DEF_CACHE_LATENCY ((PCI_DEF_LATENCY_TIMER << 8) | PCI_DEF_CACHE_LINE_SZ)
+
+
+
+#define cfgaddr(dev, where) (((dev->bus->number & 0xff) << 0x10) | \
+ ((dev->devfn & 0xff) << 0x08) | \
+ (where & 0xfc)) | PCI_ENABLE
+
+
+/*
+ * We can't address 8 and 16 bit words directly. Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int am5120_read_config_byte (struct pci_dev *dev,
+ int where, unsigned char *val)
+{
+ *pci_config_address_reg = cfgaddr(dev, where);
+ *val = ((*pci_config_data_reg) >> ((where&3)<<3)) & 0xff;
+// printk("pci_read_byte 0x%x == 0x%x\n", where, *val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int am5120_read_config_word (struct pci_dev *dev,
+ int where, unsigned short *val)
+{
+ if (where & 1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ *pci_config_address_reg = cfgaddr(dev, where);
+ *val = ((*pci_config_data_reg) >> ((where&3)<<3)) & 0xffff;
+// printk("pci_read_word 0x%x == 0x%x\n", where, *val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int am5120_read_config_dword (struct pci_dev *dev,
+ int where, unsigned int *val)
+{
+ if (where & 3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ *pci_config_address_reg = cfgaddr(dev, where);
+ *val = (*pci_config_data_reg);
+// printk("pci_read_dword 0x%x == 0x%x\n", where, *val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int am5120_write_config_byte (struct pci_dev *dev,
+ int where, unsigned char val)
+{
+ *pci_config_address_reg = cfgaddr(dev, where);
+ *(volatile u8 *)(((int)pci_config_data_reg) + (where & 3)) = val;
+// printk("pci_write_byte 0x%x = 0x%x\n", where, val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int am5120_write_config_word (struct pci_dev *dev,
+ int where, unsigned short val)
+{
+ if (where & 1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ *pci_config_address_reg = cfgaddr(dev, where);
+ *(volatile u16 *)(((int)pci_config_data_reg) + (where & 2)) = (val);
+// printk("pci_write_word 0x%x = 0x%x\n", where, val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int am5120_write_config_dword (struct pci_dev *dev,
+ int where, unsigned int val)
+{
+ if (where & 3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ *pci_config_address_reg = cfgaddr(dev, where);
+ *pci_config_data_reg = (val);
+// printk("pci_write_dword 0x%x = 0x%x\n", where, val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+
+struct pci_ops am5120_pci_ops = {
+ am5120_read_config_byte,
+ am5120_read_config_word,
+ am5120_read_config_dword,
+ am5120_write_config_byte,
+ am5120_write_config_word,
+ am5120_write_config_dword
+};
+struct resource pciioport_resource = {
+ "pci IO space",
+ 0x11500000,
+ 0x115ffff0-1,
+ IORESOURCE_IO
+};
+
+struct resource pciiomem_resource = {
+ "pci memory space",
+ 0x11400000,
+ 0x11500000-1,
+ IORESOURCE_MEM
+};
+
+static void am5120_pcibios_fixup(struct pci_dev *dev)
+{
+ printk("am5120 fix up\n");
+ pci_write_config_word(dev, PCI_COMMAND, PCI_CMM_DEF);
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, PCI_DEF_CACHE_LATENCY);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
+
+}
+
+struct pci_channel mips_pci_channels[] = {
+ { &am5120_pci_ops, &pciioport_resource, &pciiomem_resource,0,0xff},
+ { NULL, NULL, NULL , NULL , NULL}
+};
+
+
+
+unsigned __init int pcibios_assign_all_busses(void)
+{
+ return 1;
+}
+
+void __init pcibios_fixup(void)
+{
+ printk("pcibios_fixup\n");
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+ struct pci_dev *dev;
+ int slot_num;
+
+ printk("fixup IRQ\n");
+ pci_for_each_dev(dev) {
+ slot_num = PCI_SLOT(dev->devfn);
+ switch(slot_num) {
+ case 2:
+ dev->irq = 6;
+ pci_write_config_word(dev, PCI_INTERRUPT_LINE, 6);
+ break;
+ case 3:
+ dev->irq = 7;
+ pci_write_config_word(dev, PCI_INTERRUPT_LINE, 7);
+ break;
+ case 4:
+ dev->irq = 8;
+ pci_write_config_word(dev, PCI_INTERRUPT_LINE, 8);
+ break;
+ default: break;
+ }
+ }
+}
+
+void __init pcibios_fixup_resources(struct pci_dev *dev)
+{
+ printk("fixup resource\n");
+ if (dev->devfn == 0)
+ {
+ printk("fixup host controller\n");
+ am5120_pcibios_fixup(dev);
+ }
+}
+
+#endif /* CONFIG_PCI */
diff -ruN linux-2.6.10/arch/mips/am5120/prom.c linux-2.6.10-adm.1/arch/mips/am5120/prom.c
--- linux-2.6.10/arch/mips/am5120/prom.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/prom.c 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,70 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;
+;------------------------------------------------------------------------------
+;
+; Project : ADM5120
+; Creator : daniell@admtek.com.tw
+; File : arch/mips/am5120/prom.c
+; Date : 2003.3.4
+; Abstract:
+;
+;Modification History:
+;
+; Jeroen Vreeken (pe1rxq@amsat.org)
+; Ripped out cmdline and env stuff left over from YAMON cut-and-paste.
+;
+;*****************************************************************************/
+
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+
+extern void am5120_serial_console_init(void);
+void setup_prom_printf(int);
+void prom_printf(char *, ...);
+void prom_meminit(void);
+
+/*
+ * initialize the prom module.
+ */
+void __init prom_init(void)
+{
+ /* you should these macros defined in include/asm/bootinfo.h */
+ mips_machgroup = MACH_GROUP_ADM_GW;
+ mips_machtype = MACH_ADM_GW_5120;
+
+ /* set IO port base to zero */
+
+ /* init print from uart0 */
+ setup_prom_printf(0);
+
+ prom_printf("\nLINUX started...\n");
+
+ /* init command line */
+ strcpy(&(arcs_cmdline[0]), ""/*"root=/dev/ram0 console=ttyS0"*/);
+
+ /* init memory map */
+ prom_meminit();
+}
+
+
diff -ruN linux-2.6.10/arch/mips/am5120/serial.c linux-2.6.10-adm.1/arch/mips/am5120/serial.c
--- linux-2.6.10/arch/mips/am5120/serial.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/serial.c 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,1711 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;
+;------------------------------------------------------------------------------
+;
+; Project : ADM5120
+; Creator : daniell@admtek.com.tw
+; File : arch/mips/am5120/printf.c
+; Date : 2003.3.4
+; Abstract:
+;
+;Modification History:
+;
+;*****************************************************************************/
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/devpts_fs.h>
+
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/serial.h>
+#include <asm/am5120/adm5120.h>
+
+
+//#define SERIAL_DEBUG_OPEN 1
+//#define SERIAL_DEBUG_INTR 1
+
+static struct tty_driver dev_tty_driver;
+
+/*
+ * IN_W
+ */
+static inline unsigned long IN_W(unsigned long _addr)
+{
+ return (*(volatile unsigned long *)(_addr));
+}
+
+
+/*
+ * OUT_W
+ */
+static inline void OUT_W(unsigned long _addr, unsigned long _value)
+{
+ (*((volatile unsigned long *)(_addr))) = _value;
+}
+
+
+/*
+ * serial_in
+ */
+static unsigned int serial_in(struct async_struct *info, int offset)
+{
+ return IN_W(info->port + offset);
+}
+
+
+/*
+ * serial_out
+ */
+static void serial_out(struct async_struct *info, int offset,
+ int value)
+{
+ OUT_W(info->port + offset, value);
+}
+
+
+/*
+ * serial state
+ */
+static struct serial_state rs_table[] =
+{
+ {baud_base:UART_115200bps_DIVISOR, port:KSEG1ADDR(UART0_BASE), irq:1, flags:STD_COM_FLAGS, type:SERIAL_IO_MEM}
+};
+
+
+/*-------------------------------------------------------
+ * prom_printf
+ *
+ *-----------------------------------------------------*/
+/*
+ * Hooks to fake "prom" console I/O before devices
+ * are fully initialized.
+ */
+static struct async_struct prom_port_info = {0};
+
+void __init setup_prom_printf(int tty_no)
+{
+ struct serial_state *ser = &rs_table[tty_no];
+
+ prom_port_info.state = ser;
+ prom_port_info.magic = SERIAL_MAGIC;
+ prom_port_info.port = ser->port;
+ prom_port_info.flags = ser->flags;
+
+ /* set baudrate to 115200 */
+ serial_out(&prom_port_info, UART_LCR_L_REG, prom_port_info.state->baud_base);
+ serial_out(&prom_port_info, UART_LCR_M_REG, prom_port_info.state->baud_base >> 8);
+
+ /* Set default line mode */
+ serial_out(&prom_port_info, UART_LCR_H_REG, UART_WLEN_8BITS | UART_ENABLE_FIFO);
+
+ /* Enable uart port */
+ serial_out(&prom_port_info, UART_CR_REG, UART_PORT_EN);
+}
+
+
+/*
+ * putPromChar
+ */
+int putPromChar(char c)
+{
+ if (!prom_port_info.state) { /* need to init device first */
+ return 0;
+ }
+
+ while ((serial_in(&prom_port_info, UART_FR_REG) &
+ UART_TX_FIFO_FULL) != 0);
+
+ serial_out(&prom_port_info, UART_DR_REG, c);
+
+ return 1;
+}
+
+
+/*
+ * getPromChar
+ */
+char getPromChar(void)
+{
+ if (!prom_port_info.state) /* need to init device first */
+ return 0;
+
+ if ((serial_in(&prom_port_info, UART_FR_REG) & UART_RX_FIFO_EMPTY))
+ return 0;
+
+ return(serial_in(&prom_port_info, UART_DR_REG));
+}
+
+
+static char buf[1024];
+
+/*
+ * prom_printf
+ */
+void __init prom_printf(char *fmt, ...)
+{
+ va_list args;
+ int l;
+ char *p, *buf_end;
+ long flags;
+
+ int putPromChar(char);
+
+ /* Low level, brute force, not SMP safe... */
+ save_and_cli(flags);
+ va_start(args, fmt);
+ l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
+ va_end(args);
+
+ buf_end = buf + l;
+
+ for (p = buf; p < buf_end; p++) {
+ /* Crude cr/nl handling is better than none */
+ if(*p == '\n')putPromChar('\r');
+ putPromChar(*p);
+ }
+ restore_flags(flags);
+}
+
+
+/*-------------------------------------------------------
+ * console driver
+ *
+ *-----------------------------------------------------*/
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ * The console_lock must be held when we get here.
+ */
+static void serial_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ int i;
+
+ for (i = 0; i < count; i++, s++)
+ {
+ if (*s == '\n')
+ putPromChar('\r');
+ putPromChar(*s);
+ }
+}
+
+
+/*
+ * Receive character from the serial port
+ */
+static int serial_console_wait_key(struct console *co)
+{
+ return 0;
+}
+
+
+/*
+ * Get serial console device
+ */
+static struct tty_driver *serial_console_device(struct console *c, int *index)
+{
+ *index=c->index;
+ return &dev_tty_driver;
+}
+
+
+/*
+ * Setup initial baud/bits/parity. We do two things here:
+ * - construct a cflag setting for the first rs_open()
+ * - initialize the serial port
+ * Return non-zero if we didn't find a serial port.
+ */
+static int __init serial_console_setup(struct console *co, char *options)
+{
+ return 0;
+}
+
+
+/*
+ * Console data structure
+ */
+static struct console sercons = {
+ name: "ttyS",
+ write: serial_console_write,
+ device: serial_console_device,
+// wait_key: serial_console_wait_key,
+ setup: serial_console_setup,
+ flags: CON_PRINTBUFFER,
+ index: -1,
+};
+
+/*
+ * Register console.
+ */
+static int __init am5120_serial_console_init(void)
+{
+ register_console(&sercons);
+ return 0;
+}
+console_initcall(am5120_serial_console_init);
+
+/*------------------------------------------------------
+ * Register tty driver
+ *
+ *----------------------------------------------------*/
+
+static char *serial_version = "0.01";
+static char *serial_revdate = "2003-04-17";
+
+#define LOCAL_VERSTRING ""
+
+#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
+#define WAKEUP_CHARS 256
+#define RS_ISR_PASS_LIMIT 256
+
+static unsigned char *tmp_buf;
+#ifdef DECLARE_MUTEX
+static DECLARE_MUTEX(tmp_buf_sem);
+#else
+static struct semaphore tmp_buf_sem = MUTEX;
+#endif
+
+static int serial_refcount;
+static struct tty_struct *serial_table[NR_PORTS];
+static struct termios *serial_termios[NR_PORTS];
+static struct termios *serial_termios_locked[NR_PORTS];
+static unsigned char *tmp_buf = 0;
+static struct async_struct *IRQ_ports[NR_IRQS] = {0};
+
+
+
+
+static void do_softint(void *private_)
+{
+ struct async_struct *info = (struct async_struct *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ wake_up_interruptible(&tty->write_wait);
+#ifdef SERIAL_HAVE_POLL_WAIT
+ wake_up_interruptible(&tty->poll_wait);
+#endif
+ }
+}
+
+
+static int get_async_struct(int line, struct async_struct **ret_info)
+{
+ struct async_struct *info;
+ struct serial_state *sstate;
+
+ sstate = rs_table + line;
+ sstate->count++;
+ if (sstate->info) {
+ *ret_info = sstate->info;
+ return 0;
+ }
+
+ info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
+ if (!info) {
+ sstate->count--;
+ return -ENOMEM;
+ }
+
+ memset(info, 0, sizeof(struct async_struct));
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
+ info->magic = SERIAL_MAGIC;
+ info->port = sstate->port;
+ info->flags = sstate->flags;
+ info->io_type = sstate->io_type;
+ info->iomem_base = sstate->iomem_base;
+ info->iomem_reg_shift = sstate->iomem_reg_shift;
+ info->xmit_fifo_size = sstate->xmit_fifo_size;
+ info->line = line;
+ INIT_WORK(&info->work, do_softint, info);
+// info->tqueue.routine = do_softint;
+// info->tqueue.data = info;
+ info->state = sstate;
+ if (sstate->info) {
+ kfree(info);
+ *ret_info = sstate->info;
+ return 0;
+ }
+ *ret_info = sstate->info = info;
+ return 0;
+}
+
+
+static void transmit_chars(struct async_struct *info, int *intr_done)
+{
+ if (info->x_char) {
+ serial_out(info, UART_DR_REG, info->x_char);
+ info->state->icount.tx++;
+ info->x_char = 0;
+ if (intr_done)
+ *intr_done = 0;
+ return;
+ }
+
+ if (info->xmit.head == info->xmit.tail
+ || info->tty->stopped
+ || info->tty->hw_stopped) {
+ info->IER &= ~UART_TX_INT_EN;
+ serial_out(info, UART_CR_REG, info->IER);
+ return;
+ }
+
+ do {
+ while ((serial_in(info, UART_FR_REG) & UART_TX_FIFO_FULL) != 0)
+ ;
+
+ serial_out(info, UART_DR_REG, info->xmit.buf[info->xmit.tail]);
+ info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1);
+ info->state->icount.tx++;
+ if (info->xmit.head == info->xmit.tail)
+ break;
+ } while (1);
+
+ //if (CIRC_CNT(info->xmit.head,
+ // info->xmit.tail,
+ // SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
+ //rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("THRE...");
+#endif
+
+ if (intr_done)
+ *intr_done = 0;
+
+ if (info->xmit.head == info->xmit.tail) {
+ info->IER &= ~UART_TX_INT_EN;
+ serial_out(info, UART_CR_REG, info->IER);
+ }
+}
+
+
+
+static void receive_chars(struct async_struct *info,
+ struct pt_regs * regs)
+{
+ struct tty_struct *tty = info->tty;
+ unsigned char ch;
+ //int ignored = 0;
+ struct async_icount *icount;
+ unsigned int status;
+ unsigned int rsr_flag;
+
+ icount = &info->state->icount;
+
+ do {
+ ch = serial_in(info, UART_DR_REG);
+
+ rsr_flag = serial_in(info, UART_RSR_REG);
+ serial_out(info, UART_RSR_REG, rsr_flag);
+
+ if (rsr_flag & UART_RX_ERROR)
+ goto ignore_char;
+
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ goto ignore_char;
+
+ *tty->flip.char_buf_ptr = ch;
+ icount->rx++;
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("DR%02x...", ch);
+#endif
+ *tty->flip.flag_buf_ptr = 0;
+
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ tty->flip.count++;
+
+ status = serial_in(info, UART_FR_REG);
+
+ } while (!(status & UART_RX_FIFO_EMPTY));
+
+ignore_char:
+
+ tty_flip_buffer_push(tty);
+}
+
+
+/*
+ * This is the serial driver's interrupt routine for a single port
+ */
+irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ int status;
+ int pass_counter = 0;
+ struct async_struct * info;
+ int handled=IRQ_NONE;
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("rs_interrupt(%d)...", irq);
+#endif
+
+ info = IRQ_ports[irq];
+ if (!info || !info->tty)
+ return handled;
+
+ do {
+ status = serial_in(info, UART_IIR_REG);
+
+ if (status & (UART_RX_INT | UART_RX_TIMEOUT_INT))
+ {
+ //if ((serial_in(info, UART_FR_REG) & UART_RX_FIFO_EMPTY))
+ // break;
+ handled=IRQ_HANDLED;
+ receive_chars(info, regs);
+ }
+
+ if (status & UART_TX_INT)
+ {
+ handled=IRQ_HANDLED;
+ transmit_chars(info, 0);
+ }
+
+ if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+ break;
+ }
+
+ } while (serial_in(info, UART_IIR_REG) & (UART_RX_INT | UART_RX_TIMEOUT_INT | UART_TX_INT));
+
+ info->last_active = jiffies;
+ return handled;
+}
+
+
+static int startup(struct async_struct * info)
+{
+ unsigned long flags;
+ int retval=0;
+ irqreturn_t (*handler)(int, void *, struct pt_regs *);
+ struct serial_state *state= info->state;
+ unsigned long page;
+
+ if (info->flags & ASYNC_INITIALIZED)
+ return retval;
+
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ save_flags(flags);
+
+ cli();
+
+ if (!CONFIGURED_SERIAL_PORT(state) || !state->type)
+ {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ free_page(page);
+ goto errout;
+ }
+
+ if (info->xmit.buf)
+ free_page(page);
+ else
+ info->xmit.buf = (unsigned char *) page;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("starting up ttyS%d (irq %d)...", info->line, state->irq);
+#endif
+
+ /*
+ * Allocate the IRQ if necessary
+ */
+ if ((!IRQ_ports[state->irq] || !IRQ_ports[state->irq]->next_port))
+ {
+ if (IRQ_ports[state->irq])
+ {
+ retval = -EBUSY;
+ goto errout;
+ }
+ else
+ handler = rs_interrupt;
+
+ retval = request_irq(state->irq, handler, SA_SHIRQ,
+ "serial", &IRQ_ports[state->irq]);
+ if (retval)
+ {
+ if (capable(CAP_SYS_ADMIN))
+ {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ }
+ goto errout;
+ }
+ }
+
+ /*
+ * Insert serial port into IRQ chain.
+ */
+ info->prev_port = 0;
+ info->next_port = IRQ_ports[state->irq];
+
+ if (info->next_port)
+ info->next_port->prev_port = info;
+
+ IRQ_ports[state->irq] = info;
+
+ /*
+ * Now, initialize the UART
+ */
+ serial_out(info, UART_LCR_L_REG, info->state->baud_base);
+ serial_out(info, UART_LCR_M_REG, info->state->baud_base >> 8);
+ serial_out(info, UART_LCR_H_REG, (UART_WLEN_8BITS | UART_ENABLE_FIFO));
+
+ /*
+ * Finally, enable interrupts
+ */
+ info->IER = UART_RX_INT_EN | UART_RX_TIMEOUT_INT_EN | UART_PORT_EN;
+ serial_out(info, UART_CR_REG, info->IER);
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->xmit.head = info->xmit.tail = 0;
+
+ /*
+ * and set the speed of the serial port
+ */
+ info->flags |= ASYNC_INITIALIZED;
+ restore_flags(flags);
+
+ return 0;
+
+errout:
+ restore_flags(flags);
+ return retval;
+}
+
+
+/*
+ * This routine is called whenever a serial port is opened. It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain. It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int rs_open(struct tty_struct *tty, struct file * filp)
+{
+ struct async_struct *info;
+ int retval, line;
+ unsigned long page;
+
+// line = MINOR(tty->device) - tty->driver.minor_start;
+ line=0;
+ if ((line < 0) || (line >= NR_PORTS))
+ {
+ return -ENODEV;
+ }
+
+ retval = get_async_struct(line, &info);
+ if (retval)
+ {
+ return retval;
+ }
+
+ tty->driver_data = info;
+ info->tty = tty;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+ info->state->count);
+#endif
+
+ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+ if (!tmp_buf)
+ {
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ {
+ return -ENOMEM;
+ }
+
+ if (tmp_buf)
+ free_page(page);
+ else
+ tmp_buf = (unsigned char *) page;
+ }
+
+ /*
+ * If the port is the middle of closing, bail out now
+ */
+ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING))
+ {
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+
+ return -EAGAIN;
+ }
+
+ /*
+ * Start up serial port
+ */
+ retval = startup(info);
+ if (retval)
+ {
+ return retval;
+ }
+
+#if 0
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open returning after block_til_ready with %d\n",
+ retval);
+#endif
+ return retval;
+ }
+#endif
+
+ if ((info->state->count == 1) &&
+ (info->flags & ASYNC_SPLIT_TERMIOS))
+ {
+// if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+// *tty->termios = info->state->normal_termios;
+// else
+// *tty->termios = info->state->callout_termios;
+ }
+
+// info->session = current->session;
+// info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open ttys%d successful...", info->line);
+#endif
+
+ return 0;
+}
+
+
+/*
+ * rs_close()
+ *
+ * This routine is called when the serial port gets closed. First, we
+ * wait for the last remaining data to be sent. Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+ struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct serial_state *state;
+ unsigned long flags;
+
+ state = info->state;
+
+ save_flags(flags);
+ cli();
+
+ //if (tty_hung_up_p(filp)) {
+ // DBG_CNT("before DEC-hung");
+ // restore_flags(flags);
+ // return;
+ //}
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_close ttys%d, count = %d\n", info->line, state->count);
+#endif
+
+ if ((tty->count == 1) && (state->count != 1)) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. state->count should always
+ * be one in these conditions. If it's greater than
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
+ */
+ //printk("rs_close: bad serial port count; tty->count is 1, "
+ // "state->count is %d\n", state->count);
+ state->count = 1;
+ }
+
+ if (--state->count < 0) {
+ //printk("rs_close: bad serial port count for ttys%d: %d\n",
+ // info->line, state->count);
+ state->count = 0;
+ }
+
+ restore_flags(flags);
+ return;
+
+#if 0
+ info->flags |= ASYNC_CLOSING;
+ restore_flags(flags);
+ /*
+ * Save the termios structure, since this port may have
+ * separate termios for callout and dialin.
+ */
+ if (info->flags & ASYNC_NORMAL_ACTIVE)
+ info->state->normal_termios = *tty->termios;
+ if (info->flags & ASYNC_CALLOUT_ACTIVE)
+ info->state->callout_termios = *tty->termios;
+ /*
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+
+ if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, info->closing_wait);
+
+ /*
+ * At this point we stop accepting input. To do this, we
+ * disable the receive line status interrupts, and tell the
+ * interrupt driver to stop checking the data ready bit in the
+ * line status register.
+ */
+ //info->IER &= ~UART_IER_RLSI;
+ //info->read_status_mask &= ~UART_LSR_DR;
+ //if (info->flags & ASYNC_INITIALIZED) {
+ // serial_out(info, UART_IER, info->IER);
+ /*
+ * Before we drop DTR, make sure the UART transmitter
+ * has completely drained; this is especially
+ * important if there is a transmit FIFO!
+ */
+ // rs_wait_until_sent(tty, info->timeout);
+ //}
+ //shutdown(info);
+
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = 0;
+ //if (info->blocked_open) {
+ // if (info->close_delay) {
+ // set_current_state(TASK_INTERRUPTIBLE);
+ // schedule_timeout(info->close_delay);
+ // }
+ // wake_up_interruptible(&info->open_wait);
+ //}
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+ ASYNC_CLOSING);
+
+ wake_up_interruptible(&info->close_wait);
+#endif
+}
+
+
+static int rs_write(struct tty_struct * tty, const unsigned char *buf,
+ int count)
+{
+ int c, ret = 0;
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+
+ if (!tty || !info->xmit.buf || !tmp_buf)
+ return 0;
+
+ save_flags(flags);
+ if (0/*from_user*/) {
+ down(&tmp_buf_sem);
+ while (1) {
+ int c1;
+ c = CIRC_SPACE_TO_END(info->xmit.head,
+ info->xmit.tail,
+ SERIAL_XMIT_SIZE);
+ if (count < c)
+ c = count;
+ if (c <= 0)
+ break;
+
+ c -= copy_from_user(tmp_buf, buf, c);
+ if (!c) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
+ cli();
+ c1 = CIRC_SPACE_TO_END(info->xmit.head,
+ info->xmit.tail,
+ SERIAL_XMIT_SIZE);
+ if (c1 < c)
+ c = c1;
+ memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
+ info->xmit.head = ((info->xmit.head + c) &
+ (SERIAL_XMIT_SIZE-1));
+ restore_flags(flags);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ up(&tmp_buf_sem);
+ } else {
+ cli();
+ while (1) {
+ c = CIRC_SPACE_TO_END(info->xmit.head,
+ info->xmit.tail,
+ SERIAL_XMIT_SIZE);
+ if (count < c)
+ c = count;
+ if (c <= 0) {
+ break;
+ }
+ memcpy(info->xmit.buf + info->xmit.head, buf, c);
+ info->xmit.head = ((info->xmit.head + c) &
+ (SERIAL_XMIT_SIZE-1));
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ restore_flags(flags);
+ }
+ if (info->xmit.head != info->xmit.tail
+ && !tty->stopped
+ && !tty->hw_stopped
+ && !(info->IER & UART_TX_INT)) {
+ info->IER |= UART_TX_INT_EN;
+ serial_out(info, UART_CR_REG, info->IER);
+ }
+ return ret;
+}
+
+
+static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+{
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+
+ if (!tty || !info->xmit.buf)
+ return;
+
+ save_flags(flags);
+ cli();
+
+ if (CIRC_SPACE(info->xmit.head,
+ info->xmit.tail,
+ SERIAL_XMIT_SIZE) == 0) {
+ restore_flags(flags);
+ return;
+ }
+
+ info->xmit.buf[info->xmit.head] = ch;
+ info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
+ restore_flags(flags);
+}
+
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+
+ if (info->xmit.head == info->xmit.tail
+ || tty->stopped
+ || tty->hw_stopped
+ || !info->xmit.buf)
+ return;
+
+ save_flags(flags);
+ cli();
+
+ info->IER |= UART_TX_INT_EN;
+ serial_out(info, UART_CR_REG, info->IER);
+ restore_flags(flags);
+}
+
+
+static int rs_write_room(struct tty_struct *tty)
+{
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+
+ return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+}
+
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+
+ return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+}
+
+
+static void rs_flush_buffer(struct tty_struct *tty)
+{
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ info->xmit.head = info->xmit.tail = 0;
+ restore_flags(flags);
+ wake_up_interruptible(&tty->write_wait);
+#ifdef SERIAL_HAVE_POLL_WAIT
+ wake_up_interruptible(&tty->poll_wait);
+#endif
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+}
+
+
+static int get_serial_info(struct async_struct * info,
+ struct serial_struct * retinfo)
+{
+ struct serial_struct tmp;
+ struct serial_state *state = info->state;
+
+ if (!retinfo)
+ return -EFAULT;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = state->type;
+ tmp.line = state->line;
+ tmp.port = state->port;
+ //if (HIGH_BITS_OFFSET)
+ // tmp.port_high = state->port >> HIGH_BITS_OFFSET;
+ //else
+ tmp.port_high = 0;
+ tmp.irq = state->irq;
+ tmp.flags = state->flags;
+ tmp.xmit_fifo_size = state->xmit_fifo_size;
+ tmp.baud_base = state->baud_base;
+ tmp.close_delay = state->close_delay;
+ tmp.closing_wait = state->closing_wait;
+ tmp.custom_divisor = state->custom_divisor;
+ tmp.hub6 = state->hub6;
+ tmp.io_type = state->io_type;
+ if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+ return -EFAULT;
+ return 0;
+}
+
+
+#if 0
+static int set_serial_info(struct async_struct * info,
+ struct serial_struct * new_info)
+{
+ struct serial_struct new_serial;
+ struct serial_state old_state, *state;
+ unsigned int i,change_irq,change_port;
+ int retval = 0;
+ unsigned long new_port;
+
+ if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+ return -EFAULT;
+ state = info->state;
+ old_state = *state;
+
+ new_port = new_serial.port;
+ if (HIGH_BITS_OFFSET)
+ new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
+
+ change_irq = new_serial.irq != state->irq;
+ change_port = (new_port != ((int) state->port)) ||
+ (new_serial.hub6 != state->hub6);
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ if (change_irq || change_port ||
+ (new_serial.baud_base != state->baud_base) ||
+ (new_serial.type != state->type) ||
+ (new_serial.close_delay != state->close_delay) ||
+ (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
+ ((new_serial.flags & ~ASYNC_USR_MASK) !=
+ (state->flags & ~ASYNC_USR_MASK)))
+ return -EPERM;
+ state->flags = ((state->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK));
+ info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK));
+ state->custom_divisor = new_serial.custom_divisor;
+ goto check_and_exit;
+ }
+
+ new_serial.irq = irq_cannonicalize(new_serial.irq);
+
+ if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
+ (new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) ||
+ (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) ||
+ (new_serial.type == PORT_STARTECH)) {
+ return -EINVAL;
+ }
+
+ if ((new_serial.type != state->type) ||
+ (new_serial.xmit_fifo_size <= 0))
+ new_serial.xmit_fifo_size =
+ uart_config[new_serial.type].dfl_xmit_fifo_size;
+
+ /* Make sure address is not already in use */
+ if (new_serial.type) {
+ for (i = 0 ; i < NR_PORTS; i++)
+ if ((state != &rs_table[i]) &&
+ (rs_table[i].port == new_port) &&
+ rs_table[i].type)
+ return -EADDRINUSE;
+ }
+
+ if ((change_port || change_irq) && (state->count > 1))
+ return -EBUSY;
+
+ /*
+ * OK, past this point, all the error checking has been done.
+ * At this point, we start making changes.....
+ */
+
+ state->baud_base = new_serial.baud_base;
+ state->flags = ((state->flags & ~ASYNC_FLAGS) |
+ (new_serial.flags & ASYNC_FLAGS));
+ info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
+ (info->flags & ASYNC_INTERNAL_FLAGS));
+ state->custom_divisor = new_serial.custom_divisor;
+ state->close_delay = new_serial.close_delay * HZ/100;
+ state->closing_wait = new_serial.closing_wait * HZ/100;
+ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ info->xmit_fifo_size = state->xmit_fifo_size =
+ new_serial.xmit_fifo_size;
+
+ if ((state->type != PORT_UNKNOWN) && state->port) {
+ release_region(state->port,8);
+ }
+ state->type = new_serial.type;
+ if (change_port || change_irq) {
+ /*
+ * We need to shutdown the serial port at the old
+ * port/irq combination.
+ */
+ shutdown(info);
+ state->irq = new_serial.irq;
+ info->port = state->port = new_port;
+ info->hub6 = state->hub6 = new_serial.hub6;
+ if (info->hub6)
+ info->io_type = state->io_type = SERIAL_IO_HUB6;
+ else if (info->io_type == SERIAL_IO_HUB6)
+ info->io_type = state->io_type = SERIAL_IO_PORT;
+ }
+ if ((state->type != PORT_UNKNOWN) && state->port) {
+ request_region(state->port,8,"serial(set)");
+ }
+
+
+check_and_exit:
+ if (!state->port || !state->type)
+ return 0;
+ if (info->flags & ASYNC_INITIALIZED) {
+ if (((old_state.flags & ASYNC_SPD_MASK) !=
+ (state->flags & ASYNC_SPD_MASK)) ||
+ (old_state.custom_divisor != state->custom_divisor)) {
+ if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ info->tty->alt_speed = 460800;
+ change_speed(info, 0);
+ }
+ } else {
+ retval = startup(info);
+ }
+ return retval;
+}
+#endif
+
+
+static int rs_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct async_icount cprev, cnow; /* kernel counter temps */
+ struct serial_icounter_struct icount;
+ unsigned long flags;
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+ (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
+ switch (cmd) {
+ //case TIOCMGET:
+ // return get_modem_info(info, (unsigned int *) arg);
+ case TIOCMBIS:
+ case TIOCMBIC:
+ //case TIOCMSET:
+ // return set_modem_info(info, cmd, (unsigned int *) arg);
+ case TIOCGSERIAL:
+ return get_serial_info(info,
+ (struct serial_struct *) arg);
+ //case TIOCSSERIAL:
+ // return set_serial_info(info,
+ //(struct serial_struct *) arg);
+ //case TIOCSERCONFIG:
+ // return do_autoconfig(info);
+
+ //case TIOCSERGETLSR: /* Get line status register */
+ // return get_lsr_info(info, (unsigned int *) arg);
+
+ case TIOCSERGSTRUCT:
+ if (copy_to_user((struct async_struct *) arg,
+ info, sizeof(struct async_struct)))
+ return -EFAULT;
+ return 0;
+
+
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was
+ */
+ case TIOCMIWAIT:
+#if 0
+ save_flags(flags);
+ cli();
+ /* note the counters on entry */
+ cprev = info->state->icount;
+ restore_flags(flags);
+ /* Force modem status interrupts on */
+ info->IER |= UART_IER_MSI;
+ serial_out(info, UART_IER, info->IER);
+ while (1) {
+ interruptible_sleep_on(&info->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ save_flags(flags); cli();
+ cnow = info->state->icount; /* atomic copy */
+ restore_flags(flags);
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+ return 0;
+ }
+ cprev = cnow;
+ }
+ /* NOTREACHED */
+#endif
+
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+ case TIOCGICOUNT:
+ save_flags(flags);
+ cli();
+ cnow = info->state->icount;
+ restore_flags(flags);
+ icount.cts = cnow.cts;
+ icount.dsr = cnow.dsr;
+ icount.rng = cnow.rng;
+ icount.dcd = cnow.dcd;
+ icount.rx = cnow.rx;
+ icount.tx = cnow.tx;
+ icount.frame = cnow.frame;
+ icount.overrun = cnow.overrun;
+ icount.parity = cnow.parity;
+ icount.brk = cnow.brk;
+ icount.buf_overrun = cnow.buf_overrun;
+
+ if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+ return -EFAULT;
+ return 0;
+ case TIOCSERGWILD:
+ case TIOCSERSWILD:
+ /* "setserial -W" is called in Debian boot */
+ printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ *
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_throttle(struct tty_struct * tty)
+{
+#if 0
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("throttle %s: %d....\n", tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (I_IXOFF(tty))
+ rs_send_xchar(tty, STOP_CHAR(tty));
+
+ if (tty->termios->c_cflag & CRTSCTS)
+ info->MCR &= ~UART_MCR_RTS;
+
+ save_flags(flags); cli();
+ serial_out(info, UART_MCR, info->MCR);
+ restore_flags(flags);
+#endif
+}
+
+
+static void rs_unthrottle(struct tty_struct * tty)
+{
+#if 0
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("unthrottle %s: %d....\n", tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+ info->x_char = 0;
+ else
+ rs_send_xchar(tty, START_CHAR(tty));
+ }
+ //if (tty->termios->c_cflag & CRTSCTS)
+ // info->MCR |= UART_MCR_RTS;
+ save_flags(flags);
+ cli();
+ //serial_out(info, UART_MCR, info->MCR);
+ restore_flags(flags);
+#endif
+}
+
+
+static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+#if 0
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+ unsigned int cflag = tty->termios->c_cflag;
+
+ if ((cflag == old_termios->c_cflag)
+ && (RELEVANT_IFLAG(tty->termios->c_iflag)
+ == RELEVANT_IFLAG(old_termios->c_iflag)))
+ return;
+
+ /* Handle transition to B0 status */
+ if ((old_termios->c_cflag & CBAUD) &&
+ !(cflag & CBAUD)) {
+ info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+ save_flags(flags); cli();
+ serial_out(info, UART_MCR, info->MCR);
+ restore_flags(flags);
+ }
+
+ /* Handle transition away from B0 status */
+ if (!(old_termios->c_cflag & CBAUD) &&
+ (cflag & CBAUD)) {
+ info->MCR |= UART_MCR_DTR;
+ if (!(tty->termios->c_cflag & CRTSCTS) ||
+ !test_bit(TTY_THROTTLED, &tty->flags)) {
+ info->MCR |= UART_MCR_RTS;
+ }
+ save_flags(flags); cli();
+ serial_out(info, UART_MCR, info->MCR);
+ restore_flags(flags);
+ }
+
+ /* Handle turning off CRTSCTS */
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ rs_start(tty);
+ }
+#endif
+}
+
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rs_stop(struct tty_struct *tty)
+{
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ if (info->IER & UART_TX_INT_EN) {
+ info->IER &= ~UART_TX_INT_EN;
+ serial_out(info, UART_CR_REG, info->IER);
+ }
+ restore_flags(flags);
+}
+
+
+
+static void rs_start(struct tty_struct *tty)
+{
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ if (info->xmit.head != info->xmit.tail
+ && info->xmit.buf
+ && !(info->IER & UART_TX_INT_EN)) {
+ info->IER |= UART_TX_INT_EN;
+ serial_out(info, UART_CR_REG, info->IER);
+ }
+ restore_flags(flags);
+}
+
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rs_hangup(struct tty_struct *tty)
+{
+ struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct serial_state *state = info->state;
+
+ state = info->state;
+
+ rs_flush_buffer(tty);
+
+ if (info->flags & ASYNC_CLOSING)
+ return;
+
+ info->event = 0;
+ state->count = 0;
+// info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE);
+ info->tty = 0;
+ wake_up_interruptible(&info->open_wait);
+}
+
+
+/*
+ * rs_break() --- routine which turns the break handling on or off
+ */
+static void rs_break(struct tty_struct *tty, int break_state)
+{
+ struct async_struct * info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
+
+ if (!CONFIGURED_SERIAL_PORT(info))
+ return;
+
+ save_flags(flags);
+ cli();
+ if (break_state == -1)
+ info->LCR |= UART_SEND_BREAK;
+ else
+ info->LCR &= ~UART_SEND_BREAK;
+
+ serial_out(info, UART_LCR_H_REG, info->LCR);
+ restore_flags(flags);
+}
+
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void rs_send_xchar(struct tty_struct *tty, char ch)
+{
+ struct async_struct *info = (struct async_struct *)tty->driver_data;
+
+ info->x_char = ch;
+ if (ch) {
+ /* Make sure transmit interrupts are on */
+ info->IER |= UART_TX_INT_EN;
+ serial_out(info, UART_CR_REG, info->IER);
+ }
+}
+
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+#if 0
+ struct async_struct * info = (struct async_struct *)tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+ int lsr;
+
+ if (info->state->type == PORT_UNKNOWN)
+ return;
+
+ if (info->xmit_fifo_size == 0)
+ return; /* Just in case.... */
+
+ orig_jiffies = jiffies;
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ *
+ * Note: we have to use pretty tight timings here to satisfy
+ * the NIST-PCTS.
+ */
+ char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+ char_time = char_time / 5;
+ if (char_time == 0)
+ char_time = 1;
+ if (timeout && timeout < char_time)
+ char_time = timeout;
+ /*
+ * If the transmitter hasn't cleared in twice the approximate
+ * amount of time to send the entire FIFO, it probably won't
+ * ever clear. This assumes the UART isn't doing flow
+ * control, which is currently the case. Hence, if it ever
+ * takes longer than info->timeout, this is probably due to a
+ * UART bug of some kind. So, we clamp the timeout parameter at
+ * 2*info->timeout.
+ */
+ if (!timeout || timeout > 2*info->timeout)
+ timeout = 2*info->timeout;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+ printk("jiff=%lu...", jiffies);
+#endif
+ while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(char_time);
+ if (signal_pending(current))
+ break;
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
+ set_current_state(TASK_RUNNING);
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+#endif
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static inline int line_info(char *buf, struct serial_state *state)
+{
+#if 0
+ struct async_struct *info = state->info, scr_info;
+ char stat_buf[30], control, status;
+ int ret;
+ unsigned long flags;
+
+ ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d",
+ state->line, uart_config[state->type].name,
+ state->port, state->irq);
+
+ if (!state->port || (state->type == PORT_UNKNOWN)) {
+ ret += sprintf(buf+ret, "\n");
+ return ret;
+ }
+
+ /*
+ * Figure out the current RS-232 lines
+ */
+ if (!info) {
+ info = &scr_info; /* This is just for serial_{in,out} */
+
+ info->magic = SERIAL_MAGIC;
+ info->port = state->port;
+ info->flags = state->flags;
+ info->quot = 0;
+ info->tty = 0;
+ }
+ save_flags(flags); cli();
+ status = serial_in(info, UART_MSR);
+ control = info != &scr_info ? info->MCR : serial_in(info, UART_MCR);
+ restore_flags(flags);
+
+ stat_buf[0] = 0;
+ stat_buf[1] = 0;
+ if (control & UART_MCR_RTS)
+ strcat(stat_buf, "|RTS");
+ if (status & UART_MSR_CTS)
+ strcat(stat_buf, "|CTS");
+ if (control & UART_MCR_DTR)
+ strcat(stat_buf, "|DTR");
+ if (status & UART_MSR_DSR)
+ strcat(stat_buf, "|DSR");
+ if (status & UART_MSR_DCD)
+ strcat(stat_buf, "|CD");
+ if (status & UART_MSR_RI)
+ strcat(stat_buf, "|RI");
+
+ if (info->quot) {
+ ret += sprintf(buf+ret, " baud:%d",
+ state->baud_base / info->quot);
+ }
+
+ ret += sprintf(buf+ret, " tx:%d rx:%d",
+ state->icount.tx, state->icount.rx);
+
+ if (state->icount.frame)
+ ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
+
+ if (state->icount.parity)
+ ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
+
+ if (state->icount.brk)
+ ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
+
+ if (state->icount.overrun)
+ ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
+
+ /*
+ * Last thing is the RS-232 status lines
+ */
+ ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+ return ret;
+#endif
+ return 0;
+}
+
+
+int rs_read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int i, len = 0, l;
+ off_t begin = 0;
+
+ len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n",
+ serial_version, LOCAL_VERSTRING, serial_revdate);
+ for (i = 0; i < NR_PORTS && len < 4000; i++) {
+ l = line_info(page + len, &rs_table[i]);
+ len += l;
+ if (len+begin > off+count)
+ goto done;
+ if (len+begin < off) {
+ begin += len;
+ len = 0;
+ }
+ }
+ *eof = 1;
+done:
+ if (off >= len+begin)
+ return 0;
+ *start = page + (off-begin);
+ return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+
+/*
+ * This routine must be called by kernel at boot time
+ */
+int __init serial5120_init(void)
+{
+ memset(&dev_tty_driver, 0, sizeof(struct tty_driver));
+
+ dev_tty_driver.magic = TTY_DRIVER_MAGIC;
+ dev_tty_driver.driver_name = "/dev/ttyS0";
+ dev_tty_driver.name = "ttyS0";
+ dev_tty_driver.major = TTY_MAJOR;
+ dev_tty_driver.minor_start = 64;
+ dev_tty_driver.num = 1;
+ dev_tty_driver.type = TTY_DRIVER_TYPE_SERIAL;
+ dev_tty_driver.subtype = SERIAL_TYPE_NORMAL;
+ dev_tty_driver.init_termios = tty_std_termios;
+ dev_tty_driver.init_termios.c_cflag =
+ B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+ dev_tty_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+// dev_tty_driver.refcount = &serial_refcount;
+// dev_tty_driver.table = serial_table;
+ dev_tty_driver.termios = serial_termios;
+ dev_tty_driver.termios_locked = serial_termios_locked;
+
+ dev_tty_driver.open = rs_open;
+ dev_tty_driver.close = rs_close;
+ dev_tty_driver.write = rs_write;
+ dev_tty_driver.put_char = rs_put_char;
+ dev_tty_driver.flush_chars = rs_flush_chars;
+ dev_tty_driver.write_room = rs_write_room;
+ dev_tty_driver.chars_in_buffer = rs_chars_in_buffer;
+ dev_tty_driver.flush_buffer = rs_flush_buffer;
+ dev_tty_driver.ioctl = rs_ioctl;
+ dev_tty_driver.throttle = rs_throttle;
+ dev_tty_driver.unthrottle = rs_unthrottle;
+ dev_tty_driver.set_termios = rs_set_termios;
+ dev_tty_driver.stop = rs_stop;
+ dev_tty_driver.start = rs_start;
+ dev_tty_driver.hangup = rs_hangup;
+ dev_tty_driver.break_ctl = rs_break;
+ dev_tty_driver.send_xchar = rs_send_xchar;
+ dev_tty_driver.wait_until_sent = rs_wait_until_sent;
+ dev_tty_driver.read_proc = rs_read_proc;
+
+ if (tty_register_driver(&dev_tty_driver))
+ panic("Couldn't register /dev/ttyS0 driver\n");
+
+ return 0;
+}
+
+__initcall(serial5120_init);
diff -ruN linux-2.6.10/arch/mips/am5120/setup.c linux-2.6.10-adm.1/arch/mips/am5120/setup.c
--- linux-2.6.10/arch/mips/am5120/setup.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/setup.c 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,119 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;
+;------------------------------------------------------------------------------
+;
+; Project : ADM5120
+; Creator : daniell@admtek.com.tw
+; File : arch/mips/am5120/setup.c
+; Date : 2003.3.4
+; Abstract:
+;
+;Modification History:
+;
+;*****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/types.h>
+#include <linux/string.h> /* for memset */
+
+#include <asm/reboot.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/am5120/adm5120.h>
+
+
+//extern struct rtc_ops am5120_rtc_ops;
+//extern struct rtc_ops *rtc_ops;
+
+void mips_timer_setup(struct irqaction *irq);
+void mips_time_init(void);
+
+int am5120_pci_module;
+
+
+void am5120_restart(char *command)
+{
+ int i;
+
+ /* Disable All ports*/
+ ADM5120_SW_REG(Port_conf0_REG) |= SW_DISABLE_PORT_MASK;
+
+ /* Disable CPU port */
+ ADM5120_SW_REG(CPUp_conf_REG) |= SW_CPU_PORT_DISABLE;
+
+ // Wait until switch DMA idle. At least 1ms is required!!!!
+ for (i=0; i <1000000; i++);
+
+ ADM5120_SW_REG(SftRest_REG) = SOFTWARE_RESET;
+}
+
+
+void am5120_halt(void)
+{
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+ while (1);
+}
+
+
+void am5120_power_off(void)
+{
+ am5120_halt();
+}
+
+static int __init am5120_setup(void)
+{
+ printk("ADM5120 board setup\n");
+
+ board_time_init = mips_time_init;
+ board_timer_setup = mips_timer_setup;
+
+ _machine_restart = am5120_restart;
+ _machine_halt = am5120_halt;
+ _machine_power_off = am5120_power_off;
+
+// rtc_ops = &am5120_rtc_ops;
+
+ set_io_port_base(KSEG1);
+
+ /* check pci in existence or not */
+ if (ADM5120_SW_REG(CODE_REG) & CPU_PQFP_MODE)
+ {
+ printk("System no PCI BIOS\n");
+ am5120_pci_module = 0;
+ }
+ else
+ {
+ printk("System has PCI BIOS\n");
+ am5120_pci_module = 1;
+ }
+ return 0;
+}
+
+early_initcall(am5120_setup);
+
+const char *get_system_type(void)
+{
+ return "ADM5120 Board";
+}
diff -ruN linux-2.6.10/arch/mips/am5120/time.c linux-2.6.10-adm.1/arch/mips/am5120/time.c
--- linux-2.6.10/arch/mips/am5120/time.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/am5120/time.c 2005-01-27 21:06:17.000000000 +0100
@@ -0,0 +1,98 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2005 Jeroen Vreeken (pe1rxq@amsat.org)
+ *
+ * ########################################################################
+ *
+ * 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/types.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/hardirq.h>
+#include <asm/div64.h>
+#include <asm/cpu.h>
+#include <asm/am5120/adm5120.h>
+
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <asm/time.h>
+#include <asm/mipsregs.h>
+
+
+unsigned int mips_counter_frequency;
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ5 | STATUS_IE)
+
+#define MIPS_CPU_TIMER_IRQ 7
+
+
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+ write_c0_compare(read_c0_count()+ mips_counter_frequency/HZ);
+ ll_timer_interrupt(MIPS_CPU_TIMER_IRQ, regs);
+}
+
+
+void __init mips_time_init(void)
+{
+ unsigned long clock;
+
+ clock = (ADM5120_SW_REG(CODE_REG) & CODE_CLK_MASK) >> CODE_CLK_SHIFT;
+
+ switch (clock)
+ {
+ case CPU_CLK_175MHZ:
+ mips_counter_frequency = CPU_SPEED_175M;
+ printk("CPU clock: 175MHz\n");
+ break;
+
+ case CPU_CLK_200MHZ:
+ mips_counter_frequency = CPU_SPEED_200M;
+ printk("CPU clock: 200MHz\n");
+ break;
+
+ case CPU_CLK_225MHZ:
+ mips_counter_frequency = CPU_SPEED_225M;
+ printk("CPU clock: 225MHz\n");
+ break;
+
+ case CPU_CLK_250MHZ:
+ mips_counter_frequency = CPU_SPEED_250M;
+ printk("CPU clock: 250MHz\n");
+ break;
+ }
+}
+
+
+void __init mips_timer_setup(struct irqaction *irq)
+{
+ /* to generate the first timer interrupt */
+ write_c0_compare(read_c0_count()+ mips_counter_frequency/HZ);
+ clear_c0_status(ST0_BEV);
+ set_c0_status(ALLINTS);
+}
diff -ruN linux-2.6.10/arch/mips/kernel/head.S linux-2.6.10-adm.1/arch/mips/kernel/head.S
--- linux-2.6.10/arch/mips/kernel/head.S 2004-12-24 22:35:01.000000000 +0100
+++ linux-2.6.10-adm.1/arch/mips/kernel/head.S 2005-01-27 21:06:16.000000000 +0100
@@ -127,12 +127,16 @@
* Necessary for machines which link their kernels at KSEG0.
*/
.fill 0x400
+#ifdef CONFIG_MIPS_AM5120
+ /* AM5120 bootloader jumps to 0x6d8 */
+ .fill 0x2d8
+ j kernel_entry
+#endif
EXPORT(stext) # used for profiling
EXPORT(_stext)
__INIT
-
NESTED(kernel_entry, 16, sp) # kernel entry point
setup_c0_status_pri
diff -ruN linux-2.6.10/include/asm-mips/am5120/adm5120.h linux-2.6.10-adm.1/include/asm-mips/am5120/adm5120.h
--- linux-2.6.10/include/asm-mips/am5120/adm5120.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/include/asm-mips/am5120/adm5120.h 2005-01-27 21:06:27.000000000 +0100
@@ -0,0 +1,1084 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;
+;------------------------------------------------------------------------------
+;
+; Project : ADM5120
+; Creator :
+; File : include/asm/am5120/adm5120.h
+; Date : 2003.3.10
+; Abstract:
+;
+;Modification History:
+;
+; Jeroen Vreeken (pe1rxq@amsat.org)
+; Changed UART_BAUDDIV() to minimize for rounding errors.
+; Reformatted (somebody likes 4 character tabs....)
+;
+;*****************************************************************************/
+
+
+#ifndef __ADM5120_H__
+#define __ADM5120_H__
+
+
+#include <asm/addrspace.h>
+
+
+/*========================= Physical Memory Map ============================*/
+#define SDRAM_BASE 0x00000000
+#define SMEM1_BASE 0x10000000
+
+#define EXTIO0_BASE 0x10C00000
+#define EXTIO1_BASE 0x10E00000
+#define MPMC_BASE 0x11000000
+#define USBHOST_BASE 0x11200000
+#define PCIMEM_BASE 0x11400000
+#define PCIIO_BASE 0x11500000
+#define PCICFG_BASE 0x115FFFF0
+#define MIPS_BASE 0x11A00000
+#define SWCTRL_BASE 0x12000000
+
+#define INTC_BASE 0x12200000
+#define SYSC_BASE 0x12400000
+
+#define UART0_BASE 0x12600000
+#define UART1_BASE 0x12800000
+
+#define SMEM0_BASE 0x1FC00000
+
+
+/*======================= MIPS interrupt ===================*/
+#define MIPSINT_SOFT0 0
+#define MIPSINT_SOFT1 1
+#define MIPSINT_IRQ 2
+#define MIPSINT_FIQ 3
+#define MIPSINT_REV0 4
+#define MIPSINT_REV1 5
+#define MIPSINT_REV2 6
+#define MIPSINT_TIMER 7
+
+#define STATUS_IE 0x00000001
+
+/*==================== MultiPort Memory Controller (MPMC) ==================*/
+/* registers offset */
+#define MPMC_CONTROL_REG 0x0000
+#define MPMC_STATUS_REG 0x0004
+#define MPMC_CONFIG_REG 0x0008
+
+#define MPMC_DM_CONTROL_REG 0x0020
+#define MPMC_DM_REFRESH_REG 0x0024
+
+#define MPMC_DM_TRP_REG 0x0030
+#define MPMC_DM_TRAS_REG 0x0034
+#define MPMC_DM_TSREX_REG 0x0038
+#define MPMC_DM_TAPR_REG 0x003C
+#define MPMC_DM_TDAL_REG 0x0040
+#define MPMC_DM_TWR_REG 0x0044
+#define MPMC_DM_TRC_REG 0x0048
+#define MPMC_DM_TRFC_REG 0x004C
+#define MPMC_DM_TXSR_REG 0x0050
+#define MPMC_DM_TRRD_REG 0x0054
+#define MPMC_DM_TMRD_REG 0x0058
+
+#define MPMC_SM_EXTWAIT_REG 0x0080
+
+#define MPMC_DM_CONFIG0_REG 0x0100
+#define MPMC_DM_RASCAS0_REG 0x0104
+
+#define MPMC_DM_CONFIG1_REG 0x0120
+#define MPMC_DM_RASCAS1_REG 0x0124
+
+#define MPMC_SM_CONFIG0_REG 0x0200
+#define MPMC_SM_WAITWEN0_REG 0x0204
+#define MPMC_SM_WAITOEN0_REG 0x0208
+#define MPMC_SM_WAITRD0_REG 0x020C
+#define MPMC_SM_WAITPAGE0_REG 0x0210
+#define MPMC_SM_WAITWR0_REG 0x0214
+#define MPMC_SM_WAITTURN0_REG 0x0218
+
+#define MPMC_SM_CONFIG1_REG 0x0220
+#define MPMC_SM_WAITWEN1_REG 0x0224
+#define MPMC_SM_WAITOEN1_REG 0x0228
+#define MPMC_SM_WAITRD1_REG 0x022C
+#define MPMC_SM_WAITPAGE1_REG 0x0230
+#define MPMC_SM_WAITWR1_REG 0x0234
+#define MPMC_SM_WAITTURN1_REG 0x0238
+
+#define MPMC_SM_CONFIG2_REG 0x0240
+#define MPMC_SM_WAITWEN2_REG 0x0244
+#define MPMC_SM_WAITOEN2_REG 0x0248
+#define MPMC_SM_WAITRD2_REG 0x024C
+#define MPMC_SM_WAITPAGE2_REG 0x0250
+#define MPMC_SM_WAITWR2_REG 0x0254
+#define MPMC_SM_WAITTURN2_REG 0x0258
+
+#define MPMC_SM_CONFIG3_REG 0x0260
+#define MPMC_SM_WAITWEN3_REG 0x0264
+#define MPMC_SM_WAITOEN3_REG 0x0268
+#define MPMC_SM_WAITRD3_REG 0x026C
+#define MPMC_SM_WAITPAGE3_REG 0x0270
+#define MPMC_SM_WAITWR3_REG 0x0274
+#define MPMC_SM_WAITTURN3_REG 0x0278
+
+/* Macro for access MPMC register */
+#define MPMC_REG(_offset) \
+ (*((volatile unsigned long *)(KSEG1ADDR(MPMC_BASE + (_offset)))))
+
+
+/* MPMC_CONTROL_REG (offset: 0x0000) */
+#define MPMC_DRAIN_W_BUF 0x00000008
+#define MPMC_LOW_POWER_MODE 0x00000004
+#define MPMC_ADDR_MIRROR 0x00000002
+#define MPMC_ENABLE 0x00000001
+#define MPMC_CONTROL_MASK 0x0000000f
+
+/* MPMC_STATUS_REG (offset: 0x0004) */
+#define MPMC_SREFACK 0x00000004
+#define MPMC_WBUF_DIRTY 0x00000002
+#define MPMC_BUSY 0x00000001
+#define MPMC_STATUS_MASK 0x00000007
+
+/* MPMC_CONFIG_REG (offset: 0x0008) */
+#define MPMC_CLK_RATIO_1_1 0x00000000
+#define MPMC_CLK_RATIO_1_2 0x00000100
+#define MPMC_LITTLE_ENDIAN 0x00000000
+#define MPMC_BIG_ENDIAN 0x00000001
+#define MPMC_CONFIG_MASK 0x00000101
+
+/* MPMC_DM_CONTROL_REG (offset: 0x0020) */
+#define DM_PVHHOUT_HI_VOLTAGE 0x00008000
+#define DM_RPOUT_HI_VOLTAGE 0x00004000
+#define DM_DEEP_SLEEP_MODE 0x00002000
+
+#define DM_SDRAM_NOP 0x00000180
+#define DM_SDRAM_PRECHARGE_ALL 0x00000100
+#define DM_SDRAM_MODE_SETTING 0x00000080
+#define DM_SDRAM_NORMAL_OP 0x00000000
+#define DM_SDRAM_OPMODE_MASK 0x00000180
+
+#define DM_SELF_REFRESH_MODE 0x00000004
+#define DM_CLKOUT_ALWAYS 0x00000002
+#define DM_CLKEN_ALWAYS 0x00000001
+
+#define MPMC_DM_CONTROL_MASK 0x0000e187
+
+
+/* MPMC_DM_REFRESH_REG (offset:0x0024) */
+#define MPMC_DM_REFRESH_MASK 0x00000300
+
+/* MPMC_DM_TRP_REG (offset: 0x0030) */
+#define MPMC_DM_TRP_MASK 0x0000000f
+
+/* MPMC_DM_TRAS_REG (offset: 0x0034) */
+#define MPMC_DM_TRAS_MASK 0x0000000f
+
+/* MPMC_DM_TSREX_REG (offset: 0x0038) */
+#define MPMC_DM_TSREX_MASK 0x0000000f
+
+/* MPMC_DM_TAPR_REG (offset: 0x003C) */
+#define MPMC_DM_TAPR_MASK 0x0000000f
+
+/* MPMC_DM_TDAL_REG (offset: 0x0040) */
+#define MPMC_DM_TDAL_MASK 0x0000000f
+
+/* MPMC_DM_TWR_REG (offset: 0x0044) */
+#define MPMC_DM_TWR_MASK 0x0000000f
+
+/* MPMC_DM_TRC_REG (offset: 0x0048) */
+#define MPMC_DM_TRC_MASK 0x0000001f
+
+/* MPMC_DM_TRFC_REG (offset: 0x004C) */
+#define MPMC_DM_TRFC_MASK 0x0000001f
+
+/* MPMC_DM_TXSR_REG (offset: 0x0050) */
+#define MPMC_DM_TXSR_MASK 0x0000001f
+
+/* MPMC_DM_TRRD_REG (offset: 0x0054) */
+#define MPMC_DM_TRRD_MASK 0x0000000f
+
+/* MPMC_DM_TMRD_REG (offset: 0x0058) */
+#define MPMC_DM_TMRD_MASK 0x0000000f
+
+/* MPMC_SM_EXTWAIT_REG (offset: 0x0080) */
+#define MPMC_SM_EXTWAIT_MASK 0x0000003f
+
+
+/* MPMC_DM_CONFIG0_REG (offset: 0x0100) */
+/* MPMC_DM_CONFIG1_REG (offset: 0x0120) */
+#define DM_CFG_ROW_WIDTH_13BIT 0x20000000
+#define DM_CFG_ROW_WIDTH_12BIT 0x10000000
+#define DM_CFG_ROW_WIDTH_11BIT 0x00000000
+#define DM_CFG_ROW_WIDTH_MASK 0x30000000
+#define DM_CFG_ROW_WIDTH_SHIFT 28
+
+#define DM_CFG_2BANK_DEV 0x00000000
+#define DM_CFG_4BANK_DEV 0x04000000
+#define DM_CFG_BANK_SHIFT 26
+
+#define DM_CFG_COL_WIDTH_11BIT 0x01400000
+#define DM_CFG_COL_WIDTH_10BIT 0x01000000
+#define DM_CFG_COL_WIDTH_9BIT 0x00c00000
+#define DM_CFG_COL_WIDTH_8BIT 0x00800000
+#define DM_CFG_COL_WIDTH_7BIT 0x00400000
+#define DM_CFG_COL_WIDTH_6BIT 0x00000000
+#define DM_CFG_COL_WIDTH_MASK 0x01c00000
+#define DM_CFG_COL_WIDTH_SHIFT 22
+
+#define DM_CFG_WRITE_PROTECT 0x00100000
+#define DM_CFG_BUFFER_EN 0x00080000
+
+#define DM_CFG_ADDR_MAPPING_MASK 0x00005F80
+
+#define DM_CFG_DEV_SYNC_FLASH 0x00000010
+#define DM_CFG_DEV_LOWPOWER_SDRAM 0x00000008
+#define DM_CFG_DEV_SDRAM 0x00000000
+#define DM_CFG_DEV_MASK 0x00000018
+
+
+/* MPMC_DM_RASCAS0_REG (offset: 0x0104) */
+/* MPMC_DM_RASCAS1_REG (offset: 0x0124) */
+
+#define DM_CAS_LATENCY_3 0x00000300
+#define DM_CAS_LATENCY_2 0x00000200
+#define DM_CAS_LATENCY_1 0x00000100
+
+#define DM_RAS_LATENCY_3 0x00000003
+#define DM_RAS_LATENCY_2 0x00000002
+#define DM_RAS_LATENCY_1 0x00000001
+
+
+/* MPMC_SM_CONFIG0_REG (offset: 0x0200) */
+/* MPMC_SM_CONFIG1_REG (offset: 0x0220) */
+/* MPMC_SM_CONFIG2_REG (offset: 0x0240) */
+/* MPMC_SM_CONFIG3_REG (offset: 0x0260) */
+
+#define SM_WRITE_PROTECT 0x00100000
+#define SM_WRITEBUF_ENABLE 0x00080000
+#define SM_EXTENDED_WAIT 0x00000100
+#define SM_PB 0x00000080
+#define SM_CS_HIGH 0x00000040
+#define SM_PAGE_MODE 0x00000008
+
+#define SM_MEM_WIDTH_32BIT 0x00000002
+#define SM_MEM_WIDTH_16BIT 0x00000001
+#define SM_MEM_WIDTH_8BIT 0x00000000
+
+#define MPMC_SM_CONFIG_MASK 0x001801cb
+
+
+/* MPMC_SM_WAITWEN0_REG (offset: 0x0204) */
+/* MPMC_SM_WAITWEN1_REG (offset: 0x0224) */
+/* MPMC_SM_WAITWEN2_REG (offset: 0x0244) */
+/* MPMC_SM_WAITWEN3_REG (offset: 0x0264) */
+#define MPMC_SM_WAITWEN_MASK 0x0000000f
+
+
+/* MPMC_SM_WAITOEN0_REG (offset: 0x0208) */
+/* MPMC_SM_WAITOEN1_REG (offset: 0x0228) */
+/* MPMC_SM_WAITOEN2_REG (offset: 0x0248) */
+/* MPMC_SM_WAITOEN3_REG (offset: 0x0268) */
+#define MPMC_SM_WAITOEN_MASK 0x0000000f
+
+/* MPMC_SM_WAITRD0_REG (offset: 0x020C) */
+/* MPMC_SM_WAITRD1_REG (offset: 0x022C) */
+/* MPMC_SM_WAITRD2_REG (offset: 0x024C) */
+/* MPMC_SM_WAITRD3_REG (offset: 0x026C) */
+#define MPMC_SM_WAITRD_MASK 0x0000001f
+
+/* MPMC_SM_WAITPAGE0_REG (offset: 0x0210) */
+/* MPMC_SM_WAITPAGE1_REG (offset: 0x0230) */
+/* MPMC_SM_WAITPAGE2_REG (offset: 0x0250) */
+/* MPMC_SM_WAITPAGE3_REG (offset: 0x0270) */
+#define MPMC_SM_WAITPAGE_MASK 0x0000001f
+
+
+/* MPMC_SM_WAITWR0_REG (offset: 0x0214) */
+/* MPMC_SM_WAITWR1_REG (offset: 0x0234) */
+/* MPMC_SM_WAITWR2_REG (offset: 0x0254) */
+/* MPMC_SM_WAITWR3_REG (offset: 0x0274) */
+#define MPMC_SM_WAITWR_MASK 0x0000001f
+
+
+/* MPMC_SM_WAITTURN0_REG (offset: 0x0218) */
+/* MPMC_SM_WAITTURN1_REG (offset: 0x0238) */
+/* MPMC_SM_WAITTURN2_REG (offset: 0x0258) */
+/* MPMC_SM_WAITTURN3_REG (offset: 0x0278) */
+#define MPMC_SM_WAITTURN_MASK 0x0000000f
+
+
+/* SDRAM mode register */
+/* ref: SDRAM data sheet. Ex: Micron MT48LC4M16A2 data sheet. */
+#define SDRAM_BTLEN_1 0x0000
+#define SDRAM_BTLEN_2 0x0001
+#define SDRAM_BTLEN_4 0x0002
+#define SDRAM_BTLEN_8 0x0003
+#define SDRAM_BTLEN_FULLPAGE 0x0007
+#define SDRAM_BTLEN_MASK 0x0007
+
+#define SDRAM_BT_SEQUENCIAL 0x0000
+#define SDRAM_BT_INTERLEVED 0x0008
+
+#define SDRAM_CAS_LATENCY_2 0x0020
+#define SDRAM_CAS_LATENCY_3 0x0030
+#define SDRAM_CAS_LATENCY_MASK 0x0030
+
+#define SDRAM_OPMODE_STANDARD 0x0000
+#define SDRAM_OPMODE_MASK 0x0180
+
+#define SDRAM_WBTMODE_ENABLE 0x0000
+#define SDRAM_WBTMODE_DISABLE 0x0200
+
+#define SDRAM_MODEREG_MASK 0x03FF
+
+
+
+/*========================== Interrupt Controller ==========================*/
+/* registers offset */
+#define IRQ_STATUS_REG 0x00 /* Read */
+#define IRQ_RAW_STATUS_REG 0x04 /* Read */
+#define IRQ_ENABLE_REG 0x08 /* Read/Write */
+#define IRQ_DISABLE_REG 0x0C /* Write */
+#define IRQ_SOFT_REG 0x10 /* Write */
+
+#define IRQ_MODE_REG 0x14 /* Read/Write */
+#define FIQ_STATUS_REG 0x18 /* Read */
+
+/* test registers */
+#define IRQ_TESTSRC_REG 0x1c /* Read/Write */
+#define IRQ_SRCSEL_REG 0x20 /* Read/Write */
+#define IRQ_LEVEL_REG 0x24 /* Read/Write */
+
+/* Macro for accessing Interrupt controller register */
+#define ADM5120_INTC_REG(_reg) \
+ (*((volatile unsigned long *)(KSEG1ADDR(INTC_BASE + (_reg)))))
+
+/* interrupt levels */
+#define INT_LVL_TIMER 0 /* Timer */
+#define INT_LVL_UART0 1 /* Uart 0 */
+#define INT_LVL_UART1 2 /* Uart 1 */
+#define INT_LVL_USBHOST 3 /* USB Host */
+#define INT_LVL_EXTIO_0 4 /* External I/O 0 */
+#define INT_LVL_EXTIO_1 5 /* External I/O 1 */
+#define INT_LVL_PCI_0 6 /* PCI 0 */
+#define INT_LVL_PCI_1 7 /* PCI 1 */
+#define INT_LVL_PCI_2 8 /* PCI 2 */
+#define INT_LVL_SWITCH 9 /* Switch */
+#define INT_LVL_MAX INT_LVL_SWITCH
+
+/* interrupts */
+#define IRQ_TIMER (0x1 << INT_LVL_TIMER)
+#define IRQ_UART0 (0x1 << INT_LVL_UART0)
+#define IRQ_UART1 (0x1 << INT_LVL_UART1)
+#define IRQ_USBHOST (0x1 << INT_LVL_USBHOST)
+#define IRQ_EXTIO_0 (0x1 << INT_LVL_EXTIO_0)
+#define IRQ_EXTIO_1 (0x1 << INT_LVL_EXTIO_1)
+#define IRQ_PCI_INT0 (0x1 << INT_LVL_PCI_0)
+#define IRQ_PCI_INT1 (0x1 << INT_LVL_PCI_1)
+#define IRQ_PCI_INT2 (0x1 << INT_LVL_PCI_2)
+#define IRQ_SWITCH (0x1 << INT_LVL_SWITCH)
+
+#define IRQ_MASK 0x3ff
+
+
+/* IRQ LEVEL reg */
+#define IRQ_EXTIO0_ACT_LOW IRQ_EXTIO_0
+#define IRQ_EXTIO1_ACT_LOW IRQ_EXTIO_1
+#define IRQ_PCIINT0_ACT_LOW IRQ_PCI_INT0
+#define IRQ_PCIINT1_ACT_LOW IRQ_PCI_INT1
+#define IRQ_PCIINT2_ACT_LOW IRQ_PCI_INT2
+
+#define IRQ_LEVEL_MASK 0x01F0
+
+/*========================= Switch Control Register ========================*/
+/* Control Register */
+#define CODE_REG 0x0000
+#define SftRest_REG 0x0004
+#define Boot_done_REG 0x0008
+#define SWReset_REG 0x000C
+#define Global_St_REG 0x0010
+#define PHY_st_REG 0x0014
+#define Port_st_REG 0x0018
+#define Mem_control_REG 0x001C
+#define SW_conf_REG 0x0020
+#define CPUp_conf_REG 0x0024
+#define Port_conf0_REG 0x0028
+#define Port_conf1_REG 0x002C
+#define Port_conf2_REG 0x0030
+
+#define VLAN_G1_REG 0x0040
+#define VLAN_G2_REG 0x0044
+#define Send_trig_REG 0x0048
+#define Srch_cmd_REG 0x004C
+#define ADDR_st0_REG 0x0050
+#define ADDR_st1_REG 0x0054
+#define MAC_wt0_REG 0x0058
+#define MAC_wt1_REG 0x005C
+#define BW_cntl0_REG 0x0060
+#define BW_cntl1_REG 0x0064
+#define PHY_cntl0_REG 0x0068
+#define PHY_cntl1_REG 0x006C
+#define FC_th_REG 0x0070
+#define Adj_port_th_REG 0x0074
+#define Port_th_REG 0x0078
+#define PHY_cntl2_REG 0x007C
+#define PHY_cntl3_REG 0x0080
+#define Pri_cntl_REG 0x0084
+#define VLAN_pri_REG 0x0088
+#define TOS_en_REG 0x008C
+#define TOS_map0_REG 0x0090
+#define TOS_map1_REG 0x0094
+#define Custom_pri1_REG 0x0098
+#define Custom_pri2_REG 0x009C
+
+#define Empty_cnt_REG 0x00A4
+#define Port_cnt_sel_REG 0x00A8
+#define Port_cnt_REG 0x00AC
+#define SW_Int_st_REG 0x00B0
+#define SW_Int_mask_REG 0x00B4
+
+// GPIO config
+#define GPIO_conf0_REG 0x00B8
+#define GPIO_conf2_REG 0x00BC
+
+// Watch dog
+#define Watchdog0_REG 0x00C0
+#define Watchdog1_REG 0x00C4
+
+#define Swap_in_REG 0x00C8
+#define Swap_out_REG 0x00CC
+
+// Tx/Rx Descriptors
+#define Send_HBaddr_REG 0x00D0
+#define Send_LBaddr_REG 0x00D4
+#define Recv_HBaddr_REG 0x00D8
+#define Recv_LBaddr_REG 0x00DC
+#define Send_HWaddr_REG 0x00E0
+#define Send_LWaddr_REG 0x00E4
+#define Recv_HWaddr_REG 0x00E8
+#define Recv_LWaddr_REG 0x00EC
+
+// Timer Control
+#define Timer_int_REG 0x00F0
+#define Timer_REG 0x00F4
+
+// LED control
+#define Port0_LED_REG 0x0100
+#define Port1_LED_REG 0x0104
+#define Port2_LED_REG 0x0108
+#define Port3_LED_REG 0x010c
+#define Port4_LED_REG 0x0110
+
+
+/* Macros for accessing Switch control register */
+#define ADM5120_SW_REG(_reg) \
+ (*((volatile unsigned long *)(KSEG1ADDR(SWCTRL_BASE + (_reg)))))
+
+
+
+/* CODE_REG */
+#define CODE_ID_MASK 0x00FFFF
+#define CODE_ADM5120_ID 0x5120
+
+#define CODE_REV_MASK 0x0F0000
+#define CODE_REV_SHIFT 16
+#define CODE_REV_ADM5120_0 0x8
+
+#define CODE_CLK_MASK 0x300000
+#define CODE_CLK_SHIFT 20
+
+#define CPU_CLK_175MHZ 0x0
+#define CPU_CLK_200MHZ 0x1
+#define CPU_CLK_225MHZ 0x2
+#define CPU_CLK_250MHZ 0x3
+
+#define CPU_SPEED_175M (175000000/2)
+#define CPU_SPEED_200M (200000000/2)
+#define CPU_SPEED_225M (225000000/2)
+#define CPU_SPEED_250M (250000000/2)
+
+#define CPU_NAND_BOOT 0x01000000
+#define CPU_DCACHE_2K_WAY (0x1 << 25)
+#define CPU_DCACHE_2WAY (0x1 << 26)
+#define CPU_ICACHE_2K_WAY (0x1 << 27)
+#define CPU_ICACHE_2WAY (0x1 << 28)
+
+#define CPU_GMII_SUPPORT 0x20000000
+
+#define CPU_PQFP_MODE (0x1 << 29)
+
+#define CPU_CACHE_LINE_SIZE 16
+
+/* SftRest_REG */
+#define SOFTWARE_RESET 0x1
+
+/* Boot_done_REG */
+#define BOOT_DONE 0x1
+
+/* SWReset_REG */
+#define SWITCH_RESET 0x1
+
+/* Global_St_REG */
+#define DATA_BUF_BIST_FAILED (0x1 << 0)
+#define LINK_TAB_BIST_FAILED (0x1 << 1)
+#define MC_TAB_BIST_FAILED (0x1 << 2)
+#define ADDR_TAB_BIST_FAILED (0x1 << 3)
+#define DCACHE_D_FAILED (0x3 << 4)
+#define DCACHE_T_FAILED (0x1 << 6)
+#define ICACHE_D_FAILED (0x3 << 7)
+#define ICACHE_T_FAILED (0x1 << 9)
+#define BIST_FAILED_MASK 0x03FF
+
+#define ALLMEM_TEST_DONE (0x1 << 10)
+
+#define SKIP_BLK_CNT_MASK 0x1FF000
+#define SKIP_BLK_CNT_SHIFT 12
+
+
+/* PHY_st_REG */
+#define PORT_LINK_MASK 0x0000001F
+#define PORT_MII_LINKFAIL 0x00000020
+#define PORT_SPEED_MASK 0x00001F00
+
+#define PORT_GMII_SPD_MASK 0x00006000
+#define PORT_GMII_SPD_10M 0x00000000
+#define PORT_GMII_SPD_100M 0x00002000
+#define PORT_GMII_SPD_1000M 0x00004000
+
+#define PORT_DUPLEX_MASK 0x003F0000
+#define PORT_FLOWCTRL_MASK 0x1F000000
+
+#define PORT_GMII_FLOWCTRL_MASK 0x60000000
+#define PORT_GMII_FC_ON 0x20000000
+#define PORT_GMII_RXFC_ON 0x20000000
+#define PORT_GMII_TXFC_ON 0x40000000
+
+/* Port_st_REG */
+#define PORT_SECURE_ST_MASK 0x001F
+#define MII_PORT_TXC_ERR 0x0080
+
+/* Mem_control_REG */
+#define SDRAM_SIZE_4MBYTES 0x0001
+#define SDRAM_SIZE_8MBYTES 0x0002
+#define SDRAM_SIZE_16MBYTES 0x0003
+#define SDRAM_SIZE_64MBYTES 0x0004
+#define SDRAM_SIZE_128MBYTES 0x0005
+#define SDRAM_SIZE_MASK 0x0007
+
+#define MEMCNTL_SDRAM1_EN (0x1 << 5)
+
+#define ROM_SIZE_DISABLE 0x0000
+#define ROM_SIZE_512KBYTES 0x0001
+#define ROM_SIZE_1MBYTES 0x0002
+#define ROM_SIZE_2MBYTES 0x0003
+#define ROM_SIZE_4MBYTES 0x0004
+#define ROM_SIZE_8MBYTES 0x0005
+#define ROM_SIZE_MASK 0x0007
+
+#define ROM0_SIZE_SHIFT 8
+#define ROM1_SIZE_SHIFT 16
+
+
+/* SW_conf_REG */
+#define SW_AGE_TIMER_MASK 0x000000F0
+#define SW_AGE_TIMER_DISABLE 0x00000000
+#define SW_AGE_TIMER_FAST 0x00000080
+#define SW_AGE_TIMER_300SEC 0x00000010
+#define SW_AGE_TIMER_600SEC 0x00000020
+#define SW_AGE_TIMER_1200SEC 0x00000030
+#define SW_AGE_TIMER_2400SEC 0x00000040
+#define SW_AGE_TIMER_4800SEC 0x00000050
+#define SW_AGE_TIMER_9600SEC 0x00000060
+#define SW_AGE_TIMER_19200SEC 0x00000070
+//#define SW_AGE_TIMER_38400SEC 0x00000070
+
+#define SW_BC_PREV_MASK 0x00000300
+#define SW_BC_PREV_DISABLE 0x00000000
+#define SW_BC_PREV_64BC 0x00000100
+#define SW_BC_PREV_48BC 0x00000200
+#define SW_BC_PREV_32BC 0x00000300
+
+#define SW_MAX_LEN_MASK 0x00000C00
+#define SW_MAX_LEN_1536 0x00000000
+#define SW_MAX_LEN_1522 0x00000800
+#define SW_MAX_LEN_1518 0x00000400
+
+#define SW_DIS_COLABT 0x00001000
+
+#define SW_HASH_ALG_MASK 0x00006000
+#define SW_HASH_ALG_DIRECT 0x00000000
+#define SW_HASH_ALG_XOR48 0x00002000
+#define SW_HASH_ALG_XOR32 0x00004000
+
+#define SW_DISABLE_BACKOFF_TIMER 0x00008000
+
+#define SW_BP_NUM_MASK 0x000F0000
+#define SW_BP_NUM_SHIFT 16
+#define SW_BP_MODE_MASK 0x00300000
+#define SW_BP_MODE_DISABLE 0x00000000
+#define SW_BP_MODE_JAM 0x00100000
+#define SW_BP_MODE_JAMALL 0x00200000
+#define SW_BP_MODE_CARRIER 0x00300000
+#define SW_RESRV_MC_FILTER 0x00400000
+#define SW_BISR_DISABLE 0x00800000
+
+#define SW_DIS_MII_WAS_TX 0x01000000
+#define SW_BISS_EN 0x02000000
+#define SW_BISS_TH_MASK 0x0C000000
+#define SW_BISS_TH_SHIFT 26
+#define SW_REQ_LATENCY_MASK 0xF0000000
+#define SW_REQ_LATENCY_SHIFT 28
+
+
+/* CPUp_conf_REG */
+#define SW_CPU_PORT_DISABLE 0x00000001
+#define SW_PADING_CRC 0x00000002
+#define SW_BRIDGE_MODE 0x00000004
+
+#define SW_DIS_UN_SHIFT 9
+#define SW_DIS_UN_MASK (0x3F << SW_DIS_UN_SHIFT)
+#define SW_DIS_MC_SHIFT 16
+#define SW_DIS_MC_MASK (0x3F << SW_DIS_MC_SHIFT)
+#define SW_DIS_BC_SHIFT 24
+#define SW_DIS_BC_MASK (0x3F << SW_DIS_BC_SHIFT)
+
+
+/* Port_conf0_REG */
+#define SW_DISABLE_PORT_MASK 0x0000003F
+#define SW_EN_MC_MASK 0x00003F00
+#define SW_EN_MC_SHIFT 8
+#define SW_EN_BP_MASK 0x003F0000
+#define SW_EN_BP_SHIFT 16
+#define SW_EN_FC_MASK 0x3F000000
+#define SW_EN_FC_SHIFT 24
+
+
+/* Port_conf1_REG */
+#define SW_DIS_SA_LEARN_MASK 0x0000003F
+#define SW_PORT_BLOCKING_MASK 0x00000FC0
+#define SW_PORT_BLOCKING_SHIFT 6
+#define SW_PORT_BLOCKING_ON 0x1
+
+#define SW_PORT_BLOCKING_MODE_MASK 0x0003F000
+#define SW_PORT_BLOCKING_MODE_SHIFT 12
+#define SW_PORT_BLOCKING_CTRLONLY 0x1
+
+#define SW_EN_PORT_AGE_MASK 0x03F00000
+#define SW_EN_PORT_AGE_SHIFT 20
+#define SW_EN_SA_SECURED_MASK 0xFC000000
+#define SW_EN_SA_SECURED_SHIFT 26
+
+
+/* Port_conf2_REG */
+#define SW_GMII_AN_EN 0x00000001
+#define SW_GMII_FORCE_SPD_MASK 0x00000006
+#define SW_GMII_FORCE_SPD_10M 0
+#define SW_GMII_FORCE_SPD_100M 0x2
+#define SW_GMII_FORCE_SPD_1000M 0x4
+
+#define SW_GMII_FORCE_FULL_DUPLEX 0x00000008
+
+#define SW_GMII_FORCE_RXFC 0x00000010
+#define SW_GMII_FORCE_TXFC 0x00000020
+
+#define SW_GMII_EN 0x00000040
+#define SW_GMII_REVERSE 0x00000080
+
+#define SW_GMII_TXC_CHECK_EN 0x00000100
+
+#define SW_LED_FLASH_TIME_MASK 0x00030000
+#define SW_LED_FLASH_TIME_30MS 0x00000000
+#define SW_LED_FLASH_TIME_60MS 0x00010000
+#define SW_LED_FLASH_TIME_240MS 0x00020000
+#define SW_LED_FLASH_TIME_480MS 0x00030000
+
+
+/* Send_trig_REG */
+#define SEND_TRIG_LOW 0x0001
+#define SEND_TRIG_HIGH 0x0002
+
+
+/* Srch_cmd_REG */
+#define SW_MAC_SEARCH_START 0x000001
+#define SW_MAX_SEARCH_AGAIN 0x000002
+
+
+/* MAC_wt0_REG */
+#define SW_MAC_WRITE 0x00000001
+#define SW_MAC_WRITE_DONE 0x00000002
+#define SW_MAC_FILTER_EN 0x00000004
+#define SW_MAC_VLANID_SHIFT 3
+#define SW_MAC_VLANID_MASK 0x00000038
+#define SW_MAC_VLANID_EN 0x00000040
+#define SW_MAC_PORTMAP_MASK 0x00001F80
+#define SW_MAC_PORTMAP_SHIFT 7
+#define SW_MAC_AGE_MASK (0x7 << 13)
+#define SW_MAC_AGE_STATIC (0x7 << 13)
+#define SW_MAC_AGE_VALID (0x1 << 13)
+#define SW_MAC_AGE_EMPTY 0
+
+/* BW_cntl0_REG */
+#define SW_PORT_TX_NOLIMIT 0
+#define SW_PORT_TX_64K 1
+#define SW_PORT_TX_128K 2
+#define SW_PORT_TX_256K 3
+#define SW_PORT_TX_512K 4
+#define SW_PORT_TX_1M 5
+#define SW_PORT_TX_4M 6
+#define SW_PORT_TX_10MK 7
+
+/* BW_cntl1_REG */
+#define SW_TRAFFIC_SHAPE_IPG (0x1 << 31)
+
+/* PHY_cntl0_REG */
+#define SW_PHY_ADDR_MASK 0x0000001F
+#define PHY_ADDR_MAX 0x1f
+#define SW_PHY_REG_ADDR_MASK 0x00001F00
+#define SW_PHY_REG_ADDR_SHIFT 8
+#define PHY_REG_ADDR_MAX 0x1f
+#define SW_PHY_WRITE 0x00002000
+#define SW_PHY_READ 0x00004000
+#define SW_PHY_WDATA_MASK 0xFFFF0000
+#define SW_PHY_WDATA_SHIFT 16
+
+
+/* PHY_cntl1_REG */
+#define SW_PHY_WRITE_DONE 0x00000001
+#define SW_PHY_READ_DONE 0x00000002
+#define SW_PHY_RDATA_MASK 0xFFFF0000
+#define SW_PHY_RDATA_SHIFT 16
+
+/* FC_th_REG */
+/* Adj_port_th_REG */
+/* Port_th_REG */
+
+/* PHY_cntl2_REG */
+#define SW_PHY_AN_MASK 0x0000001F
+#define SW_PHY_SPD_MASK 0x000003E0
+#define SW_PHY_SPD_SHIFT 5
+#define SW_PHY_DPX_MASK 0x00007C00
+#define SW_PHY_DPX_SHIFT 10
+#define SW_FORCE_FC_MASK 0x000F8000
+#define SW_FORCE_FC_SHIFT 15
+#define SW_PHY_NORMAL_MASK 0x01F00000
+#define SW_PHY_NORMAL_SHIFT 20
+#define SW_PHY_AUTOMDIX_MASK 0x3E000000
+#define SW_PHY_AUTOMDIX_SHIFT 25
+#define SW_PHY_REC_MCCAVERAGE 0x40000000
+
+
+/* PHY_cntl3_REG */
+/* Pri_cntl_REG */
+/* VLAN_pri_REG */
+/* TOS_en_REG */
+/* TOS_map0_REG */
+/* TOS_map1_REG */
+/* Custom_pri1_REG */
+/* Custom_pri2_REG */
+/* Empty_cnt_REG */
+/* Port_cnt_sel_REG */
+/* Port_cnt_REG */
+
+
+/* SW_Int_st_REG & SW_Int_mask_REG */
+#define SEND_H_DONE_INT 0x0000001
+#define SEND_L_DONE_INT 0x0000002
+#define RX_H_DONE_INT 0x0000004
+#define RX_L_DONE_INT 0x0000008
+#define RX_H_DESC_FULL_INT 0x0000010
+#define RX_L_DESC_FULL_INT 0x0000020
+#define PORT0_QUE_FULL_INT 0x0000040
+#define PORT1_QUE_FULL_INT 0x0000080
+#define PORT2_QUE_FULL_INT 0x0000100
+#define PORT3_QUE_FULL_INT 0x0000200
+#define PORT4_QUE_FULL_INT 0x0000400
+#define PORT5_QUE_FULL_INT 0x0000800
+
+#define CPU_QUE_FULL_INT 0x0002000
+#define GLOBAL_QUE_FULL_INT 0x0004000
+#define MUST_DROP_INT 0x0008000
+#define BC_STORM_INT 0x0010000
+
+#define PORT_STATUS_CHANGE_INT 0x0040000
+#define INTRUDER_INT 0x0080000
+#define WATCHDOG0_EXPR_INT 0x0100000
+#define WATCHDOG1_EXPR_INT 0x0200000
+#define RX_DESC_ERR_INT 0x0400000
+#define SEND_DESC_ERR_INT 0x0800000
+#define CPU_HOLD_INT 0x1000000
+#define SWITCH_INT_MASK 0x1FDEFFF
+
+
+/* GPIO_conf0_REG */
+#define GPIO0_INPUT_MODE 0x00000001
+#define GPIO1_INPUT_MODE 0x00000002
+#define GPIO2_INPUT_MODE 0x00000004
+#define GPIO3_INPUT_MODE 0x00000008
+#define GPIO4_INPUT_MODE 0x00000010
+#define GPIO5_INPUT_MODE 0x00000020
+#define GPIO6_INPUT_MODE 0x00000040
+#define GPIO7_INPUT_MODE 0x00000080
+
+#define GPIO0_OUTPUT_MODE 0
+#define GPIO1_OUTPUT_MODE 0
+#define GPIO2_OUTPUT_MODE 0
+#define GPIO3_OUTPUT_MODE 0
+#define GPIO4_OUTPUT_MODE 0
+#define GPIO5_OUTPUT_MODE 0
+#define GPIO6_OUTPUT_MODE 0
+#define GPIO7_OUTPUT_MODE 0
+
+#define GPIO0_INPUT_MASK 0x00000100
+#define GPIO1_INPUT_MASK 0x00000200
+#define GPIO2_INPUT_MASK 0x00000400
+#define GPIO3_INPUT_MASK 0x00000800
+#define GPIO4_INPUT_MASK 0x00001000
+#define GPIO5_INPUT_MASK 0x00002000
+#define GPIO6_INPUT_MASK 0x00004000
+#define GPIO7_INPUT_MASK 0x00008000
+
+#define GPIO0_OUTPUT_EN 0x00010000
+#define GPIO1_OUTPUT_EN 0x00020000
+#define GPIO2_OUTPUT_EN 0x00040000
+#define GPIO3_OUTPUT_EN 0x00080000
+#define GPIO4_OUTPUT_EN 0x00100000
+#define GPIO5_OUTPUT_EN 0x00200000
+#define GPIO6_OUTPUT_EN 0x00400000
+#define GPIO7_OUTPUT_EN 0x00800000
+
+#define GPIO_CONF0_OUTEN_MASK 0x00ff0000
+
+#define GPIO0_OUTPUT_HI 0x01000000
+#define GPIO1_OUTPUT_HI 0x02000000
+#define GPIO2_OUTPUT_HI 0x04000000
+#define GPIO3_OUTPUT_HI 0x08000000
+#define GPIO4_OUTPUT_HI 0x10000000
+#define GPIO5_OUTPUT_HI 0x20000000
+#define GPIO6_OUTPUT_HI 0x40000000
+#define GPIO7_OUTPUT_HI 0x80000000
+
+#define GPIO0_OUTPUT_LOW 0
+#define GPIO1_OUTPUT_LOW 0
+#define GPIO2_OUTPUT_LOW 0
+#define GPIO3_OUTPUT_LOW 0
+#define GPIO4_OUTPUT_LOW 0
+#define GPIO5_OUTPUT_LOW 0
+#define GPIO6_OUTPUT_LOW 0
+#define GPIO7_OUTPUT_LOW 0
+
+
+/* GPIO_conf2_REG */
+#define EXTIO_WAIT_EN (0x1 << 6)
+#define EXTIO_CS1_INT1_EN (0x1 << 5)
+#define EXTIO_CS0_INT0_EN (0x1 << 4)
+
+/* Watchdog0_REG, Watchdog1_REG */
+#define WATCHDOG0_RESET_EN 0x80000000
+#define WATCHDOG1_DROP_EN 0x80000000
+
+#define WATCHDOG_TIMER_SET_MASK 0x7FFF0000
+#define WATCHDOG_TIMER_SET_SHIFT 16
+#define WATCHDOG_TIMER_MASK 0x00007FFF
+
+
+/* Timer_int_REG */
+#define SW_TIMER_INT_DISABLE 0x10000
+#define SW_TIMER_INT 0x1
+
+/* Timer_REG */
+#define SW_TIMER_EN 0x10000
+#define SW_TIMER_MASK 0xffff
+#define SW_TIMER_10MS_TICKS 0x3D09
+#define SW_TIMER_1MS_TICKS 0x61A
+#define SW_TIMER_100US_TICKS 0x9D
+
+
+/* Port0_LED_REG, Port1_LED_REG, Port2_LED_REG, Port3_LED_REG, Port4_LED_REG*/
+#define GPIOL_INPUT_MODE 0x00
+#define GPIOL_OUTPUT_FLASH 0x01
+#define GPIOL_OUTPUT_LOW 0x02
+#define GPIOL_OUTPUT_HIGH 0x03
+#define GPIOL_LINK_LED 0x04
+#define GPIOL_SPEED_LED 0x05
+#define GPIOL_DUPLEX_LED 0x06
+#define GPIOL_ACT_LED 0x07
+#define GPIOL_COL_LED 0x08
+#define GPIOL_LINK_ACT_LED 0x09
+#define GPIOL_DUPLEX_COL_LED 0x0A
+#define GPIOL_10MLINK_ACT_LED 0x0B
+#define GPIOL_100MLINK_ACT_LED 0x0C
+#define GPIOL_CTRL_MASK 0x0F
+
+#define GPIOL_INPUT_MASK 0x7000
+#define GPIOL_INPUT_0_MASK 0x1000
+#define GPIOL_INPUT_1_MASK 0x2000
+#define GPIOL_INPUT_2_MASK 0x4000
+
+#define PORT_LED0_SHIFT 0
+#define PORT_LED1_SHIFT 4
+#define PORT_LED2_SHIFT 8
+
+
+/*=========================== UART Control Register ========================*/
+#define UART_DR_REG 0x00
+#define UART_RSR_REG 0x04
+#define UART_ECR_REG 0x04
+#define UART_LCR_H_REG 0x08
+#define UART_LCR_M_REG 0x0c
+#define UART_LCR_L_REG 0x10
+#define UART_CR_REG 0x14
+#define UART_FR_REG 0x18
+#define UART_IIR_REG 0x1c
+#define UART_ICR_REG 0x1C
+#define UART_ILPR_REG 0x20
+
+/* rsr/ecr reg */
+#define UART_OVERRUN_ERR 0x08
+#define UART_BREAK_ERR 0x04
+#define UART_PARITY_ERR 0x02
+#define UART_FRAMING_ERR 0x01
+#define UART_RX_STATUS_MASK 0x0f
+#define UART_RX_ERROR ( UART_BREAK_ERR | UART_PARITY_ERR | UART_FRAMING_ERR)
+
+/* lcr_h reg */
+#define UART_SEND_BREAK 0x01
+#define UART_PARITY_EN 0x02
+#define UART_EVEN_PARITY 0x04
+#define UART_TWO_STOP_BITS 0x08
+#define UART_ENABLE_FIFO 0x10
+
+#define UART_WLEN_5BITS 0x00
+#define UART_WLEN_6BITS 0x20
+#define UART_WLEN_7BITS 0x40
+#define UART_WLEN_8BITS 0x60
+#define UART_WLEN_MASK 0x60
+
+/* cr reg */
+#define UART_PORT_EN 0x01
+#define UART_SIREN 0x02
+#define UART_SIRLP 0x04
+#define UART_MODEM_STATUS_INT_EN 0x08
+#define UART_RX_INT_EN 0x10
+#define UART_TX_INT_EN 0x20
+#define UART_RX_TIMEOUT_INT_EN 0x40
+#define UART_LOOPBACK_EN 0x80
+
+/* fr reg */
+#define UART_CTS 0x01
+#define UART_DSR 0x02
+#define UART_DCD 0x04
+#define UART_BUSY 0x08
+#define UART_RX_FIFO_EMPTY 0x10
+#define UART_TX_FIFO_FULL 0x20
+#define UART_RX_FIFO_FULL 0x40
+#define UART_TX_FIFO_EMPTY 0x80
+
+/* iir/icr reg */
+#define UART_MODEM_STATUS_INT 0x01
+#define UART_RX_INT 0x02
+#define UART_TX_INT 0x04
+#define UART_RX_TIMEOUT_INT 0x08
+
+#define UART_INT_MASK 0x0f
+
+#define ADM5120_UARTCLK_FREQ 62500000
+
+/* This is slightly different from the ADM5120 manual, this method has better
+ rounding for higher baudrates
+ - Jeroen
+ */
+#define UART_BAUDDIV(_rate) \
+ ((unsigned long)(((ADM5120_UARTCLK_FREQ)/(8*(_rate))+1)/2 - 1))
+
+/* uart_baudrate */
+#define UART_230400bps_DIVISOR UART_BAUDDIV(230400)
+#define UART_115200bps_DIVISOR UART_BAUDDIV(115200)
+#define UART_76800bps_DIVISOR UART_BAUDDIV(76800)
+#define UART_57600bps_DIVISOR UART_BAUDDIV(57600)
+#define UART_38400bps_DIVISOR UART_BAUDDIV(38400)
+#define UART_19200bps_DIVISOR UART_BAUDDIV(19200)
+#define UART_14400bps_DIVISOR UART_BAUDDIV(14400)
+#define UART_9600bps_DIVISOR UART_BAUDDIV(9600)
+#define UART_2400bps_DIVISOR UART_BAUDDIV(2400)
+#define UART_1200bps_DIVISOR UART_BAUDDIV(1200)
+
+
+/* Cache Controller */
+//#define ADM5120_CACHE_CTRL_BASE 0x70000000
+#define ADM5120_CACHE_LINE_SIZE 16
+//#define ADM5120_CACHE_CTRL_REGSIZE 4
+
+
+/********** GPIO macro *************/
+#define GPIO_MEASURE 0x000f00f0 //enable output status of pin 0, 1, 2, 3
+
+#define GPIO_MEASURE_INIT() \
+do { \
+ ADM5120_SW_REG(GPIO_conf0_REG) = GPIO_MEASURE; \
+} while (0)
+
+
+#define GPIO_SET_HI(num) \
+do { \
+ ADM5120_SW_REG(GPIO_conf0_REG) |= 1 << (24 + num); \
+} while (0)
+
+
+#define GPIO_SET_LOW(num) \
+do { \
+ ADM5120_SW_REG(GPIO_conf0_REG) &= ~(1 << (24 + num)); \
+} while (0)
+
+
+#define GPIO_TOGGLE(num) \
+do { \
+ ADM5120_SW_REG(GPIO_conf0_REG) ^= (1 << (24 + num)); \
+} while (0)
+
+
+#define BOOT_LINE_SIZE 256
+#define BSP_STR_LEN 64
+
+/*
+ * System configuration
+ */
+typedef struct BOARD_CFG_S
+{
+ unsigned long blmagic;
+ unsigned char bootline[BOOT_LINE_SIZE+1];
+
+ unsigned long macmagic;
+ unsigned char mac[4][8];
+
+ unsigned long idmagic;
+ unsigned char serial[BSP_STR_LEN+1];
+
+ unsigned long vermagic;
+ unsigned char ver[BSP_STR_LEN+1];
+
+} BOARD_CFG_T, *PBOARD_CFG_T;
+
+
+#define BL_MAGIC 0x6c62676d
+#define MAC_MAGIC 0x636d676d
+#define VER_MAGIC 0x7276676d
+#define ID_MAGIC 0x6469676d
+
+
+
+
+
+#endif /* __ADM5120_H__ */
diff -ruN linux-2.6.10/include/asm-mips/am5120/mx.h linux-2.6.10-adm.1/include/asm-mips/am5120/mx.h
--- linux-2.6.10/include/asm-mips/am5120/mx.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/include/asm-mips/am5120/mx.h 2005-01-27 21:06:27.000000000 +0100
@@ -0,0 +1,69 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Technology, Corp. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK TECHNOLOGY CORP.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;------------------------------------------------------------------------------
+;
+; Project : Common plateform
+; Creator : Simon
+; File : nv_drv.h
+;
+;Modification History:
+; Location Resonder Modification Description
+; ------------ ---------- ----------------------------------------------
+;
+;*****************************************************************************/
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef _FLASH_H_
+#define _FLASH_H_
+
+enum FLASH_E
+{
+ FLASH_NOT_FIT_IN = -2,
+ FLASH_ERROR = -1,
+ FLASH_OK = 0,
+ FLASH_PARTIAL_DONE
+};
+
+typedef struct FLASH_DESC_S
+{
+ struct FLASH_DESC_S *next;
+ int flash_size;
+ int addr_inc;
+ int byte_width;
+ char *start;
+ unsigned long *blocks;
+ int num;
+ int (*erase)(struct FLASH_DESC_S *cp, char *flash, int cells);
+ int (*read) (struct FLASH_DESC_S *cp, char *flash, char *dst, int cells);
+ int (*write)(struct FLASH_DESC_S *cp, char *flash, char *src, int cells);
+}
+FLASH_DESC;
+
+
+int flash_init();
+int flash_add(FLASH_DESC *cp);
+int flash_erase(char *flash, int size);
+int flash_read (char *flash, char *dst, int size);
+int flash_write(char *flash, char *src, int size);
+
+
+#endif /* _FLASH_H_ */
+
+#if __cplusplus
+}
+#endif
diff -ruN linux-2.6.10/include/asm-mips/am5120/mx29lv320b.h linux-2.6.10-adm.1/include/asm-mips/am5120/mx29lv320b.h
--- linux-2.6.10/include/asm-mips/am5120/mx29lv320b.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/include/asm-mips/am5120/mx29lv320b.h 2005-01-27 21:06:27.000000000 +0100
@@ -0,0 +1,61 @@
+/*****************************************************************************
+;
+; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.
+;
+; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
+; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.
+; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A
+; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS
+; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE
+; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,
+; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,
+; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
+; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.
+; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD
+; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.
+;
+;------------------------------------------------------------------------------
+;
+; Project : ADM5120
+; Creator :
+; File : include/asm/am5120/mx29lv320b.h
+; Date : 2003.07.30
+; Abstract:
+;
+;Modification History:
+;
+;
+;*****************************************************************************/
+
+
+#ifndef __MX29LV320B_H__
+#define __MX29LV320B_H__
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#define FLASH_PHYS_ADDR 0x1FC00000
+#define FLASH_SIZE 0x200000
+
+#define FLASH_PARTITION1_ADDR 0x00000000
+#define FLASH_PARTITION1_SIZE 0x00200000
+
+struct map_info mx29lv320b_map = {
+ .name = "MX29LV320B flash device",
+ .size = FLASH_SIZE,
+ .buswidth = 2,
+};
+
+struct mtd_partition mx29lv320b_parts[] = {
+ {
+ .name = "Flash Disk 1",
+ .offset = FLASH_PARTITION1_ADDR,
+ .size = FLASH_PARTITION1_SIZE
+ }
+};
+
+#define PARTITION_COUNT (sizeof(mx29lv320b_parts)/sizeof(struct mtd_partition))
+
+#endif /* __MX29LV320B_H__ */
+
diff -ruN linux-2.6.10/include/asm-mips/am5120/prom.h linux-2.6.10-adm.1/include/asm-mips/am5120/prom.h
--- linux-2.6.10/include/asm-mips/am5120/prom.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-adm.1/include/asm-mips/am5120/prom.h 2005-01-27 21:06:27.000000000 +0100
@@ -0,0 +1,49 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 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.
+ *
+ * ########################################################################
+ *
+ * MIPS boards bootprom interface for the Linux kernel.
+ *
+ */
+
+#ifndef _MIPS_PROM_H
+#define _MIPS_PROM_H
+
+extern char *prom_getcmdline(void);
+extern char *prom_getenv(char *name);
+extern void setup_prom_printf(int tty_no);
+extern void prom_printf(char *fmt, ...);
+extern void prom_init_cmdline(void);
+extern void prom_meminit(void);
+extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
+extern void prom_free_prom_memory (void);
+extern void mips_display_message(const char *str);
+extern void mips_display_word(unsigned int num);
+extern int get_ethernet_addr(char *ethernet_addr);
+
+/* Memory descriptor management. */
+#define PROM_MAX_PMEMBLOCKS 32
+struct prom_pmemblock {
+ unsigned long base; /* Within KSEG0. */
+ unsigned int size; /* In bytes. */
+ unsigned int type; /* free or prom memory */
+};
+
+#endif /* !(_MIPS_PROM_H) */
diff -ruN linux-2.6.10/include/asm-mips/bootinfo.h linux-2.6.10-adm.1/include/asm-mips/bootinfo.h
--- linux-2.6.10/include/asm-mips/bootinfo.h 2004-12-24 22:34:26.000000000 +0100
+++ linux-2.6.10-adm.1/include/asm-mips/bootinfo.h 2005-01-27 21:06:26.000000000 +0100
@@ -212,6 +212,12 @@
#define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
#define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
+/*
+ * Valid machtype for group ADMtek
+ */
+#define MACH_GROUP_ADM_GW 23
+#define MACH_ADM_GW_5120 0
+
#define CL_SIZE COMMAND_LINE_SIZE
const char *get_system_type(void);
diff -ruN linux-2.6.10/include/linux/init.h linux-2.6.10-adm.1/include/linux/init.h
--- linux-2.6.10/include/linux/init.h 2004-12-24 22:33:50.000000000 +0100
+++ linux-2.6.10-adm.1/include/linux/init.h 2005-01-27 21:06:29.000000000 +0100
@@ -86,6 +86,8 @@
static initcall_t __initcall_##fn __attribute_used__ \
__attribute__((__section__(".initcall" level ".init"))) = fn
+#define early_initcall(fn) __define_initcall(".early1",fn)
+
#define core_initcall(fn) __define_initcall("1",fn)
#define postcore_initcall(fn) __define_initcall("2",fn)
#define arch_initcall(fn) __define_initcall("3",fn)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] ADM5120 for 2.6.10
2005-01-27 20:34 [PATCH] ADM5120 for 2.6.10 Jeroen Vreeken
@ 2005-01-27 21:01 ` sjhill
2005-01-27 21:17 ` Jeroen Vreeken
0 siblings, 1 reply; 8+ messages in thread
From: sjhill @ 2005-01-27 21:01 UTC (permalink / raw)
To: Jeroen Vreeken; +Cc: linux-mips
Greetings.
First, thank you for your patch. However, there are a number of things
that you have to do before it will be accepted.
1) You should be creating your patch against the Linux/MIPS kernel
tree present in CVS. You can go to http://www.linux-mips.org/
to see how to get the latest code.
2) Change your machine config definition of 'MIPS_AM5120' to be
'MIPS_ADM5120' as it makes more sense.
3) A number of your files, 'arch/mips/am5120/5120_rtc.c' for an
example, has an unacceptable copyright banner in it. Your code
will not be accepted unless it is licensed under GPL or a shared
BSD style license. Please speak with your management and get
approval. You will also need to sign off your code contribution.
4) It might be good to have your serial driver up in 'drivers/serial'
instead of down in 'arch/mips' somewhere. Perhaps someone else
will have comments on that.
5) Your PCI code should be located in 'arch/mips/pci'.
6) Your change to 'include/linux/init.h' for early init calls
is unnecessary. The latest tree already supports this and
the linker script takes care of placing them in the proper
section.
After you have addressed the issues above, please re-submit your patch.
Thanks!
-Steve
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] ADM5120 for 2.6.10
2005-01-27 21:01 ` sjhill
@ 2005-01-27 21:17 ` Jeroen Vreeken
2005-01-27 21:32 ` sjhill
0 siblings, 1 reply; 8+ messages in thread
From: Jeroen Vreeken @ 2005-01-27 21:17 UTC (permalink / raw)
To: sjhill, linux-mips
sjhill@realitydiluted.com wrote:
>Greetings.
>
>First, thank you for your patch. However, there are a number of things
>that you have to do before it will be accepted.
>
> 1) You should be creating your patch against the Linux/MIPS kernel
> tree present in CVS. You can go to http://www.linux-mips.org/
> to see how to get the latest code.
>
> 2) Change your machine config definition of 'MIPS_AM5120' to be
> 'MIPS_ADM5120' as it makes more sense.
>
> 3) A number of your files, 'arch/mips/am5120/5120_rtc.c' for an
> example, has an unacceptable copyright banner in it. Your code
> will not be accepted unless it is licensed under GPL or a shared
> BSD style license. Please speak with your management and get
> approval. You will also need to sign off your code contribution.
>
> 4) It might be good to have your serial driver up in 'drivers/serial'
> instead of down in 'arch/mips' somewhere. Perhaps someone else
> will have comments on that.
>
> 5) Your PCI code should be located in 'arch/mips/pci'.
>
> 6) Your change to 'include/linux/init.h' for early init calls
> is unnecessary. The latest tree already supports this and
> the linker script takes care of placing them in the proper
> section.
>
>After you have addressed the issues above, please re-submit your patch.
>Thanks!
>
I agree with your points...
Just to clarify: I don't intend this patch to be merged with anything,
its just an intermediate step I thought people here might be interested in.
I'll try to make that clearer if I post further patches.
With respect to point 3, I am not an admtek employee, its just a hobby
project. I also send an mail about this copyright notice earlier, since
nobody started shouting it was wrong to remove these messages I asume I
can modify them into something sensible.
Jeroen
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] ADM5120 for 2.6.10
2005-01-27 21:17 ` Jeroen Vreeken
@ 2005-01-27 21:32 ` sjhill
2005-01-27 22:00 ` Jeroen Vreeken
0 siblings, 1 reply; 8+ messages in thread
From: sjhill @ 2005-01-27 21:32 UTC (permalink / raw)
To: Jeroen Vreeken; +Cc: sjhill, linux-mips
> I agree with your points...
> Just to clarify: I don't intend this patch to be merged with anything,
> its just an intermediate step I thought people here might be interested in.
> I'll try to make that clearer if I post further patches.
>
If you do not plan on it being merged, it might be good if you posted
the patches somewhere instead of flooding our mail boxes with extra
bits we probably won't care about. I'm not trying to be mean, but just
take into account people with slow connections and very little time.
Maybe upload the stuff to a FTP site and provide a URL to it.
> With respect to point 3, I am not an admtek employee, its just a hobby
> project. I also send an mail about this copyright notice earlier, since
> nobody started shouting it was wrong to remove these messages I asume I
> can modify them into something sensible.
>
You should be talking to ADMTek about being allowed to post this code
then. Otherwise, it should not be not be on the list.
-Steve
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] ADM5120 for 2.6.10
@ 2005-01-27 22:00 ` Jeroen Vreeken
0 siblings, 0 replies; 8+ messages in thread
From: Jeroen Vreeken @ 2005-01-27 22:00 UTC (permalink / raw)
Cc: linux-mips
sjhill@realitydiluted.com wrote:
>You should be talking to ADMTek about being allowed to post this code
>then. Otherwise, it should not be not be on the list.
>
>
I am confident I am allowed to post the code. It is published publicly
on the web and the blurb while irritating (which is why I want it
changed) does mention that you are excepted from the mentioned
restrictions if you have the appropriate license agreement.
Since there is no doubt this code hase been distributed under the GPL I
have such a license.
Btw I did contact admtek to ask for formal approval to change it to
something less scary.
Jeroen
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] ADM5120 for 2.6.10
@ 2005-01-27 22:00 ` Jeroen Vreeken
0 siblings, 0 replies; 8+ messages in thread
From: Jeroen Vreeken @ 2005-01-27 22:00 UTC (permalink / raw)
Cc: linux-mips
sjhill@realitydiluted.com wrote:
>You should be talking to ADMTek about being allowed to post this code
>then. Otherwise, it should not be not be on the list.
>
>
I am confident I am allowed to post the code. It is published publicly
on the web and the blurb while irritating (which is why I want it
changed) does mention that you are excepted from the mentioned
restrictions if you have the appropriate license agreement.
Since there is no doubt this code hase been distributed under the GPL I
have such a license.
Btw I did contact admtek to ask for formal approval to change it to
something less scary.
Jeroen
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] ADM5120 for 2.6.10
2005-01-27 22:00 ` Jeroen Vreeken
(?)
@ 2005-01-28 16:56 ` Tsang-Ren Chang
2005-01-28 17:03 ` sjhill
-1 siblings, 1 reply; 8+ messages in thread
From: Tsang-Ren Chang @ 2005-01-28 16:56 UTC (permalink / raw)
To: linux-mips
Jeroen Vreeken wrote:
> sjhill@realitydiluted.com wrote:
>
>> You should be talking to ADMTek about being allowed to post this code
>> then. Otherwise, it should not be not be on the list.
>>
>>
> I am confident I am allowed to post the code. It is published publicly
> on the web and the blurb while irritating (which is why I want it
> changed) does mention that you are excepted from the mentioned
> restrictions if you have the appropriate license agreement.
> Since there is no doubt this code hase been distributed under the GPL
> I have such a license.
> Btw I did contact admtek to ask for formal approval to change it to
> something less scary.
>
> Jeroen
>
>
> .
>
Hi Jeroen:
I agree with your point. I think the copyright notices of ADMTek in
arch/mips/am5120/ directory infringed GPL.
All the modifications of linux-2.4.18-admtek should be distributed under
the GPL without exception.
Best regards,
TR Chang
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] ADM5120 for 2.6.10
2005-01-28 16:56 ` Tsang-Ren Chang
@ 2005-01-28 17:03 ` sjhill
0 siblings, 0 replies; 8+ messages in thread
From: sjhill @ 2005-01-28 17:03 UTC (permalink / raw)
To: Tsang-Ren Chang; +Cc: linux-mips
> Hi Jeroen:
> I agree with your point. I think the copyright notices of ADMTek in
> arch/mips/am5120/ directory infringed GPL.
> All the modifications of linux-2.4.18-admtek should be distributed under
> the GPL without exception.
>
> Best regards,
> TR Chang
>
Are you the original copyright holder? I am just trying to get
a path of responsibility established. Thanks!
-Steve
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2005-01-28 17:03 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-27 20:34 [PATCH] ADM5120 for 2.6.10 Jeroen Vreeken
2005-01-27 21:01 ` sjhill
2005-01-27 21:17 ` Jeroen Vreeken
2005-01-27 21:32 ` sjhill
2005-01-27 22:00 ` Jeroen Vreeken
2005-01-27 22:00 ` Jeroen Vreeken
2005-01-28 16:56 ` Tsang-Ren Chang
2005-01-28 17:03 ` sjhill
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.