X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/a4a0c48042e240d42bbf68e9711a6e6cb0747e18..3bcc74c2a18c30b525a8215e22acd846c371c234:/target/linux/linux-2.4/patches/ar7/000-ar7_support.patch diff --git a/target/linux/linux-2.4/patches/ar7/000-ar7_support.patch b/target/linux/linux-2.4/patches/ar7/000-ar7_support.patch index 49360226e..d5bbe4227 100644 --- a/target/linux/linux-2.4/patches/ar7/000-ar7_support.patch +++ b/target/linux/linux-2.4/patches/ar7/000-ar7_support.patch @@ -1,3516 +1,4119 @@ -diff -urN kernel-base/arch/mips/ar7/ar7/ar7_jump.S kernel-current/arch/mips/ar7/ar7/ar7_jump.S ---- kernel-base/arch/mips/ar7/ar7/ar7_jump.S 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/ar7/ar7_jump.S 2005-07-10 06:40:39.582267168 +0200 -@@ -0,0 +1,89 @@ -+/* -+ * $Id$ -+ * Copyright (C) $Date$ $Author$ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ */ +diff -urN linux.old/Makefile linux.dev/Makefile +--- linux.old/Makefile 2005-10-21 16:43:16.316951500 +0200 ++++ linux.dev/Makefile 2005-11-10 01:10:45.771570000 +0100 +@@ -91,7 +91,7 @@ + + CPPFLAGS := -D__KERNEL__ -I$(HPATH) + +-CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ ++CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -Os \ + -fno-strict-aliasing -fno-common + ifndef CONFIG_FRAME_POINTER + CFLAGS += -fomit-frame-pointer +diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile +--- linux.old/arch/mips/Makefile 2005-10-21 16:43:16.316951500 +0200 ++++ linux.dev/arch/mips/Makefile 2005-11-10 01:10:45.775570250 +0100 +@@ -369,6 +369,16 @@ + endif + + # ++# Texas Instruments AR7 ++# + -+#include -+#include ++ifdef CONFIG_AR7 ++LIBS += arch/mips/ar7/ar7.o ++SUBDIRS += arch/mips/ar7 ++LOADADDR += 0x94020000 ++endif + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++# + # DECstation family + # + ifdef CONFIG_DECSTATION +diff -urN linux.old/arch/mips/ar7/Makefile linux.dev/arch/mips/ar7/Makefile +--- linux.old/arch/mips/ar7/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/Makefile 2005-11-10 01:13:51.443173750 +0100 +@@ -0,0 +1,14 @@ ++.S.s: ++ $(CPP) $(AFLAGS) $< -o $*.s ++ ++.S.o: ++ $(CC) $(AFLAGS) -c $< -o $*.o + -+.text -+ -+.set noreorder -+.set noat -+ -+/* TLB Miss Vector */ -+ -+LEAF(jump_tlb_miss) -+ .set mips2 -+ lui k0,0x9400 -+ ori k0,0 -+ jr k0 -+ nop -+END(jump_tlb_miss) -+ -+ /* Unused TLB Miss Vector */ -+ -+LEAF(jump_tlb_miss_unused) -+ .set mips2 -+ lui k0,0x9400 -+ ori k0,0x80 -+ jr k0 -+ nop -+END(jump_tlb_miss_unused) -+ -+ /* Cache Error Vector */ -+ -+LEAF(jump_cache_error) -+ .set mips2 -+ lui k0,0x9400 -+ ori k0,0x100 -+ jr k0 -+ nop -+END(jump_cache_error) -+ -+ /* General Exception */ -+ -+LEAF(jump_general_exception) -+ .set mips2 -+ lui k0,0x9400 -+ ori k0,0x180 -+ jr k0 -+ nop -+END(jump_general_exception) -+ -+ /* Dedicated Interrupt */ -+ -+LEAF(jump_dedicated_interrupt) -+ .set mips2 -+ lui k0,0x9400 -+ ori k0,0x200 -+ jr k0 -+ nop -+END(jump_dedicated_interrupt) -+ -+ .set at -diff -urN kernel-base/arch/mips/ar7/ar7/ar7_paging.c kernel-current/arch/mips/ar7/ar7/ar7_paging.c ---- kernel-base/arch/mips/ar7/ar7/ar7_paging.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/ar7/ar7_paging.c 2005-07-10 07:08:33.725758672 +0200 -@@ -0,0 +1,314 @@ ++EXTRA_CFLAGS := -I$(TOPDIR)/include/asm/ar7 -DLITTLE_ENDIAN -D_LINK_KSEG0_ ++O_TARGET := ar7.o ++ ++obj-y := tnetd73xx_misc.o misc.o ++export-objs := misc.o irq.o init.o ++obj-y += setup.o irq.o int-handler.o reset.o init.o psp_env.o memory.o promlib.o cmdline.o ++ ++include $(TOPDIR)/Rules.make +diff -urN linux.old/arch/mips/ar7/cmdline.c linux.dev/arch/mips/ar7/cmdline.c +--- linux.old/arch/mips/ar7/cmdline.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/cmdline.c 2005-11-10 01:14:16.372731750 +0100 +@@ -0,0 +1,88 @@ +/* -+ * -*- linux-c -*- -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive ++ * 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. + * -+ * Copyright (C) 2002 by Jeff Harrell (jharrell@ti.com) -+ * Copyright (C) 2002 Texas Instruments, Inc. ++ * 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. + * ++ * Kernel command line creation using the prom monitor (YAMON) argc/argv. + */ -+ -+/* -+ * This file takes care of the "memory hole" issue that exists with the standard -+ * linux kernel and the TI Avalanche ASIC. The Avalanche ASIC requires an offset -+ * of 0x14000000 due to the ASIC's memory map constraints. This file corrects the -+ * paging tables so that the only reflect valid memory (i.e. > 0x14000000) -+ * -+ * -JAH -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include +#include -+#ifdef CONFIG_BLK_DEV_INITRD -+#include -+#endif /* CONFIG_BLK_DEV_INITRD */ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define __MEMORY_START CONFIG_AR7_MEMORY -+ -+#ifdef CONFIG_DISCONTIGMEM -+pg_data_t discontig_page_data[NR_NODES]; -+bootmem_data_t discontig_node_bdata[NR_NODES]; -+#endif -+ -+static unsigned long totalram_pages; -+/* static unsigned long totalhigh_pages; */ -+ -+#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT) -+#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) -+ -+#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) -+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) -+#define PFN_PHYS(x) ((x) << PAGE_SHIFT) ++#include + -+unsigned long bootmap_size; ++#include + -+extern char *prom_getenv(char *envname); ++extern int prom_argc; ++extern int *_prom_argv; + +/* -+ * We have upto 8 empty zeroed pages so we can map one of the right colour -+ * when needed. This is necessary only on R4000 / R4400 SC and MC versions -+ * where we have to avoid VCED / VECI exceptions for good performance at -+ * any price. Since page is never written to after the initialization we -+ * don't have to care about aliases on other CPUs. ++ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. ++ * This macro take care of sign extension. + */ ++#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)])) + -+static inline unsigned long setup_zero_pages(void) ++char arcs_cmdline[CL_SIZE]; ++#ifdef CONFIG_CMDLINE_BOOL ++char __initdata cfg_cmdline[] = CONFIG_CMDLINE; ++#endif ++ ++char * __init prom_getcmdline(void) +{ -+ unsigned long order, size; -+ struct page *page; -+ if(current_cpu_data.options & MIPS_CPU_VCE) -+ order = 3; -+ else -+ order = 0; ++ return &(arcs_cmdline[0]); ++} ++ + -+ empty_zero_page = __get_free_pages(GFP_KERNEL, order); ++void __init prom_init_cmdline(void) ++{ ++ char *cp, *end; ++ int actr; ++ char *env_cmdline = prom_getenv("kernel_args"); ++ size_t len; + -+ if (!empty_zero_page) -+ panic("Oh boy, that early out of memory?"); ++ actr = 1; /* Always ignore argv[0] */ + -+ page = virt_to_page(empty_zero_page); ++ cp = end = &(arcs_cmdline[0]); ++ end += sizeof(arcs_cmdline); + -+ while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { -+ set_bit(PG_reserved, &page->flags); -+ set_page_count(page, 0); -+ page++; ++ if (env_cmdline) { ++ len = strlen(env_cmdline); ++ if (len > end - cp - 1) ++ len = end - cp - 1; ++ strncpy(cp, env_cmdline, len); ++ cp += len; ++ *cp++ = ' '; + } ++#ifdef CONFIG_CMDLINE_BOOL ++ else { ++ len = strlen(cfg_cmdline); ++ if (len > end - cp - 1) ++ len = end - cp - 1; ++ strncpy(cp, cfg_cmdline, len); ++ cp += len; ++ *cp++ = ' '; ++ } ++#endif + -+ size = PAGE_SIZE << order; -+ zero_page_mask = (size - 1) & PAGE_MASK; -+ memset((void *)empty_zero_page, 0, size); -+ -+ return 1UL << order; ++ while(actr < prom_argc) { ++ len = strlen(prom_argv(actr)); ++ if (len > end - cp - 1) ++ break; ++ strncpy(cp, prom_argv(actr), len); ++ cp += len; ++ *cp++ = ' '; ++ actr++; ++ } ++ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ ++ --cp; ++ *cp = '\0'; +} -+ +diff -urN linux.old/arch/mips/ar7/init.c linux.dev/arch/mips/ar7/init.c +--- linux.old/arch/mips/ar7/init.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/init.c 2005-11-10 01:10:45.795571500 +0100 +@@ -0,0 +1,199 @@ +/* -+ * paging_init() sets up the page tables ++ * 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. + * -+ * This routines also unmaps the page at virtual kernel address 0, so -+ * that we can trap those pesky NULL-reference errors in the kernel. ++ * PROM library initialisation code. + */ -+void __init paging_init(void) -+{ -+ unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; -+ unsigned long low, start_pfn; -+ -+ /* Initialize the entire pgd. */ -+ pgd_init((unsigned long)swapper_pg_dir); -+ pgd_init((unsigned long)swapper_pg_dir + PAGE_SIZE / 2); -+ ++#include ++#include ++#include ++#include ++#include + -+ start_pfn = START_PFN; -+ // max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; -+ low = MAX_LOW_PFN; ++#include ++#include ++#include + -+ /* Avalanche DMA-able memory 0x14000000+memsize */ ++#include + -+ zones_size[ZONE_DMA] = low - start_pfn; ++int prom_argc; ++int *_prom_argv, *_prom_envp; + -+ free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START, 0); ++/* max # of Adam2 environment variables */ ++#define MAX_ENV_ENTRY 80 + -+#ifdef CONFIG_DISCONTIGMEM -+ zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT; -+ zones_size[ZONE_NORMAL] = 0; -+ free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND, 0); -+#endif /* CONFIG_DISCONTIGMEM */ ++static t_env_var local_envp[MAX_ENV_ENTRY]; ++static int env_type = 0; ++int init_debug = 0; + -+} ++unsigned int max_env_entry; + -+extern char _ftext, _etext, _fdata, _edata, _end; -+extern char __init_begin, __init_end; ++extern char *prom_psp_getenv(char *envname); + -+void __init mem_init(void) ++static inline char *prom_adam2_getenv(char *envname) +{ -+ int codesize, reservedpages, datasize, initsize; -+ int tmp; -+ -+ max_mapnr = num_physpages = MAX_LOW_PFN - START_PFN; -+ high_memory = (void *)__va(MAX_LOW_PFN * PAGE_SIZE); -+ -+ /* free up the memory associated with Adam2 - -+ * that is the, after the first page that is -+ * reserved all the way up to the start of the kernel ++ /* ++ * Return a pointer to the given environment variable. ++ * In 64-bit mode: we're using 64-bit pointers, but all pointers ++ * in the PROM structures are only 32-bit, so we need some ++ * workarounds, if we are running in 64-bit mode. + */ -+ free_bootmem_node(NODE_DATA(0), (__MEMORY_START+PAGE_SIZE), -+ (__pa(&_ftext))-(__MEMORY_START+PAGE_SIZE) ); -+ -+ /* this will put all low memory onto the freelists */ -+ totalram_pages += free_all_bootmem_node(NODE_DATA(0)); ++ int i; ++ t_env_var *env = (t_env_var *) local_envp; + -+ /* Setup zeroed pages */ -+ totalram_pages -= setup_zero_pages(); ++ if (strcmp("bootloader", envname) == 0) ++ return "Adam2"; + ++ i = strlen(envname); ++ while (env->name) { ++ if(strncmp(envname, env->name, i) == 0) { ++ return(env->val); ++ } ++ env++; ++ } + -+#ifdef CONFIG_DISCONTIGMEM -+ totalram_pages += free_all_bootmem_node(NODE_DATA(1)); -+#endif -+ reservedpages = 0; -+ for (tmp = 0; tmp < num_physpages; tmp++) -+ /* -+ * Only count reserved RAM pages -+ */ -+ if (PageReserved(mem_map+tmp)) -+ reservedpages++; ++ return NULL; ++} + -+ codesize = (unsigned long) &_etext - (unsigned long) &_ftext; -+ datasize = (unsigned long) &_edata - (unsigned long) &_fdata; -+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; ++/* XXX "bootloader" won't be returned. ++ * Better make it an element of local_envp */ ++static inline t_env_var * ++prom_adam2_iterenv(t_env_var *env) { ++ if (!env) ++ env = local_envp; ++ else ++ env++; ++ if (env - local_envp > MAX_ENV_ENTRY || !env->name) ++ return 0; ++ return env; ++} + -+ printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n", -+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), -+ max_mapnr << (PAGE_SHIFT-10), -+ codesize >> 10, -+ reservedpages << (PAGE_SHIFT-10), -+ datasize >> 10, -+ initsize >> 10); ++char *prom_getenv(char *envname) ++{ ++ if (env_type == 1) ++ return prom_psp_getenv(envname); ++ else ++ return prom_adam2_getenv(envname); ++} + ++t_env_var * ++prom_iterenv(t_env_var *last) ++{ ++ if (env_type == 1) ++ return 0; /* not yet implemented */ ++ return prom_adam2_iterenv(last); +} + -+/* fixes paging routines for avalanche (utilized in /arch/mips/kernel/setup.c) */ ++static inline unsigned char str2hexnum(unsigned char c) ++{ ++ if (c >= '0' && c <= '9') ++ return c - '0'; ++ if (c >= 'a' && c <= 'f') ++ return c - 'a' + 10; ++ return 0; /* foo */ ++} + -+void avalanche_bootmem_init(void) ++static inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ -+ unsigned long start_pfn, max_pfn; -+ unsigned long max_low_pfn; -+ unsigned int memsize,memory_end,memory_start; -+ char *memsize_str; ++ int i; + -+ memsize_str = prom_getenv("memsize"); -+ if (!memsize_str) { -+ memsize = 0x02000000; -+ } else { -+ memsize = simple_strtol(memsize_str, NULL, 0); -+ } ++ for (i = 0; i < 6; i++) { ++ unsigned char num; + ++ if((*str == '.') || (*str == ':')) ++ str++; ++ num = str2hexnum(*str++) << 4; ++ num |= (str2hexnum(*str++)); ++ ea[i] = num; ++ } ++} + -+ memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; -+ memory_end = memory_start + memsize; ++int get_ethernet_addr(char *ethernet_addr) ++{ ++ char *ethaddr_str; + -+ /* -+ * Find the highest memory page fram number we have available -+ */ ++ ethaddr_str = prom_getenv("ethaddr"); ++ if (!ethaddr_str) { ++ printk("ethaddr not set in boot prom\n"); ++ return -1; ++ } ++ str2eaddr(ethernet_addr, ethaddr_str); + -+ max_pfn = PFN_DOWN(__pa(memory_end)); ++ if (init_debug > 1) { ++ int i; ++ printk("get_ethernet_addr: "); ++ for (i=0; i<5; i++) ++ printk("%02x:", (unsigned char)*(ethernet_addr+i)); ++ printk("%02x\n", *(ethernet_addr+i)); ++ } + -+ /* -+ * Determine the low and high memory ranges -+ */ ++ return 0; ++} + -+ max_low_pfn = max_pfn; ++struct psbl_rec { ++ unsigned int psbl_size; ++ unsigned int env_base; ++ unsigned int env_size; ++ unsigned int ffs_base; ++ unsigned int ffs_size; ++}; + -+ /* -+ * Partially used pages are not usable - thus we are -+ * rounding upwards: -+ */ ++static const char psp_env_version[] = "TIENV0.8"; + -+ start_pfn = PFN_UP(__pa(&_end)); ++int __init prom_init(int argc, char **argv, char **envp) ++{ ++ int i; + -+ /* -+ * Find a proper area for the bootmem bitmap. After this -+ * bootstrap step all allocations (until the page allocator is -+ * intact) must be done via bootmem_alloc(). -+ */ ++ t_env_var *env = (t_env_var *) envp; ++ struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x94000300)); ++ void *psp_env = (void *)KSEG1ADDR(psbl->env_base); + -+ bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, -+ __MEMORY_START>>PAGE_SHIFT, max_low_pfn); ++ prom_argc = argc; ++ _prom_argv = (int *)argv; ++ _prom_envp = (int *)envp; + ++ if(strcmp(psp_env, psp_env_version) == 0) { ++ /* PSPBOOT */ + -+ /* -+ * Register fully available low RAM pages with the bootmem allocator. -+ */ ++ env_type = 1; ++ _prom_envp = psp_env; ++ max_env_entry = (psbl->env_size / 16) - 1; ++ } else { ++ /* Copy what we need locally so we are not dependent on ++ * bootloader RAM. In Adam2, the environment parameters ++ * are in flash but the table that references them is in ++ * RAM ++ */ + -+ { -+ unsigned long curr_pfn, last_pfn, pages; ++ for(i=0; i < MAX_ENV_ENTRY; i++, env++) { ++ if (env->name) { ++ local_envp[i].name = env->name; ++ local_envp[i].val = env->val; ++ } else { ++ local_envp[i].name = NULL; ++ local_envp[i].val = NULL; ++ } ++ } ++ } + -+ /* -+ * We are rounding up the start address of usable memory: -+ */ -+ curr_pfn = PFN_UP(__MEMORY_START); ++ set_io_port_base(0); + -+ /* -+ * ... and at the end of the usable range downwards: -+ */ -+ last_pfn = PFN_DOWN(__pa(memory_end)); ++ prom_printf("\nLINUX started...\n"); ++ prom_init_cmdline(); ++ prom_meminit(); + -+ if (last_pfn > max_low_pfn) -+ last_pfn = max_low_pfn; ++ return 0; ++} +diff -urN linux.old/arch/mips/ar7/int-handler.S linux.dev/arch/mips/ar7/int-handler.S +--- linux.old/arch/mips/ar7/int-handler.S 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/int-handler.S 2005-11-10 01:12:43.938955000 +0100 +@@ -0,0 +1,63 @@ ++/* ++ * Copyright 2004 PMC-Sierra Inc. ++ * Author: Manish Lachwani (lachwani@pmc-sierra.com) ++ * Adaption for AR7: Enrik Berkhan ++ * ++ * First-level interrupt dispatcher for the TI AR7 ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++#define __ASSEMBLY__ ++#include ++#include ++#include ++#include ++#include ++#include + -+ pages = last_pfn - curr_pfn; ++/* ++ * First level interrupt dispatcher for TI AR7 based boards ++ */ + ++ .align 5 ++ NESTED(ar7IRQ, PT_SIZE, sp) ++ SAVE_ALL ++ CLI ++ .set at + -+ free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn), -+ PFN_PHYS(pages)); -+ } ++ mfc0 t0, CP0_CAUSE ++ mfc0 t2, CP0_STATUS + -+ /* -+ * Reserve the kernel text and -+ * Reserve the bootmem bitmap. We do this in two steps (first step -+ * was init_bootmem()), because this catches the (definitely buggy) -+ * case of us accidentally initializing the bootmem allocator with -+ * an invalid RAM area. -+ */ -+ reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE, -+ (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START); ++ and t0, t2 + -+ /* -+ * reserve physical page 0 - it's a special BIOS page on many boxes, -+ * enabling clean reboots, SMP operation, laptop functions. -+ */ -+ reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE); -+} ++ andi t1, t0, STATUSF_IP2 /* hw0 hardware interrupt */ ++ bnez t1, ll_hw0_irq + -+extern char __init_begin, __init_end; ++ andi t1, t0, STATUSF_IP7 /* R4k CPU timer */ ++ bnez t1, ll_timer_irq + -+void free_initmem(void) -+{ -+ unsigned long addr; -+ // prom_free_prom_memory (); ++ .set reorder + -+ addr = (unsigned long) &__init_begin; -+ while (addr < (unsigned long) &__init_end) { -+ ClearPageReserved(virt_to_page(addr)); -+ set_page_count(virt_to_page(addr), 1); -+ free_page(addr); -+ totalram_pages++; -+ addr += PAGE_SIZE; -+ } -+ printk("Freeing unused kernel memory: %dk freed\n", -+ (&__init_end - &__init_begin) >> 10); -+} ++ /* wrong alarm or masked ... */ ++ j spurious_interrupt ++ nop ++ END(ar7IRQ) + -+void si_meminfo(struct sysinfo *val) -+{ -+ val->totalram = totalram_pages; -+ val->sharedram = 0; -+ val->freeram = nr_free_pages(); -+ val->bufferram = atomic_read(&buffermem_pages); -+ val->totalhigh = 0; -+ val->freehigh = nr_free_highpages(); -+ val->mem_unit = PAGE_SIZE; ++ .align 5 + -+ return; -+} -diff -urN kernel-base/arch/mips/ar7/ar7/gpio.c kernel-current/arch/mips/ar7/ar7/gpio.c ---- kernel-base/arch/mips/ar7/ar7/gpio.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/ar7/gpio.c 2005-07-10 09:46:52.164776456 +0200 -@@ -0,0 +1,132 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++ll_hw0_irq: ++ li a0, 2 ++ move a1, sp ++ jal do_IRQ ++ j ret_from_irq + -+#include -+#include -+#include ++ll_timer_irq: ++ li a0, 7 ++ move a1, sp ++ jal do_IRQ ++ j ret_from_irq ++ ++ +diff -urN linux.old/arch/mips/ar7/irq.c linux.dev/arch/mips/ar7/irq.c +--- linux.old/arch/mips/ar7/irq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/irq.c 2005-11-10 01:12:43.938955000 +0100 +@@ -0,0 +1,427 @@ ++/* ++ * Nitin Dhingra, iamnd@ti.com ++ * Copyright (C) 2002 Texas Instruments, Inc. All rights reserved. ++ * ++ * ######################################################################## ++ * ++ * This program is free software; you can distribute it and/or modify it ++ * under the terms of the GNU General Public License (Version 2) as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. ++ * ++ * ######################################################################## ++ * ++ * Routines for generic manipulation of the interrupts found on the Texas ++ * Instruments avalanche board ++ * ++ */ + ++#include ++#include + -+#if defined (CONFIG_AR7RD) || defined(CONFIG_AR7WRD) ++#include ++#include ++#include ++#include + -+#define AR7_RESET_FILE "led_mod/ar7reset" -+#define AR7_RESET_GPIO 11 -+#define RESET_POLL_TIME 1 -+#define RESET_HOLD_TIME 4 -+#define NO_OF_LEDS -+#define TRUE 1 -+#define FALSE 0 ++#define shutdown_avalanche_irq disable_avalanche_irq ++#define mask_and_ack_avalanche_irq disable_avalanche_irq + -+static struct proc_dir_entry *reset_file; -+static int res_state = 0; -+static int count; -+static struct timer_list *pTimer = NULL; -+static ssize_t proc_read_reset_fops(struct file *filp, char *buf, size_t count, loff_t * offp); ++static unsigned int startup_avalanche_irq(unsigned int irq); ++static void end_avalanche_irq(unsigned int irq); ++void enable_avalanche_irq(unsigned int irq_nr); ++void disable_avalanche_irq(unsigned int irq_nr); ++void ar7_hw0_interrupt(int interrupt, void *dev, struct pt_regs *regs); + -+struct file_operations reset_fops = { -+ read:proc_read_reset_fops ++static struct hw_interrupt_type avalanche_irq_type = { ++ "AR7", ++ startup_avalanche_irq, ++ shutdown_avalanche_irq, ++ enable_avalanche_irq, ++ disable_avalanche_irq, ++ mask_and_ack_avalanche_irq, ++ end_avalanche_irq, ++ NULL +}; + -+#endif -+ -+static spinlock_t device_lock; -+led_reg_t temp[15]; ++static int ar7_irq_base; + -+static void gpio_led_on(unsigned long param) -+{ -+ unsigned int flags; ++static struct irqaction ar7_hw0_action = { ++ ar7_hw0_interrupt, 0, 0, "AR7 on hw0", NULL, NULL ++}; + -+ spin_lock_irqsave(&device_lock, flags); -+ tnetd73xx_gpio_out(param, FALSE); -+ spin_unlock_irqrestore(&device_lock, flags); -+} ++struct avalanche_ictrl_regs *avalanche_hw0_icregs; /* Interrupt control regs (primary) */ ++struct avalanche_exctrl_regs *avalanche_hw0_ecregs; /* Exception control regs (secondary) */ ++struct avalanche_ipace_regs *avalanche_hw0_ipaceregs; ++struct avalanche_channel_int_number *avalanche_hw0_chregs; /* Channel control registers */ + -+static void gpio_led_off(unsigned long param) -+{ -+ unsigned int flags = 0x00; ++/* ++ This remaps interrupts to exist on other channels than the default ++ channels. essentially we can use the line # as the index for this ++ array ++ */ + -+ spin_lock_irqsave(&device_lock, flags); -+ tnetd73xx_gpio_out(param, TRUE); -+ spin_unlock_irqrestore(&device_lock, flags); -+} ++static unsigned long line_to_channel[AVINTNUM(AVALANCHE_INT_END_PRIMARY)]; ++unsigned long uni_secondary_interrupt = 0; + -+static void gpio_led_init(unsigned long param) ++static void end_avalanche_irq(unsigned int irq) +{ -+ tnetd73xx_gpio_ctrl(param, GPIO_PIN, GPIO_OUTPUT_PIN); ++ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) ++ enable_avalanche_irq(irq); +} + -+static void board_gpio_reset(void) ++void disable_avalanche_irq(unsigned int irq_nr) +{ -+ tnetd73xx_gpio_init(); ++ unsigned long flags; ++ unsigned long chan_nr=0; + -+ /* Initialize the link mask */ -+ device_lock = SPIN_LOCK_UNLOCKED; -+ return; -+} ++ save_and_cli(flags); ++ ++ /* irq_nr represents the line number for the interrupt. We must ++ * disable the channel number associated with that line number. ++ */ + -+#if defined(CONFIG_AR7WRD) ++ if(irq_nr > AVALANCHE_INT_END_PRIMARY_REG2) ++ chan_nr = AVINTNUM(irq_nr); /*CHECK THIS ALSO*/ ++ else ++ chan_nr = line_to_channel[AVINTNUM(irq_nr)];/* WE NEED A LINE TO CHANNEL MAPPING FUNCTION HERE*/ + -+static ssize_t proc_read_reset_fops(struct file *filp, char *buf, size_t count, loff_t * offp) -+{ -+ char *pdata = NULL; -+ char line[3]; -+ int len = 0; -+ if (*offp != 0) -+ return 0; ++ /* disable the interrupt channel bit */ + -+ pdata = buf; -+ len = sprintf(line, "%d\n", res_state); -+ res_state = 0; -+ copy_to_user(buf, line, len); -+ *offp = len; -+ return len; -+} ++ /* primary interrupt #'s 0-31 */ + -+static void reset_timer_func(unsigned long data) -+{ -+ count = (tnetd73xx_gpio_in(AR7_RESET_GPIO) == 0) ? count + 1 : 0; -+ if (count >= RESET_HOLD_TIME / RESET_POLL_TIME) -+ res_state = 1; -+ pTimer->expires = jiffies + HZ * RESET_POLL_TIME; -+ add_timer(pTimer); -+ return; -+} ++ if(chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1)) ++ avalanche_hw0_icregs->intecr1 = (1 << chan_nr); + -+static void reset_init(void) -+{ -+ /* Create board reset proc file */ -+ reset_file = create_proc_entry(AR7_RESET_FILE, 0777, NULL); -+ if (reset_file == NULL) -+ goto reset_file; -+ reset_file->owner = THIS_MODULE; -+ reset_file->proc_fops = &reset_fops; ++ /* primary interrupt #'s 32-39 */ + -+ /* Initialise GPIO 11 for input */ -+ tnetd73xx_gpio_ctrl(AR7_RESET_GPIO, GPIO_PIN, GPIO_INPUT_PIN); ++ else if ((chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG2)) && ++ (chan_nr > AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1))) ++ avalanche_hw0_icregs->intecr2 = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_SECONDARY))); + -+ /* Create a timer which fires every seconds */ -+ pTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); -+ init_timer(pTimer); -+ pTimer->function = reset_timer_func; -+ pTimer->data = 0; -+ /* Start the timer */ -+ reset_timer_func(0); -+ return; ++ else /* secondary interrupt #'s 0-31 */ ++ avalanche_hw0_ecregs->exiecr = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_PRIMARY))); + -+ reset_file: -+ remove_proc_entry(AR7_RESET_FILE, NULL); -+ return; ++ restore_flags(flags); +} -+#endif + -+ -+void board_gpio_init(void) ++void enable_avalanche_irq(unsigned int irq_nr) +{ -+ board_gpio_reset(); -+ return; -+} -diff -urN kernel-base/arch/mips/ar7/ar7/ledmod.c kernel-current/arch/mips/ar7/ar7/ledmod.c ---- kernel-base/arch/mips/ar7/ar7/ledmod.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/ar7/ledmod.c 2005-07-10 09:45:36.692250024 +0200 -@@ -0,0 +1,712 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++ unsigned long flags; ++ unsigned long chan_nr=0; + -+#define LED_ON 1 -+#define LED_OFF 2 -+#define LED_BLINK 3 -+#define LED_FLASH 4 ++ save_and_cli(flags); + -+#define LED_BLINK_UP 5 -+#define LED_BLINK_DOWN 6 ++ /* irq_nr represents the line number for the interrupt. We must ++ * disable the channel number associated with that line number. ++ */ + -+typedef struct state_entry { -+ unsigned char mode; -+ unsigned char led; -+ void (*handler) (struct state_entry * pState); -+ unsigned long param; -+} state_entry_t; -+ -+typedef struct mod_entry { -+ state_entry_t *states[MAX_STATE_ID]; -+} mod_entry_t; -+ -+static mod_entry_t *modArr[MAX_MOD_ID]; -+static struct proc_dir_entry *led_proc_dir, *led_file; -+ -+/* index of the array is the led number HARDWARE SPECIFIC*/ -+typedef struct led_data { -+ led_reg_t *led; -+ int state; -+ struct timer_list *pTimer; -+ unsigned char timer_running; -+ unsigned long param; -+} led_data_t; -+ -+led_data_t led_arr[MAX_LED_ID + 1]; -+/*!!! The last device is actually being used for ar7 reset to factory default */ -+#if 1 -+/* Ron add for adsl LED blink */ -+#define GPIO_ADSL_ACT (1<<6) -+#define GPIO_ADSL_DOWN (1<<8) -+#define BLINK_FAST 5*HZ/100 -+#define BLINK_SLOW 15*HZ/100 -+static struct timer_list my_led_timer; -+static int my_blink_count = 0; -+static int my_mode = 1; -+void led_operation(int mod, int state); -+ -+static void my_led_on(unsigned long gpio, int logic) -+{ -+ if (logic > 0) -+ GPIO_DATA_OUTPUT |= gpio; ++ if(irq_nr > AVALANCHE_INT_END_PRIMARY_REG2) ++ chan_nr = AVINTNUM(irq_nr); + else -+ GPIO_DATA_OUTPUT &= ~gpio; ++ chan_nr = line_to_channel[AVINTNUM(irq_nr)]; + -+} -+static void my_led_off(unsigned long gpio, int logic) -+{ -+ if (logic > 0) -+ GPIO_DATA_OUTPUT &= ~gpio; -+ else -+ GPIO_DATA_OUTPUT |= gpio; ++ /* enable the interrupt channel bit */ + -+} ++ /* primary interrupt #'s 0-31 */ ++ if(chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1)) ++ avalanche_hw0_icregs->intesr1 = (1 << chan_nr); + -+static void my_led_init(unsigned long gpio, int init, int logic) -+{ -+ GPIO_DATA_ENABLE |= gpio; -+ GPIO_DATA_DIR &= ~gpio; -+ if (init) -+ my_led_on(gpio, logic); -+ else -+ my_led_off(gpio, logic); ++ /* primary interrupt #'s 32 throuth 39 */ ++ else if ((chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG2)) && ++ (chan_nr > AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1))) ++ avalanche_hw0_icregs->intesr2 = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_SECONDARY))); ++ ++ else /* secondary interrupt #'s 0-31 */ ++ avalanche_hw0_ecregs->exiesr = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_PRIMARY))); ++ ++ restore_flags(flags); +} + -+static void my_led_blink_timer(unsigned long data) ++static unsigned int startup_avalanche_irq(unsigned int irq) +{ -+ unsigned long gpio = GPIO_ADSL_ACT; -+ unsigned int speed = BLINK_FAST; -+ if (my_mode == 2) { -+ gpio = GPIO_ADSL_DOWN; -+ speed = BLINK_SLOW; -+ } -+ if (my_blink_count) { -+ if (GPIO_DATA_OUTPUT & gpio) { -+ GPIO_DATA_OUTPUT &= ~gpio; -+ if (my_mode != 2) -+ my_blink_count = 0; -+ } else { -+ GPIO_DATA_OUTPUT |= gpio; -+ } -+ } -+ my_led_timer.expires = jiffies + speed; -+ add_timer(&my_led_timer); ++ enable_avalanche_irq(irq); ++ return 0; /* never anything pending */ +} + -+/* Ron add for ADSL led blink */ -+#endif -+static spinlock_t config_lock; ++void __init ar7_irq_init(int base) ++{ ++ int i; + -+static void board_led_link_up(state_entry_t * pState); -+static void board_led_link_down(state_entry_t * pState); -+static void board_led_activity_on(state_entry_t * pState); -+static void board_led_activity_off(state_entry_t * pState); -+static void led_timer_func(unsigned long data); ++ avalanche_hw0_icregs = (struct avalanche_ictrl_regs *)AVALANCHE_ICTRL_REGS_BASE; ++ avalanche_hw0_ecregs = (struct avalanche_exctrl_regs *)AVALANCHE_ECTRL_REGS_BASE; ++ avalanche_hw0_ipaceregs = (struct avalanche_ipace_regs *)AVALANCHE_IPACE_REGS_BASE; ++ avalanche_hw0_chregs = (struct avalanche_channel_int_number *)AVALANCHE_CHCTRL_REGS_BASE; + -+extern void board_gpio_init(void); -+extern void uart_led_init(void); ++ /* Disable interrupts and clear pending ++ */ + -+static ssize_t proc_read_led_fops(struct file *filp, char *buf, size_t count, loff_t * offp); -+static ssize_t proc_write_led_fops(struct file *filp, const char *buffer, size_t count, loff_t * offp); -+static int config_led(unsigned long y); ++ avalanche_hw0_icregs->intecr1 = 0xffffffff; /* disable interrupts 0:31 */ ++ avalanche_hw0_icregs->intcr1 = 0xffffffff; /* clear interrupts 0:31 */ ++ avalanche_hw0_icregs->intecr2 = 0xff; /* disable interrupts 32:39 */ ++ avalanche_hw0_icregs->intcr2 = 0xff; /* clear interrupts 32:39 */ ++ avalanche_hw0_ecregs->exiecr = 0xffffffff; /* disable secondary interrupts 0:31 */ ++ avalanche_hw0_ecregs->excr = 0xffffffff; /* clear secondary interrupts 0:31 */ + -+struct file_operations led_fops = { -+ read:proc_read_led_fops, -+ write:proc_write_led_fops, -+}; + -+static int led_atoi(char *name) -+{ -+ int val = 0; -+ for (;; name++) { -+ switch (*name) { -+ case '0'...'9': -+ val = val * 10 + (*name - '0'); -+ break; -+ default: -+ return val; -+ } -+ } -+} ++ // avalanche_hw0_ipaceregs->ipacep = (2*get_avalanche_vbus_freq()/1000000)*4; ++ /* hack for speeding up the pacing. */ ++ printk("the pacing pre-scalar has been set as 600.\n"); ++ avalanche_hw0_ipaceregs->ipacep = 600; ++ /* Channel to line mapping, Line to Channel mapping */ + -+static int free_memory(void) -+{ -+ int i, j; ++ for(i = 0; i < 40; i++) ++ avalanche_int_set(i,i); + -+ for (i = 0; i < MAX_MOD_ID; i++) { -+ if (modArr[i] != NULL) { -+ for (j = 0; j < MAX_STATE_ID; j++) { -+ if (modArr[i]->states[j] != NULL) -+ kfree(modArr[i]->states[j]); -+ } -+ kfree(modArr[i]); -+ modArr[i] = NULL; -+ } ++ ar7_irq_base = base; ++ for (i = base; i <= base+40; i++) ++ { ++ irq_desc[i].status = IRQ_DISABLED; ++ irq_desc[i].action = 0; ++ irq_desc[i].depth = 1; ++ irq_desc[i].handler = &avalanche_irq_type; + } -+ return 0; -+} -+ -+static int led_on(state_entry_t * pState) -+{ -+ if (led_arr[pState->led].led == NULL) -+ return -1; -+ led_arr[pState->led].led->onfunc(led_arr[pState->led].led->param); -+ return 0; -+} + -+static int led_off(state_entry_t * pState) -+{ -+ if (led_arr[pState->led].led == NULL) -+ return -1; -+ led_arr[pState->led].led->offfunc(led_arr[pState->led].led->param); -+ return 0; -+} ++ setup_irq(2, &ar7_hw0_action); ++ set_c0_status(IE_IRQ0); + -+static void board_led_link_up(state_entry_t * pState) -+{ -+ led_arr[pState->led].state = LED_ON; -+ if (led_arr[pState->led].timer_running == 0) -+ led_on(pState); + return; +} + -+static void board_led_link_down(state_entry_t * pState) ++void ar7_hw0_interrupt(int interrupt, void *dev, struct pt_regs *regs) +{ -+ led_arr[pState->led].state = LED_OFF; -+ if (led_arr[pState->led].timer_running == 0) -+ led_off(pState); -+ return; -+} ++ int irq; ++ unsigned long int_line_number, status; ++ int i, chan_nr = 0; + -+static void add_led_timer(state_entry_t * pState) -+{ -+ led_arr[pState->led].pTimer->expires = -+ jiffies + HZ * (pState->param) / 1000; -+ led_arr[pState->led].param = pState->param; -+ led_arr[pState->led].pTimer->data = pState; -+ add_timer(led_arr[pState->led].pTimer); -+} ++ int_line_number = ((avalanche_hw0_icregs->pintir >> 16) & 0x3F); ++ chan_nr = ((avalanche_hw0_icregs->pintir) & 0x3F); + -+static void board_led_activity_on(state_entry_t * pState) -+{ -+ if (led_arr[pState->led].timer_running == 0) { -+ led_on(pState); -+ add_led_timer(pState); -+ led_arr[pState->led].timer_running = 1; -+ led_arr[pState->led].state = LED_BLINK_UP; -+ } else if (led_arr[pState->led].timer_running > 0xF0) { -+ led_arr[pState->led].state = LED_BLINK_UP; -+ led_arr[pState->led].pTimer->expires = -+ jiffies + HZ * (pState->param) / 1000; -+ led_arr[pState->led].param = pState->param; -+ led_arr[pState->led].pTimer->data = pState; -+ } -+ return; -+} ++ if(chan_nr < 32) /* primary 0-31 */ ++ { ++ if( chan_nr != uni_secondary_interrupt) ++ avalanche_hw0_icregs->intcr1 = (1<led].timer_running == 0) { -+ led_off(pState); -+ add_led_timer(pState); -+ led_arr[pState->led].timer_running = 1; -+ led_arr[pState->led].state = LED_BLINK_UP; -+ } else if (led_arr[pState->led].timer_running > 0xF0) { -+ led_arr[pState->led].state = LED_BLINK_UP; -+ led_arr[pState->led].pTimer->expires = -+ jiffies + HZ * (pState->param) / 1000; -+ led_arr[pState->led].param = pState->param; -+ led_arr[pState->led].pTimer->data = pState; + } -+ return; -+} -+ -+static void board_led_link_flash(state_entry_t * pState) -+{ -+ if (led_on(pState)) -+ return; -+ if (led_arr[pState->led].timer_running == 0) -+ add_led_timer(pState); -+ else -+ led_arr[pState->led].param = pState->param; -+ led_arr[pState->led].timer_running = 0xFF; -+ led_arr[pState->led].state = LED_FLASH; -+ return; -+} + -+static void led_timer_func(unsigned long data) -+{ -+ state_entry_t *pState = NULL; -+ mod_entry_t *pMod = NULL; -+ unsigned int flags; ++ if((chan_nr < 40) && (chan_nr > 31)) /* primary 32-39 */ ++ { ++ avalanche_hw0_icregs->intcr2 = (1<<(chan_nr-32)); ++ } + -+ spin_lock_irqsave(&config_lock, flags); + -+ pState = (state_entry_t *) data; ++ /* If the Priority Interrupt Index Register returns 40 then no ++ * interrupts are pending ++ */ + -+ if (led_arr[pState->led].state == LED_BLINK_DOWN) { -+ led_arr[pState->led].timer_running = 0; -+ if (pState->mode == 2) -+ led_arr[pState->led].state = LED_OFF; -+ else -+ led_arr[pState->led].state = LED_ON; -+ } else if (led_arr[pState->led].state == LED_BLINK_UP) { -+ led_arr[pState->led].pTimer->expires = -+ jiffies + HZ * (led_arr[pState->led].param) / 1000; -+ led_arr[pState->led].pTimer->data = pState; -+ add_timer(led_arr[pState->led].pTimer); -+ if (pState->mode == 2) { -+ led_off(pState); -+ led_arr[pState->led].state = LED_BLINK_DOWN; -+ } else { -+ led_on(pState); -+ led_arr[pState->led].state = LED_BLINK_DOWN; -+ } -+ led_arr[pState->led].timer_running = 1; -+ } else if (led_arr[pState->led].state == LED_FLASH) { -+ led_arr[pState->led].pTimer->expires = -+ jiffies + HZ * (led_arr[pState->led].param) / 1000; -+ led_arr[pState->led].pTimer->data = pState; -+ add_timer(led_arr[pState->led].pTimer); -+ -+ if (led_arr[pState->led].timer_running == 0xFF) { -+ led_off(pState); -+ led_arr[pState->led].timer_running--; -+ } else { -+ led_on(pState); -+ led_arr[pState->led].timer_running++; -+ } -+ spin_unlock_irqrestore(&config_lock, flags); ++ if(chan_nr == 40) + return; -+ } else if (led_arr[pState->led].state == LED_OFF) { -+ led_off(pState); -+ led_arr[pState->led].timer_running = 0; -+ } else if (led_arr[pState->led].state == LED_ON) { -+ led_on(pState); -+ led_arr[pState->led].timer_running = 0; -+ } -+ spin_unlock_irqrestore(&config_lock, flags); -+ return; -+} -+ -+static ssize_t proc_read_led_fops(struct file *filp, -+ char *buf, size_t count, loff_t * offp) -+{ -+ char *pdata = NULL; -+ int i = 0, j = 0, len = 0, totallen = 0; -+ char line[255]; -+ -+ if (*offp != 0) -+ return 0; -+ -+ pdata = buf; -+ len += sprintf(line, "LEDS Registered for use are:"); -+ for (i = 0; i < MAX_LED_ID; i++) -+ if (led_arr[i].led != NULL) -+ len += sprintf(&line[len], " %d ", i); -+ line[len++] = '\n'; -+ -+ copy_to_user(pdata, line, len); -+ pdata += len; -+ totallen += len; -+ len = 0; -+ len = sprintf(line, "USER MODULE INFORMATION:\n"); -+ copy_to_user(pdata, line, len); -+ pdata += len; -+ totallen += len; -+ len = 0; -+ for (i = 0; i < MAX_MOD_ID; i++) { -+ if (modArr[i] != NULL) { -+ len = sprintf(line, " Module ID = %d \n", i); -+ copy_to_user(pdata, line, len); -+ pdata += len; -+ totallen += len; -+ len = 0; -+ for (j = 0; j < MAX_STATE_ID; j++) { -+ if (modArr[i]->states[j] != NULL) { -+ len = sprintf(line, " State = %d , Led = %d,", j, -+ modArr[i]->states[j]->led); -+ copy_to_user(pdata, line, len); -+ pdata += len; -+ totallen += len; -+ -+ len = 0; -+ switch (modArr[i]->states[j]->mode) { -+ case 1: -+ len = sprintf(line, " Mode = OFF\n"); -+ break; -+ case 2: -+ len = sprintf(line, " Mode = BLINK_ON , On Time(ms) = %d\n", -+ (unsigned int) modArr[i]->states[j]-> -+ param); -+ break; -+ case 3: -+ len = sprintf(line, " Mode = BLINK_OFF , Off Time(ms) = %d\n", -+ (unsigned int) modArr[i]->states[j]-> -+ param); -+ break; -+ case 4: -+ len = sprintf(line, " Mode = ON \n"); -+ break; -+ case 5: -+ len = sprintf(line, " Mode = FLASH , Time Period(ms) = %d\n", -+ (unsigned int) modArr[i]->states[j]-> -+ param); -+ break; -+ default: -+ break; + -+ } -+ copy_to_user(pdata, line, len); -+ pdata += len; -+ totallen += len; -+ -+ len = 0; -+ } ++ if(chan_nr == uni_secondary_interrupt) /* secondary 0-31 */ ++ { ++ status = avalanche_hw0_ecregs->exsr; ++ for(i=0; i < 32; i++) ++ { ++ if (status & 1<excr = 1 << i; ++ break; + } + } -+ } -+ /* Return with configuration information for LEDs */ -+ *offp = totallen; -+ return totallen; -+} -+ -+static ssize_t proc_write_led_fops(struct file *filp, const char *buffer, size_t count, loff_t * offp) -+{ -+ char *pdata = NULL, *ptemp = NULL; -+ char line[10], temp[10]; -+ int i = 0; -+ int mod = 0xFFFF, state = 0xFFFF; -+ int flag = 0; ++ irq = i+40; + -+ /* Check if this write is for configuring stuff */ -+ if (*(int *) (buffer) == 0xFFEEDDCC) { -+ printk("<1>proc write:Calling Configuration\n"); -+ config_led((unsigned long) (buffer + sizeof(int))); -+ return count; -+ } ++ /* clear the universal secondary interrupt */ ++ avalanche_hw0_icregs->intcr1 = 1 << uni_secondary_interrupt; + -+ if (count >= 10) { -+ printk("<1>proc write:Input too long,max length = %d\n", 10); -+ return count; + } -+ memset(temp, 0x00, 10); -+ memset(line, 0x00, 10); -+ copy_from_user(line, buffer, count); -+ line[count] = 0x00; -+ pdata = line; -+ ptemp = temp; -+ while (flag == 0) { -+ if (i > 10) -+ break; -+ if (((*pdata) >= '0') && ((*pdata) <= '9')) { -+ *ptemp = *pdata; -+ ptemp++; -+ } else if ((*pdata) == ',') { -+ *ptemp = 0x00; -+ flag = 1; -+ } -+ pdata++; -+ i++; -+ }; -+ if (flag == 1) -+ mod = led_atoi(temp); + else -+ return count; ++ irq = chan_nr; + -+ ptemp = temp; -+ *ptemp = 0x00; -+ flag = 0; -+ while (flag == 0) { -+ if (i > 10) -+ break; -+ if (((*pdata) >= '0') && ((*pdata) <= '9')) { -+ *ptemp = *pdata; -+ ptemp++; -+ } else if ((*pdata) == 0x00) { -+ *ptemp = 0x00; -+ flag = 1; -+ } -+ pdata++; -+ i++; -+ }; -+ if (flag == 1) -+ state = led_atoi(temp); -+ else -+ return count; -+ if ((mod == 0xFFFF) || (state == 0xFFFF)) -+ return count; -+ else -+ led_operation(mod, state); -+ return count; ++ do_IRQ(irq + ar7_irq_base, regs); ++ return; +} + -+static int config_led(unsigned long y) ++void avalanche_int_set(int channel, int line) +{ -+ config_elem_t *pcfg = NULL; -+ char *pdata = NULL; -+ int i; -+ int length = 0, number = 0; -+ unsigned int flags; -+ -+ spin_lock_irqsave(&config_lock, flags); -+ -+ /* ioctl to configure */ -+ length = *((int *) y); -+ pdata = (char *) y + sizeof(int); -+ number = (length - sizeof(int)) / sizeof(config_elem_t); -+ pcfg = (config_elem_t *) (pdata); -+ -+ /* Check if an earlier configuration exists IF yes free it up */ -+ free_memory(); -+ -+ for (i = 0; i < number; i++) { -+ /* If no structure has been allocated for the module do so */ -+ if (modArr[pcfg->name] == NULL) { -+ printk("<1>module = %d\n", pcfg->name); -+ if (pcfg->name >= MAX_MOD_ID) { -+ printk -+ ("<1>Exiting Configuration: Module ID too large %d\n", -+ pcfg->name); -+ free_memory(); -+ spin_unlock_irqrestore(&config_lock, flags); -+ return -1; -+ } -+ modArr[pcfg->name] = kmalloc(sizeof(mod_entry_t), GFP_KERNEL); -+ if (modArr[pcfg->name] == NULL) { -+ printk -+ ("<1>Exiting Configuration: Error in allocating memory\n"); -+ free_memory(); -+ spin_unlock_irqrestore(&config_lock, flags); -+ return -1; -+ } -+ memset(modArr[pcfg->name], 0x00, sizeof(mod_entry_t)); -+ } -+ -+ /* if no structure is allocated previously for this state -+ allocate a structure, if it's already there fill it up */ -+ if (modArr[pcfg->name]->states[pcfg->state] == NULL) { -+ printk("<1>STATE = %d\n", pcfg->state); -+ if (pcfg->state >= MAX_STATE_ID) { -+ printk("<1>Exiting Configuration: State ID too large\n"); -+ free_memory(); -+ spin_unlock_irqrestore(&config_lock, flags); -+ return -1; -+ } -+ modArr[pcfg->name]->states[pcfg->state] = -+ kmalloc(sizeof(state_entry_t), GFP_KERNEL); -+ if (modArr[pcfg->name]->states[pcfg->state] == NULL) { -+ free_memory(); -+ spin_unlock_irqrestore(&config_lock, flags); -+ return -1; -+ } -+ memset(modArr[pcfg->name]->states[pcfg->state], 0x00, -+ sizeof(state_entry_t)); -+ } -+ /* Fill up the fields of the state */ -+ if (pcfg->led >= MAX_LED_ID) { -+ printk("<1>led = %d\n", pcfg->led); -+ free_memory(); -+ spin_unlock_irqrestore(&config_lock, flags); -+ return -1; -+ } -+ modArr[pcfg->name]->states[pcfg->state]->led = pcfg->led; -+ modArr[pcfg->name]->states[pcfg->state]->mode = pcfg->mode; -+ modArr[pcfg->name]->states[pcfg->state]->param = pcfg->param; -+ switch (pcfg->mode) { -+ case 1: -+ modArr[pcfg->name]->states[pcfg->state]->handler = -+ board_led_link_down; ++ switch(channel) ++ { ++ case(0): ++ avalanche_hw0_chregs->cintnr0 = line; + break; -+ case 2: -+ case 3: -+ case 5: -+ if (pcfg->mode == 2) -+ modArr[pcfg->name]->states[pcfg->state]->handler = -+ board_led_activity_on; -+ else if (pcfg->mode == 3) -+ modArr[pcfg->name]->states[pcfg->state]->handler = -+ board_led_activity_off; -+ else -+ modArr[pcfg->name]->states[pcfg->state]->handler = -+ board_led_link_flash; ++ case(1): ++ avalanche_hw0_chregs->cintnr1 = line; ++ break; ++ case(2): ++ avalanche_hw0_chregs->cintnr2 = line; ++ break; ++ case(3): ++ avalanche_hw0_chregs->cintnr3 = line; ++ break; ++ case(4): ++ avalanche_hw0_chregs->cintnr4 = line; ++ break; ++ case(5): ++ avalanche_hw0_chregs->cintnr5 = line; ++ break; ++ case(6): ++ avalanche_hw0_chregs->cintnr6 = line; ++ break; ++ case(7): ++ avalanche_hw0_chregs->cintnr7 = line; ++ break; ++ case(8): ++ avalanche_hw0_chregs->cintnr8 = line; ++ break; ++ case(9): ++ avalanche_hw0_chregs->cintnr9 = line; ++ break; ++ case(10): ++ avalanche_hw0_chregs->cintnr10 = line; ++ break; ++ case(11): ++ avalanche_hw0_chregs->cintnr11 = line; ++ break; ++ case(12): ++ avalanche_hw0_chregs->cintnr12 = line; ++ break; ++ case(13): ++ avalanche_hw0_chregs->cintnr13 = line; ++ break; ++ case(14): ++ avalanche_hw0_chregs->cintnr14 = line; ++ break; ++ case(15): ++ avalanche_hw0_chregs->cintnr15 = line; ++ break; ++ case(16): ++ avalanche_hw0_chregs->cintnr16 = line; ++ break; ++ case(17): ++ avalanche_hw0_chregs->cintnr17 = line; ++ break; ++ case(18): ++ avalanche_hw0_chregs->cintnr18 = line; ++ break; ++ case(19): ++ avalanche_hw0_chregs->cintnr19 = line; ++ break; ++ case(20): ++ avalanche_hw0_chregs->cintnr20 = line; ++ break; ++ case(21): ++ avalanche_hw0_chregs->cintnr21 = line; ++ break; ++ case(22): ++ avalanche_hw0_chregs->cintnr22 = line; ++ break; ++ case(23): ++ avalanche_hw0_chregs->cintnr23 = line; ++ break; ++ case(24): ++ avalanche_hw0_chregs->cintnr24 = line; ++ break; ++ case(25): ++ avalanche_hw0_chregs->cintnr25 = line; ++ break; ++ case(26): ++ avalanche_hw0_chregs->cintnr26 = line; ++ break; ++ case(27): ++ avalanche_hw0_chregs->cintnr27 = line; ++ break; ++ case(28): ++ avalanche_hw0_chregs->cintnr28 = line; ++ break; ++ case(29): ++ avalanche_hw0_chregs->cintnr29 = line; ++ break; ++ case(30): ++ avalanche_hw0_chregs->cintnr30 = line; ++ break; ++ case(31): ++ avalanche_hw0_chregs->cintnr31 = line; ++ break; ++ case(32): ++ avalanche_hw0_chregs->cintnr32 = line; ++ break; ++ case(33): ++ avalanche_hw0_chregs->cintnr33 = line; ++ break; ++ case(34): ++ avalanche_hw0_chregs->cintnr34 = line; ++ break; ++ case(35): ++ avalanche_hw0_chregs->cintnr35 = line; ++ break; ++ case(36): ++ avalanche_hw0_chregs->cintnr36 = line; ++ break; ++ case(37): ++ avalanche_hw0_chregs->cintnr37 = line; ++ break; ++ case(38): ++ avalanche_hw0_chregs->cintnr38 = line; + break; -+ case 4: -+ modArr[pcfg->name]->states[pcfg->state]->handler = -+ board_led_link_up; ++ case(39): ++ avalanche_hw0_chregs->cintnr39 = line; + break; + default: -+ printk("<1>Exiting Configuration: Unknown LED Mode\n"); -+ free_memory(); -+ spin_unlock_irqrestore(&config_lock, flags); -+ return -1; -+ } -+ pcfg++; ++ printk("Error: Unknown Avalanche interrupt channel\n"); + } -+ spin_unlock_irqrestore(&config_lock, flags); -+ return 0; -+} -+ -+ -+int led_init(void) -+{ -+ -+ /* Clear our memory */ -+ memset(modArr, 0x00, sizeof(mod_entry_t *) * MAX_MOD_ID); -+ memset(led_arr, 0x00, sizeof(led_data_t *) * MAX_LED_ID); -+ -+ /* Create spin lock for config data structure */ -+ config_lock = SPIN_LOCK_UNLOCKED; -+ -+ /* Create directory */ -+ led_proc_dir = proc_mkdir("led_mod", NULL); -+ if (led_proc_dir == NULL) -+ goto out; + -+ /* Create adsl file */ -+ led_file = create_proc_entry("led", 0777, led_proc_dir); -+ if (led_file == NULL) -+ goto led_file; -+ led_file->owner = THIS_MODULE; -+ led_file->proc_fops = &led_fops; ++ line_to_channel[line] = channel; /* Suraj check */ + -+ memset(modArr, 0x00, sizeof(mod_entry_t *) * MAX_MOD_ID); -+ /* Reset the GPIO pins */ -+ board_gpio_init(); ++ if (channel == UNIFIED_SECONDARY_INTERRUPT) ++ uni_secondary_interrupt = line; + -+ /* Ron add for ADSL LED blink */ -+ my_mode = 1; -+ my_led_init(GPIO_ADSL_ACT, 0, -1); -+ my_led_init(GPIO_ADSL_DOWN, 0, -1); -+ init_timer(&my_led_timer); -+ my_led_timer.function = my_led_blink_timer; -+ my_led_timer.data = 0; -+ my_led_timer.expires = jiffies + BLINK_SLOW; -+ add_timer(&my_led_timer); -+ /* Ron add for ADSL LED blink */ -+ return 0; ++} + -+ led_file: -+ remove_proc_entry("led", led_proc_dir); -+ out: -+ return 0; + -+} ++#define AVALANCHE_MAX_PACING_BLK 3 ++#define AVALANCHE_PACING_LOW_VAL 2 ++#define AVALANCHE_PACING_HIGH_VAL 63 + -+void led_operation(int mod, int state) ++int avalanche_request_pacing(int irq_nr, unsigned int blk_num, ++ unsigned int pace_value) +{ ++ unsigned int blk_offset; ++ unsigned long flags; + -+ unsigned int flags; ++ if(irq_nr < MIPS_EXCEPTION_OFFSET && ++ irq_nr >= AVALANCHE_INT_END_PRIMARY) ++ return (0); + -+ spin_lock_irqsave(&config_lock, flags); -+#if 1 -+ /* Ron Add for ADSL LED blink */ -+ //printk("mod==%d state==%d\n",mod,state); ++ if(blk_num > AVALANCHE_MAX_PACING_BLK) ++ return(-1); + -+ if (mod == 1) { -+ switch (state) { -+ /* off */ -+ case 1: -+ my_mode = 1; -+ my_blink_count = 0; -+ my_led_off(GPIO_ADSL_ACT, -1); -+ my_led_off(GPIO_ADSL_DOWN, -1); -+ break; -+ /* sync */ -+ case 2: -+ if (my_mode == 1) { -+ my_mode = 2; -+ my_led_off(GPIO_ADSL_ACT, -1); -+ my_blink_count++; -+ } -+ break; -+ /* on */ -+ case 3: -+ my_mode = 3; -+ my_blink_count = 0; -+ my_led_off(GPIO_ADSL_DOWN, -1); -+ my_led_on(GPIO_ADSL_ACT, -1); -+ break; -+ /* off */ -+ case 4: -+ my_mode = 4; -+ my_led_off(GPIO_ADSL_DOWN, -1); -+ my_blink_count++; -+ break; -+ } -+ } /* Ron add for ADSL LED Blink */ -+#endif -+ if ((mod >= MAX_MOD_ID) || (state >= MAX_STATE_ID)) { -+ spin_unlock_irqrestore(&config_lock, flags); -+ return; -+ } -+ if (modArr[mod] == NULL) { -+ spin_unlock_irqrestore(&config_lock, flags); -+ return; -+ } -+ if (modArr[mod]->states[state] == NULL) { -+ spin_unlock_irqrestore(&config_lock, flags); -+ return; -+ } -+ /* Call the function handler */ -+ modArr[mod]->states[state]->handler(modArr[mod]->states[state]); ++ if(pace_value > AVALANCHE_PACING_HIGH_VAL && ++ pace_value < AVALANCHE_PACING_LOW_VAL) ++ return(-1); + -+ spin_unlock_irqrestore(&config_lock, flags); -+} ++ blk_offset = blk_num*8; + -+void register_led_drv(int device, led_reg_t * pInfo) -+{ -+ unsigned int flags; -+ struct timer_list *pTimer = NULL; ++ save_and_cli(flags); + -+ spin_lock_irqsave(&config_lock, flags); ++ /* disable the interrupt pacing, if enabled previously */ ++ avalanche_hw0_ipaceregs->ipacemax &= ~(0xff << blk_offset); + -+ led_arr[device].led = pInfo; -+ if (led_arr[device].led->init != 0x00) -+ led_arr[device].led->init(led_arr[device].led->param); -+ if (led_arr[device].led->offfunc != 0x00) -+ led_arr[device].led->offfunc(led_arr[device].led->param); ++ /* clear the pacing map */ ++ avalanche_hw0_ipaceregs->ipacemap &= ~(0xff << blk_offset); + -+ /* Create a timer for blinking */ -+ pTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); -+ init_timer(pTimer); -+ pTimer->function = led_timer_func; -+ pTimer->data = 0; -+ led_arr[device].pTimer = pTimer; -+ led_arr[device].timer_running = 0; ++ /* setup the new values */ ++ avalanche_hw0_ipaceregs->ipacemap |= ((AVINTNUM(irq_nr)) << blk_offset); ++ avalanche_hw0_ipaceregs->ipacemax |= ((0x80 | pace_value) << blk_offset); + -+ spin_unlock_irqrestore(&config_lock, flags); ++ restore_flags(flags); + -+ return; ++ return(0); +} +diff -urN linux.old/arch/mips/ar7/memory.c linux.dev/arch/mips/ar7/memory.c +--- linux.old/arch/mips/ar7/memory.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/memory.c 2005-11-10 01:14:16.372731750 +0100 +@@ -0,0 +1,103 @@ ++/* ++ * 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. ++ * ++ * ######################################################################## ++ * ++ */ + -+void deregister_led_drv(int device) -+{ -+ unsigned int flags; ++#include ++#include ++#include ++#include + -+ spin_lock_irqsave(&config_lock, flags); -+ led_arr[device].led = NULL; ++#include ++#include ++#include + -+ if (led_arr[device].pTimer != NULL) { -+ del_timer(led_arr[device].pTimer); -+ kfree(led_arr[device].pTimer); -+ } -+ spin_unlock_irqrestore(&config_lock, flags); ++extern char _ftext; ++extern int preserve_adam2; + -+ return; -+} ++void __init prom_meminit(void) ++{ ++ char *memsize_str; ++ unsigned long memsize, adam2size; + -+EXPORT_SYMBOL_NOVERS(led_init); -+EXPORT_SYMBOL_NOVERS(led_operation); -+EXPORT_SYMBOL_NOVERS(register_led_drv); -+EXPORT_SYMBOL_NOVERS(deregister_led_drv); -diff -urN kernel-base/arch/mips/ar7/ar7/Makefile kernel-current/arch/mips/ar7/ar7/Makefile ---- kernel-base/arch/mips/ar7/ar7/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/ar7/Makefile 2005-07-10 09:31:33.038504888 +0200 -@@ -0,0 +1,31 @@ -+# $Id$ -+# Copyright (C) $Date$ $Author$ -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ /* assume block before kernel is used by bootloader */ ++ adam2size = __pa(&_ftext) - PHYS_OFFSET; + -+.S.s: -+ $(CPP) $(AFLAGS) $< -o $*.s ++ memsize_str = prom_getenv("memsize"); ++ if (!memsize_str) { ++ memsize = 0x02000000; ++ } else { ++ memsize = simple_strtol(memsize_str, NULL, 0); ++ } + -+.S.o: -+ $(CC) $(AFLAGS) -c $< -o $*.o ++#if 0 ++ add_memory_region(0x00000000, PHYS_OFFSET, BOOT_MEM_RESERVED); ++#endif ++ add_memory_region(PHYS_OFFSET, adam2size, BOOT_MEM_ROM_DATA); ++ add_memory_region(PHYS_OFFSET+adam2size, memsize-adam2size, ++ BOOT_MEM_RAM); ++} + -+EXTRA_CFLAGS := -DLITTLE_ENDIAN -D_LINK_KSEG0_ ++unsigned long __init prom_free_prom_memory (void) ++{ ++ int i; ++ unsigned long freed = 0; ++ unsigned long addr; + -+O_TARGET := ar7.o ++ if (preserve_adam2) { ++ char *firstfree_str = prom_getenv("firstfreeaddress"); ++ unsigned long firstfree = 0; + -+export-objs:= ledmod.o gpio.o -+obj-y += ar7_paging.o ar7_jump.o ledmod.o gpio.o tnetd73xx_misc.o ++ if (firstfree_str) ++ firstfree = simple_strtol(firstfree_str, NULL, 0); + -+include $(TOPDIR)/Rules.make -diff -urN kernel-base/arch/mips/ar7/ar7/tnetd73xx_misc.c kernel-current/arch/mips/ar7/ar7/tnetd73xx_misc.c ---- kernel-base/arch/mips/ar7/ar7/tnetd73xx_misc.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/ar7/tnetd73xx_misc.c 2005-07-10 09:57:09.935860976 +0200 -@@ -0,0 +1,926 @@ -+/****************************************************************************** -+ * FILE PURPOSE: TNETD73xx Misc modules API Source -+ ****************************************************************************** -+ * FILE NAME: tnetd73xx_misc.c -+ * -+ * DESCRIPTION: Clock Control, Reset Control, Power Management, GPIO -+ * FSER Modules API -+ * As per TNETD73xx specifications -+ * -+ * REVISION HISTORY: -+ * 27 Nov 02 - Sharath Kumar PSP TII -+ * 14 Feb 03 - Anant Gole PSP TII -+ * -+ * (C) Copyright 2002, Texas Instruments, Inc -+ *******************************************************************************/ ++ if (firstfree && firstfree < (unsigned long)&_ftext) { ++ printk("Preserving ADAM2 memory.\n"); ++ } else if (firstfree) { ++ printk("Can't preserve ADAM2 memory, " ++ "firstfreeaddress = %08lx.\n", firstfree); ++ preserve_adam2 = 0; ++ } else { ++ printk("Can't preserve ADAM2 memory, " ++ "firstfreeaddress unknown!\n"); ++ preserve_adam2 = 0; ++ } ++ } + ++ if (!preserve_adam2) { ++ for (i = 0; i < boot_mem_map.nr_map; i++) { ++ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) ++ continue; + -+#include -+#include -+#include -+#include ++ 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); ++ } ++ return freed >> PAGE_SHIFT; ++} +diff -urN linux.old/arch/mips/ar7/misc.c linux.dev/arch/mips/ar7/misc.c +--- linux.old/arch/mips/ar7/misc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/misc.c 2005-11-10 01:12:43.946955500 +0100 +@@ -0,0 +1,322 @@ ++#include ++#include ++#include ++#include + +#define TRUE 1 -+#define FALSE 0 + -+/* TNETD73XX Revision */ -+__u32 tnetd73xx_get_revision(void) -+{ -+ /* Read Chip revision register - This register is from GPIO module */ -+ return ( (__u32) REG32_DATA(TNETD73XX_CVR)); -+} ++static unsigned int avalanche_vbus_freq; ++ ++REMOTE_VLYNQ_DEV_RESET_CTRL_FN p_remote_vlynq_dev_reset_ctrl = NULL; + +/***************************************************************************** -+ * Reset Control Module ++ * Reset Control Module. + *****************************************************************************/ -+ -+ -+void tnetd73xx_reset_ctrl(TNETD73XX_RESET_MODULE_T reset_module, TNETD73XX_RESET_CTRL_T reset_ctrl) ++void avalanche_reset_ctrl(unsigned int module_reset_bit, ++ AVALANCHE_RESET_CTRL_T reset_ctrl) +{ -+ __u32 reset_status; -+ -+ /* read current reset register */ -+ REG32_READ(TNETD73XX_RST_CTRL_PRCR, reset_status); ++ volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR; ++ ++ if(module_reset_bit >= 32 && module_reset_bit < 64) ++ return; + -+ if (reset_ctrl == OUT_OF_RESET) ++ if(module_reset_bit >= 64) + { -+ /* bring module out of reset */ -+ reset_status |= (1 << reset_module); ++ if(p_remote_vlynq_dev_reset_ctrl) { ++ p_remote_vlynq_dev_reset_ctrl(module_reset_bit - 64, reset_ctrl); ++ return; ++ } ++ else ++ return; + } ++ ++ if(reset_ctrl == OUT_OF_RESET) ++ *reset_reg |= 1 << module_reset_bit; + else -+ { -+ /* put module in reset */ -+ reset_status &= (~(1 << reset_module)); -+ } -+ -+ /* write to the reset register */ -+ REG32_WRITE(TNETD73XX_RST_CTRL_PRCR, reset_status); ++ *reset_reg &= ~(1 << module_reset_bit); ++ return; +} + -+ -+TNETD73XX_RESET_CTRL_T tnetd73xx_get_reset_status (TNETD73XX_RESET_MODULE_T reset_module) ++AVALANCHE_RESET_CTRL_T avalanche_get_reset_status(unsigned int module_reset_bit) +{ -+ __u32 reset_status; ++ volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR; + -+ REG32_READ(TNETD73XX_RST_CTRL_PRCR, reset_status); -+ return ( (reset_status & (1 << reset_module)) ? OUT_OF_RESET : IN_RESET ); ++ return (((*reset_reg) & (1 << module_reset_bit)) ? OUT_OF_RESET : IN_RESET ); +} + -+void tnetd73xx_sys_reset(TNETD73XX_SYS_RST_MODE_T mode) ++void avalanche_sys_reset(AVALANCHE_SYS_RST_MODE_T mode) +{ -+ REG32_WRITE(TNETD73XX_RST_CTRL_SWRCR, mode); ++ volatile unsigned int *sw_reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_SWRCR; ++ *sw_reset_reg = mode; +} + -+#define TNETD73XX_RST_CTRL_RSR_MASK 0x3 ++#define AVALANCHE_RST_CTRL_RSR_MASK 0x3 + -+TNETD73XX_SYS_RESET_STATUS_T tnetd73xx_get_sys_last_reset_status() ++AVALANCHE_SYS_RESET_STATUS_T avalanche_get_sys_last_reset_status() +{ -+ __u32 sys_reset_status; -+ -+ REG32_READ(TNETD73XX_RST_CTRL_RSR, sys_reset_status); ++ volatile unsigned int *sys_reset_status = (unsigned int*) AVALANCHE_RST_CTRL_RSR; + -+ return ( (TNETD73XX_SYS_RESET_STATUS_T) (sys_reset_status & TNETD73XX_RST_CTRL_RSR_MASK) ); ++ return ( (AVALANCHE_SYS_RESET_STATUS_T) (*sys_reset_status & AVALANCHE_RST_CTRL_RSR_MASK) ); +} + + +/***************************************************************************** + * Power Control Module + *****************************************************************************/ -+#define TNETD73XX_GLOBAL_POWER_DOWN_MASK 0x3FFFFFFF /* bit 31, 30 masked */ -+#define TNETD73XX_GLOBAL_POWER_DOWN_BIT 30 /* shift to bit 30, 31 */ ++#define AVALANCHE_GLOBAL_POWER_DOWN_MASK 0x3FFFFFFF /* bit 31, 30 masked */ ++#define AVALANCHE_GLOBAL_POWER_DOWN_BIT 30 /* shift to bit 30, 31 */ + + -+void tnetd73xx_power_ctrl(TNETD73XX_POWER_MODULE_T power_module, TNETD73XX_POWER_CTRL_T power_ctrl) ++void avalanche_power_ctrl(unsigned int module_power_bit, AVALANCHE_POWER_CTRL_T power_ctrl) +{ -+ __u32 power_status; -+ -+ /* read current power down control register */ -+ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); ++ volatile unsigned int *power_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR; + + if (power_ctrl == POWER_CTRL_POWER_DOWN) -+ { + /* power down the module */ -+ power_status |= (1 << power_module); -+ } ++ *power_reg |= (1 << module_power_bit); + else -+ { + /* power on the module */ -+ power_status &= (~(1 << power_module)); -+ } ++ *power_reg &= (~(1 << module_power_bit)); ++} ++ ++AVALANCHE_POWER_CTRL_T avalanche_get_power_status(unsigned int module_power_bit) ++{ ++ volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR; + -+ /* write to the reset register */ -+ REG32_WRITE(TNETD73XX_POWER_CTRL_PDCR, power_status); ++ return (((*power_status_reg) & (1 << module_power_bit)) ? POWER_CTRL_POWER_DOWN : POWER_CTRL_POWER_UP); +} + -+TNETD73XX_POWER_CTRL_T tnetd73xx_get_pwr_status(TNETD73XX_POWER_MODULE_T power_module) ++void avalanche_set_global_power_mode(AVALANCHE_SYS_POWER_MODE_T power_mode) +{ -+ __u32 power_status; ++ volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR; + -+ /* read current power down control register */ -+ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); ++ *power_status_reg &= AVALANCHE_GLOBAL_POWER_DOWN_MASK; ++ *power_status_reg |= ( power_mode << AVALANCHE_GLOBAL_POWER_DOWN_BIT); ++} ++ ++AVALANCHE_SYS_POWER_MODE_T avalanche_get_global_power_mode(void) ++{ ++ volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR; + -+ return ( (power_status & (1 << power_module)) ? POWER_CTRL_POWER_DOWN : POWER_CTRL_POWER_UP ); ++ return((AVALANCHE_SYS_POWER_MODE_T) (((*power_status_reg) & (~AVALANCHE_GLOBAL_POWER_DOWN_MASK)) ++ >> AVALANCHE_GLOBAL_POWER_DOWN_BIT)); +} + -+void tnetd73xx_set_global_pwr_mode(TNETD73XX_SYS_POWER_MODE_T power_mode) ++/***************************************************************************** ++ * GPIO Control ++ *****************************************************************************/ ++ ++/**************************************************************************** ++ * FUNCTION: avalanche_gpio_init ++ ***************************************************************************/ ++void avalanche_gpio_init(void) ++{ ++ spinlock_t closeLock; ++ unsigned int closeFlag; ++ volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR; ++ spin_lock_irqsave(&closeLock, closeFlag); ++ *reset_reg |= (1 << AVALANCHE_GPIO_RESET_BIT); ++ spin_unlock_irqrestore(&closeLock, closeFlag); ++} ++ ++/**************************************************************************** ++ * FUNCTION: avalanche_gpio_ctrl ++ ***************************************************************************/ ++int avalanche_gpio_ctrl(unsigned int gpio_pin, ++ AVALANCHE_GPIO_PIN_MODE_T pin_mode, ++ AVALANCHE_GPIO_PIN_DIRECTION_T pin_direction) +{ -+ __u32 power_status; ++ spinlock_t closeLock; ++ unsigned int closeFlag; ++ volatile unsigned int *gpio_ctrl = (unsigned int*)AVALANCHE_GPIO_ENBL; ++ ++ if(gpio_pin >= 32) ++ return(-1); ++ ++ spin_lock_irqsave(&closeLock, closeFlag); + -+ /* read current power down control register */ -+ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); ++ if(pin_mode == GPIO_PIN) ++ { ++ *gpio_ctrl |= (1 << gpio_pin); + -+ power_status &= TNETD73XX_GLOBAL_POWER_DOWN_MASK; -+ power_status |= ( power_mode << TNETD73XX_GLOBAL_POWER_DOWN_BIT); ++ gpio_ctrl = (unsigned int*)AVALANCHE_GPIO_DIR; ++ ++ if(pin_direction == GPIO_INPUT_PIN) ++ *gpio_ctrl |= (1 << gpio_pin); ++ else ++ *gpio_ctrl &= ~(1 << gpio_pin); ++ } ++ else /* FUNCTIONAL PIN */ ++ { ++ *gpio_ctrl &= ~(1 << gpio_pin); ++ } ++ ++ spin_unlock_irqrestore(&closeLock, closeFlag); + -+ /* write to power down control register */ -+ REG32_WRITE(TNETD73XX_POWER_CTRL_PDCR, power_status); ++ return (0); +} + -+TNETD73XX_SYS_POWER_MODE_T tnetd73xx_get_global_pwr_mode() ++/**************************************************************************** ++ * FUNCTION: avalanche_gpio_out ++ ***************************************************************************/ ++int avalanche_gpio_out_bit(unsigned int gpio_pin, int value) +{ -+ __u32 power_status; ++ spinlock_t closeLock; ++ unsigned int closeFlag; ++ volatile unsigned int *gpio_out = (unsigned int*) AVALANCHE_GPIO_DATA_OUT; ++ ++ if(gpio_pin >= 32) ++ return(-1); ++ ++ spin_lock_irqsave(&closeLock, closeFlag); ++ if(value == TRUE) ++ *gpio_out |= 1 << gpio_pin; ++ else ++ *gpio_out &= ~(1 << gpio_pin); ++ spin_unlock_irqrestore(&closeLock, closeFlag); + -+ /* read current power down control register */ -+ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); ++ return(0); ++} + -+ power_status &= (~TNETD73XX_GLOBAL_POWER_DOWN_MASK); -+ power_status = ( power_status >> TNETD73XX_GLOBAL_POWER_DOWN_BIT); ++/**************************************************************************** ++ * FUNCTION: avalanche_gpio_in ++ ***************************************************************************/ ++int avalanche_gpio_in_bit(unsigned int gpio_pin) ++{ ++ spinlock_t closeLock; ++ unsigned int closeFlag; ++ volatile unsigned int *gpio_in = (unsigned int*) AVALANCHE_GPIO_DATA_IN; ++ int ret_val = 0; ++ ++ if(gpio_pin >= 32) ++ return(-1); + -+ return ( (TNETD73XX_SYS_POWER_MODE_T) power_status ); ++ spin_lock_irqsave(&closeLock, closeFlag); ++ ret_val = ((*gpio_in) & (1 << gpio_pin)); ++ spin_unlock_irqrestore(&closeLock, closeFlag); ++ ++ return (ret_val); +} + ++/**************************************************************************** ++ * FUNCTION: avalanche_gpio_out_val ++ ***************************************************************************/ ++int avalanche_gpio_out_value(unsigned int out_val, unsigned int out_mask, ++ unsigned int reg_index) ++{ ++ spinlock_t closeLock; ++ unsigned int closeFlag; ++ volatile unsigned int *gpio_out = (unsigned int*) AVALANCHE_GPIO_DATA_OUT; + -+/***************************************************************************** -+ * Wakeup Control -+ *****************************************************************************/ ++ if(reg_index > 0) ++ return(-1); + -+#define TNETD73XX_WAKEUP_POLARITY_BIT 16 ++ spin_lock_irqsave(&closeLock, closeFlag); ++ *gpio_out &= ~out_mask; ++ *gpio_out |= out_val; ++ spin_unlock_irqrestore(&closeLock, closeFlag); + -+void tnetd73xx_wakeup_ctrl(TNETD73XX_WAKEUP_INTERRUPT_T wakeup_int, -+ TNETD73XX_WAKEUP_CTRL_T wakeup_ctrl, -+ TNETD73XX_WAKEUP_POLARITY_T wakeup_polarity) ++ return(0); ++} ++ ++/**************************************************************************** ++ * FUNCTION: avalanche_gpio_in_value ++ ***************************************************************************/ ++int avalanche_gpio_in_value(unsigned int* in_val, unsigned int reg_index) +{ -+ __u32 wakeup_status; ++ spinlock_t closeLock; ++ unsigned int closeFlag; ++ volatile unsigned int *gpio_in = (unsigned int*) AVALANCHE_GPIO_DATA_IN; ++ ++ if(reg_index > 0) ++ return(-1); + -+ /* read the wakeup control register */ -+ REG32_READ(TNETD73XX_POWER_CTRL_WKCR, wakeup_status); ++ spin_lock_irqsave(&closeLock, closeFlag); ++ *in_val = *gpio_in; ++ spin_unlock_irqrestore(&closeLock, closeFlag); ++ ++ return (0); ++} ++ ++/*********************************************************************** ++ * ++ * Wakeup Control Module for TNETV1050 Communication Processor ++ * ++ ***********************************************************************/ ++ ++#define AVALANCHE_WAKEUP_POLARITY_BIT 16 ++ ++void avalanche_wakeup_ctrl(AVALANCHE_WAKEUP_INTERRUPT_T wakeup_int, ++ AVALANCHE_WAKEUP_CTRL_T wakeup_ctrl, ++ AVALANCHE_WAKEUP_POLARITY_T wakeup_polarity) ++{ ++ volatile unsigned int *wakeup_status_reg = (unsigned int*) AVALANCHE_WAKEUP_CTRL_WKCR; + + /* enable/disable */ + if (wakeup_ctrl == WAKEUP_ENABLED) -+ { + /* enable wakeup */ -+ wakeup_status |= wakeup_int; -+ } ++ *wakeup_status_reg |= wakeup_int; + else -+ { + /* disable wakeup */ -+ wakeup_status &= (~wakeup_int); -+ } ++ *wakeup_status_reg &= (~wakeup_int); + + /* set polarity */ + if (wakeup_polarity == WAKEUP_ACTIVE_LOW) -+ { -+ wakeup_status |= (wakeup_int << TNETD73XX_WAKEUP_POLARITY_BIT); -+ } ++ *wakeup_status_reg |= (wakeup_int << AVALANCHE_WAKEUP_POLARITY_BIT); + else -+ { -+ wakeup_status &= ~(wakeup_int << TNETD73XX_WAKEUP_POLARITY_BIT); -+ } -+ -+ /* write the wakeup control register */ -+ REG32_WRITE(TNETD73XX_POWER_CTRL_WKCR, wakeup_status); ++ *wakeup_status_reg &= ~(wakeup_int << AVALANCHE_WAKEUP_POLARITY_BIT); +} + ++void avalanche_set_vbus_freq(unsigned int new_vbus_freq) ++{ ++ avalanche_vbus_freq = new_vbus_freq; ++} + -+/***************************************************************************** -+ * FSER Control -+ *****************************************************************************/ ++unsigned int avalanche_get_vbus_freq() ++{ ++ return(avalanche_vbus_freq); ++} + -+void tnetd73xx_fser_ctrl(TNETD73XX_FSER_MODE_T fser_mode) ++unsigned int avalanche_get_chip_version_info() +{ -+ REG32_WRITE(TNETD73XX_FSER_BASE, fser_mode); ++ return(*(volatile unsigned int*)AVALANCHE_CVR); +} + -+/***************************************************************************** -+ * Clock Control -+ *****************************************************************************/ ++SET_MDIX_ON_CHIP_FN_T p_set_mdix_on_chip_fn = NULL; + -+#define MIN(x,y) ( ((x) < (y)) ? (x) : (y) ) -+#define MAX(x,y) ( ((x) > (y)) ? (x) : (y) ) -+#define ABS(x) ( ((signed)(x) > 0) ? (x) : (-(x)) ) -+#define CEIL(x,y) ( ((x) + (y) / 2) / (y) ) ++int avalanche_set_mdix_on_chip(unsigned int base_addr, unsigned int operation) ++{ ++ if(p_set_mdix_on_chip_fn) ++ return (p_set_mdix_on_chip_fn(base_addr, operation)); ++ else ++ return(-1); ++} + -+#define CLKC_CLKCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x20 + (0x20 * (x))) -+#define CLKC_CLKPLLCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x30 + (0x20 * (x))) ++unsigned int avalanche_is_mdix_on_chip(void) ++{ ++ return(p_set_mdix_on_chip_fn ? 1:0); ++} + -+#define CLKC_PRE_DIVIDER 0x0000001F -+#define CLKC_POST_DIVIDER 0x001F0000 ++EXPORT_SYMBOL(avalanche_reset_ctrl); ++EXPORT_SYMBOL(avalanche_get_reset_status); ++EXPORT_SYMBOL(avalanche_sys_reset); ++EXPORT_SYMBOL(avalanche_get_sys_last_reset_status); ++EXPORT_SYMBOL(avalanche_power_ctrl); ++EXPORT_SYMBOL(avalanche_get_power_status); ++EXPORT_SYMBOL(avalanche_set_global_power_mode); ++EXPORT_SYMBOL(avalanche_get_global_power_mode); ++EXPORT_SYMBOL(avalanche_set_mdix_on_chip); ++EXPORT_SYMBOL(avalanche_is_mdix_on_chip); ++ ++EXPORT_SYMBOL(avalanche_gpio_init); ++EXPORT_SYMBOL(avalanche_gpio_ctrl); ++EXPORT_SYMBOL(avalanche_gpio_out_bit); ++EXPORT_SYMBOL(avalanche_gpio_in_bit); ++EXPORT_SYMBOL(avalanche_gpio_out_value); ++EXPORT_SYMBOL(avalanche_gpio_in_value); ++ ++EXPORT_SYMBOL(avalanche_set_vbus_freq); ++EXPORT_SYMBOL(avalanche_get_vbus_freq); ++ ++EXPORT_SYMBOL(avalanche_get_chip_version_info); ++ +diff -urN linux.old/arch/mips/ar7/platform.h linux.dev/arch/mips/ar7/platform.h +--- linux.old/arch/mips/ar7/platform.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/platform.h 2005-11-10 01:10:45.799571750 +0100 +@@ -0,0 +1,65 @@ ++#ifndef _PLATFORM_H_ ++#define _PLATFORM_H_ + -+#define CLKC_PLL_STATUS 0x1 -+#define CLKC_PLL_FACTOR 0x0000F000 ++#include + -+#define BOOTCR_PLL_BYPASS (1 << 5) -+#define BOOTCR_MIPS_ASYNC_MODE (1 << 25) + -+#define MIPS_PLL_SELECT 0x00030000 -+#define SYSTEM_PLL_SELECT 0x0000C000 -+#define USB_PLL_SELECT 0x000C0000 -+#define ADSLSS_PLL_SELECT 0x00C00000 ++/* Important: The definition of ENV_SPACE_SIZE should match with that in ++ * PSPBoot. (/psp_boot/inc/psbl/env.h) ++ */ ++#ifdef CONFIG_MIPS_AVALANCHE_TICFG ++#define ENV_SPACE_SIZE (10 * 1024) ++#endif + -+#define MIPS_AFECLKI_SELECT 0x00000000 -+#define MIPS_REFCLKI_SELECT 0x00010000 -+#define MIPS_XTAL3IN_SELECT 0x00020000 ++#ifdef CONFIG_MIPS_TNETV1050SDB ++#define TNETV1050SDB ++#define DUAL_FLASH ++#endif + -+#define SYSTEM_AFECLKI_SELECT 0x00000000 -+#define SYSTEM_REFCLKI_SELECT 0x00004000 -+#define SYSTEM_XTAL3IN_SELECT 0x00008000 -+#define SYSTEM_MIPSPLL_SELECT 0x0000C000 ++#ifdef CONFIG_MIPS_AR7DB ++#define TNETD73XX_BOARD ++#define AR7DB ++#endif + -+#define USB_SYSPLL_SELECT 0x00000000 -+#define USB_REFCLKI_SELECT 0x00040000 -+#define USB_XTAL3IN_SELECT 0x00080000 -+#define USB_MIPSPLL_SELECT 0x000C0000 ++#ifdef CONFIG_MIPS_AR7RD ++#define TNETD73XX_BOARD ++#define AR7RD ++#endif + -+#define ADSLSS_AFECLKI_SELECT 0x00000000 -+#define ADSLSS_REFCLKI_SELECT 0x00400000 -+#define ADSLSS_XTAL3IN_SELECT 0x00800000 -+#define ADSLSS_MIPSPLL_SELECT 0x00C00000 ++#ifdef CONFIG_AR7WRD ++#define TNETD73XX_BOARD ++#define AR7WRD ++#endif + -+#define SYS_MAX CLK_MHZ(150) -+#define SYS_MIN CLK_MHZ(1) ++#ifdef CONFIG_MIPS_AR7VWI ++#define TNETD73XX_BOARD ++#define AR7VWi ++#endif + -+#define MIPS_SYNC_MAX SYS_MAX -+#define MIPS_ASYNC_MAX CLK_MHZ(160) -+#define MIPS_MIN CLK_MHZ(1) ++/* Merging from the DEV_DSL-PSPL4.3.2.7_Patch release. */ ++#ifdef CONFIG_MIPS_AR7VW ++#define TNETD73XX_BOARD ++#define AR7WRD ++#endif + -+#define USB_MAX CLK_MHZ(100) -+#define USB_MIN CLK_MHZ(1) -+ -+#define ADSL_MAX CLK_MHZ(180) -+#define ADSL_MIN CLK_MHZ(1) ++#ifdef CONFIG_MIPS_AR7WI ++#define TNETD73XX_BOARD ++#define AR7Wi ++#endif + -+#define PLL_MUL_MAXFACTOR 15 -+#define MAX_DIV_VALUE 32 -+#define MIN_DIV_VALUE 1 ++#ifdef CONFIG_MIPS_AR7V ++#define TNETD73XX_BOARD ++#define AR7V ++#endif + -+#define MIN_PLL_INP_FREQ CLK_MHZ(8) -+#define MAX_PLL_INP_FREQ CLK_MHZ(100) ++#ifdef CONFIG_MIPS_AR7V ++#define TNETD73XX_BOARD ++#define AR7V ++#endif + -+#define DIVIDER_LOCK_TIME 10100 -+#define PLL_LOCK_TIME 10100 * 75 ++#ifdef CONFIG_MIPS_WA1130 ++#define AVALANCHE ++#define WLAN ++#endif + ++#endif +diff -urN linux.old/arch/mips/ar7/promlib.c linux.dev/arch/mips/ar7/promlib.c +--- linux.old/arch/mips/ar7/promlib.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/promlib.c 2005-11-10 01:14:16.372731750 +0100 +@@ -0,0 +1,48 @@ ++/* ++ * 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. ++ * ++ * Putting things on the screen/serial line using Adam2 facilities. ++ */ + ++#include ++#include + -+/**************************************************************************** -+ * DATA PURPOSE: PRIVATE Variables -+ **************************************************************************/ -+static __u32 *clk_src[4]; -+static __u32 mips_pll_out; -+static __u32 sys_pll_out; -+static __u32 afeclk_inp; -+static __u32 refclk_inp; -+static __u32 xtal_inp; -+static __u32 present_min; -+static __u32 present_max; -+ -+/* Forward References */ -+static __u32 find_gcd(__u32 min, __u32 max); -+static __u32 compute_prediv( __u32 divider, __u32 min, __u32 max); -+static void get_val(__u32 base_freq, __u32 output_freq,__u32 *multiplier, __u32 *divider); -+static __u32 get_base_frequency(TNETD73XX_CLKC_ID_T clk_id); -+static void find_approx(__u32 *,__u32 *,__u32); ++#define AVALANCHE_YAMON_FUNCTION_BASE (KSEG1ADDR(0x10000500)) ++#define AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR \ ++ (AVALANCHE_YAMON_FUNCTION_BASE + 1 * 0x4) ++#define AVALANCHE_YAMON_PROM_EXIT \ ++ (AVALANCHE_YAMON_FUNCTION_BASE + 8 * 0x4) + -+/**************************************************************************** -+ * FUNCTION: tnetd73xx_clkc_init -+ **************************************************************************** -+ * Description: The routine initializes the internal variables depending on -+ * on the sources selected for different clocks. -+ ***************************************************************************/ -+void tnetd73xx_clkc_init(__u32 afeclk, __u32 refclk, __u32 xtal3in) ++void prom_putchar(char c) +{ ++ static char buf[1]; ++ void (*prom_print_str)(unsigned int dummy, char *s, int len) = ++ (void *)(*(uint32_t *)AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR); + -+ __u32 choice; ++ buf[0] = c; ++ prom_print_str(1, buf, 1); ++ return; ++} + -+ afeclk_inp = afeclk; -+ refclk_inp = refclk; -+ xtal_inp = xtal3in; ++void adam2_exit(int retval) ++{ ++ void (*yamon_exit)(int retval) = ++ (void *)(*(uint32_t *)AVALANCHE_YAMON_PROM_EXIT); + -+ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & MIPS_PLL_SELECT; -+ switch(choice) -+ { -+ case MIPS_AFECLKI_SELECT: -+ clk_src[CLKC_MIPS] = &afeclk_inp; -+ break; ++ yamon_exit(retval); ++ return; ++} +diff -urN linux.old/arch/mips/ar7/psp_env.c linux.dev/arch/mips/ar7/psp_env.c +--- linux.old/arch/mips/ar7/psp_env.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/psp_env.c 2005-11-10 01:10:45.799571750 +0100 +@@ -0,0 +1,350 @@ ++#include ++#include ++#include ++#include ++#include ++#include + -+ case MIPS_REFCLKI_SELECT: -+ clk_src[CLKC_MIPS] = &refclk_inp; -+ break; ++#include "platform.h" + -+ case MIPS_XTAL3IN_SELECT: -+ clk_src[CLKC_MIPS] = &xtal_inp; -+ break; ++#define ENV_CELL_SIZE 16 + -+ default : -+ clk_src[CLKC_MIPS] = 0; ++/* control field decode */ ++#define ENV_GARBAGE_BIT 0x01 /* Env is garbage if this bit is off */ ++#define ENV_DYNAMIC_BIT 0x02 /* Env is dynamic if this bit is off */ + -+ } ++#define ENV_CTRL_MASK 0x03 ++#define ENV_PREFINED (ENV_GARBAGE_BIT | ENV_DYNAMIC_BIT) ++#define ENV_DYNAMIC (ENV_GARBAGE_BIT) + -+ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & SYSTEM_PLL_SELECT; -+ switch(choice) -+ { -+ case SYSTEM_AFECLKI_SELECT: -+ clk_src[CLKC_SYS] = &afeclk_inp; -+ break; ++struct env_variable { ++ unsigned char varNum; ++ unsigned char ctrl; ++ unsigned short chksum; ++ unsigned char numCells; ++ unsigned char data[ENV_CELL_SIZE - 5]; /* The data section starts ++ * here, continues for ++ * numCells. ++ */ ++}; ++ ++extern unsigned int max_env_entry; ++ ++/* Internal macros */ ++#define get_next_block(var) ((struct env_variable *)( (char*)(var) + (var)->numCells * ENV_CELL_SIZE)) ++ ++typedef enum ENV_VARS { ++ env_vars_start = 0, ++ CPUFREQ, ++ MEMSZ, ++ FLASHSZ, ++ MODETTY0, ++ MODETTY1, ++ PROMPT, ++ BOOTCFG, ++ HWA_0, ++#if !defined (AVALANCHE) || defined(TNETC401B) ++ HWA_1, ++#endif ++#if !defined(TNETV1020_BOARD) ++ HWA_RNDIS, ++#endif ++#if defined (TNETD73XX_BOARD) ++ HWA_3, ++#endif ++ IPA, ++ IPA_SVR, ++ BLINE_MAC0, ++#if !defined (AVALANCHE) || defined(TNETC401B) ++ BLINE_MAC1, ++#endif ++#if !defined(TNETV1020_BOARD) ++ BLINE_RNDIS, ++#endif ++#if defined (TNETD73XX_BOARD) ++ BLINE_ATM, ++#endif ++#if !defined(TNETV1020_BOARD) ++ USB_PID, ++ USB_VID, ++ USB_EPPOLLI, ++#endif ++ IPA_GATEWAY, ++ SUBNET_MASK, ++#if defined (TNETV1050_BOARD) ++ BLINE_ESWITCH, ++#endif ++#if !defined(TNETV1020_BOARD) ++ USB_SERIAL, ++ HWA_HRNDIS, /* Host (PC) side RNDIS address */ ++#endif ++ REMOTE_USER, ++ REMOTE_PASS, ++ REMOTE_DIR, ++ SYSFREQ, ++ LINK_TIMEOUT, ++#ifndef AVALANCHE /* Avalanche boards use only one mac port */ ++ MAC_PORT, ++#endif ++ PATH, ++ HOSTNAME, ++#ifdef WLAN ++ HW_REV_MAJOR, ++ HW_REV_MINOR, ++ HW_PATCH, ++ SW_PATCH, ++ SERIAL_NUMBER, ++#endif ++ TFTPCFG, ++#if defined (TNETV1050_BOARD) ++ HWA_ESWITCH, ++#endif ++ /* ++ * Add new env variables here. ++ * NOTE: New environment variables should always be placed at the end, ie ++ * just before env_vars_end. ++ */ + -+ case SYSTEM_REFCLKI_SELECT: -+ clk_src[CLKC_SYS] = &refclk_inp; -+ break; ++ env_vars_end ++} ENV_VARS; + -+ case SYSTEM_XTAL3IN_SELECT: -+ clk_src[CLKC_SYS] = &xtal_inp; -+ break; + -+ case SYSTEM_MIPSPLL_SELECT: -+ clk_src[CLKC_SYS] = &mips_pll_out; -+ break; ++struct env_description { ++ ENV_VARS idx; ++ char *nm; ++ char *alias; ++}; + -+ default : -+ clk_src[CLKC_SYS] = 0; ++#define ENVSTR(x) #x ++#define _ENV_ENTRY(x) {.idx = x, .nm = ENVSTR(x), .alias = NULL} ++ ++struct env_description env_ns[] = { ++ _ENV_ENTRY(env_vars_start), /* start. */ ++ _ENV_ENTRY(CPUFREQ), ++ _ENV_ENTRY(MEMSZ), ++ _ENV_ENTRY(FLASHSZ), ++ _ENV_ENTRY(MODETTY0), ++ _ENV_ENTRY(MODETTY1), ++ _ENV_ENTRY(PROMPT), ++ _ENV_ENTRY(BOOTCFG), ++ _ENV_ENTRY(HWA_0), ++#if !defined (AVALANCHE) || defined(TNETC401B) ++ _ENV_ENTRY(HWA_1), ++#endif ++#if !defined(TNETV1020_BOARD) ++ _ENV_ENTRY(HWA_RNDIS), ++#endif ++#if defined (TNETD73XX_BOARD) ++ _ENV_ENTRY(HWA_3), ++#endif ++ _ENV_ENTRY(IPA), ++ _ENV_ENTRY(IPA_SVR), ++ _ENV_ENTRY(IPA_GATEWAY), ++ _ENV_ENTRY(SUBNET_MASK), ++ _ENV_ENTRY(BLINE_MAC0), ++#if !defined (AVALANCHE) || defined(TNETC401B) ++ _ENV_ENTRY(BLINE_MAC1), ++#endif ++#if !defined(TNETV1020_BOARD) ++ _ENV_ENTRY(BLINE_RNDIS), ++#endif ++#if defined (TNETD73XX_BOARD) ++ _ENV_ENTRY(BLINE_ATM), ++#endif ++#if !defined(TNETV1020_BOARD) ++ _ENV_ENTRY(USB_PID), ++ _ENV_ENTRY(USB_VID), ++ _ENV_ENTRY(USB_EPPOLLI), ++#endif ++#if defined (TNETV1050_BOARD) ++ _ENV_ENTRY(BLINE_ESWITCH), ++#endif ++#if !defined(TNETV1020_BOARD) ++ _ENV_ENTRY(USB_SERIAL), ++ _ENV_ENTRY(HWA_HRNDIS), ++#endif ++ _ENV_ENTRY(REMOTE_USER), ++ _ENV_ENTRY(REMOTE_PASS), ++ _ENV_ENTRY(REMOTE_DIR), ++ _ENV_ENTRY(SYSFREQ), ++ _ENV_ENTRY(LINK_TIMEOUT), ++#ifndef AVALANCHE /* Avalanche boards use only one mac port */ ++ _ENV_ENTRY(MAC_PORT), ++#endif ++ _ENV_ENTRY(PATH), ++ _ENV_ENTRY(HOSTNAME), ++#ifdef WLAN ++ _ENV_ENTRY(HW_REV_MAJOR), ++ _ENV_ENTRY(HW_REV_MINOR), ++ _ENV_ENTRY(HW_PATCH), ++ _ENV_ENTRY(SW_PATCH), ++ _ENV_ENTRY(SERIAL_NUMBER), ++#endif ++ _ENV_ENTRY(TFTPCFG), ++#if defined (TNETV1050_BOARD) ++ _ENV_ENTRY(HWA_ESWITCH), ++#endif ++ /* ++ * Add new entries below this. ++ */ ++ /* Adam2 environment name alias. */ ++ { .idx = IPA, .nm = "my_ipaddress" }, ++ { .idx = CPUFREQ, .nm = "cpufrequency" }, ++ { .idx = SYSFREQ, .nm = "sysfrequency" }, ++ { .idx = HWA_0, .nm = "maca" }, ++#ifndef AVALANCHE ++ { .idx = HWA_1, .nm = "macb" }, ++#endif ++ { .idx = MODETTY0, .nm = "modetty0" }, ++ { .idx = MODETTY1, .nm = "modetty1" }, ++ { .idx = MEMSZ, .nm = "memsize" }, + -+ } ++ _ENV_ENTRY(env_vars_end) /* delimiter. */ ++}; + ++static inline int var_to_idx(const char* var) ++{ ++ int ii; + -+ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & ADSLSS_PLL_SELECT; -+ switch(choice) -+ { -+ case ADSLSS_AFECLKI_SELECT: -+ clk_src[CLKC_ADSLSS] = &afeclk_inp; -+ break; ++ /* go over the list of pre-defined environment variables */ ++ for (ii = env_vars_start; env_ns[ii].idx != env_vars_end; ii++){ ++ /* check if the env variable is listed */ ++ if (strcmp(env_ns[ii].nm, var) == 0) { ++ return env_ns[ii].idx; ++ } + -+ case ADSLSS_REFCLKI_SELECT: -+ clk_src[CLKC_ADSLSS] = &refclk_inp; -+ break; ++ /* if an alias is present, check if the alias matches ++ * the description ++ */ ++ if (env_ns[ii].alias != NULL) { ++ if (strcmp(env_ns[ii].alias, var) == 0) { ++ return env_ns[ii].idx; ++ } ++ } ++ } ++ return 0; ++} + -+ case ADSLSS_XTAL3IN_SELECT: -+ clk_src[CLKC_ADSLSS] = &xtal_inp; -+ break; ++extern int *_prom_envp; + -+ case ADSLSS_MIPSPLL_SELECT: -+ clk_src[CLKC_ADSLSS] = &mips_pll_out; -+ break; ++/* FIXME: reading from the flash is extremly unstable. Sometime a read returns garbage, ++ * the next read some seconds later is ok. It looks like something is hidding or ++ * overlay the flash address at 0xb0000000. Is this possible? ++ * ++ * The readb() and while() usage below is a attempt of a workarround - with limited success. ++ */ + -+ default : -+ clk_src[CLKC_ADSLSS] = 0; ++static inline struct env_variable* get_var_by_number(int index) ++{ ++ struct env_variable *env_var = (struct env_variable *)_prom_envp; ++ volatile unsigned char nr; ++ int i; + -+ } ++ env_var++; /* skip signature */ + ++ i = 0; ++ nr = readb(&(env_var->varNum)); + -+ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & USB_PLL_SELECT; -+ switch(choice) -+ { -+ case USB_SYSPLL_SELECT: -+ clk_src[CLKC_USB] = &sys_pll_out ; -+ break; ++ while (i < max_env_entry && nr != 0xFF) { ++ if ((env_var->ctrl & ENV_CTRL_MASK) == ENV_PREFINED) { ++ if (nr == index) { ++ return env_var; ++ } ++ } ++ i++; ++ env_var = get_next_block(env_var); ++ nr = readb(&(env_var->varNum)); ++ } + -+ case USB_REFCLKI_SELECT: -+ clk_src[CLKC_USB] = &refclk_inp; -+ break; ++ return NULL; ++} + -+ case USB_XTAL3IN_SELECT: -+ clk_src[CLKC_USB] = &xtal_inp; -+ break; ++static inline struct env_variable* get_var_by_name(char *var) ++{ ++ struct env_variable *env_var = (struct env_variable *)_prom_envp; ++ volatile unsigned char nr; ++ int i; + -+ case USB_MIPSPLL_SELECT: -+ clk_src[CLKC_USB] = &mips_pll_out; -+ break; ++ env_var++; /* skip signature */ + -+ default : -+ clk_src[CLKC_USB] = 0; ++ nr = readb(&(env_var->varNum)); ++ i = 0; + ++ while (i < max_env_entry && nr != 0xFF) { ++ if ((env_var->ctrl & ENV_CTRL_MASK) == ENV_DYNAMIC) { ++ if (strcmp(var, env_var->data) == 0) ++ return env_var; ++ } ++ i++; ++ env_var = get_next_block(env_var); ++ nr = readb(&(env_var->varNum)); + } ++ return NULL; +} + ++static inline struct env_variable* get_var(char *var) ++{ ++ int index = var_to_idx(var); + ++ if (index) ++ return get_var_by_number(index); ++ else ++ return get_var_by_name(var); + -+/**************************************************************************** -+ * FUNCTION: tnetd73xx_clkc_set_freq -+ **************************************************************************** -+ * Description: The above routine is called to set the output_frequency of the -+ * selected clock(using clk_id) to the required value given -+ * by the variable output_freq. -+ ***************************************************************************/ -+TNETD73XX_ERR tnetd73xx_clkc_set_freq -+( -+ TNETD73XX_CLKC_ID_T clk_id, -+ __u32 output_freq -+) -+{ -+ __u32 base_freq; -+ __u32 multiplier; -+ __u32 divider; -+ __u32 min_prediv; -+ __u32 max_prediv; -+ __u32 prediv; -+ __u32 postdiv; -+ __u32 temp; -+ -+ /* check if PLLs are bypassed*/ -+ if(REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_PLL_BYPASS) -+ { -+ return TNETD73XX_ERR_ERROR; -+ } -+ -+ /*check if the requested output_frequency is in valid range*/ -+ switch( clk_id ) -+ { -+ case CLKC_SYS: -+ if( output_freq < SYS_MIN || output_freq > SYS_MAX) -+ { -+ return TNETD73XX_ERR_ERROR; -+ } -+ present_min = SYS_MIN; -+ present_max = SYS_MAX; -+ break; ++ return NULL; ++} + -+ case CLKC_MIPS: -+ if((output_freq < MIPS_MIN) || -+ (output_freq > ((REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_MIPS_ASYNC_MODE) ? MIPS_ASYNC_MAX: MIPS_SYNC_MAX))) -+ { -+ return TNETD73XX_ERR_ERROR; -+ } -+ present_min = MIPS_MIN; -+ present_max = (REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_MIPS_ASYNC_MODE) ? MIPS_ASYNC_MAX: MIPS_SYNC_MAX; -+ break; ++static inline char *get_value(struct env_variable* env_var) ++{ ++ unsigned char *name; ++ unsigned char *value; ++ unsigned short chksum; ++ int i; + -+ case CLKC_USB: -+ if( output_freq < USB_MIN || output_freq > USB_MAX) -+ { -+ return TNETD73XX_ERR_ERROR; -+ } -+ present_min = USB_MIN; -+ present_max = USB_MAX; -+ break; ++ chksum = env_var->varNum + env_var->ctrl + env_var->numCells; + -+ case CLKC_ADSLSS: -+ if( output_freq < ADSL_MIN || output_freq > ADSL_MAX) -+ { -+ return TNETD73XX_ERR_ERROR; -+ } -+ present_min = ADSL_MIN; -+ present_max = ADSL_MAX; -+ break; -+ } ++ if ((env_var->ctrl & ENV_CTRL_MASK) == ENV_DYNAMIC) { ++ name = env_var->data; ++ value = env_var->data + strlen(name) + 1; + ++ for(i = 0; i < strlen(name); i++) ++ chksum += name[i]; ++ } else ++ value = env_var->data; + -+ base_freq = get_base_frequency(clk_id); ++ for (i = 0; i < strlen(value); i++) ++ chksum += value[i]; + ++ chksum += env_var->chksum; ++ chksum = ~(chksum); + -+ /* check for minimum base frequency value */ -+ if( base_freq < MIN_PLL_INP_FREQ) -+ { -+ return TNETD73XX_ERR_ERROR; -+ } ++ if(chksum != 0) { ++ return NULL; ++ } + -+ get_val(output_freq, base_freq, &multiplier, ÷r); ++ return value; ++} + -+ /* check multiplier range */ -+ if( (multiplier > PLL_MUL_MAXFACTOR) || (multiplier <= 0) ) -+ { -+ return TNETD73XX_ERR_ERROR; -+ } ++struct psbl_rec { ++ unsigned int psbl_size; ++ unsigned int env_base; ++ unsigned int env_size; ++ unsigned int ffs_base; ++ unsigned int ffs_size; ++}; + -+ /* check divider value */ -+ if( divider == 0 ) -+ { -+ return TNETD73XX_ERR_ERROR; -+ } ++char *prom_psp_getenv(char *envname) ++{ ++ struct env_variable* env_var; ++ char *value; + -+ /*compute minimum and maximum predivider values */ -+ min_prediv = MAX(base_freq / MAX_PLL_INP_FREQ + 1, divider / MAX_DIV_VALUE + 1); -+ max_prediv = MIN(base_freq / MIN_PLL_INP_FREQ, MAX_DIV_VALUE); ++ if (strcmp("bootloader", envname) == 0) ++ return "PSPBoot"; + -+ /*adjust the value of divider so that it not less than minimum predivider value*/ -+ if (divider < min_prediv) -+ { -+ temp = CEIL(min_prediv, divider); -+ if ((temp * multiplier) > PLL_MUL_MAXFACTOR) -+ { -+ return TNETD73XX_ERR_ERROR ; -+ } -+ else -+ { -+ multiplier = temp * multiplier; -+ divider = min_prediv; -+ } ++ if (!(env_var = get_var(envname))) ++ return NULL; + -+ } ++ value = get_value(env_var); + -+ /* compute predivider and postdivider values */ -+ prediv = compute_prediv (divider, min_prediv, max_prediv); -+ postdiv = CEIL(divider,prediv); ++ return value; ++} +diff -urN linux.old/arch/mips/ar7/reset.c linux.dev/arch/mips/ar7/reset.c +--- linux.old/arch/mips/ar7/reset.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/reset.c 2005-11-10 01:14:16.372731750 +0100 +@@ -0,0 +1,98 @@ ++/* ++ * 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. ++ * ++ * ######################################################################## ++ * ++ * Reset the AR7 boards. ++ * ++ */ + -+ /*return fail if postdivider value falls out of range */ -+ if(postdiv > MAX_DIV_VALUE) -+ { -+ return TNETD73XX_ERR_ERROR; -+ } ++#include ++#include ++#include ++#include + ++#include ++#include ++#include + -+ /*write predivider and postdivider values*/ -+ /* pre-Divider and post-divider are 5 bit N+1 dividers */ -+ REG32_WRITE(CLKC_CLKCR(clk_id), ((postdiv -1) & 0x1F) << 16 | ((prediv -1) & 0x1F) ); ++int preserve_adam2 = 1; + -+ /*wait for divider output to stabilise*/ -+ for(temp =0; temp < DIVIDER_LOCK_TIME; temp++); ++extern void adam2_exit(int retval); + -+ /*write to PLL clock register*/ ++static void ar7_machine_restart(char *command); ++static void ar7_machine_halt(void); ++static void ar7_machine_power_off(void); + -+ if(clk_id == CLKC_SYS) -+ { -+ /* but before writing put DRAM to hold mode */ -+ REG32_DATA(TNETD73XX_EMIF_SDRAM_CFG) |= 0x80000000; -+ } -+ /*Bring PLL into div mode */ -+ REG32_WRITE(CLKC_CLKPLLCR(clk_id), 0x4); ++static void ar7_machine_restart(char *command) ++{ ++ volatile uint32_t *softres_reg = (void *)(KSEG1ADDR(0x08611600 + 0x4)); + -+ /*compute the word to be written to PLLCR -+ *corresponding to multiplier value -+ */ -+ multiplier = (((multiplier - 1) & 0xf) << 12)| ((255 <<3) | 0x0e); ++ *softres_reg = 1; ++} + -+ /* wait till PLL enters div mode */ -+ while(REG32_DATA(CLKC_CLKPLLCR(clk_id)) & CLKC_PLL_STATUS) -+ /*nothing*/; ++static void ar7_machine_halt(void) ++{ + -+ REG32_WRITE(CLKC_CLKPLLCR(clk_id), multiplier); ++ if (preserve_adam2) { ++ set_c0_status(ST0_BEV); ++ adam2_exit(0); ++ } else { ++ /* I'd like to have Alt-SysRq-b work in this state. ++ * What's missing here? The timer interrupt is still running. ++ * Why doesn't the UART work anymore? */ ++ while(1) { ++ __asm__(".set\tmips3\n\t" ++ "wait\n\t" ++ ".set\tmips0"); ++ } ++ } ++} + -+ while(!REG32_DATA(CLKC_CLKPLLCR(clk_id)) & CLKC_PLL_STATUS) -+ /*nothing*/; ++static void ar7_machine_power_off(void) ++{ ++ volatile uint32_t *power_reg = (void *)(KSEG1ADDR(0x08610A00)); ++ uint32_t power_state = *power_reg; + ++ /* add something to turn LEDs off? */ + -+ /*wait for External pll to lock*/ -+ for(temp =0; temp < PLL_LOCK_TIME; temp++); ++ power_state &= ~(3 << 30); ++ power_state |= (3 << 30); /* power down */ ++ *power_reg = power_state; + -+ if(clk_id == CLKC_SYS) -+ { -+ /* Bring DRAM out of hold */ -+ REG32_DATA(TNETD73XX_EMIF_SDRAM_CFG) &= ~0x80000000; -+ } ++ printk("after power down?\n"); ++} + -+ return TNETD73XX_ERR_OK ; ++void ar7_reboot_setup(void) ++{ ++ _machine_restart = ar7_machine_restart; ++ _machine_halt = ar7_machine_halt; ++ _machine_power_off = ar7_machine_power_off; +} + -+/**************************************************************************** -+ * FUNCTION: tnetd73xx_clkc_get_freq -+ **************************************************************************** -+ * Description: The above routine is called to get the output_frequency of the -+ * selected clock( clk_id) -+ ***************************************************************************/ -+__u32 tnetd73xx_clkc_get_freq -+( -+ TNETD73XX_CLKC_ID_T clk_id -+) ++static int __init ar7_do_preserve_adam2(char *s) +{ ++ if (!strcmp(s, "no") || !strcmp(s, "0")) ++ preserve_adam2 = 0; ++ else ++ preserve_adam2 = 1; ++ return 1; ++} + -+ __u32 clk_ctrl_register; -+ __u32 clk_pll_setting; -+ __u32 clk_predivider; -+ __u32 clk_postdivider; -+ __u16 pll_factor; -+ __u32 base_freq; -+ __u32 divider; ++__setup("adam2=", ar7_do_preserve_adam2); +diff -urN linux.old/arch/mips/ar7/setup.c linux.dev/arch/mips/ar7/setup.c +--- linux.old/arch/mips/ar7/setup.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/setup.c 2005-11-10 01:12:43.946955500 +0100 +@@ -0,0 +1,143 @@ ++/* ++ * 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. ++ */ + -+ base_freq = get_base_frequency(clk_id); ++#include ++#include ++#include ++#include + -+ clk_ctrl_register = REG32_DATA(CLKC_CLKCR(clk_id)); ++#include ++#include ++#include ++#include ++#include ++#include + -+ /* pre-Divider and post-divider are 5 bit N+1 dividers */ -+ clk_predivider = (CLKC_PRE_DIVIDER & clk_ctrl_register) + 1; -+ clk_postdivider = ((CLKC_POST_DIVIDER & clk_ctrl_register) >> 16) + 1; ++#ifdef CONFIG_KGDB ++extern void rs_kgdb_hook(int); ++extern void breakpoint(void); ++int remote_debug = 0; ++#endif + -+ divider = clk_predivider * clk_postdivider; ++extern void ar7_reboot_setup(void); ++extern void ar7_irq_init(int); ++extern asmlinkage void ar7IRQ(void); + ++void ar7_time_init(void) ++{ ++ /* XXX runtime */ ++ mips_hpt_frequency = CONFIG_AR7_CPU * 500000; ++} + -+ if( (REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_PLL_BYPASS)) -+ { -+ return (CEIL(base_freq, divider)); /* PLLs bypassed.*/ -+ } ++void ar7_timer_setup(struct irqaction *irq) ++{ ++ setup_irq(7, irq); ++ set_c0_status(IE_IRQ5); ++} + ++void __init init_IRQ(void) ++{ ++ init_generic_irq(); ++ mips_cpu_irq_init(0); ++ ar7_irq_init(8); + -+ else -+ { -+ /* return the current clock speed based upon the PLL setting */ -+ clk_pll_setting = REG32_DATA(CLKC_CLKPLLCR(clk_id)); ++ /* Now safe to set the exception vector. */ ++ set_except_vector(0, ar7IRQ); + -+ /* Get the PLL multiplication factor */ -+ pll_factor = ((clk_pll_setting & CLKC_PLL_FACTOR) >> 12) + 1; ++#ifdef CONFIG_KGDB ++ if (remote_debug) ++ { ++ set_debug_traps(); ++ breakpoint(); ++ } ++#endif ++} + -+ /* Check if we're in divide mode or multiply mode */ -+ if((clk_pll_setting & 0x1) == 0) -+ { -+ /* We're in divide mode */ -+ if(pll_factor < 0x10) -+ return (CEIL(base_freq >> 1, divider)); -+ else -+ return (CEIL(base_freq >> 2, divider)); -+ } ++const char *get_system_type(void) ++{ ++ return "Texas Instruments AR7"; ++} + -+ else /* We're in PLL mode */ -+ { -+ /* See if PLLNDIV & PLLDIV are set */ -+ if((clk_pll_setting & 0x0800) && (clk_pll_setting & 0x2)) -+ { -+ if(clk_pll_setting & 0x1000) -+ { -+ /* clk = base_freq * k/2 */ -+ return(CEIL((base_freq * pll_factor) >> 1, divider)); -+ } -+ else -+ { -+ /* clk = base_freq * (k-1) / 4)*/ -+ return(CEIL((base_freq * (pll_factor - 1)) >>2, divider)); -+ } -+ } -+ else -+ { -+ if(pll_factor < 0x10) -+ { -+ /* clk = base_freq * k */ -+ return(CEIL(base_freq * pll_factor, divider)); -+ } ++void __init ar7_setup(void) ++{ ++#ifdef CONFIG_KGDB ++ int rs_putDebugChar(char); ++ char rs_getDebugChar(void); ++ extern int (*generic_putDebugChar)(char); ++ extern char (*generic_getDebugChar)(void); ++#endif ++ char *argptr; ++#ifdef CONFIG_SERIAL_CONSOLE ++ argptr = prom_getcmdline(); ++ if ((argptr = strstr(argptr, "console=")) == NULL) { ++ char console[20]; ++ char *s; ++ int i = 0; ++ ++ s = prom_getenv("modetty0"); ++ strcpy(console, "38400"); ++ ++ if (s != NULL) { ++ while (s[i] >= '0' && s[i] <= '9') ++ i++; ++ ++ if (i > 0) { ++ strncpy(console, s, i); ++ console[i] = 0; ++ } ++ } ++ ++ argptr = prom_getcmdline(); ++ strcat(argptr, " console=ttyS0,"); ++ strcat(argptr, console); ++ } ++#endif + -+ else -+ { -+ /* clk = base_freq */ -+ return(CEIL(base_freq, divider)); -+ } -+ } -+ } -+ return(0); /* Should never reach here */ ++#ifdef CONFIG_KGDB ++ argptr = prom_getcmdline(); ++ if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { ++ int line; ++ argptr += strlen("kgdb=ttyS"); ++ if (*argptr != '0' && *argptr != '1') ++ printk("KGDB: Uknown serial line /dev/ttyS%c, " ++ "falling back to /dev/ttyS1\n", *argptr); ++ line = *argptr == '0' ? 0 : 1; ++ printk("KGDB: Using serial line /dev/ttyS%d for session\n", ++ line ? 1 : 0); + -+ } ++ rs_kgdb_hook(line); ++ generic_putDebugChar = rs_putDebugChar; ++ generic_getDebugChar = rs_getDebugChar; + -+} ++ prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " ++ "please connect your debugger\n", line ? 1 : 0); + ++ remote_debug = 1; ++ /* Breakpoints are in init_IRQ() */ ++ } ++#endif + -+/* local helper functions */ ++ argptr = prom_getcmdline(); ++ if ((argptr = strstr(argptr, "nofpu")) != NULL) ++ cpu_data[0].options &= ~MIPS_CPU_FPU; + -+ /**************************************************************************** -+ * FUNCTION: get_base_frequency -+ **************************************************************************** -+ * Description: The above routine is called to get base frequency of the clocks. -+ ***************************************************************************/ ++ ar7_reboot_setup(); ++ ++ board_time_init = ar7_time_init; ++ board_timer_setup = ar7_timer_setup; ++} +diff -urN linux.old/arch/mips/ar7/tnetd73xx_misc.c linux.dev/arch/mips/ar7/tnetd73xx_misc.c +--- linux.old/arch/mips/ar7/tnetd73xx_misc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/arch/mips/ar7/tnetd73xx_misc.c 2005-11-10 01:12:43.946955500 +0100 +@@ -0,0 +1,921 @@ ++/****************************************************************************** ++ * FILE PURPOSE: TNETD73xx Misc modules API Source ++ ****************************************************************************** ++ * FILE NAME: tnetd73xx_misc.c ++ * ++ * DESCRIPTION: Clock Control, Reset Control, Power Management, GPIO ++ * FSER Modules API ++ * As per TNETD73xx specifications ++ * ++ * REVISION HISTORY: ++ * 27 Nov 02 - Sharath Kumar PSP TII ++ * 14 Feb 03 - Anant Gole PSP TII ++ * ++ * (C) Copyright 2002, Texas Instruments, Inc ++ *******************************************************************************/ ++ ++#include ++#include ++#include + -+static __u32 get_base_frequency(TNETD73XX_CLKC_ID_T clk_id) ++/* TNETD73XX Revision */ ++u32 tnetd73xx_get_revision(void) +{ -+ /* update the current MIPs PLL output value, if the required -+ * source is MIPS PLL -+ */ -+ if ( clk_src[clk_id] == &mips_pll_out) -+ { -+ *clk_src[clk_id] = tnetd73xx_clkc_get_freq(CLKC_MIPS); -+ } ++ /* Read Chip revision register - This register is from GPIO module */ ++ return ( (u32) REG32_DATA(TNETD73XX_CVR)); ++} + ++/***************************************************************************** ++ * Reset Control Module ++ *****************************************************************************/ + -+ /* update the current System PLL output value, if the required -+ * source is system PLL -+ */ -+ if ( clk_src[clk_id] == &sys_pll_out) -+ { -+ *clk_src[clk_id] = tnetd73xx_clkc_get_freq(CLKC_SYS); -+ } + -+ return (*clk_src[clk_id]); ++void tnetd73xx_reset_ctrl(TNETD73XX_RESET_MODULE_T reset_module, TNETD73XX_RESET_CTRL_T reset_ctrl) ++{ ++ u32 reset_status; + -+} ++ /* read current reset register */ ++ REG32_READ(TNETD73XX_RST_CTRL_PRCR, reset_status); + ++ if (reset_ctrl == OUT_OF_RESET) ++ { ++ /* bring module out of reset */ ++ reset_status |= (1 << reset_module); ++ } ++ else ++ { ++ /* put module in reset */ ++ reset_status &= (~(1 << reset_module)); ++ } + ++ /* write to the reset register */ ++ REG32_WRITE(TNETD73XX_RST_CTRL_PRCR, reset_status); ++} + -+/**************************************************************************** -+ * FUNCTION: find_gcd -+ **************************************************************************** -+ * Description: The above routine is called to find gcd of 2 numbers. -+ ***************************************************************************/ -+static __u32 find_gcd -+( -+__u32 min, -+__u32 max -+) ++ ++TNETD73XX_RESET_CTRL_T tnetd73xx_get_reset_status (TNETD73XX_RESET_MODULE_T reset_module) +{ -+ if (max % min == 0) -+ { -+ return min; -+ } -+ else -+ { -+ return find_gcd(max % min, min); -+ } ++ u32 reset_status; ++ ++ REG32_READ(TNETD73XX_RST_CTRL_PRCR, reset_status); ++ return ( (reset_status & (1 << reset_module)) ? OUT_OF_RESET : IN_RESET ); +} + -+/**************************************************************************** -+ * FUNCTION: compute_prediv -+ **************************************************************************** -+ * Description: The above routine is called to compute predivider value -+ ***************************************************************************/ -+static __u32 compute_prediv(__u32 divider, __u32 min, __u32 max) ++void tnetd73xx_sys_reset(TNETD73XX_SYS_RST_MODE_T mode) +{ -+__u16 prediv; ++ REG32_WRITE(TNETD73XX_RST_CTRL_SWRCR, mode); ++} ++ ++#define TNETD73XX_RST_CTRL_RSR_MASK 0x3 + -+/* return the divider itself it it falls within the range of predivider*/ -+if (min <= divider && divider <= max) ++TNETD73XX_SYS_RESET_STATUS_T tnetd73xx_get_sys_last_reset_status() +{ -+ return divider; ++ u32 sys_reset_status; ++ ++ REG32_READ(TNETD73XX_RST_CTRL_RSR, sys_reset_status); ++ ++ return ( (TNETD73XX_SYS_RESET_STATUS_T) (sys_reset_status & TNETD73XX_RST_CTRL_RSR_MASK) ); +} + -+/* find a value for prediv such that it is a factor of divider */ -+for (prediv = max; prediv >= min ; prediv--) ++ ++/***************************************************************************** ++ * Power Control Module ++ *****************************************************************************/ ++#define TNETD73XX_GLOBAL_POWER_DOWN_MASK 0x3FFFFFFF /* bit 31, 30 masked */ ++#define TNETD73XX_GLOBAL_POWER_DOWN_BIT 30 /* shift to bit 30, 31 */ ++ ++ ++void tnetd73xx_power_ctrl(TNETD73XX_POWER_MODULE_T power_module, TNETD73XX_POWER_CTRL_T power_ctrl) +{ -+ if ( (divider % prediv) == 0 ) -+ { -+ return prediv; -+ } -+} ++ u32 power_status; ++ ++ /* read current power down control register */ ++ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); ++ ++ if (power_ctrl == POWER_CTRL_POWER_DOWN) ++ { ++ /* power down the module */ ++ power_status |= (1 << power_module); ++ } ++ else ++ { ++ /* power on the module */ ++ power_status &= (~(1 << power_module)); ++ } + -+/* No such factor exists, return min as prediv */ -+return min; ++ /* write to the reset register */ ++ REG32_WRITE(TNETD73XX_POWER_CTRL_PDCR, power_status); +} + -+/**************************************************************************** -+ * FUNCTION: get_val -+ **************************************************************************** -+ * Description: This routine is called to get values of divider and multiplier. -+ ***************************************************************************/ ++TNETD73XX_POWER_CTRL_T tnetd73xx_get_pwr_status(TNETD73XX_POWER_MODULE_T power_module) ++{ ++ u32 power_status; ++ ++ /* read current power down control register */ ++ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); ++ ++ return ( (power_status & (1 << power_module)) ? POWER_CTRL_POWER_DOWN : POWER_CTRL_POWER_UP ); ++} + -+static void get_val(__u32 output_freq, __u32 base_freq,__u32 *multiplier, __u32 *divider) ++void tnetd73xx_set_global_pwr_mode(TNETD73XX_SYS_POWER_MODE_T power_mode) +{ -+ __u32 temp_mul; -+ __u32 temp_div; -+ __u32 gcd; -+ __u32 min_freq; -+ __u32 max_freq; ++ u32 power_status; + -+ /* find gcd of base_freq, output_freq */ -+ min_freq = (base_freq < output_freq) ? base_freq : output_freq; -+ max_freq = (base_freq > output_freq) ? base_freq : output_freq; -+ gcd = find_gcd(min_freq , max_freq); ++ /* read current power down control register */ ++ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); + -+ if(gcd == 0) -+ return; /* ERROR */ ++ power_status &= TNETD73XX_GLOBAL_POWER_DOWN_MASK; ++ power_status |= ( power_mode << TNETD73XX_GLOBAL_POWER_DOWN_BIT); + -+ /* compute values of multiplier and divider */ -+ temp_mul = output_freq / gcd; -+ temp_div = base_freq / gcd; ++ /* write to power down control register */ ++ REG32_WRITE(TNETD73XX_POWER_CTRL_PDCR, power_status); ++} + ++TNETD73XX_SYS_POWER_MODE_T tnetd73xx_get_global_pwr_mode() ++{ ++ u32 power_status; + -+ /* set multiplier such that 1 <= multiplier <= PLL_MUL_MAXFACTOR */ -+ if( temp_mul > PLL_MUL_MAXFACTOR ) -+ { -+ if((temp_mul / temp_div) > PLL_MUL_MAXFACTOR) -+ return; ++ /* read current power down control register */ ++ REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); + -+ find_approx(&temp_mul,&temp_div,base_freq); -+ } ++ power_status &= (~TNETD73XX_GLOBAL_POWER_DOWN_MASK); ++ power_status = ( power_status >> TNETD73XX_GLOBAL_POWER_DOWN_BIT); + -+ *multiplier = temp_mul; -+ *divider = temp_div; ++ return ( (TNETD73XX_SYS_POWER_MODE_T) power_status ); +} + -+/**************************************************************************** -+ * FUNCTION: find_approx -+ **************************************************************************** -+ * Description: This function gets the approx value of num/denom. -+ ***************************************************************************/ + -+static void find_approx(__u32 *num,__u32 *denom,__u32 base_freq) -+{ -+ __u32 num1; -+ __u32 denom1; -+ __u32 num2; -+ __u32 denom2; -+ int closest; -+ int prev_closest; -+ __u32 temp_num; -+ __u32 temp_denom; -+ __u32 normalize; -+ __u32 gcd; -+ __u32 output_freq; -+ -+ num1 = *num; -+ denom1 = *denom; -+ -+ prev_closest = 0x7fffffff; /* maximum possible value */ -+ num2 = num1; -+ denom2 = denom1; -+ -+ /* start with max */ -+ for(temp_num = 15; temp_num >=1; temp_num--) -+ { ++/***************************************************************************** ++ * Wakeup Control ++ *****************************************************************************/ + -+ temp_denom = CEIL(temp_num * denom1, num1); -+ output_freq = (temp_num * base_freq) / temp_denom; ++#define TNETD73XX_WAKEUP_POLARITY_BIT 16 + -+ if(temp_denom < 1) -+ { -+ break; -+ } -+ else -+ { -+ normalize = CEIL(num1,temp_num); -+ closest = (ABS((num1 * (temp_denom) ) - (temp_num * denom1))) * normalize; -+ if(closest < prev_closest && output_freq > present_min && output_freq (y)) ? (x) : (y) ) ++#define ABS(x) ( ((signed)(x) > 0) ? (x) : (-(x)) ) ++#define CEIL(x,y) ( ((x) + (y) / 2) / (y) ) + -diff -urN kernel-base/arch/mips/ar7/cmdline.c kernel-current/arch/mips/ar7/cmdline.c ---- kernel-base/arch/mips/ar7/cmdline.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/cmdline.c 2005-07-10 06:40:39.584266864 +0200 -@@ -0,0 +1,64 @@ -+/* -+ * 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. -+ * -+ * Kernel command line creation using the prom monitor (YAMON) argc/argv. -+ */ -+#include -+#include ++#define CLKC_CLKCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x20 + (0x20 * (x))) ++#define CLKC_CLKPLLCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x30 + (0x20 * (x))) + -+#include ++#define CLKC_PRE_DIVIDER 0x0000001F ++#define CLKC_POST_DIVIDER 0x001F0000 + -+extern int prom_argc; -+extern int *_prom_argv; ++#define CLKC_PLL_STATUS 0x1 ++#define CLKC_PLL_FACTOR 0x0000F000 + -+/* -+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. -+ * This macro take care of sign extension. -+ */ -+#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)])) ++#define BOOTCR_PLL_BYPASS (1 << 5) ++#define BOOTCR_MIPS_ASYNC_MODE (1 << 25) + -+char arcs_cmdline[CL_SIZE]; ++#define MIPS_PLL_SELECT 0x00030000 ++#define SYSTEM_PLL_SELECT 0x0000C000 ++#define USB_PLL_SELECT 0x000C0000 ++#define ADSLSS_PLL_SELECT 0x00C00000 + -+char * __init prom_getcmdline(void) -+{ -+ return &(arcs_cmdline[0]); -+} ++#define MIPS_AFECLKI_SELECT 0x00000000 ++#define MIPS_REFCLKI_SELECT 0x00010000 ++#define MIPS_XTAL3IN_SELECT 0x00020000 + ++#define SYSTEM_AFECLKI_SELECT 0x00000000 ++#define SYSTEM_REFCLKI_SELECT 0x00004000 ++#define SYSTEM_XTAL3IN_SELECT 0x00008000 ++#define SYSTEM_MIPSPLL_SELECT 0x0000C000 + -+void __init prom_init_cmdline(void) -+{ -+ char *cp; -+ int actr; ++#define USB_SYSPLL_SELECT 0x00000000 ++#define USB_REFCLKI_SELECT 0x00040000 ++#define USB_XTAL3IN_SELECT 0x00080000 ++#define USB_MIPSPLL_SELECT 0x000C0000 + -+ actr = 1; /* Always ignore argv[0] */ ++#define ADSLSS_AFECLKI_SELECT 0x00000000 ++#define ADSLSS_REFCLKI_SELECT 0x00400000 ++#define ADSLSS_XTAL3IN_SELECT 0x00800000 ++#define ADSLSS_MIPSPLL_SELECT 0x00C00000 + -+ cp = &(arcs_cmdline[0]); -+#ifdef CONFIG_CMDLINE_BOOL -+ strcpy(cp, CONFIG_CMDLINE); -+ cp += strlen(CONFIG_CMDLINE); -+ *cp++ = ' '; -+#endif -+ while(actr < prom_argc) { -+ strcpy(cp, prom_argv(actr)); -+ cp += strlen(prom_argv(actr)); -+ *cp++ = ' '; -+ actr++; -+ } -+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ -+ --cp; -+ *cp = '\0'; -+} -diff -urN kernel-base/arch/mips/ar7/init.c kernel-current/arch/mips/ar7/init.c ---- kernel-base/arch/mips/ar7/init.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/init.c 2005-07-10 06:40:39.584266864 +0200 -@@ -0,0 +1,146 @@ -+/* -+ * 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. -+ * -+ * PROM library initialisation code. -+ */ -+#include -+#include -+#include -+#include -+#include ++#define SYS_MAX CLK_MHZ(150) ++#define SYS_MIN CLK_MHZ(1) + -+#include -+#include -+#include ++#define MIPS_SYNC_MAX SYS_MAX ++#define MIPS_ASYNC_MAX CLK_MHZ(160) ++#define MIPS_MIN CLK_MHZ(1) + -+/* Environment variable */ -+typedef struct { -+ char *name; -+ char *val; -+} t_env_var; ++#define USB_MAX CLK_MHZ(100) ++#define USB_MIN CLK_MHZ(1) + -+int prom_argc; -+int *_prom_argv, *_prom_envp; ++#define ADSL_MAX CLK_MHZ(180) ++#define ADSL_MIN CLK_MHZ(1) + -+/* max # of Adam2 environment variables */ -+#define MAX_ENV_ENTRY 80 ++#define PLL_MUL_MAXFACTOR 15 ++#define MAX_DIV_VALUE 32 ++#define MIN_DIV_VALUE 1 + -+static t_env_var local_envp[MAX_ENV_ENTRY]; -+int init_debug = 0; ++#define MIN_PLL_INP_FREQ CLK_MHZ(8) ++#define MAX_PLL_INP_FREQ CLK_MHZ(100) + -+char *prom_getenv(char *envname) -+{ -+ /* -+ * Return a pointer to the given environment variable. -+ * In 64-bit mode: we're using 64-bit pointers, but all pointers -+ * in the PROM structures are only 32-bit, so we need some -+ * workarounds, if we are running in 64-bit mode. -+ */ -+ int i, index=0; -+ t_env_var *env = (t_env_var *) local_envp; ++#define DIVIDER_LOCK_TIME 10100 ++#define PLL_LOCK_TIME 10100 * 75 + -+ i = strlen(envname); -+ while (env->name) { -+ if(strncmp(envname, env->name, i) == 0) { -+ return(env->val); -+ } -+ env++; -+ } + -+ return NULL; -+} + -+static inline unsigned char str2hexnum(unsigned char c) ++ /**************************************************************************** ++ * DATA PURPOSE: PRIVATE Variables ++ **************************************************************************/ ++ static u32 *clk_src[4]; ++ static u32 mips_pll_out; ++ static u32 sys_pll_out; ++ static u32 afeclk_inp; ++ static u32 refclk_inp; ++ static u32 xtal_inp; ++ static u32 present_min; ++ static u32 present_max; ++ ++ /* Forward References */ ++ static u32 find_gcd(u32 min, u32 max); ++ static u32 compute_prediv( u32 divider, u32 min, u32 max); ++ static void get_val(u32 base_freq, u32 output_freq,u32 *multiplier, u32 *divider); ++ static u32 get_base_frequency(TNETD73XX_CLKC_ID_T clk_id); ++ static void find_approx(u32 *,u32 *,u32); ++ ++ /**************************************************************************** ++ * FUNCTION: tnetd73xx_clkc_init ++ **************************************************************************** ++ * Description: The routine initializes the internal variables depending on ++ * on the sources selected for different clocks. ++ ***************************************************************************/ ++void tnetd73xx_clkc_init(u32 afeclk, u32 refclk, u32 xtal3in) +{ -+ if (c >= '0' && c <= '9') -+ return c - '0'; -+ if (c >= 'a' && c <= 'f') -+ return c - 'a' + 10; -+ return 0; /* foo */ -+} + -+static inline void str2eaddr(unsigned char *ea, unsigned char *str) -+{ -+ int i; ++ u32 choice; + -+ for (i = 0; i < 6; i++) { -+ unsigned char num; ++ afeclk_inp = afeclk; ++ refclk_inp = refclk; ++ xtal_inp = xtal3in; + -+ if((*str == '.') || (*str == ':')) -+ str++; -+ num = str2hexnum(*str++) << 4; -+ num |= (str2hexnum(*str++)); -+ ea[i] = num; -+ } -+} ++ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & MIPS_PLL_SELECT; ++ switch(choice) ++ { ++ case MIPS_AFECLKI_SELECT: ++ clk_src[CLKC_MIPS] = &afeclk_inp; ++ break; + -+int get_ethernet_addr(char *ethernet_addr) -+{ -+ char *ethaddr_str; ++ case MIPS_REFCLKI_SELECT: ++ clk_src[CLKC_MIPS] = &refclk_inp; ++ break; ++ ++ case MIPS_XTAL3IN_SELECT: ++ clk_src[CLKC_MIPS] = &xtal_inp; ++ break; ++ ++ default : ++ clk_src[CLKC_MIPS] = 0; + -+ ethaddr_str = prom_getenv("ethaddr"); -+ if (!ethaddr_str) { -+ printk("ethaddr not set in boot prom\n"); -+ return -1; + } -+ str2eaddr(ethernet_addr, ethaddr_str); + -+ if (init_debug > 1) { -+ int i; -+ printk("get_ethernet_addr: "); -+ for (i=0; i<5; i++) -+ printk("%02x:", (unsigned char)*(ethernet_addr+i)); -+ printk("%02x\n", *(ethernet_addr+i)); ++ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & SYSTEM_PLL_SELECT; ++ switch(choice) ++ { ++ case SYSTEM_AFECLKI_SELECT: ++ clk_src[CLKC_SYS] = &afeclk_inp; ++ break; ++ ++ case SYSTEM_REFCLKI_SELECT: ++ clk_src[CLKC_SYS] = &refclk_inp; ++ break; ++ ++ case SYSTEM_XTAL3IN_SELECT: ++ clk_src[CLKC_SYS] = &xtal_inp; ++ break; ++ ++ case SYSTEM_MIPSPLL_SELECT: ++ clk_src[CLKC_SYS] = &mips_pll_out; ++ break; ++ ++ default : ++ clk_src[CLKC_SYS] = 0; ++ + } + -+ return 0; -+} + -+int __init prom_init(int argc, char **argv, char **envp) -+{ -+ int i; -+ t_env_var *env = (t_env_var *) envp; ++ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & ADSLSS_PLL_SELECT; ++ switch(choice) ++ { ++ case ADSLSS_AFECLKI_SELECT: ++ clk_src[CLKC_ADSLSS] = &afeclk_inp; ++ break; + -+ prom_argc = argc; -+ _prom_argv = (int *)argv; -+ _prom_envp = (int *)envp; ++ case ADSLSS_REFCLKI_SELECT: ++ clk_src[CLKC_ADSLSS] = &refclk_inp; ++ break; ++ ++ case ADSLSS_XTAL3IN_SELECT: ++ clk_src[CLKC_ADSLSS] = &xtal_inp; ++ break; ++ ++ case ADSLSS_MIPSPLL_SELECT: ++ clk_src[CLKC_ADSLSS] = &mips_pll_out; ++ break; ++ ++ default : ++ clk_src[CLKC_ADSLSS] = 0; + -+ /* Copy what we need locally so we are not dependent on -+ * bootloader RAM. In Adam2, the environment parameters -+ * are in flash but the table that references them is in -+ * RAM -+ */ -+ for(i=0; i < MAX_ENV_ENTRY; i++, env++) { -+ if (env->name) { -+ local_envp[i].name = env->name; -+ local_envp[i].val = env->val; -+ } else { -+ local_envp[i].name = NULL; -+ local_envp[i].val = NULL; -+ } + } + -+ set_io_port_base(0); + -+ prom_printf("\nLINUX started...\n"); -+ prom_init_cmdline(); -+ prom_meminit(); ++ choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & USB_PLL_SELECT; ++ switch(choice) ++ { ++ case USB_SYSPLL_SELECT: ++ clk_src[CLKC_USB] = &sys_pll_out ; ++ break; + -+ return 0; ++ case USB_REFCLKI_SELECT: ++ clk_src[CLKC_USB] = &refclk_inp; ++ break; ++ ++ case USB_XTAL3IN_SELECT: ++ clk_src[CLKC_USB] = &xtal_inp; ++ break; ++ ++ case USB_MIPSPLL_SELECT: ++ clk_src[CLKC_USB] = &mips_pll_out; ++ break; ++ ++ default : ++ clk_src[CLKC_USB] = 0; ++ ++ } +} + -+EXPORT_SYMBOL(prom_getenv); -diff -urN kernel-base/arch/mips/ar7/irq.c kernel-current/arch/mips/ar7/irq.c ---- kernel-base/arch/mips/ar7/irq.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/irq.c 2005-07-10 10:02:30.212171576 +0200 -@@ -0,0 +1,705 @@ -+/* -+ * Nitin Dhingra, iamnd@ti.com -+ * Copyright (C) 2002 Texas Instruments, Inc. All rights reserved. -+ * -+ * ######################################################################## -+ * -+ * This program is free software; you can distribute it and/or modify it -+ * under the terms of the GNU General Public License (Version 2) as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -+ * -+ * ######################################################################## -+ * -+ * Routines for generic manipulation of the interrupts found on the Texas -+ * Instruments avalanche board -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#define shutdown_avalanche_irq disable_avalanche_irq -+#define mask_and_ack_avalanche_irq disable_avalanche_irq -+ -+static unsigned int startup_avalanche_irq(unsigned int irq); -+static void end_avalanche_irq(unsigned int irq); -+void enable_avalanche_irq(unsigned int irq_nr); -+void disable_avalanche_irq(unsigned int irq_nr); -+ -+static struct hw_interrupt_type avalanche_irq_type = { -+ "TI AVALANCHE", -+ startup_avalanche_irq, -+ shutdown_avalanche_irq, -+ enable_avalanche_irq, -+ disable_avalanche_irq, -+ mask_and_ack_avalanche_irq, -+ end_avalanche_irq, -+ NULL -+}; + -+irq_desc_t irq_desc_ti[AVALANCHE_INT_END+1] __cacheline_aligned = -+{ [0 ... AVALANCHE_INT_END] = { 0, &avalanche_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; + ++/**************************************************************************** ++ * FUNCTION: tnetd73xx_clkc_set_freq ++ **************************************************************************** ++ * Description: The above routine is called to set the output_frequency of the ++ * selected clock(using clk_id) to the required value given ++ * by the variable output_freq. ++ ***************************************************************************/ ++TNETD73XX_ERR tnetd73xx_clkc_set_freq ++( ++ TNETD73XX_CLKC_ID_T clk_id, ++ u32 output_freq ++ ) ++{ ++ u32 base_freq; ++ u32 multiplier; ++ u32 divider; ++ u32 min_prediv; ++ u32 max_prediv; ++ u32 prediv; ++ u32 postdiv; ++ u32 temp; ++ ++ /* check if PLLs are bypassed*/ ++ if(REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_PLL_BYPASS) ++ { ++ return TNETD73XX_ERR_ERROR; ++ } + -+unsigned long spurious_count = 0; ++ /*check if the requested output_frequency is in valid range*/ ++ switch( clk_id ) ++ { ++ case CLKC_SYS: ++ if( output_freq < SYS_MIN || output_freq > SYS_MAX) ++ { ++ return TNETD73XX_ERR_ERROR; ++ } ++ present_min = SYS_MIN; ++ present_max = SYS_MAX; ++ break; + -+struct avalanche_ictrl_regs *avalanche_hw0_icregs; /* Interrupt control regs (primary) */ -+struct avalanche_exctrl_regs *avalanche_hw0_ecregs; /* Exception control regs (secondary) */ -+struct avalanche_ipace_regs *avalanche_hw0_ipaceregs; -+struct avalanche_channel_int_number *avalanche_hw0_chregs; /* Channel control registers */ ++ case CLKC_MIPS: ++ if((output_freq < MIPS_MIN) || ++ (output_freq > ((REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_MIPS_ASYNC_MODE) ? MIPS_ASYNC_MAX: MIPS_SYNC_MAX))) ++ { ++ return TNETD73XX_ERR_ERROR; ++ } ++ present_min = MIPS_MIN; ++ present_max = (REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_MIPS_ASYNC_MODE) ? MIPS_ASYNC_MAX: MIPS_SYNC_MAX; ++ break; + -+extern asmlinkage void mipsIRQ(void); ++ case CLKC_USB: ++ if( output_freq < USB_MIN || output_freq > USB_MAX) ++ { ++ return TNETD73XX_ERR_ERROR; ++ } ++ present_min = USB_MIN; ++ present_max = USB_MAX; ++ break; + ++ case CLKC_ADSLSS: ++ if( output_freq < ADSL_MIN || output_freq > ADSL_MAX) ++ { ++ return TNETD73XX_ERR_ERROR; ++ } ++ present_min = ADSL_MIN; ++ present_max = ADSL_MAX; ++ break; ++ } + -+/* -+ * The avalanche/MIPS interrupt line numbers are used to represent the -+ * interrupts within the irqaction arrays. The index notation is -+ * is as follows: -+ * -+ * 0-7 MIPS CPU Exceptions (HW/SW) -+ * 8-47 Primary Interrupts (Avalanche) -+ * 48-79 Secondary Interrupts (Avalanche) -+ * -+ */ + ++ base_freq = get_base_frequency(clk_id); + -+static struct irqaction *hw0_irq_action_primary[AVINTNUM(AVALANCHE_INT_END_PRIMARY)] = -+{ -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL -+}; + -+static struct irqaction *hw0_irq_action_secondary[AVINTNUM(AVALANCHE_INT_END_SECONDARY)] = -+{ -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL -+}; ++ /* check for minimum base frequency value */ ++ if( base_freq < MIN_PLL_INP_FREQ) ++ { ++ return TNETD73XX_ERR_ERROR; ++ } + -+/* -+ This remaps interrupts to exist on other channels than the default -+ channels. essentially we can use the line # as the index for this -+ array -+ */ ++ get_val(output_freq, base_freq, &multiplier, ÷r); + ++ /* check multiplier range */ ++ if( (multiplier > PLL_MUL_MAXFACTOR) || (multiplier <= 0) ) ++ { ++ return TNETD73XX_ERR_ERROR; ++ } + -+static unsigned long line_to_channel[AVINTNUM(AVALANCHE_INT_END_PRIMARY)]; -+unsigned long uni_secondary_interrupt = 0; ++ /* check divider value */ ++ if( divider == 0 ) ++ { ++ return TNETD73XX_ERR_ERROR; ++ } + -+static struct irqaction r4ktimer_action = { -+ NULL, 0, 0, "R4000 timer/counter", NULL, NULL, -+}; ++ /*compute minimum and maximum predivider values */ ++ min_prediv = MAX(base_freq / MAX_PLL_INP_FREQ + 1, divider / MAX_DIV_VALUE + 1); ++ max_prediv = MIN(base_freq / MIN_PLL_INP_FREQ, MAX_DIV_VALUE); + -+static struct irqaction *irq_action[8] = { -+ NULL, /* SW int 0 */ -+ NULL, /* SW int 1 */ -+ NULL, /* HW int 0 */ -+ NULL, -+ NULL, -+ NULL, /* HW int 3 */ -+ NULL, /* HW int 4 */ -+ &r4ktimer_action /* HW int 5 */ -+}; ++ /*adjust the value of divider so that it not less than minimum predivider value*/ ++ if (divider < min_prediv) ++ { ++ temp = CEIL(min_prediv, divider); ++ if ((temp * multiplier) > PLL_MUL_MAXFACTOR) ++ { ++ return TNETD73XX_ERR_ERROR ; ++ } ++ else ++ { ++ multiplier = temp * multiplier; ++ divider = min_prediv; ++ } + -+static void end_avalanche_irq(unsigned int irq) -+{ -+ if (!(irq_desc_ti[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) -+ enable_avalanche_irq(irq); -+} ++ } + -+void disable_avalanche_irq(unsigned int irq_nr) -+{ -+ unsigned long flags; -+ unsigned long chan_nr=0; -+ unsigned long int_bit=0; ++ /* compute predivider and postdivider values */ ++ prediv = compute_prediv (divider, min_prediv, max_prediv); ++ postdiv = CEIL(divider,prediv); + -+ if(irq_nr >= AVALANCHE_INT_END) ++ /*return fail if postdivider value falls out of range */ ++ if(postdiv > MAX_DIV_VALUE) + { -+ printk("whee, invalid irq_nr %d\n", irq_nr); -+ panic("IRQ, you lose..."); ++ return TNETD73XX_ERR_ERROR; + } + -+ save_and_cli(flags); + ++ /*write predivider and postdivider values*/ ++ /* pre-Divider and post-divider are 5 bit N+1 dividers */ ++ REG32_WRITE(CLKC_CLKCR(clk_id), ((postdiv -1) & 0x1F) << 16 | ((prediv -1) & 0x1F) ); + -+ if(irq_nr < MIPS_EXCEPTION_OFFSET) -+ { -+ /* disable mips exception */ ++ /*wait for divider output to stabilise*/ ++ for(temp =0; temp < DIVIDER_LOCK_TIME; temp++); + -+ int_bit = read_c0_status() & ~(1 << (8+irq_nr)); -+ change_c0_status(ST0_IM,int_bit); -+ restore_flags(flags); -+ return; ++ /*write to PLL clock register*/ ++ ++ if(clk_id == CLKC_SYS) ++ { ++ /* but before writing put DRAM to hold mode */ ++ REG32_DATA(TNETD73XX_EMIF_SDRAM_CFG) |= 0x80000000; + } ++ /*Bring PLL into div mode */ ++ REG32_WRITE(CLKC_CLKPLLCR(clk_id), 0x4); + -+ /* irq_nr represents the line number for the interrupt. We must -+ * disable the channel number associated with that line number. ++ /*compute the word to be written to PLLCR ++ *corresponding to multiplier value + */ ++ multiplier = (((multiplier - 1) & 0xf) << 12)| ((255 <<3) | 0x0e); + -+ if(irq_nr > AVALANCHE_INT_END_PRIMARY_REG2) -+ chan_nr = AVINTNUM(irq_nr); /*CHECK THIS ALSO*/ -+ else -+ chan_nr = line_to_channel[AVINTNUM(irq_nr)];/* WE NEED A LINE TO CHANNEL MAPPING FUNCTION HERE*/ -+ -+ /* disable the interrupt channel bit */ ++ /* wait till PLL enters div mode */ ++ while(REG32_DATA(CLKC_CLKPLLCR(clk_id)) & CLKC_PLL_STATUS) ++ /*nothing*/; + -+ /* primary interrupt #'s 0-31 */ ++ REG32_WRITE(CLKC_CLKPLLCR(clk_id), multiplier); + -+ if(chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1)) -+ avalanche_hw0_icregs->intecr1 = (1 << chan_nr); ++ while(!REG32_DATA(CLKC_CLKPLLCR(clk_id)) & CLKC_PLL_STATUS) ++ /*nothing*/; + -+ /* primary interrupt #'s 32-39 */ + -+ else if ((chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG2)) && -+ (chan_nr > AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1))) -+ avalanche_hw0_icregs->intecr2 = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_SECONDARY))); ++ /*wait for External pll to lock*/ ++ for(temp =0; temp < PLL_LOCK_TIME; temp++); + -+ else /* secondary interrupt #'s 0-31 */ -+ avalanche_hw0_ecregs->exiecr = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_PRIMARY))); ++ if(clk_id == CLKC_SYS) ++ { ++ /* Bring DRAM out of hold */ ++ REG32_DATA(TNETD73XX_EMIF_SDRAM_CFG) &= ~0x80000000; ++ } + -+ restore_flags(flags); ++ return TNETD73XX_ERR_OK ; +} + -+void enable_avalanche_irq(unsigned int irq_nr) ++/**************************************************************************** ++ * FUNCTION: tnetd73xx_clkc_get_freq ++ **************************************************************************** ++ * Description: The above routine is called to get the output_frequency of the ++ * selected clock( clk_id) ++ ***************************************************************************/ ++u32 tnetd73xx_clkc_get_freq ++( ++ TNETD73XX_CLKC_ID_T clk_id ++ ) +{ -+ unsigned long flags; -+ unsigned long chan_nr=0; -+ unsigned long int_bit=0; + -+ if(irq_nr > AVALANCHE_INT_END) { -+ printk("whee, invalid irq_nr %d\n", irq_nr); -+ panic("IRQ, you lose..."); -+ } ++ u32 clk_ctrl_register; ++ u32 clk_pll_setting; ++ u32 clk_predivider; ++ u32 clk_postdivider; ++ u16 pll_factor; ++ u32 base_freq; ++ u32 divider; + -+ save_and_cli(flags); ++ base_freq = get_base_frequency(clk_id); ++ ++ clk_ctrl_register = REG32_DATA(CLKC_CLKCR(clk_id)); + ++ /* pre-Divider and post-divider are 5 bit N+1 dividers */ ++ clk_predivider = (CLKC_PRE_DIVIDER & clk_ctrl_register) + 1; ++ clk_postdivider = ((CLKC_POST_DIVIDER & clk_ctrl_register) >> 16) + 1; + -+ if(irq_nr < MIPS_EXCEPTION_OFFSET) ++ divider = clk_predivider * clk_postdivider; ++ ++ ++ if( (REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_PLL_BYPASS)) + { -+ /* Enable MIPS exceptions */ -+ int_bit = read_c0_status(); -+ change_c0_status(ST0_IM,int_bit | (1<<(8+irq_nr))); -+ restore_flags(flags); -+ return; ++ return (CEIL(base_freq, divider)); /* PLLs bypassed.*/ + } + -+ /* irq_nr represents the line number for the interrupt. We must -+ * disable the channel number associated with that line number. -+ */ + -+ if(irq_nr > AVALANCHE_INT_END_PRIMARY_REG2) -+ chan_nr = AVINTNUM(irq_nr); + else -+ chan_nr = line_to_channel[AVINTNUM(irq_nr)]; ++ { ++ /* return the current clock speed based upon the PLL setting */ ++ clk_pll_setting = REG32_DATA(CLKC_CLKPLLCR(clk_id)); + -+ /* enable the interrupt channel bit */ ++ /* Get the PLL multiplication factor */ ++ pll_factor = ((clk_pll_setting & CLKC_PLL_FACTOR) >> 12) + 1; + -+ /* primary interrupt #'s 0-31 */ -+ if(chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1)) -+ avalanche_hw0_icregs->intesr1 = (1 << chan_nr); ++ /* Check if we're in divide mode or multiply mode */ ++ if((clk_pll_setting & 0x1) == 0) ++ { ++ /* We're in divide mode */ ++ if(pll_factor < 0x10) ++ return (CEIL(base_freq >> 1, divider)); ++ else ++ return (CEIL(base_freq >> 2, divider)); ++ } + -+ /* primary interrupt #'s 32 throuth 39 */ -+ else if ((chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG2)) && -+ (chan_nr > AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1))) -+ avalanche_hw0_icregs->intesr2 = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_SECONDARY))); ++ else /* We're in PLL mode */ ++ { ++ /* See if PLLNDIV & PLLDIV are set */ ++ if((clk_pll_setting & 0x0800) && (clk_pll_setting & 0x2)) ++ { ++ if(clk_pll_setting & 0x1000) ++ { ++ /* clk = base_freq * k/2 */ ++ return(CEIL((base_freq * pll_factor) >> 1, divider)); ++ } ++ else ++ { ++ /* clk = base_freq * (k-1) / 4)*/ ++ return(CEIL((base_freq * (pll_factor - 1)) >>2, divider)); ++ } ++ } ++ else ++ { ++ if(pll_factor < 0x10) ++ { ++ /* clk = base_freq * k */ ++ return(CEIL(base_freq * pll_factor, divider)); ++ } + -+ else /* secondary interrupt #'s 0-31 */ -+ avalanche_hw0_ecregs->exiesr = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_PRIMARY))); ++ else ++ { ++ /* clk = base_freq */ ++ return(CEIL(base_freq, divider)); ++ } ++ } ++ } ++ return(0); /* Should never reach here */ + -+ restore_flags(flags); -+} ++ } + -+static unsigned int startup_avalanche_irq(unsigned int irq) -+{ -+ enable_avalanche_irq(irq); -+ return 0; /* never anything pending */ +} + + -+int get_irq_list(char *buf) -+{ -+ int i, len = 0; -+ int num = 0; -+ struct irqaction *action; ++/* local helper functions */ + -+ for (i = 0; i < MIPS_EXCEPTION_OFFSET; i++, num++) ++/**************************************************************************** ++ * FUNCTION: get_base_frequency ++ **************************************************************************** ++ * Description: The above routine is called to get base frequency of the clocks. ++ ***************************************************************************/ ++ ++static u32 get_base_frequency(TNETD73XX_CLKC_ID_T clk_id) ++{ ++ /* update the current MIPs PLL output value, if the required ++ * source is MIPS PLL ++ */ ++ if ( clk_src[clk_id] == &mips_pll_out) + { -+ action = irq_action[i]; -+ if (!action) -+ continue; -+ len += sprintf(buf+len, "%2d: %8d %c %s", -+ num, kstat.irqs[0][num], -+ (action->flags & SA_INTERRUPT) ? '+' : ' ', -+ action->name); -+ for (action=action->next; action; action = action->next) { -+ len += sprintf(buf+len, ",%s %s", -+ (action->flags & SA_INTERRUPT) ? " +" : "", -+ action->name); -+ } -+ len += sprintf(buf+len, " [MIPS interrupt]\n"); ++ *clk_src[clk_id] = tnetd73xx_clkc_get_freq(CLKC_MIPS); + } + + -+ for (i = 0; i < AVINTNUM(AVALANCHE_INT_END); i++,num++) ++ /* update the current System PLL output value, if the required ++ * source is system PLL ++ */ ++ if ( clk_src[clk_id] == &sys_pll_out) + { -+ if(i < AVINTNUM(AVALANCHE_INT_END_PRIMARY)) -+ action = hw0_irq_action_primary[i]; -+ else -+ action = hw0_irq_action_secondary[i-AVINTNUM(AVALANCHE_INT_END_PRIMARY)]; -+ if (!action) -+ continue; -+ len += sprintf(buf+len, "%2d: %8d %c %s", -+ num, kstat.irqs[0][ LNXINTNUM(i) ], -+ (action->flags & SA_INTERRUPT) ? '+' : ' ', -+ action->name); -+ -+ for (action=action->next; action; action = action->next) -+ { -+ len += sprintf(buf+len, ",%s %s", -+ (action->flags & SA_INTERRUPT) ? " +" : "", -+ action->name); -+ } -+ -+ if(i < AVINTNUM(AVALANCHE_INT_END_PRIMARY)) -+ len += sprintf(buf+len, " [hw0 (Avalanche Primary)]\n"); -+ else -+ len += sprintf(buf+len, " [hw0 (Avalanche Secondary)]\n"); -+ ++ *clk_src[clk_id] = tnetd73xx_clkc_get_freq(CLKC_SYS); + } + -+ return len; -+} -+ -+int request_irq(unsigned int irq, -+ void (*handler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, -+ const char * devname, -+ void *dev_id) -+{ -+ struct irqaction *action; -+ -+ if (irq > AVALANCHE_INT_END) -+ return -EINVAL; -+ if (!handler) -+ return -EINVAL; ++ return (*clk_src[clk_id]); + -+ action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); -+ if(!action) -+ return -ENOMEM; ++} + -+ action->handler = handler; -+ action->flags = irqflags; -+ action->mask = 0; -+ action->name = devname; -+ irq_desc_ti[irq].action = action; -+ action->dev_id = dev_id; + -+ action->next = 0; + -+ if(irq < MIPS_EXCEPTION_OFFSET) ++/**************************************************************************** ++ * FUNCTION: find_gcd ++ **************************************************************************** ++ * Description: The above routine is called to find gcd of 2 numbers. ++ ***************************************************************************/ ++static u32 find_gcd ++( ++ u32 min, ++ u32 max ++ ) ++{ ++ if (max % min == 0) + { -+ irq_action[irq] = action; -+ enable_avalanche_irq(irq); -+ return 0; ++ return min; + } -+ -+ if(irq < AVALANCHE_INT_END_PRIMARY) -+ hw0_irq_action_primary[line_to_channel[AVINTNUM(irq)]] = action; + else -+ hw0_irq_action_secondary[irq - AVALANCHE_INT_END_PRIMARY] = action; -+ -+ enable_avalanche_irq(irq); -+ -+ return 0; ++ { ++ return find_gcd(max % min, min); ++ } +} + -+void free_irq(unsigned int irq, void *dev_id) ++/**************************************************************************** ++ * FUNCTION: compute_prediv ++ **************************************************************************** ++ * Description: The above routine is called to compute predivider value ++ ***************************************************************************/ ++static u32 compute_prediv(u32 divider, u32 min, u32 max) +{ -+ struct irqaction *action; ++ u16 prediv; + -+ if (irq > AVALANCHE_INT_END) { -+ printk("Trying to free IRQ%d\n",irq); -+ return; ++ /* return the divider itself it it falls within the range of predivider*/ ++ if (min <= divider && divider <= max) ++ { ++ return divider; + } + -+ if(irq < MIPS_EXCEPTION_OFFSET) ++ /* find a value for prediv such that it is a factor of divider */ ++ for (prediv = max; prediv >= min ; prediv--) + { -+ action = irq_action[irq]; -+ irq_action[irq] = NULL; -+ irq_desc_ti[irq].action = NULL; -+ disable_avalanche_irq(irq); -+ kfree(action); -+ return; ++ if ( (divider % prediv) == 0 ) ++ { ++ return prediv; ++ } + } + -+ if(irq < AVALANCHE_INT_END_PRIMARY) { -+ action = hw0_irq_action_primary[line_to_channel[AVINTNUM(irq)]]; -+ hw0_irq_action_primary[line_to_channel[AVINTNUM(irq)]] = NULL; -+ irq_desc_ti[irq].action = NULL; -+ } -+ else { -+ action = hw0_irq_action_secondary[irq - AVALANCHE_INT_END_PRIMARY]; -+ hw0_irq_action_secondary[irq - AVALANCHE_INT_END_PRIMARY] = NULL; -+ irq_desc_ti[irq].action = NULL; -+ } -+ -+ disable_avalanche_irq(irq); -+ kfree(action); ++ /* No such factor exists, return min as prediv */ ++ return min; +} + -+#ifdef CONFIG_KGDB -+extern void breakpoint(void); -+extern int remote_debug; -+#endif ++/**************************************************************************** ++ * FUNCTION: get_val ++ **************************************************************************** ++ * Description: This routine is called to get values of divider and multiplier. ++ ***************************************************************************/ + -+//void init_IRQ(void) __init; -+void __init init_IRQ(void) ++static void get_val(u32 output_freq, u32 base_freq,u32 *multiplier, u32 *divider) +{ -+ int i; -+ -+ avalanche_hw0_icregs = (struct avalanche_ictrl_regs *)AVALANCHE_ICTRL_REGS_BASE; -+ avalanche_hw0_ecregs = (struct avalanche_exctrl_regs *)AVALANCHE_ECTRL_REGS_BASE; -+ avalanche_hw0_ipaceregs = (struct avalanche_ipace_regs *)AVALANCHE_IPACE_REGS_BASE; -+ avalanche_hw0_chregs = (struct avalanche_channel_int_number *)AVALANCHE_CHCTRL_REGS_BASE; -+ -+ /* Disable interrupts and clear pending -+ */ -+ -+ avalanche_hw0_icregs->intecr1 = 0xffffffff; /* disable interrupts 0:31 */ -+ avalanche_hw0_icregs->intcr1 = 0xffffffff; /* clear interrupts 0:31 */ -+ avalanche_hw0_icregs->intecr2 = 0xff; /* disable interrupts 32:39 */ -+ avalanche_hw0_icregs->intcr2 = 0xff; /* clear interrupts 32:39 */ -+ avalanche_hw0_ecregs->exiecr = 0xffffffff; /* disable secondary interrupts 0:31 */ -+ avalanche_hw0_ecregs->excr = 0xffffffff; /* clear secondary interrupts 0:31 */ -+ ++ u32 temp_mul; ++ u32 temp_div; ++ u32 gcd; ++ u32 min_freq; ++ u32 max_freq; + -+ /* Channel to line mapping, Line to Channel mapping */ ++ /* find gcd of base_freq, output_freq */ ++ min_freq = (base_freq < output_freq) ? base_freq : output_freq; ++ max_freq = (base_freq > output_freq) ? base_freq : output_freq; ++ gcd = find_gcd(min_freq , max_freq); + -+ for(i = 0; i < 40; i++) -+ avalanche_int_set(i,i); ++ if(gcd == 0) ++ return; /* ERROR */ + -+ /* Now safe to set the exception vector. */ -+ set_except_vector(0, mipsIRQ); ++ /* compute values of multiplier and divider */ ++ temp_mul = output_freq / gcd; ++ temp_div = base_freq / gcd; + -+ /* Setup the IRQ description array. These will be mapped -+ * as flat interrupts numbers. The mapping is as follows -+ * -+ * 0-7 MIPS CPU Exceptions (HW/SW) -+ * 8-46 Primary Interrupts (Avalanche) -+ * 47-78 Secondary Interrupts (Avalanche) -+ */ + -+ for (i = 0; i <= AVALANCHE_INT_END; i++) ++ /* set multiplier such that 1 <= multiplier <= PLL_MUL_MAXFACTOR */ ++ if( temp_mul > PLL_MUL_MAXFACTOR ) + { -+ irq_desc_ti[i].status = IRQ_DISABLED; -+ irq_desc_ti[i].action = 0; -+ irq_desc_ti[i].depth = 1; -+ irq_desc_ti[i].handler = &avalanche_irq_type; -+ } ++ if((temp_mul / temp_div) > PLL_MUL_MAXFACTOR) ++ return; + -+#ifdef CONFIG_KGDB -+ if (remote_debug) -+ { -+ set_debug_traps(); -+ breakpoint(); ++ find_approx(&temp_mul,&temp_div,base_freq); + } -+#endif ++ ++ *multiplier = temp_mul; ++ *divider = temp_div; +} + ++/**************************************************************************** ++ * FUNCTION: find_approx ++ **************************************************************************** ++ * Description: This function gets the approx value of num/denom. ++ ***************************************************************************/ + -+void avalanche_hw0_irqdispatch(struct pt_regs *regs) ++static void find_approx(u32 *num,u32 *denom,u32 base_freq) +{ -+ struct irqaction *action; -+ int irq, cpu = smp_processor_id(); -+ unsigned long int_line_number,status; -+ int i,secondary = 0; -+ int chan_nr=0; -+ -+ int_line_number = ((avalanche_hw0_icregs->pintir >> 16) & 0x3F); -+ chan_nr = ((avalanche_hw0_icregs->pintir) & 0x3F); -+ -+ -+ if(chan_nr < 32) ++ u32 num1; ++ u32 denom1; ++ u32 num2; ++ u32 denom2; ++ int32_t closest; ++ int32_t prev_closest; ++ u32 temp_num; ++ u32 temp_denom; ++ u32 normalize; ++ u32 gcd; ++ u32 output_freq; ++ ++ num1 = *num; ++ denom1 = *denom; ++ ++ prev_closest = 0x7fffffff; /* maximum possible value */ ++ num2 = num1; ++ denom2 = denom1; ++ ++ /* start with max */ ++ for(temp_num = 15; temp_num >=1; temp_num--) + { -+ if( chan_nr != uni_secondary_interrupt) -+ avalanche_hw0_icregs->intcr1 = (1< 31)) -+ { -+ avalanche_hw0_icregs->intcr2 = (1<<(chan_nr-AVINTNUM(AVALANCHE_INT_END_SECONDARY))); -+ } -+ + -+ /* If the Priority Interrupt Index Register returns 40 then no -+ * interrupts are pending -+ */ -+ -+ if(chan_nr == 40) -+ return; ++ temp_denom = CEIL(temp_num * denom1, num1); ++ output_freq = (temp_num * base_freq) / temp_denom; + -+ if(chan_nr == uni_secondary_interrupt) -+ { -+ status = avalanche_hw0_ecregs->exsr; -+ for(i=0; i < AVINTNUM(AVALANCHE_INT_END_SECONDARY); i++) ++ if(temp_denom < 1) + { -+ if (status & 1< present_min && output_freq excr = 1 << i; -+ break; ++ prev_closest = closest; ++ num2 = temp_num; ++ denom2 = temp_denom; + } -+ } -+ irq = i; -+ secondary = 1; + -+ /* clear the universal secondary interrupt */ -+ avalanche_hw0_icregs->intcr1 = 1 << uni_secondary_interrupt; ++ } + + } -+ else -+ irq = chan_nr; + -+ /* Suraj Add code to clear secondary interrupt */ ++ gcd = find_gcd(num2,denom2); ++ num2 = num2 / gcd; ++ denom2 = denom2 /gcd; + -+ if(secondary) -+ action = hw0_irq_action_secondary[irq]; -+ else -+ action = hw0_irq_action_primary[irq]; ++ *num = num2; ++ *denom = denom2; ++} + -+ /* if action == NULL, then we don't have a handler for the irq */ + -+ if ( action == NULL ) { -+ printk("No handler for hw0 irq: %i\n", irq); -+ return; -+ } ++/***************************************************************************** ++ * GPIO Control ++ *****************************************************************************/ ++ ++/**************************************************************************** ++ * FUNCTION: tnetd73xx_gpio_init ++ ***************************************************************************/ ++void tnetd73xx_gpio_init() ++{ ++ /* Bring module out of reset */ ++ tnetd73xx_reset_ctrl(RESET_MODULE_GPIO, OUT_OF_RESET); ++ REG32_WRITE(TNETD73XX_GPIOENR, 0xFFFFFFFF); ++} + -+ irq_enter(cpu,irq); -+ if(secondary) ++/**************************************************************************** ++ * FUNCTION: tnetd73xx_gpio_ctrl ++ ***************************************************************************/ ++void tnetd73xx_gpio_ctrl(TNETD73XX_GPIO_PIN_T gpio_pin, ++ TNETD73XX_GPIO_PIN_MODE_T pin_mode, ++ TNETD73XX_GPIO_PIN_DIRECTION_T pin_direction) ++{ ++ u32 pin_status; ++ REG32_READ(TNETD73XX_GPIOENR, pin_status); ++ if (pin_mode == GPIO_PIN) + { -+ kstat.irqs[0][(irq + AVINTNUM(AVALANCHE_INT_END_PRIMARY)) + 8]++; -+ action->handler((irq + AVALANCHE_INT_END_PRIMARY), action->dev_id, regs); ++ pin_status |= (1 << gpio_pin); ++ REG32_WRITE(TNETD73XX_GPIOENR, pin_status); ++ ++ /* Set pin direction */ ++ REG32_READ(TNETD73XX_GPIOPDIRR, pin_status); ++ if (pin_direction == GPIO_INPUT_PIN) ++ { ++ pin_status |= (1 << gpio_pin); ++ } ++ else /* GPIO_OUTPUT_PIN */ ++ { ++ pin_status &= (~(1 << gpio_pin)); ++ } ++ REG32_WRITE(TNETD73XX_GPIOPDIRR, pin_status); + } -+ else ++ else /* FUNCTIONAL PIN */ + { -+ kstat.irqs[0][irq + 8]++; -+ action->handler(LNXINTNUM(irq), action->dev_id, regs); ++ pin_status &= (~(1 << gpio_pin)); ++ REG32_WRITE(TNETD73XX_GPIOENR, pin_status); + } + -+ irq_exit(cpu,irq); -+ -+ if(softirq_pending(cpu)) -+ do_softirq(); -+ -+ return; +} + -+void avalanche_int_set(int channel, int line) ++/**************************************************************************** ++ * FUNCTION: tnetd73xx_gpio_out ++ ***************************************************************************/ ++void tnetd73xx_gpio_out(TNETD73XX_GPIO_PIN_T gpio_pin, int value) +{ -+ switch(channel) ++ u32 pin_value; ++ ++ REG32_READ(TNETD73XX_GPIODOUTR, pin_value); ++ if (value == 1) + { -+ case(0): -+ avalanche_hw0_chregs->cintnr0 = line; -+ break; -+ case(1): -+ avalanche_hw0_chregs->cintnr1 = line; -+ break; -+ case(2): -+ avalanche_hw0_chregs->cintnr2 = line; -+ break; -+ case(3): -+ avalanche_hw0_chregs->cintnr3 = line; -+ break; -+ case(4): -+ avalanche_hw0_chregs->cintnr4 = line; -+ break; -+ case(5): -+ avalanche_hw0_chregs->cintnr5 = line; -+ break; -+ case(6): -+ avalanche_hw0_chregs->cintnr6 = line; -+ break; -+ case(7): -+ avalanche_hw0_chregs->cintnr7 = line; -+ break; -+ case(8): -+ avalanche_hw0_chregs->cintnr8 = line; -+ break; -+ case(9): -+ avalanche_hw0_chregs->cintnr9 = line; -+ break; -+ case(10): -+ avalanche_hw0_chregs->cintnr10 = line; -+ break; -+ case(11): -+ avalanche_hw0_chregs->cintnr11 = line; -+ break; -+ case(12): -+ avalanche_hw0_chregs->cintnr12 = line; -+ break; -+ case(13): -+ avalanche_hw0_chregs->cintnr13 = line; -+ break; -+ case(14): -+ avalanche_hw0_chregs->cintnr14 = line; -+ break; -+ case(15): -+ avalanche_hw0_chregs->cintnr15 = line; -+ break; -+ case(16): -+ avalanche_hw0_chregs->cintnr16 = line; -+ break; -+ case(17): -+ avalanche_hw0_chregs->cintnr17 = line; -+ break; -+ case(18): -+ avalanche_hw0_chregs->cintnr18 = line; -+ break; -+ case(19): -+ avalanche_hw0_chregs->cintnr19 = line; -+ break; -+ case(20): -+ avalanche_hw0_chregs->cintnr20 = line; -+ break; -+ case(21): -+ avalanche_hw0_chregs->cintnr21 = line; -+ break; -+ case(22): -+ avalanche_hw0_chregs->cintnr22 = line; -+ break; -+ case(23): -+ avalanche_hw0_chregs->cintnr23 = line; -+ break; -+ case(24): -+ avalanche_hw0_chregs->cintnr24 = line; -+ break; -+ case(25): -+ avalanche_hw0_chregs->cintnr25 = line; -+ break; -+ case(26): -+ avalanche_hw0_chregs->cintnr26 = line; -+ break; -+ case(27): -+ avalanche_hw0_chregs->cintnr27 = line; -+ break; -+ case(28): -+ avalanche_hw0_chregs->cintnr28 = line; -+ break; -+ case(29): -+ avalanche_hw0_chregs->cintnr29 = line; -+ break; -+ case(30): -+ avalanche_hw0_chregs->cintnr30 = line; -+ break; -+ case(31): -+ avalanche_hw0_chregs->cintnr31 = line; -+ break; -+ case(32): -+ avalanche_hw0_chregs->cintnr32 = line; -+ break; -+ case(33): -+ avalanche_hw0_chregs->cintnr33 = line; -+ break; -+ case(34): -+ avalanche_hw0_chregs->cintnr34 = line; -+ break; -+ case(35): -+ avalanche_hw0_chregs->cintnr35 = line; -+ break; -+ case(36): -+ avalanche_hw0_chregs->cintnr36 = line; -+ break; -+ case(37): -+ avalanche_hw0_chregs->cintnr37 = line; -+ break; -+ case(38): -+ avalanche_hw0_chregs->cintnr38 = line; -+ break; -+ case(39): -+ avalanche_hw0_chregs->cintnr39 = line; -+ break; -+ default: -+ printk("Error: Unknown Avalanche interrupt channel\n"); ++ pin_value |= (1 << gpio_pin); + } -+ -+ line_to_channel[line] = channel; /* Suraj check */ -+ -+ if (channel == UNIFIED_SECONDARY_INTERRUPT) -+ uni_secondary_interrupt = line; -+ ++ else ++ { ++ pin_value &= (~(1 << gpio_pin)); ++ } ++ REG32_WRITE(TNETD73XX_GPIODOUTR, pin_value); +} + -+ -+#define AVALANCHE_MAX_PACING_BLK 3 -+#define AVALANCHE_PACING_LOW_VAL 2 -+#define AVALANCHE_PACING_HIGH_VAL 63 -+ -+int avalanche_request_pacing(int irq_nr, unsigned int blk_num, -+ unsigned int pace_value) ++/**************************************************************************** ++ * FUNCTION: tnetd73xx_gpio_in ++ ***************************************************************************/ ++int tnetd73xx_gpio_in(TNETD73XX_GPIO_PIN_T gpio_pin) +{ -+ unsigned int blk_offset; -+ unsigned long flags; -+ -+ if(irq_nr < MIPS_EXCEPTION_OFFSET && -+ irq_nr >= AVALANCHE_INT_END_PRIMARY) -+ return (0); -+ -+ if(blk_num > AVALANCHE_MAX_PACING_BLK) -+ return(-1); -+ -+ if(pace_value > AVALANCHE_PACING_HIGH_VAL && -+ pace_value < AVALANCHE_PACING_LOW_VAL) -+ return(-1); -+ -+ blk_offset = blk_num*8; ++ u32 pin_value; ++ REG32_READ(TNETD73XX_GPIODINR, pin_value); ++ return ( (pin_value & (1 << gpio_pin)) ? 1 : 0 ); ++} + -+ save_and_cli(flags); +diff -urN linux.old/arch/mips/config-shared.in linux.dev/arch/mips/config-shared.in +--- linux.old/arch/mips/config-shared.in 2005-10-21 16:43:18.917114000 +0200 ++++ linux.dev/arch/mips/config-shared.in 2005-11-10 01:12:43.950955750 +0100 +@@ -20,6 +20,16 @@ + mainmenu_option next_comment + comment 'Machine selection' + dep_bool 'Support for Acer PICA 1 chipset (EXPERIMENTAL)' CONFIG_ACER_PICA_61 $CONFIG_EXPERIMENTAL ++dep_bool 'Support for Texas Instruments AR7 (EXPERIMENTAL)' CONFIG_AR7 $CONFIG_MIPS32 $CONFIG_EXPERIMENTAL ++if [ "$CONFIG_AR7" = "y" ]; then ++ choice 'Texas Instruments Reference Platform' \ ++ "AR7DB CONFIG_AR7DB \ ++ AR7RD CONFIG_AR7RD \ ++ AR7WRD CONFIG_AR7WRD" AR7DB ++ int 'Texas Instruments AR7 CPU Frequency' CONFIG_AR7_CPU 150 ++ int 'Texas Instruments AR7 System Frequency' CONFIG_AR7_SYS 125 ++ hex 'Texas Instruments AR7 SDRAM Start' CONFIG_AR7_MEMORY 0x14000000 ++fi + dep_bool 'Support for Alchemy Bosporus board' CONFIG_MIPS_BOSPORUS $CONFIG_MIPS32 + dep_bool 'Support for FIC Multimedia Player board' CONFIG_MIPS_FICMMP $CONFIG_MIPS32 + dep_bool 'Support for Alchemy Mirage board' CONFIG_MIPS_MIRAGE $CONFIG_MIPS32 +@@ -239,6 +249,11 @@ + define_bool CONFIG_NONCOHERENT_IO y + define_bool CONFIG_PC_KEYB y + fi ++if [ "$CONFIG_AR7" = "y" ]; then ++ define_bool CONFIG_IRQ_CPU y ++ define_bool CONFIG_NONCOHERENT_IO y ++ define_bool CONFIG_SWAP_IO_SPACE y ++fi + if [ "$CONFIG_CASIO_E55" = "y" ]; then + define_bool CONFIG_IRQ_CPU y + define_bool CONFIG_NONCOHERENT_IO y +@@ -736,6 +751,7 @@ + mainmenu_option next_comment + comment 'General setup' + if [ "$CONFIG_ACER_PICA_61" = "y" -o \ ++ "$CONFIG_AR7" = "y" -o \ + "$CONFIG_CASIO_E55" = "y" -o \ + "$CONFIG_DDB5074" = "y" -o \ + "$CONFIG_DDB5476" = "y" -o \ +@@ -797,6 +813,7 @@ + bool 'Networking support' CONFIG_NET + + if [ "$CONFIG_ACER_PICA_61" = "y" -o \ ++ "$CONFIG_AR7" = "y" -o \ + "$CONFIG_CASIO_E55" = "y" -o \ + "$CONFIG_DECSTATION" = "y" -o \ + "$CONFIG_IBM_WORKPAD" = "y" -o \ +diff -urN linux.old/arch/mips/kernel/head.S linux.dev/arch/mips/kernel/head.S +--- linux.old/arch/mips/kernel/head.S 2005-10-21 16:43:16.396956500 +0200 ++++ linux.dev/arch/mips/kernel/head.S 2005-11-10 01:10:45.807572250 +0100 +@@ -75,11 +75,11 @@ + * size! + */ + NESTED(except_vec4, 0, sp) +- .set push +- .set noreorder +-1: j 1b /* Dummy, will be replaced */ +- nop +- .set pop ++ .set mips2 ++ lui k0, 0x9400 ++ ori k0, 0x200 ++ jr k0 ++ nop + END(except_vec4) + + /* +diff -urN linux.old/arch/mips/kernel/mips_ksyms.c linux.dev/arch/mips/kernel/mips_ksyms.c +--- linux.old/arch/mips/kernel/mips_ksyms.c 2004-02-18 14:36:30.000000000 +0100 ++++ linux.dev/arch/mips/kernel/mips_ksyms.c 2005-11-10 01:10:45.811572500 +0100 +@@ -40,6 +40,12 @@ + extern long __strnlen_user_nocheck_asm(const char *s); + extern long __strnlen_user_asm(const char *s); + ++#ifdef CONFIG_AR7 ++#include ++int avalanche_request_pacing(int irq_nr, unsigned int blk_num, unsigned int pace_value); ++#endif + -+ /* disable the interrupt pacing, if enabled previously */ -+ avalanche_hw0_ipaceregs->ipacemax &= ~(0xff << blk_offset); + -+ /* clear the pacing map */ -+ avalanche_hw0_ipaceregs->ipacemap &= ~(0xff << blk_offset); + EXPORT_SYMBOL(mips_machtype); + #ifdef CONFIG_EISA + EXPORT_SYMBOL(EISA_bus); +@@ -103,3 +109,10 @@ + #endif + + EXPORT_SYMBOL(get_wchan); + -+ /* setup the new values */ -+ avalanche_hw0_ipaceregs->ipacemap |= ((AVINTNUM(irq_nr)) << blk_offset); -+ avalanche_hw0_ipaceregs->ipacemax |= ((0x80 | pace_value) << blk_offset); ++#ifdef CONFIG_AR7 ++EXPORT_SYMBOL_NOVERS(avalanche_request_pacing); ++EXPORT_SYMBOL_NOVERS(prom_getenv); ++EXPORT_SYMBOL_NOVERS(prom_iterenv); ++#endif + -+ restore_flags(flags); +diff -urN linux.old/arch/mips/kernel/setup.c linux.dev/arch/mips/kernel/setup.c +--- linux.old/arch/mips/kernel/setup.c 2005-10-21 16:43:16.396956500 +0200 ++++ linux.dev/arch/mips/kernel/setup.c 2005-11-10 01:14:16.376732000 +0100 +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + struct cpuinfo_mips cpu_data[NR_CPUS]; + EXPORT_SYMBOL(cpu_data); +@@ -88,7 +89,7 @@ + struct boot_mem_map boot_mem_map; + + unsigned char aux_device_present; +-extern char _ftext, _etext, _fdata, _edata, _end; ++extern char _ftext, _etext, _fdata, _edata, _fbss, _end; + + static char command_line[CL_SIZE]; + char saved_command_line[CL_SIZE]; +@@ -116,6 +117,7 @@ + + static struct resource code_resource = { "Kernel code" }; + static struct resource data_resource = { "Kernel data" }; ++static struct resource bss_resource = { "Kernel bss" }; + + asmlinkage void __init + init_arch(int argc, char **argv, char **envp, int *prom_vec) +@@ -272,7 +274,7 @@ + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long start, end; + +- if (boot_mem_map.map[i].type != BOOT_MEM_RAM) ++ if (boot_mem_map.map[i].type == BOOT_MEM_RESERVED) + continue; + + start = PFN_UP(boot_mem_map.map[i].addr); +@@ -320,7 +322,8 @@ + #endif + + /* Initialize the boot-time allocator with low memory only. */ +- bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn); ++ bootmap_size = init_bootmem_node(NODE_DATA(0), first_usable_pfn, ++ PFN_UP(PHYS_OFFSET), max_low_pfn); + + /* + * Register fully available low RAM pages with the bootmem allocator. +@@ -371,11 +374,12 @@ + continue; + + /* Register lowmem ranges */ +- free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); ++ free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn), ++ size< 0x0fffffff) { /* maximum for single J instruction */ ++ /* lui k0, 0x0000 */ ++ *(volatile u32 *)(KSEG0+0x200) = 0x3c1a0000 | (handler >> 16); ++ /* ori k0, 0x0000 */ ++ *(volatile u32 *)(KSEG0+0x204) = 0x375a0000 | (handler & 0xffff); ++ /* jr k0 */ ++ *(volatile u32 *)(KSEG0+0x208) = 0x03400008; ++ /* nop */ ++ *(volatile u32 *)(KSEG0+0x20C) = 0x00000000; ++ flush_icache_range(KSEG0+0x200, KSEG0+0x210); ++ } else { + *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | + (0x03ffffff & (handler >> 2)); +- flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); ++ flush_icache_range(KSEG0+0x200, KSEG0+0x204); ++ } + } + return (void *)old_handler; + } +diff -urN linux.old/arch/mips/mm/init.c linux.dev/arch/mips/mm/init.c +--- linux.old/arch/mips/mm/init.c 2004-02-18 14:36:30.000000000 +0100 ++++ linux.dev/arch/mips/mm/init.c 2005-11-10 01:14:16.376732000 +0100 +@@ -235,10 +235,13 @@ + #endif + } + ++#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT) ++#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) + -+ return(0); -+} -diff -urN kernel-base/arch/mips/ar7/Makefile kernel-current/arch/mips/ar7/Makefile ---- kernel-base/arch/mips/ar7/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/Makefile 2005-07-10 08:23:55.081408136 +0200 -@@ -0,0 +1,29 @@ -+# $Id$ -+# Copyright (C) $Date$ $Author$ -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. + void __init paging_init(void) + { + unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; +- unsigned long max_dma, high, low; ++ unsigned long max_dma, high, low, start; + + pagetable_init(); + +@@ -247,7 +250,8 @@ + #endif + + max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; +- low = max_low_pfn; ++ start = START_PFN; ++ low = MAX_LOW_PFN - start; + high = highend_pfn; + + #ifdef CONFIG_ISA +@@ -270,7 +274,8 @@ + zones_size[ZONE_HIGHMEM] = high - low; + #endif + +- free_area_init(zones_size); ++ free_area_init_node(0, NODE_DATA(0), 0, zones_size, ++ start << PAGE_SHIFT, 0); + } + + #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) +@@ -283,7 +288,7 @@ + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long addr, end; + +- if (boot_mem_map.map[i].type != BOOT_MEM_RAM) ++ if (boot_mem_map.map[i].type == BOOT_MEM_RESERVED) + /* not usable memory */ + continue; + +@@ -313,16 +318,17 @@ + max_mapnr = num_physpages = highend_pfn; + num_mappedpages = max_low_pfn; + #else +- max_mapnr = num_mappedpages = num_physpages = max_low_pfn; ++ max_mapnr = num_mappedpages = num_physpages = MAX_LOW_PFN - START_PFN; + #endif +- high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); +- +- totalram_pages += free_all_bootmem(); ++ ++ high_memory = (void *) __va(MAX_LOW_PFN * PAGE_SIZE); ++ ++ totalram_pages += free_all_bootmem_node(NODE_DATA(0)); + totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ + + reservedpages = ram = 0; +- for (tmp = 0; tmp < max_low_pfn; tmp++) +- if (page_is_ram(tmp)) { ++ for (tmp = 0; tmp < max_mapnr; tmp++) ++ if (page_is_ram(START_PFN + tmp)) { + ram++; + if (PageReserved(mem_map+tmp)) + reservedpages++; +@@ -377,13 +383,13 @@ + #endif + + extern char __init_begin, __init_end; +-extern void prom_free_prom_memory(void) __init; ++extern unsigned long prom_free_prom_memory(void) __init; + + void free_initmem(void) + { + unsigned long addr; + +- prom_free_prom_memory (); ++ totalram_pages += prom_free_prom_memory (); + + addr = (unsigned long) &__init_begin; + while (addr < (unsigned long) &__init_end) { +diff -urN linux.old/drivers/char/Config.in linux.dev/drivers/char/Config.in +--- linux.old/drivers/char/Config.in 2005-10-21 16:43:16.440959250 +0200 ++++ linux.dev/drivers/char/Config.in 2005-11-10 01:10:45.843574500 +0100 +@@ -188,6 +188,14 @@ + tristate 'Total Impact briQ front panel driver' CONFIG_BRIQ_PANEL + fi + ++if [ "$CONFIG_AR7" = "y" ]; then ++ bool 'VLYNQ support for the TI SOC' CONFIG_AR7_VLYNQ ++ dep_bool 'VLYNQ clock source Internal' CONFIG_VLYNQ_CLK_LOCAL $CONFIG_AR7_VLYNQ ++ ++ define_int CONFIG_AR7_VLYNQ_PORTS 2 ++ tristate 'ADAM2 environment support (read-only)' CONFIG_AR7_ADAM2 ++fi ++ + source drivers/i2c/Config.in + + mainmenu_option next_comment +diff -urN linux.old/drivers/char/Config.in.orig linux.dev/drivers/char/Config.in.orig +--- linux.old/drivers/char/Config.in.orig 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/char/Config.in.orig 2005-11-10 01:10:45.863575750 +0100 +@@ -0,0 +1,414 @@ +# -+# This program is distributed in the hope that 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. ++# Character device configuration +# -+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++mainmenu_option next_comment ++comment 'Character devices' ++ ++bool 'Virtual terminal' CONFIG_VT ++if [ "$CONFIG_VT" = "y" ]; then ++ bool ' Support for console on virtual terminal' CONFIG_VT_CONSOLE ++ if [ "$CONFIG_GSC_LASI" = "y" ]; then ++ bool ' Support for Lasi/Dino PS2 port' CONFIG_GSC_PS2 ++ fi ++fi ++tristate 'Standard/generic (8250/16550 and compatible UARTs) serial support' CONFIG_SERIAL ++if [ "$CONFIG_SERIAL" = "y" ]; then ++ bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE ++ if [ "$CONFIG_GSC_LASI" = "y" ]; then ++ bool ' serial port on GSC support' CONFIG_SERIAL_GSC ++ fi ++ if [ "$CONFIG_IA64" = "y" ]; then ++ bool ' Support for serial port described by EFI HCDP table' CONFIG_SERIAL_HCDP ++ fi ++ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then ++ tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL ++ tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL ++ fi ++fi ++dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL ++if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then ++ bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS ++ bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ ++ bool ' Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_DETECT_IRQ ++ bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT ++ bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6 ++fi ++bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD ++if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then ++ tristate ' Computone IntelliPort Plus serial support' CONFIG_COMPUTONE ++ tristate ' Comtrol Rocketport support' CONFIG_ROCKETPORT ++ tristate ' Cyclades async mux support' CONFIG_CYCLADES ++ if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CYCLADES" != "n" ]; then ++ bool ' Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR ++ fi ++ if [ "$CONFIG_X86_64" != "y" ]; then ++ tristate ' Digiboard Intelligent Async Support' CONFIG_DIGIEPCA ++ if [ "$CONFIG_DIGIEPCA" = "n" ]; then ++ tristate ' Digiboard PC/Xx Support' CONFIG_DIGI ++ fi ++ fi ++ dep_tristate ' Hayes ESP serial port support' CONFIG_ESPSERIAL $CONFIG_ISA ++ tristate ' Moxa Intellio support' CONFIG_MOXA_INTELLIO ++ tristate ' Moxa SmartIO support' CONFIG_MOXA_SMARTIO ++ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then ++ dep_tristate ' Multi-Tech multiport card support (EXPERIMENTAL)' CONFIG_ISI m ++ fi ++ tristate ' Microgate SyncLink card support' CONFIG_SYNCLINK ++ tristate ' SyncLink Multiport support' CONFIG_SYNCLINKMP ++ tristate ' HDLC line discipline support' CONFIG_N_HDLC ++ tristate ' SDL RISCom/8 card support' CONFIG_RISCOM8 ++ if [ "$CONFIG_X86_64" != "y" ]; then ++ tristate ' Specialix IO8+ card support' CONFIG_SPECIALIX ++ if [ "$CONFIG_SPECIALIX" != "n" ]; then ++ bool ' Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS ++ fi ++ tristate ' Specialix SX (and SI) card support' CONFIG_SX ++ tristate ' Specialix RIO system support' CONFIG_RIO ++ if [ "$CONFIG_RIO" != "n" ]; then ++ bool ' Support really old RIO/PCI cards' CONFIG_RIO_OLDPCI ++ fi ++ fi ++ bool ' Stallion multiport serial support' CONFIG_STALDRV ++ if [ "$CONFIG_STALDRV" = "y" ]; then ++ tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION ++ tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION ++ fi ++ if [ "$CONFIG_PARISC" = "y" ]; then ++ if [ "$CONFIG_PDC_CONSOLE" != "y" ]; then ++ bool ' Serial MUX support' CONFIG_SERIAL_MUX CONFIG_SERIAL_NONSTANDARD ++ fi ++ if [ "$CONFIG_SERIAL_MUX" != "y" ]; then ++ bool ' PDC software console support' CONFIG_PDC_CONSOLE CONFIG_SERIAL_NONSTANDARD ++ fi ++ fi ++ if [ "$CONFIG_MIPS" = "y" ]; then ++ bool ' TX3912/PR31700 serial port support' CONFIG_SERIAL_TX3912 ++ dep_bool ' Console on TX3912/PR31700 serial port' CONFIG_SERIAL_TX3912_CONSOLE $CONFIG_SERIAL_TX3912 ++ bool ' TMPTX39XX/49XX serial port support' CONFIG_SERIAL_TXX9 ++ dep_bool ' Console on TMPTX39XX/49XX serial port' CONFIG_SERIAL_TXX9_CONSOLE $CONFIG_SERIAL_TXX9 ++ if [ "$CONFIG_SOC_AU1X00" = "y" ]; then ++ bool ' Enable Au1x00 UART Support' CONFIG_AU1X00_UART ++ if [ "$CONFIG_AU1X00_UART" = "y" ]; then ++ bool ' Enable Au1x00 serial console' CONFIG_AU1X00_SERIAL_CONSOLE ++ fi ++ dep_tristate ' Au1x00 USB TTY Device support' CONFIG_AU1X00_USB_TTY $CONFIG_SOC_AU1X00 ++ if [ "$CONFIG_AU1000_USB_TTY" != "y" ]; then ++ dep_tristate ' Au1x00 USB Raw Device support' CONFIG_AU1X00_USB_RAW $CONFIG_SOC_AU1X00 ++ fi ++ if [ "$CONFIG_AU1X00_USB_TTY" != "n" -o \ ++ "$CONFIG_AU1X00_USB_RAW" != "n" ]; then ++ define_bool CONFIG_AU1X00_USB_DEVICE y ++ fi ++ fi ++ bool ' TXx927 SIO support' CONFIG_TXX927_SERIAL ++ if [ "$CONFIG_TXX927_SERIAL" = "y" ]; then ++ bool ' TXx927 SIO Console support' CONFIG_TXX927_SERIAL_CONSOLE ++ fi ++ if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then ++ bool ' Support for BCM1xxx onchip DUART' CONFIG_SIBYTE_SB1250_DUART ++ if [ "$CONFIG_SIBYTE_SB1250_DUART" = "y" ]; then ++ bool ' Console on BCM1xxx DUART' CONFIG_SIBYTE_SB1250_DUART_CONSOLE ++ if [ "$CONFIG_SIBYTE_SB1250_DUART_CONSOLE" = "y" ]; then ++ define_bool CONFIG_SERIAL_CONSOLE y ++ fi ++ fi ++ fi ++ fi ++ if [ "$CONFIG_DECSTATION" = "y" ]; then ++ bool ' DECstation serial support' CONFIG_SERIAL_DEC ++ dep_bool ' Support for console on a DECstation serial port' CONFIG_SERIAL_DEC_CONSOLE $CONFIG_SERIAL_DEC ++ dep_bool ' DZ11 serial support' CONFIG_DZ $CONFIG_SERIAL_DEC $CONFIG_MIPS32 ++ dep_bool ' Z85C30 serial support' CONFIG_ZS $CONFIG_SERIAL_DEC $CONFIG_TC ++ fi ++ if [ "$CONFIG_SGI_IP22" = "y" ]; then ++ bool ' SGI Zilog85C30 serial support' CONFIG_IP22_SERIAL ++ fi ++ if [ "$CONFIG_IA64" = "y" ]; then ++ bool ' SGI SN2 l1 serial port support' CONFIG_SGI_L1_SERIAL ++ if [ "$CONFIG_SGI_L1_SERIAL" = "y" ]; then ++ bool ' SGI SN2 l1 Console support' CONFIG_SGI_L1_SERIAL_CONSOLE ++ fi ++ if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ]; then ++ bool ' SGI SN2 IOC4 serial port support' CONFIG_SGI_IOC4_SERIAL ++ fi ++ fi ++fi ++if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then ++ tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232 ++fi ++if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then ++ bool 'DC21285 serial port support' CONFIG_SERIAL_21285 ++ if [ "$CONFIG_SERIAL_21285" = "y" ]; then ++ if [ "$CONFIG_OBSOLETE" = "y" ]; then ++ bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD ++ fi ++ bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE ++ fi ++ if [ "$CONFIG_PARISC" = "y" ]; then ++ bool ' PDC software console support' CONFIG_PDC_CONSOLE ++ fi ++fi ++if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then ++ bool 'Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD ++ if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then ++ define_bool CONFIG_IT8172_CIR y ++ else ++ bool ' Enable PS2 Keyboard Support' CONFIG_PC_KEYB ++ fi ++ bool 'Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0 ++ bool 'Enable Smart Card Reader 1 Support ' CONFIG_IT8172_SCR1 ++fi ++if [ "$CONFIG_MIPS_IVR" = "y" ]; then ++ bool 'Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD ++ if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then ++ define_bool CONFIG_IT8172_CIR y ++ fi ++ bool 'Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0 ++fi ++if [ "$CONFIG_CPU_VR41XX" = "y" ]; then ++ bool 'NEC VR4100 series Keyboard Interface Unit Support ' CONFIG_VR41XX_KIU ++fi ++bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS ++if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then ++ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 ++fi ++if [ "$CONFIG_PARPORT" != "n" ]; then ++ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT ++ if [ "$CONFIG_PRINTER" != "n" ]; then ++ bool ' Support for console on line printer' CONFIG_LP_CONSOLE ++ fi ++ dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT ++ dep_tristate 'Texas Instruments parallel link cable support' CONFIG_TIPAR $CONFIG_PARPORT ++fi + -+.S.s: -+ $(CPP) $(AFLAGS) $< -o $*.s ++if [ "$CONFIG_PPC64" = "y" ] ; then ++ bool 'pSeries Hypervisor Virtual Console support' CONFIG_HVC_CONSOLE ++fi ++if [ "$CONFIG_ALL_PPC" = "y" ]; then ++ tristate 'Total Impact briQ front panel driver' CONFIG_BRIQ_PANEL ++fi + -+.S.o: -+ $(CC) $(AFLAGS) -c $< -o $*.o ++if [ "$CONFIG_AR7" = "y" ]; then ++ bool 'VLYNQ support for the TI SOC' CONFIG_AR7_VLYNQ ++ dep_bool 'VLYNQ clock source Internal' CONFIG_VLYNQ_CLK_LOCAL $CONFIG_AR7_VLYNQ ++ ++ define_int CONFIG_AR7_VLYNQ_PORTS 2 ++fi ++ ++source drivers/i2c/Config.in ++ ++mainmenu_option next_comment ++comment 'Mice' ++tristate 'Bus Mouse Support' CONFIG_BUSMOUSE ++if [ "$CONFIG_BUSMOUSE" != "n" ]; then ++ dep_tristate ' ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE ++ dep_tristate ' Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE ++ dep_tristate ' Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE ++ if [ "$CONFIG_ADB" = "y" -a "$CONFIG_ADB_KEYBOARD" = "y" ]; then ++ dep_tristate ' Apple Desktop Bus mouse support (old driver)' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE ++ fi ++# if [ "$CONFIG_DECSTATION" = "y" ]; then ++# dep_bool ' MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE $CONFIG_ACCESSBUS ++# fi ++fi + -+O_TARGET := ar7.o ++tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE ++if [ "$CONFIG_MOUSE" != "n" ]; then ++ bool ' PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE ++ tristate ' C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE ++ tristate ' PC110 digitizer pad support' CONFIG_PC110_PAD ++ tristate ' MK712 touch screen support' CONFIG_MK712_MOUSE ++fi ++endmenu ++ ++source drivers/char/joystick/Config.in ++ ++tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE ++if [ "$CONFIG_QIC02_TAPE" != "n" ]; then ++ bool ' Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF ++ if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then ++ comment ' Edit configuration parameters in ./include/linux/tpqic02.h!' ++ else ++ comment ' Setting runtime QIC-02 configuration is done with qic02conf' ++ comment ' from the tpqic02-support package. It is available at' ++ comment ' metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/' ++ fi ++fi + -+export-objs := init.o irq.o -+obj-y := setup.o irq.o mipsIRQ.o reset.o init.o memory.o printf.o cmdline.o time.o ++tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER ++dep_mbool ' Generate a panic event to all BMCs on a panic' CONFIG_IPMI_PANIC_EVENT $CONFIG_IPMI_HANDLER ++dep_tristate ' Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER ++dep_tristate ' IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER ++dep_tristate ' IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER ++ ++mainmenu_option next_comment ++comment 'Watchdog Cards' ++bool 'Watchdog Timer Support' CONFIG_WATCHDOG ++if [ "$CONFIG_WATCHDOG" != "n" ]; then ++ bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT ++ tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT ++ tristate ' Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT ++ tristate ' ALi M7101 PMU on ALi 1535D+ Watchdog Timer' CONFIG_ALIM1535_WDT ++ tristate ' ALi M7101 PMU Watchdog Timer' CONFIG_ALIM7101_WDT ++ tristate ' AMD "Elan" SC520 Watchdog Timer' CONFIG_SC520_WDT ++ tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG ++ if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then ++ tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG ++ if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then ++ tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG ++ fi ++ fi ++ tristate ' Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT ++ tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT ++ tristate ' ICP ELectronics Wafer 5823 Watchdog' CONFIG_WAFER_WDT ++ tristate ' Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO ++ tristate ' Mixcom Watchdog' CONFIG_MIXCOMWD ++ tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT ++ dep_tristate ' SC1200 Watchdog Timer (EXPERIMENTAL)' CONFIG_SC1200_WDT $CONFIG_EXPERIMENTAL ++ tristate ' NatSemi SCx200 Watchdog' CONFIG_SCx200_WDT ++ tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG ++ tristate ' W83877F (EMACS) Watchdog Timer' CONFIG_W83877F_WDT ++ tristate ' WDT Watchdog timer' CONFIG_WDT ++ tristate ' WDT PCI Watchdog timer' CONFIG_WDTPCI ++ if [ "$CONFIG_WDT" != "n" ]; then ++ bool ' WDT501 features' CONFIG_WDT_501 ++ if [ "$CONFIG_WDT_501" = "y" ]; then ++ bool ' Fan Tachometer' CONFIG_WDT_501_FAN ++ fi ++ fi ++ tristate ' ZF MachZ Watchdog' CONFIG_MACHZ_WDT ++ if [ "$CONFIG_SGI_IP22" = "y" ]; then ++ dep_tristate ' Indy/I2 Hardware Watchdog' CONFIG_INDYDOG $CONFIG_SGI_IP22 ++ fi ++ if [ "$CONFIG_8xx" = "y" ]; then ++ tristate ' MPC8xx Watchdog Timer' CONFIG_8xx_WDT ++ fi ++fi ++endmenu ++ ++if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then ++ tristate 'NetWinder thermometer support' CONFIG_DS1620 ++ tristate 'NetWinder Button' CONFIG_NWBUTTON ++ if [ "$CONFIG_NWBUTTON" != "n" ]; then ++ bool ' Reboot Using Button' CONFIG_NWBUTTON_REBOOT ++ fi ++ tristate 'NetWinder flash support' CONFIG_NWFLASH ++fi ++tristate 'NatSemi SCx200 Support' CONFIG_SCx200 ++dep_tristate ' NatSemi SCx200 GPIO Support' CONFIG_SCx200_GPIO $CONFIG_SCx200 + -+include $(TOPDIR)/Rules.make -diff -urN kernel-base/arch/mips/ar7/memory.c kernel-current/arch/mips/ar7/memory.c ---- kernel-base/arch/mips/ar7/memory.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/memory.c 2005-07-10 06:40:39.586266560 +0200 -@@ -0,0 +1,130 @@ -+/* -+ * 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. -+ * -+ * ######################################################################## -+ * -+ * PROM library functions for acquiring/using memory descriptors given to -+ * us from the YAMON. -+ * -+ */ -+#include -+#include -+#include -+#include ++if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ] ; then ++ bool 'SGI SN2 fetchop support' CONFIG_FETCHOP ++fi + -+#include -+#include -+#include -+#include ++if [ "$CONFIG_X86" = "y" -o "$CONFIG_X86_64" = "y" ]; then ++ dep_tristate 'AMD 768/8111 Random Number Generator support' CONFIG_AMD_RNG $CONFIG_PCI ++fi ++if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then ++ dep_tristate 'Intel i8x0 Random Number Generator support' CONFIG_INTEL_RNG $CONFIG_PCI ++fi ++if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" -o \ ++ "$CONFIG_X86_64" = "y" ]; then ++ dep_tristate 'Intel/AMD/VIA HW Random Number Generator support' CONFIG_HW_RANDOM $CONFIG_PCI ++fi ++dep_tristate 'AMD 76x native power management (Experimental)' CONFIG_AMD_PM768 $CONFIG_PCI ++tristate '/dev/nvram support' CONFIG_NVRAM ++tristate 'Enhanced Real Time Clock Support' CONFIG_RTC ++if [ "$CONFIG_IA64" = "y" ]; then ++ bool 'EFI Real Time Clock Services' CONFIG_EFI_RTC ++fi ++if [ "$CONFIG_OBSOLETE" = "y" -a "$CONFIG_ALPHA_BOOK1" = "y" ]; then ++ bool 'Tadpole ANA H8 Support (OBSOLETE)' CONFIG_H8 ++fi ++if [ "$CONFIG_SGI_IP22" = "y" ]; then ++ tristate 'Dallas DS1286 RTC support' CONFIG_DS1286 ++fi ++if [ "$CONFIG_SGI_IP27" = "y" ]; then ++ tristate 'SGI M48T35 RTC support' CONFIG_SGI_IP27_RTC ++fi ++if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then ++ tristate 'Dallas DS1742 RTC support' CONFIG_DS1742 ++fi + -+enum yamon_memtypes { -+ yamon_dontuse, -+ yamon_prom, -+ yamon_free, -+}; -+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; ++tristate 'Double Talk PC internal speech card support' CONFIG_DTLK ++tristate 'Siemens R3964 line discipline' CONFIG_R3964 ++tristate 'Applicom intelligent fieldbus card support' CONFIG_APPLICOM ++if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_X86" = "y" -a "$CONFIG_X86_64" != "y" ]; then ++ dep_tristate 'Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)' CONFIG_SONYPI $CONFIG_PCI ++fi + -+/* References to section boundaries */ -+extern char _end; ++mainmenu_option next_comment ++comment 'Ftape, the floppy tape device driver' ++tristate 'Ftape (QIC-80/Travan) support' CONFIG_FTAPE ++if [ "$CONFIG_FTAPE" != "n" ]; then ++ source drivers/char/ftape/Config.in ++fi + -+#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) ++endmenu ++ ++if [ "$CONFIG_GART_IOMMU" = "y" ]; then ++ bool '/dev/agpgart (AGP Support)' CONFIG_AGP ++ define_bool CONFIG_AGP_AMD_K8 y ++else ++ tristate '/dev/agpgart (AGP Support)' CONFIG_AGP ++fi ++if [ "$CONFIG_AGP" != "n" ]; then ++ bool ' Intel 440LX/BX/GX and I815/I820/I830M/I830MP/I840/I845/I850/I860 support' CONFIG_AGP_INTEL ++ bool ' Intel I810/I815/I830M (on-board) support' CONFIG_AGP_I810 ++ bool ' VIA chipset support' CONFIG_AGP_VIA ++ bool ' AMD Irongate, 761, and 762 support' CONFIG_AGP_AMD ++ if [ "$CONFIG_GART_IOMMU" != "y" ]; then ++ bool ' AMD Opteron/Athlon64 on-CPU GART support' CONFIG_AGP_AMD_K8 ++ fi ++ bool ' Generic SiS support' CONFIG_AGP_SIS ++ bool ' ALI chipset support' CONFIG_AGP_ALI ++ bool ' Serverworks LE/HE support' CONFIG_AGP_SWORKS ++ if [ "$CONFIG_X86" = "y" ]; then ++ bool ' NVIDIA chipset support' CONFIG_AGP_NVIDIA ++ fi ++ if [ "$CONFIG_IA64" = "y" ]; then ++ bool ' Intel 460GX support' CONFIG_AGP_I460 ++ bool ' HP ZX1 AGP support' CONFIG_AGP_HP_ZX1 ++ fi ++ bool ' ATI IGP chipset support' CONFIG_AGP_ATI ++fi + ++mainmenu_option next_comment ++comment 'Direct Rendering Manager (XFree86 DRI support)' ++bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM ++if [ "$CONFIG_DRM" = "y" ]; then ++ bool ' Build drivers for old (XFree 4.0) DRM' CONFIG_DRM_OLD ++ if [ "$CONFIG_DRM_OLD" = "y" ]; then ++ comment 'DRM 4.0 drivers' ++ source drivers/char/drm-4.0/Config.in ++ else ++ comment 'DRM 4.1 drivers' ++ define_bool CONFIG_DRM_NEW y ++ source drivers/char/drm/Config.in ++ fi ++fi + -+struct prom_pmemblock * __init prom_getmdesc(void) -+{ -+ char *memsize_str; -+ unsigned int memsize; ++if [ "$CONFIG_X86" = "y" ]; then ++ tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE ++fi + -+ memsize_str = prom_getenv("memsize"); -+ if (!memsize_str) { -+ memsize = 0x02000000; -+ } else { -+ memsize = simple_strtol(memsize_str, NULL, 0); -+ } ++endmenu + -+ memset(mdesc, 0, sizeof(mdesc)); ++if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then ++ source drivers/char/pcmcia/Config.in ++fi ++if [ "$CONFIG_SOC_AU1X00" = "y" ]; then ++ tristate ' Alchemy Au1x00 GPIO device support' CONFIG_AU1X00_GPIO ++ tristate ' Au1000/ADS7846 touchscreen support' CONFIG_TS_AU1X00_ADS7846 ++ #tristate ' Alchemy Au1550 PSC SPI support' CONFIG_AU1550_PSC_SPI ++fi ++if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then ++ tristate ' ITE GPIO' CONFIG_ITE_GPIO ++fi + -+ mdesc[0].type = yamon_dontuse; -+ mdesc[0].base = 0x00000000; -+ mdesc[0].size = CONFIG_AR7_MEMORY; ++if [ "$CONFIG_X86" = "y" ]; then ++ tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE ++ dep_tristate 'HP OB600 C/CT Pop-up mouse support' CONFIG_OBMOUSE $CONFIG_INPUT_MOUSEDEV ++fi + -+ mdesc[1].type = yamon_prom; -+ mdesc[1].base = CONFIG_AR7_MEMORY; -+ mdesc[1].size = 0x00020000; ++endmenu +diff -urN linux.old/drivers/char/Makefile linux.dev/drivers/char/Makefile +--- linux.old/drivers/char/Makefile 2005-10-21 16:43:16.460960500 +0200 ++++ linux.dev/drivers/char/Makefile 2005-11-10 01:10:45.871576250 +0100 +@@ -240,6 +240,13 @@ + obj-y += joystick/js.o + endif + ++# ++# Texas Intruments VLYNQ driver ++# + -+ mdesc[2].type = yamon_free; -+ mdesc[2].base = CONFIG_AR7_MEMORY + 0x00020000; -+ mdesc[2].size = (memsize + CONFIG_AR7_MEMORY) - mdesc[2].base; ++subdir-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq ++obj-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq/avalanche_vlynq.o + -+ return &mdesc[0]; -+} + obj-$(CONFIG_FETCHOP) += fetchop.o + obj-$(CONFIG_BUSMOUSE) += busmouse.o + obj-$(CONFIG_DTLK) += dtlk.o +@@ -340,6 +347,11 @@ + obj-y += ipmi/ipmi.o + endif + ++subdir-$(CONFIG_AR7_ADAM2) += ticfg ++ifeq ($(CONFIG_AR7_ADAM2),y) ++ obj-y += ticfg/ticfg.o ++endif + -+static int __init prom_memtype_classify (unsigned int type) -+{ -+ switch (type) { -+ case yamon_free: -+ return BOOT_MEM_RAM; -+ case yamon_prom: -+ return BOOT_MEM_ROM_DATA; -+ default: -+ return BOOT_MEM_RESERVED; -+ } -+} + include $(TOPDIR)/Rules.make + + fastdep: +diff -urN linux.old/drivers/char/Makefile.orig linux.dev/drivers/char/Makefile.orig +--- linux.old/drivers/char/Makefile.orig 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/char/Makefile.orig 2005-11-10 01:10:45.871576250 +0100 +@@ -0,0 +1,374 @@ ++# ++# Makefile for the kernel character device drivers. ++# ++# Note! Dependencies are done automagically by 'make dep', which also ++# removes any old dependencies. DON'T put your own dependencies here ++# unless it's something special (ie not a .c file). ++# ++# Note 2! The CFLAGS definitions are now inherited from the ++# parent makes.. ++# + -+void __init prom_meminit(void) -+{ -+ struct prom_pmemblock *p; ++# ++# This file contains the font map for the default (hardware) font ++# ++FONTMAPFILE = cp437.uni + -+ p = prom_getmdesc(); ++O_TARGET := char.o + -+ while (p->size) { -+ long type; -+ unsigned long base, size; ++obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o + -+ type = prom_memtype_classify (p->type); -+ base = p->base; -+ size = p->size; ++# All of the (potential) objects that export symbols. ++# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. + -+ add_memory_region(base, size, type); -+ p++; -+ } -+} ++export-objs := busmouse.o console.o keyboard.o sysrq.o \ ++ misc.o pty.o random.o selection.o serial.o \ ++ sonypi.o tty_io.o tty_ioctl.o generic_serial.o \ ++ au1000_gpio.o vac-serial.o hp_psaux.o nvram.o \ ++ scx200.o fetchop.o + -+void __init prom_free_prom_memory (void) -+{ -+ int i; -+ unsigned long freed = 0; -+ unsigned long addr; ++mod-subdirs := joystick ftape drm drm-4.0 pcmcia + -+ for (i = 0; i < boot_mem_map.nr_map; i++) { -+ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) -+ continue; ++list-multi := + -+ 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 -urN kernel-base/arch/mips/ar7/mipsIRQ.S kernel-current/arch/mips/ar7/mipsIRQ.S ---- kernel-base/arch/mips/ar7/mipsIRQ.S 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/mipsIRQ.S 2005-07-10 06:40:39.587266408 +0200 -@@ -0,0 +1,120 @@ -+/* -+ * 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 ++KEYMAP =defkeymap.o ++KEYBD =pc_keyb.o ++CONSOLE =console.o ++SERIAL =serial.o + -+#include -+#include -+#include -+#include ++ifeq ($(ARCH),s390) ++ KEYMAP = ++ KEYBD = ++ CONSOLE = ++ SERIAL = ++endif + -+/* 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. -+ */ ++ifeq ($(ARCH),mips) ++ ifneq ($(CONFIG_PC_KEYB),y) ++ KEYBD = ++ endif ++ ifeq ($(CONFIG_VR41XX_KIU),y) ++ ifeq ($(CONFIG_IBM_WORKPAD),y) ++ KEYMAP = ibm_workpad_keymap.o ++ endif ++ ifeq ($(CONFIG_VICTOR_MPC30X),y) ++ KEYMAP = victor_mpc30x_keymap.o ++ endif ++ KEYBD = vr41xx_keyb.o ++ endif ++endif + -+.text -+.set noreorder -+.set noat -+ .align 5 -+NESTED(mipsIRQ, PT_SIZE, sp) -+ SAVE_ALL -+ CLI -+ .set at ++ifeq ($(ARCH),s390x) ++ KEYMAP = ++ KEYBD = ++ CONSOLE = ++ SERIAL = ++endif + -+ mfc0 s0, CP0_CAUSE # get irq bits ++ifeq ($(ARCH),m68k) ++ ifdef CONFIG_AMIGA ++ KEYBD = amikeyb.o ++ else ++ ifndef CONFIG_MAC ++ KEYBD = ++ endif ++ endif ++ SERIAL = ++endif + -+ /* First we check for r4k counter/timer IRQ. */ -+ andi a0, s0, CAUSEF_IP7 -+ beq a0, zero, 1f -+ andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt ++ifeq ($(ARCH),parisc) ++ ifdef CONFIG_GSC_PS2 ++ KEYBD = hp_psaux.o hp_keyb.o ++ else ++ KEYBD = ++ endif ++ ifdef CONFIG_SERIAL_MUX ++ CONSOLE += mux.o ++ endif ++ ifdef CONFIG_PDC_CONSOLE ++ CONSOLE += pdc_console.o ++ endif ++endif + -+ /* Wheee, a timer interrupt. */ -+ move a0, sp -+ jal ar7_timer_interrupt -+ nop ++ifdef CONFIG_Q40 ++ KEYBD += q40_keyb.o ++ SERIAL = serial.o ++endif + -+ j ret_from_irq -+ nop ++ifdef CONFIG_APOLLO ++ KEYBD += dn_keyb.o ++endif + -+ 1: -+ beq a0, zero, 1f # delay slot, check hw3 interrupt -+ nop ++ifeq ($(ARCH),parisc) ++ ifdef CONFIG_GSC_PS2 ++ KEYBD = hp_psaux.o hp_keyb.o ++ else ++ KEYBD = ++ endif ++ ifdef CONFIG_PDC_CONSOLE ++ CONSOLE += pdc_console.o ++ endif ++endif + -+ /* Wheee, combined hardware level zero interrupt. */ -+ jal avalanche_hw0_irqdispatch -+ move a0, sp # delay slot ++ifeq ($(ARCH),arm) ++ ifneq ($(CONFIG_PC_KEYMAP),y) ++ KEYMAP = ++ endif ++ ifneq ($(CONFIG_PC_KEYB),y) ++ KEYBD = ++ endif ++endif + -+ j ret_from_irq -+ nop # delay slot ++ifeq ($(ARCH),sh) ++ KEYMAP = ++ KEYBD = ++ CONSOLE = ++ ifeq ($(CONFIG_SH_HP600),y) ++ KEYMAP = defkeymap.o ++ KEYBD = scan_keyb.o hp600_keyb.o ++ CONSOLE = console.o ++ endif ++ ifeq ($(CONFIG_SH_DMIDA),y) ++ # DMIDA does not connect the HD64465 PS/2 keyboard port ++ # but we allow for USB keyboards to be plugged in. ++ KEYMAP = defkeymap.o ++ KEYBD = # hd64465_keyb.o pc_keyb.o ++ CONSOLE = console.o ++ endif ++ ifeq ($(CONFIG_SH_EC3104),y) ++ KEYMAP = defkeymap.o ++ KEYBD = ec3104_keyb.o ++ CONSOLE = console.o ++ endif ++ ifeq ($(CONFIG_SH_DREAMCAST),y) ++ KEYMAP = defkeymap.o ++ KEYBD = ++ CONSOLE = console.o ++ endif ++endif + -+ 1: -+ /* -+ * Here by mistake? This is possible, what can happen is that by the -+ * time we take the exception the IRQ pin goes low, so just leave if -+ * this is the case. -+ */ -+ move a1,s0 -+ PRINT("Got interrupt: c0_cause = %08x\n") -+ mfc0 a1, CP0_EPC -+ PRINT("c0_epc = %08x\n") -+ -+ j ret_from_irq -+ nop -+END(mipsIRQ) -diff -urN kernel-base/arch/mips/ar7/printf.c kernel-current/arch/mips/ar7/printf.c ---- kernel-base/arch/mips/ar7/printf.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/printf.c 2005-07-10 06:40:39.587266408 +0200 -@@ -0,0 +1,54 @@ -+/* -+ * 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. -+ * -+ * Putting things on the screen/serial line using Adam2 facilities. -+ */ ++ifeq ($(CONFIG_DECSTATION),y) ++ KEYMAP = ++ KEYBD = ++endif + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++ifeq ($(CONFIG_BAGET_MIPS),y) ++ KEYBD = ++ SERIAL = vac-serial.o ++endif + -+#define AVALANCHE_YAMON_FUNCTION_BASE (KSEG1ADDR(0x10000500)) -+#define AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR (AVALANCHE_YAMON_FUNCTION_BASE + 0x4) /* print_count function */ ++ifeq ($(CONFIG_NINO),y) ++ SERIAL = ++endif ++ ++ifneq ($(CONFIG_SUN_SERIAL),) ++ SERIAL = ++endif + -+static char ppbuf[1024]; ++ifeq ($(CONFIG_QTRONIX_KEYBOARD),y) ++ KEYBD = qtronix.o ++ KEYMAP = qtronixmap.o ++endif + -+void (*prom_print_str)(unsigned int out, char *s, int len); ++ifeq ($(CONFIG_DUMMY_KEYB),y) ++ KEYBD = dummy_keyb.o ++endif + -+void prom_printf(char *fmt, ...) __init; -+void prom_printf(char *fmt, ...) -+{ -+ va_list args; -+ int len; -+ prom_print_str = (void *)*(unsigned int *)AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR; ++obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o ++obj-$(CONFIG_SERIAL) += $(SERIAL) ++obj-$(CONFIG_PARPORT_SERIAL) += parport_serial.o ++obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o ++obj-$(CONFIG_SERIAL_21285) += serial_21285.o ++obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o ++obj-$(CONFIG_SERIAL_AMBA) += serial_amba.o ++obj-$(CONFIG_TS_AU1X00_ADS7846) += au1000_ts.o ++obj-$(CONFIG_SERIAL_DEC) += decserial.o ++ ++ifndef CONFIG_SUN_KEYBOARD ++ obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD) ++else ++ obj-$(CONFIG_PCI) += keyboard.o $(KEYMAP) ++endif + -+ va_start(args, fmt); -+ vsprintf(ppbuf, fmt, args); -+ len = strlen(ppbuf); ++obj-$(CONFIG_HIL) += hp_keyb.o ++obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o ++obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o ++obj-$(CONFIG_ROCKETPORT) += rocket.o ++obj-$(CONFIG_MOXA_SMARTIO) += mxser.o ++obj-$(CONFIG_MOXA_INTELLIO) += moxa.o ++obj-$(CONFIG_DIGI) += pcxx.o ++obj-$(CONFIG_DIGIEPCA) += epca.o ++obj-$(CONFIG_CYCLADES) += cyclades.o ++obj-$(CONFIG_STALLION) += stallion.o ++obj-$(CONFIG_ISTALLION) += istallion.o ++obj-$(CONFIG_SIBYTE_SB1250_DUART) += sb1250_duart.o ++obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o ++obj-$(CONFIG_RISCOM8) += riscom8.o ++obj-$(CONFIG_ISI) += isicom.o ++obj-$(CONFIG_ESPSERIAL) += esp.o ++obj-$(CONFIG_SYNCLINK) += synclink.o ++obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o ++obj-$(CONFIG_N_HDLC) += n_hdlc.o ++obj-$(CONFIG_SPECIALIX) += specialix.o ++obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o ++obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o ++obj-$(CONFIG_SX) += sx.o generic_serial.o ++obj-$(CONFIG_RIO) += rio/rio.o generic_serial.o ++obj-$(CONFIG_SH_SCI) += sh-sci.o generic_serial.o ++obj-$(CONFIG_SERIAL167) += serial167.o ++obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o ++obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o ++obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o ++obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o ++obj-$(CONFIG_SERIAL_TX3912) += generic_serial.o serial_tx3912.o ++obj-$(CONFIG_TXX927_SERIAL) += serial_txx927.o ++obj-$(CONFIG_SERIAL_TXX9) += generic_serial.o serial_txx9.o ++obj-$(CONFIG_IP22_SERIAL) += sgiserial.o ++obj-$(CONFIG_AU1X00_UART) += au1x00-serial.o ++obj-$(CONFIG_SGI_L1_SERIAL) += sn_serial.o ++ ++subdir-$(CONFIG_RIO) += rio ++subdir-$(CONFIG_INPUT) += joystick ++ ++obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o ++obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o ++obj-$(CONFIG_PRINTER) += lp.o ++obj-$(CONFIG_TIPAR) += tipar.o ++obj-$(CONFIG_OBMOUSE) += obmouse.o ++ ++ifeq ($(CONFIG_INPUT),y) ++obj-y += joystick/js.o ++endif + -+ prom_print_str(1, ppbuf, len); ++# ++# Texas Intruments VLYNQ driver ++# ++ ++subdir-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq ++obj-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq/avalanche_vlynq.o ++ ++obj-$(CONFIG_FETCHOP) += fetchop.o ++obj-$(CONFIG_BUSMOUSE) += busmouse.o ++obj-$(CONFIG_DTLK) += dtlk.o ++obj-$(CONFIG_R3964) += n_r3964.o ++obj-$(CONFIG_APPLICOM) += applicom.o ++obj-$(CONFIG_SONYPI) += sonypi.o ++obj-$(CONFIG_MS_BUSMOUSE) += msbusmouse.o ++obj-$(CONFIG_82C710_MOUSE) += qpmouse.o ++obj-$(CONFIG_AMIGAMOUSE) += amigamouse.o ++obj-$(CONFIG_ATARIMOUSE) += atarimouse.o ++obj-$(CONFIG_ADBMOUSE) += adbmouse.o ++obj-$(CONFIG_PC110_PAD) += pc110pad.o ++obj-$(CONFIG_MK712_MOUSE) += mk712.o ++obj-$(CONFIG_RTC) += rtc.o ++obj-$(CONFIG_GEN_RTC) += genrtc.o ++obj-$(CONFIG_EFI_RTC) += efirtc.o ++obj-$(CONFIG_MIPS_RTC) += mips_rtc.o ++obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o ++ifeq ($(CONFIG_PPC),) ++ obj-$(CONFIG_NVRAM) += nvram.o ++endif ++obj-$(CONFIG_TOSHIBA) += toshiba.o ++obj-$(CONFIG_I8K) += i8k.o ++obj-$(CONFIG_DS1286) += ds1286.o ++obj-$(CONFIG_DS1620) += ds1620.o ++obj-$(CONFIG_DS1742) += ds1742.o ++obj-$(CONFIG_INTEL_RNG) += i810_rng.o ++obj-$(CONFIG_AMD_RNG) += amd768_rng.o ++obj-$(CONFIG_HW_RANDOM) += hw_random.o ++obj-$(CONFIG_AMD_PM768) += amd76x_pm.o ++obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o ++ ++obj-$(CONFIG_ITE_GPIO) += ite_gpio.o ++obj-$(CONFIG_AU1X00_GPIO) += au1000_gpio.o ++obj-$(CONFIG_AU1550_PSC_SPI) += au1550_psc_spi.o ++obj-$(CONFIG_AU1X00_USB_TTY) += au1000_usbtty.o ++obj-$(CONFIG_AU1X00_USB_RAW) += au1000_usbraw.o ++obj-$(CONFIG_COBALT_LCD) += lcd.o ++ ++obj-$(CONFIG_QIC02_TAPE) += tpqic02.o ++ ++subdir-$(CONFIG_FTAPE) += ftape ++subdir-$(CONFIG_DRM_OLD) += drm-4.0 ++subdir-$(CONFIG_DRM_NEW) += drm ++subdir-$(CONFIG_PCMCIA) += pcmcia ++subdir-$(CONFIG_AGP) += agp ++ ++ifeq ($(CONFIG_FTAPE),y) ++obj-y += ftape/ftape.o ++endif + -+ va_end(args); -+ return; ++obj-$(CONFIG_H8) += h8.o ++obj-$(CONFIG_PPDEV) += ppdev.o ++obj-$(CONFIG_DZ) += dz.o ++obj-$(CONFIG_NWBUTTON) += nwbutton.o ++obj-$(CONFIG_NWFLASH) += nwflash.o ++obj-$(CONFIG_SCx200) += scx200.o ++obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o ++ ++# Only one watchdog can succeed. We probe the hardware watchdog ++# drivers first, then the softdog driver. This means if your hardware ++# watchdog dies or is 'borrowed' for some reason the software watchdog ++# still gives you some cover. ++ ++obj-$(CONFIG_PCWATCHDOG) += pcwd.o ++obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o ++obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o ++obj-$(CONFIG_IB700_WDT) += ib700wdt.o ++obj-$(CONFIG_MIXCOMWD) += mixcomwd.o ++obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o ++obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o ++obj-$(CONFIG_SC520_WDT) += sc520_wdt.o ++obj-$(CONFIG_WDT) += wdt.o ++obj-$(CONFIG_WDTPCI) += wdt_pci.o ++obj-$(CONFIG_21285_WATCHDOG) += wdt285.o ++obj-$(CONFIG_977_WATCHDOG) += wdt977.o ++obj-$(CONFIG_I810_TCO) += i810-tco.o ++obj-$(CONFIG_MACHZ_WDT) += machzwd.o ++obj-$(CONFIG_SH_WDT) += shwdt.o ++obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o ++obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o ++obj-$(CONFIG_ALIM1535_WDT) += alim1535d_wdt.o ++obj-$(CONFIG_INDYDOG) += indydog.o ++obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o ++obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o ++obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o ++obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o ++obj-$(CONFIG_INDYDOG) += indydog.o ++obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o ++ ++subdir-$(CONFIG_MWAVE) += mwave ++ifeq ($(CONFIG_MWAVE),y) ++ obj-y += mwave/mwave.o ++endif + -+} -diff -urN kernel-base/arch/mips/ar7/reset.c kernel-current/arch/mips/ar7/reset.c ---- kernel-base/arch/mips/ar7/reset.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/reset.c 2005-07-10 06:40:39.587266408 +0200 -@@ -0,0 +1,54 @@ ++subdir-$(CONFIG_IPMI_HANDLER) += ipmi ++ifeq ($(CONFIG_IPMI_HANDLER),y) ++ obj-y += ipmi/ipmi.o ++endif ++ ++include $(TOPDIR)/Rules.make ++ ++fastdep: ++ ++conmakehash: conmakehash.c ++ $(HOSTCC) $(HOSTCFLAGS) -o conmakehash conmakehash.c ++ ++consolemap_deftbl.c: $(FONTMAPFILE) conmakehash ++ ./conmakehash $(FONTMAPFILE) > consolemap_deftbl.c ++ ++consolemap_deftbl.o: consolemap_deftbl.c $(TOPDIR)/include/linux/types.h ++ ++.DELETE_ON_ERROR: ++ ++defkeymap.c: defkeymap.map ++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ ++ ++qtronixmap.c: qtronixmap.map ++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ ++ ++ibm_workpad_keymap.c: ibm_workpad_keymap.map ++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ ++ ++victor_mpc30x_keymap.c: victor_mpc30x_keymap.map ++ set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@ +diff -urN linux.old/drivers/char/avalanche_vlynq/Makefile linux.dev/drivers/char/avalanche_vlynq/Makefile +--- linux.old/drivers/char/avalanche_vlynq/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/char/avalanche_vlynq/Makefile 2005-11-10 01:10:45.871576250 +0100 +@@ -0,0 +1,16 @@ ++# ++# Makefile for the linux kernel. ++# ++# Note! Dependencies are done automagically by 'make dep', which also ++# removes any old dependencies. DON'T put your own dependencies here ++# unless it's something special (ie not a .c file). ++# ++# Note 2! The CFLAGS definitions are now in the main makefile... ++ ++O_TARGET := avalanche_vlynq.o ++ ++export-objs := vlynq_board.o ++ ++obj-y += vlynq_drv.o vlynq_hal.o vlynq_board.o ++ ++include $(TOPDIR)/Rules.make +diff -urN linux.old/drivers/char/avalanche_vlynq/vlynq_board.c linux.dev/drivers/char/avalanche_vlynq/vlynq_board.c +--- linux.old/drivers/char/avalanche_vlynq/vlynq_board.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/char/avalanche_vlynq/vlynq_board.c 2005-11-10 01:10:45.871576250 +0100 +@@ -0,0 +1,184 @@ +/* -+ * Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -+ * -+ * ######################################################################## ++ * Jeff Harrell, jharrell@ti.com ++ * Copyright (C) 2001 Texas Instruments, 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 @@ -3525,746 +4128,1670 @@ diff -urN kernel-base/arch/mips/ar7/reset.c kernel-current/arch/mips/ar7/reset.c + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * -+ * ######################################################################## -+ * -+ * Reset the MIPS boards. -+ * ++ * Texas Instruments Sangam specific setup. + */ +#include ++#include ++#include ++#include ++#include ++ ++#define SYS_VLYNQ_LOCAL_INTERRUPT_VECTOR 30 /* MSB - 1 bit */ ++#define SYS_VLYNQ_REMOTE_INTERRUPT_VECTOR 31 /* MSB bit */ ++#define SYS_VLYNQ_OPTIONS 0x7F; /* all options*/ + -+#include -+#include ++/* These defines are board specific */ + -+static void ar7_machine_restart(char *command); -+static void ar7_machine_halt(void); -+static void ar7_machine_power_off(void); + -+static void ar7_machine_restart(char *command) -+{ ++#define VLYNQ0_REMOTE_WINDOW1_OFFSET (0x0C000000) ++#define VLYNQ0_REMOTE_WINDOW1_SIZE (0x500) + -+} + -+static void ar7_machine_halt(void) ++#define VLYNQ1_REMOTE_WINDOW1_OFFSET (0x0C000000) ++#define VLYNQ1_REMOTE_WINDOW1_SIZE (0x500) ++ ++ ++extern VLYNQ_DEV vlynqDevice0, vlynqDevice1; ++int vlynq_init_status[2] = {0, 0}; ++EXPORT_SYMBOL(vlynq_init_status); ++static int reset_hack = 1; ++ ++void vlynq_ar7wrd_dev_init() +{ ++ *(unsigned long*) AVALANCHE_GPIO_ENBL |= (1<<18); ++ vlynq_delay(20000); ++ *(unsigned long*) AVALANCHE_GPIO_DIR &= ~(1<<18); ++ vlynq_delay(20000); ++ *(unsigned long*) AVALANCHE_GPIO_DATA_OUT&= ~(1<<18); ++ vlynq_delay(50000); ++ *(unsigned long*) AVALANCHE_GPIO_DATA_OUT|= (1<<18); ++ vlynq_delay(50000); ++ ++ /* Initialize the MIPS host vlynq driver for a given vlynq interface */ ++ vlynqDevice0.dev_idx = 0; /* first vlynq module - this parameter is for reference only */ ++ vlynqDevice0.module_base = AVALANCHE_LOW_VLYNQ_CONTROL_BASE; /* vlynq0 module base address */ ++ ++#if defined(CONFIG_VLYNQ_CLK_LOCAL) ++ vlynqDevice0.clk_source = VLYNQ_CLK_SOURCE_LOCAL; ++#else ++ vlynqDevice0.clk_source = VLYNQ_CLK_SOURCE_REMOTE; ++#endif ++ vlynqDevice0.clk_div = 0x01; /* board/hardware specific */ ++ vlynqDevice0.state = VLYNQ_DRV_STATE_UNINIT; /* uninitialized module */ ++ ++ /* Populate vlynqDevice0.local_mem & Vlynq0.remote_mem based on system configuration */ ++ /*Local memory configuration */ ++ ++ /* Demiurg : not good !*/ ++#if 0 ++ vlynqDevice0.local_mem.Txmap= AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE & ~(0xc0000000) ; /* physical address */ ++ vlynqDevice0.remote_mem.RxOffset[0]= VLYNQ0_REMOTE_WINDOW1_OFFSET; /* This is specific to the board on the other end */ ++ vlynqDevice0.remote_mem.RxSize[0]=VLYNQ0_REMOTE_WINDOW1_SIZE; ++#endif ++ ++ /* Demiurg : This is how it should be ! */ ++ vlynqDevice0.local_mem.Txmap = PHYSADDR(AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE); ++#define VLYNQ_ACX111_MEM_OFFSET 0xC0000000 /* Physical address of ACX111 memory */ ++#define VLYNQ_ACX111_MEM_SIZE 0x00040000 /* Total size of the ACX111 memory */ ++#define VLYNQ_ACX111_REG_OFFSET 0xF0000000 /* PHYS_ADDR of ACX111 control registers */ ++#define VLYNQ_ACX111_REG_SIZE 0x00022000 /* Size of ACX111 registers area, MAC+PHY */ ++#define ACX111_VL1_REMOTE_SIZE 0x1000000 ++ vlynqDevice0.remote_mem.RxOffset[0] = VLYNQ_ACX111_MEM_OFFSET; ++ vlynqDevice0.remote_mem.RxSize[0] = VLYNQ_ACX111_MEM_SIZE ; ++ vlynqDevice0.remote_mem.RxOffset[1] = VLYNQ_ACX111_REG_OFFSET; ++ vlynqDevice0.remote_mem.RxSize[1] = VLYNQ_ACX111_REG_SIZE ; ++ vlynqDevice0.remote_mem.Txmap = 0; ++ vlynqDevice0.local_mem.RxOffset[0] = AVALANCHE_SDRAM_BASE; ++ vlynqDevice0.local_mem.RxSize[0] = ACX111_VL1_REMOTE_SIZE; ++ ++ ++ /* Local interrupt configuration */ ++ vlynqDevice0.local_irq.intLocal = VLYNQ_INT_LOCAL; /* Host handles vlynq interrupts*/ ++ vlynqDevice0.local_irq.intRemote = VLYNQ_INT_ROOT_ISR; /* vlynq root isr used */ ++ vlynqDevice0.local_irq.map_vector = SYS_VLYNQ_LOCAL_INTERRUPT_VECTOR; ++ vlynqDevice0.local_irq.intr_ptr = 0; /* Since remote interrupts part of vlynq root isr this is unused */ ++ ++ /* Remote interrupt configuration */ ++ vlynqDevice0.remote_irq.intLocal = VLYNQ_INT_REMOTE; /* MIPS handles interrupts */ ++ vlynqDevice0.remote_irq.intRemote = VLYNQ_INT_ROOT_ISR; /* Not significant since MIPS handles interrupts */ ++ vlynqDevice0.remote_irq.map_vector = SYS_VLYNQ_REMOTE_INTERRUPT_VECTOR; ++ vlynqDevice0. remote_irq.intr_ptr = AVALANCHE_INTC_BASE; /* Not significant since MIPS handles interrupts */ ++ ++ if(reset_hack != 1) ++ printk("About to re-init the VLYNQ.\n"); ++ ++ if(vlynq_init(&vlynqDevice0,VLYNQ_INIT_PERFORM_ALL)== 0) ++ { ++ /* Suraj added the following to keep the 1130 going. */ ++ vlynq_interrupt_vector_set(&vlynqDevice0, 0 /* intr vector line running into 1130 vlynq */, ++ 0 /* intr mapped onto the interrupt register on remote vlynq and this vlynq */, ++ VLYNQ_REMOTE_DVC, 0 /* polarity active high */, 0 /* interrupt Level triggered */); ++ ++ /* System wide interrupt is 80 for 1130, please note. */ ++ vlynq_init_status[0] = 1; ++ reset_hack = 2; ++ } ++ else ++ { ++ if(reset_hack == 1) ++ printk("VLYNQ INIT FAILED: Please try cold reboot. \n"); ++ else ++ printk("Failed to initialize the VLYNQ interface at insmod.\n"); + ++ } +} + -+static void ar7_machine_power_off(void) ++void vlynq_dev_init(void) +{ ++ volatile unsigned int *reset_base = (unsigned int *) AVALANCHE_RESET_CONTROL_BASE; ++ ++ *reset_base &= ~((1 << AVALANCHE_LOW_VLYNQ_RESET_BIT)); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT)); */ ++ ++ vlynq_delay(20000); ++ ++ /* Bring vlynq out of reset if not already done */ ++ *reset_base |= (1 << AVALANCHE_LOW_VLYNQ_RESET_BIT); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT); */ ++ vlynq_delay(20000); /* Allowing sufficient time to VLYNQ to settle down.*/ ++ ++ vlynq_ar7wrd_dev_init( ); + +} + -+void ar7_reboot_setup(void) ++/* This function is board specific and should be ported for each board. */ ++void remote_vlynq_dev_reset_ctrl(unsigned int module_reset_bit, ++ AVALANCHE_RESET_CTRL_T reset_ctrl) +{ -+ _machine_restart = ar7_machine_restart; -+ _machine_halt = ar7_machine_halt; -+ _machine_power_off = ar7_machine_power_off; ++ if(module_reset_bit >= 32) ++ return; ++ ++ switch(module_reset_bit) ++ { ++ case 0: ++ if(OUT_OF_RESET == reset_ctrl) ++ { ++ if(reset_hack) return; ++ ++ vlynq_delay(20000); ++ printk("Un-resetting the remote device.\n"); ++ vlynq_dev_init(); ++ printk("Re-initialized the VLYNQ.\n"); ++ reset_hack = 2; ++ } ++ else if(IN_RESET == reset_ctrl) ++ { ++ *(unsigned long*) AVALANCHE_GPIO_DATA_OUT &= ~(1<<18); ++ ++ vlynq_delay(20000); ++ printk("Resetting the remote device.\n"); ++ reset_hack = 0; ++ } ++ else ++ ; ++ break; ++ ++ default: ++ break; ++ ++ } +} -diff -urN kernel-base/arch/mips/ar7/setup.c kernel-current/arch/mips/ar7/setup.c ---- kernel-base/arch/mips/ar7/setup.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/setup.c 2005-07-10 06:40:39.588266256 +0200 -@@ -0,0 +1,120 @@ -+/* -+ * Carsten Langgaard, carstenl@mips.com -+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. ++ +diff -urN linux.old/drivers/char/avalanche_vlynq/vlynq_drv.c linux.dev/drivers/char/avalanche_vlynq/vlynq_drv.c +--- linux.old/drivers/char/avalanche_vlynq/vlynq_drv.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/char/avalanche_vlynq/vlynq_drv.c 2005-11-10 01:10:45.891577500 +0100 +@@ -0,0 +1,243 @@ ++/****************************************************************************** ++ * FILE PURPOSE: Vlynq Linux Device Driver Source ++ ****************************************************************************** ++ * FILE NAME: vlynq_drv.c + * -+ * 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. ++ * DESCRIPTION: Vlynq Linux Device Driver Source + * -+ * 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. ++ * REVISION HISTORY: + * -+ * 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. -+ */ ++ * Date Description Author ++ *----------------------------------------------------------------------------- ++ * 17 July 2003 Initial Creation Anant Gole ++ * 17 Dec 2003 Updates Sharath Kumar ++ * ++ * (C) Copyright 2003, Texas Instruments, Inc ++ *******************************************************************************/ ++ +#include +#include ++#include +#include -+#include -+#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+#include -+#include -+#include -+#include -+#include + -+#include -+#include -+#include ++#define TI_VLYNQ_VERSION "0.2" + -+#ifdef CONFIG_KGDB -+extern void rs_kgdb_hook(int); -+int remote_debug = 0; ++/* debug on ? */ ++#define VLYNQ_DEBUG ++ ++/* Macro for debug and error printf's */ ++#ifdef VLYNQ_DEBUG ++#define DBGPRINT printk ++#else ++#define DBGPRINT(x) +#endif + -+extern struct rtc_ops no_rtc_ops; ++#define ERRPRINT printk + -+extern void ar7_reboot_setup(void); ++/* Define the max vlynq ports this driver will support. ++ Device name strings are statically added here */ ++#define MAX_VLYNQ_PORTS 2 + -+extern void ar7_time_init(void); -+extern void ar7_timer_setup(struct irqaction *irq); + -+const char *get_system_type(void) -+{ -+ return "Texas Instruments AR7"; -+} ++/* Type define for VLYNQ private structure */ ++typedef struct vlynqPriv{ ++ int irq; ++ VLYNQ_DEV *vlynqDevice; ++}VLYNQ_PRIV; + -+void __init ar7_setup(void) -+{ -+#ifdef CONFIG_KGDB -+ int rs_putDebugChar(char); -+ char rs_getDebugChar(void); -+ extern int (*generic_putDebugChar)(char); -+ extern char (*generic_getDebugChar)(void); -+#endif -+ char *argptr; -+#ifdef CONFIG_SERIAL_CONSOLE -+ argptr = prom_getcmdline(); -+ if ((argptr = strstr(argptr, "console=")) == NULL) { -+ char console[20]; -+ char *s; -+ int i = 0; -+ -+ s = prom_getenv("modetty0"); -+ strcpy(console, "38400"); -+ -+ if (s != NULL) { -+ while (s[i] >= '0' && s[i] <= '9') -+ i++; -+ -+ if (i > 0) { -+ strncpy(console, s, i); -+ console[i] = 0; -+ } -+ } -+ -+ argptr = prom_getcmdline(); -+ strcat(argptr, " console=ttyS0,"); -+ strcat(argptr, console); -+ } -+#endif ++extern int vlynq_init_status[2]; + -+#ifdef CONFIG_KGDB -+ argptr = prom_getcmdline(); -+ if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { -+ int line; -+ argptr += strlen("kgdb=ttyS"); -+ if (*argptr != '0' && *argptr != '1') -+ printk("KGDB: Uknown serial line /dev/ttyS%c, " -+ "falling back to /dev/ttyS1\n", *argptr); -+ line = *argptr == '0' ? 0 : 1; -+ printk("KGDB: Using serial line /dev/ttyS%d for session\n", -+ line ? 1 : 0); ++/* Extern Global variable for vlynq devices used in initialization of the vlynq device ++ * These variables need to be populated/initialized by the system as part of initialization ++ * process. The vlynq enumerator can run at initialization and populate these globals ++ */ + -+ rs_kgdb_hook(line); -+ generic_putDebugChar = rs_putDebugChar; -+ generic_getDebugChar = rs_getDebugChar; ++VLYNQ_DEV vlynqDevice0; ++VLYNQ_DEV vlynqDevice1; + -+ prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " -+ "please connect your debugger\n", line ? 1 : 0); ++/* Defining dummy macro AVALANCHE_HIGH_VLYNQ_INT to take ++ * care of compilation in case of single vlynq device ++ */ + -+ remote_debug = 1; -+ /* Breakpoints are in init_IRQ() */ -+ } ++#ifndef AVALANCHE_HIGH_VLYNQ_INT ++#define AVALANCHE_HIGH_VLYNQ_INT 0 +#endif + -+ argptr = prom_getcmdline(); -+ if ((argptr = strstr(argptr, "nofpu")) != NULL) -+ cpu_data[0].options &= ~MIPS_CPU_FPU; + -+ rtc_ops = &no_rtc_ops; + -+ ar7_reboot_setup(); ++/* vlynq private object */ ++VLYNQ_PRIV vlynq_priv[CONFIG_AR7_VLYNQ_PORTS] = { ++ { LNXINTNUM(AVALANCHE_LOW_VLYNQ_INT),&vlynqDevice0}, ++ { LNXINTNUM(AVALANCHE_HIGH_VLYNQ_INT),&vlynqDevice1}, ++}; + -+ board_time_init = ar7_time_init; -+ board_timer_setup = ar7_timer_setup; ++extern void vlynq_dev_init(void); ++ ++ ++/* =================================== all the operations */ ++ ++static int ++vlynq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ return 0; +} -diff -urN kernel-base/arch/mips/ar7/time.c kernel-current/arch/mips/ar7/time.c ---- kernel-base/arch/mips/ar7/time.c 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/arch/mips/ar7/time.c 2005-07-10 06:40:39.588266256 +0200 -@@ -0,0 +1,125 @@ -+/* -+ * 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. -+ * -+ * ######################################################################## -+ * -+ * Setting up the clock on the MIPS boards. -+ * -+ */ + -+#include -+#include -+#include -+#include -+#include -+#include ++static struct file_operations vlynq_fops = { ++ owner: THIS_MODULE, ++ ioctl: vlynq_ioctl, ++}; + -+#include -+#include -+#include -+#include ++/* Vlynq device object */ ++static struct miscdevice vlynq_dev [MAX_VLYNQ_PORTS] = { ++ { MISC_DYNAMIC_MINOR , "vlynq0", &vlynq_fops }, ++ { MISC_DYNAMIC_MINOR , "vlynq1", &vlynq_fops }, ++}; + -+#include -+#include -+#include + -+#include -+#include -+#include ++/* Proc read function */ ++static int ++vlynq_read_link_proc(char *buf, char **start, off_t offset, int count, int *eof, void *unused) ++{ ++ int instance; ++ int len = 0; ++ ++ len += sprintf(buf +len,"VLYNQ Devices : %d\n",CONFIG_AR7_VLYNQ_PORTS); ++ ++ for(instance =0;instance < CONFIG_AR7_VLYNQ_PORTS;instance++) ++ { ++ int link_state; ++ char *link_msg[] = {" DOWN "," UP "}; ++ ++ if(vlynq_init_status[instance] == 0) ++ link_state = 0; ++ ++ else if (vlynq_link_check(vlynq_priv[instance].vlynqDevice)) ++ link_state = 1; ++ ++ else ++ link_state = 0; + -+extern asmlinkage void mipsIRQ(void); ++ len += sprintf(buf + len, "VLYNQ %d: Link state: %s\n",instance,link_msg[link_state]); + -+static unsigned long r4k_offset; /* Amount to increment compare reg each time */ -+static unsigned long r4k_cur; /* What counter should be at next timer irq */ ++ } ++ /* Print info about vlynq device 1 */ ++ ++ return len; ++} ++ ++ ++/* Proc function to display driver version */ ++static int ++vlynq_read_ver_proc(char *buf, char **start, off_t offset, int count, int *eof, void *data) ++{ ++ int instance; ++ int len=0; ++ ++ len += sprintf(buf +len,"\nTI Linux VLYNQ Driver Version %s\n",TI_VLYNQ_VERSION); ++ return len; ++} + -+#define MIPS_CPU_TIMER_IRQ 7 -+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) + -+static inline void ack_r4ktimer(unsigned long newval) ++ ++ ++/* Wrapper for vlynq ISR */ ++static void lnx_vlynq_root_isr(int irq, void * arg, struct pt_regs *regs) +{ -+ write_c0_compare(newval); ++ vlynq_root_isr(arg); +} + -+void ar7_timer_interrupt(struct pt_regs *regs) ++/* =================================== init and cleanup */ ++ ++int vlynq_init_module(void) +{ -+ int cpu = smp_processor_id(); ++ int ret; ++ int unit = 0; ++ int instance_count = CONFIG_AR7_VLYNQ_PORTS; ++ volatile int *ptr; + -+ irq_enter(cpu, MIPS_CPU_TIMER_IRQ); ++ vlynq_dev_init(); + -+ if (r4k_offset == 0) -+ goto null; ++ DBGPRINT("Vlynq CONFIG_AR7_VLYNQ_PORTS=%d\n", CONFIG_AR7_VLYNQ_PORTS); ++ /* If num of configured vlynq ports > supported by driver return error */ ++ if (instance_count > MAX_VLYNQ_PORTS) ++ { ++ ERRPRINT("ERROR: vlynq_init_module(): Max %d supported\n", MAX_VLYNQ_PORTS); ++ return (-1); ++ } + -+ do { -+ kstat.irqs[cpu][MIPS_CPU_TIMER_IRQ]++; -+ do_timer(regs); -+ r4k_cur += r4k_offset; -+ ack_r4ktimer(r4k_cur); ++ /* register the misc device */ ++ for (unit = 0; unit < CONFIG_AR7_VLYNQ_PORTS; unit++) ++ { ++ ret = misc_register(&vlynq_dev[unit]); + -+ } while (((unsigned long)read_c0_count() -+ - r4k_cur) < 0x7fffffff); ++ if(ret < 0) ++ { ++ ERRPRINT("ERROR:Could not register vlynq device:%d\n",unit); ++ continue; ++ } ++ else ++ DBGPRINT("Vlynq Device %s registered with minor no %d as misc device. Result=%d\n", ++ vlynq_dev[unit].name, vlynq_dev[unit].minor, ret); ++#if 0 ++ ++ DBGPRINT("Calling vlynq init\n"); ++ ++ /* Read the global variable for VLYNQ device structure and initialize vlynq driver */ ++ ret = vlynq_init(vlynq_priv[unit].vlynqDevice,VLYNQ_INIT_PERFORM_ALL ); ++#endif + -+ irq_exit(cpu, MIPS_CPU_TIMER_IRQ); ++ if(vlynq_init_status[unit] == 0) ++ { ++ printk("VLYNQ %d : init failed\n",unit); ++ continue; ++ } ++ ++ /* Check link before proceeding */ ++ if (!vlynq_link_check(vlynq_priv[unit].vlynqDevice)) ++ { ++ DBGPRINT("\nError: Vlynq link not available.trying once before Exiting"); ++ } ++ else ++ { ++ DBGPRINT("Vlynq instance:%d Link UP\n",unit); ++ ++ /* Install the vlynq local root ISR */ ++ request_irq(vlynq_priv[unit].irq,lnx_vlynq_root_isr,0,vlynq_dev[unit].name,vlynq_priv[unit].vlynqDevice); ++ } ++ } + -+ if (softirq_pending(cpu)) -+ do_softirq(); ++ proc_mkdir("avalanche", NULL); ++ /* Creating proc entry for the devices */ ++ create_proc_read_entry("avalanche/vlynq_link", 0, NULL, vlynq_read_link_proc, NULL); ++ create_proc_read_entry("avalanche/vlynq_ver", 0, NULL, vlynq_read_ver_proc, NULL); ++ ++ return 0; ++} + -+ return; ++void vlynq_cleanup_module(void) ++{ ++ int unit = 0; ++ ++ for (unit = 0; unit < CONFIG_AR7_VLYNQ_PORTS; unit++) ++ { ++ DBGPRINT("vlynq_cleanup_module(): Unregistring misc device %s\n",vlynq_dev[unit].name); ++ misc_deregister(&vlynq_dev[unit]); ++ } + -+null: -+ ack_r4ktimer(0); ++ remove_proc_entry("avalanche/vlynq_link", NULL); ++ remove_proc_entry("avalanche/vlynq_ver", NULL); +} + -+/* -+ * Figure out the r4k offset, the amount to increment the compare -+ * register for each time tick. ++ ++module_init(vlynq_init_module); ++module_exit(vlynq_cleanup_module); ++ +diff -urN linux.old/drivers/char/avalanche_vlynq/vlynq_hal.c linux.dev/drivers/char/avalanche_vlynq/vlynq_hal.c +--- linux.old/drivers/char/avalanche_vlynq/vlynq_hal.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/char/avalanche_vlynq/vlynq_hal.c 2005-11-10 01:10:45.975582750 +0100 +@@ -0,0 +1,1214 @@ ++/*************************************************************************** ++**+----------------------------------------------------------------------+** ++**| **** |** ++**| **** |** ++**| ******o*** |** ++**| ********_///_**** |** ++**| ***** /_//_/ **** |** ++**| ** ** (__/ **** |** ++**| ********* |** ++**| **** |** ++**| *** |** ++**| |** ++**| Copyright (c) 2003 Texas Instruments Incorporated |** ++**| ALL RIGHTS RESERVED |** ++**| |** ++**| Permission is hereby granted to licensees of Texas Instruments |** ++**| Incorporated (TI) products to use this computer program for the sole |** ++**| purpose of implementing a licensee product based on TI products. |** ++**| No other rights to reproduce, use, or disseminate this computer |** ++**| program, whether in part or in whole, are granted. |** ++**| |** ++**| TI makes no representation or warranties with respect to the |** ++**| performance of this computer program, and specifically disclaims |** ++**| any responsibility for any damages, special or consequential, |** ++**| connected with the use of this program. |** ++**| |** ++**+----------------------------------------------------------------------+** ++***************************************************************************/ ++ ++/*************************************************************************** ++ * ------------------------------------------------------------------------------ ++ * Module : vlynq_hal.c ++ * Description : This file implements VLYNQ HAL API. ++ * ------------------------------------------------------------------------------ ++ ***************************************************************************/ ++ ++#include ++#include ++#include ++ ++/**** Local Function prototypes *******/ ++static int vlynqInterruptInit(VLYNQ_DEV *pdev); ++static void vlynq_configClock(VLYNQ_DEV *pdev); ++ ++/*** Second argument must be explicitly type casted to ++ * (VLYNQ_DEV*) inside the following functions */ ++static void vlynq_local_module_isr(void *arg1, void *arg2, void *arg3); ++static void vlynq_remote_module_isr(void *arg1, void *arg2, void *arg3); ++ ++ ++volatile int vlynq_delay_value = 0; ++ ++/* Code adopted from original vlynq driver */ ++void vlynq_delay(unsigned int clktime) ++{ ++ int i = 0; ++ volatile int *ptr = &vlynq_delay_value; ++ *ptr = 0; ++ ++ /* We are assuming that the each cycle takes about ++ * 23 assembly instructions. */ ++ for(i = 0; i < (clktime + 23)/23; i++) ++ { ++ *ptr = *ptr + 1; ++ } ++} ++ ++ ++/* ---------------------------------------------------------------------------- ++ * Function : vlynq_configClock() ++ * Description: Configures clock settings based on input parameters ++ * Adapted from original vlyna driver from Cable + */ -+static unsigned long __init cal_r4koff(void) ++static void vlynq_configClock(VLYNQ_DEV * pdev) +{ -+ return ((CONFIG_AR7_CPU_FREQUENCY*500000)/HZ); ++ unsigned int tmp; ++ ++ switch( pdev->clk_source) ++ { ++ case VLYNQ_CLK_SOURCE_LOCAL: /* we output the clock, clk_div in range [1..8]. */ ++ tmp = ((pdev->clk_div - 1) << 16) | VLYNQ_CTL_CLKDIR_MASK ; ++ VLYNQ_CTRL_REG = tmp; ++ VLYNQ_R_CTRL_REG = 0ul; ++ break; ++ case VLYNQ_CLK_SOURCE_REMOTE: /* we need to set the clock pin as input */ ++ VLYNQ_CTRL_REG = 0ul; ++ tmp = ((pdev->clk_div - 1) << 16) | VLYNQ_CTL_CLKDIR_MASK ; ++ VLYNQ_R_CTRL_REG = tmp; ++ break; ++ default: /* do nothing about the clock, but clear other bits. */ ++ tmp = ~(VLYNQ_CTL_CLKDIR_MASK | VLYNQ_CTL_CLKDIV_MASK); ++ VLYNQ_CTRL_REG &= tmp; ++ break; ++ } +} + -+void __init ar7_time_init(void) ++ /* ---------------------------------------------------------------------------- ++ * Function : vlynq_link_check() ++ * Description: This function checks the current VLYNQ for a link. ++ * An arbitrary amount of time is allowed for the link to come up . ++ * Returns 0 for "no link / failure " and 1 for "link available". ++ * ----------------------------------------------------------------------------- ++ */ ++unsigned int vlynq_link_check( VLYNQ_DEV * pdev) +{ -+ unsigned long flags; -+ unsigned int est_freq; ++ /*sleep for 64 cycles, allow link to come up*/ ++ vlynq_delay(64); ++ ++ /* check status register return OK if link is found. */ ++ if (VLYNQ_STATUS_REG & VLYNQ_STS_LINK_MASK) ++ { ++ return 1; /* Link Available */ ++ } ++ else ++ { ++ return 0; /* Link Failure */ ++ } ++} ++ ++/* ---------------------------------------------------------------------------- ++ * Function : vlynq_init() ++ * Description: Initialization function accepting paramaters for VLYNQ module ++ * initialization. The Options bitmap decides what operations are performed ++ * as a part of initialization. The Input parameters are obtained through the ++ * sub fields of VLYNQ_DEV structure. ++ */ ++ ++int vlynq_init(VLYNQ_DEV *pdev, VLYNQ_INIT_OPTIONS options) ++{ ++ unsigned int map; ++ unsigned int val=0,cnt,tmp; ++ unsigned int counter=0; ++ VLYNQ_INTERRUPT_CNTRL *intSetting=NULL; ++ ++ /* validate arguments */ ++ if( VLYNQ_OUTRANGE(pdev->clk_source, VLYNQ_CLK_SOURCE_REMOTE, VLYNQ_CLK_SOURCE_NONE) || ++ VLYNQ_OUTRANGE(pdev->clk_div, 8, 1) ) ++ { ++ return VLYNQ_INVALID_ARG; ++ } ++ ++ /** perform all sanity checks first **/ ++ if(pdev->state != VLYNQ_DRV_STATE_UNINIT) ++ return VLYNQ_INVALID_DRV_STATE; ++ ++ /** Initialize local and remote register set addresses- additional ++ * provision to access the registers directly if need be */ ++ pdev->local = (VLYNQ_REG_SET*)pdev->module_base; ++ pdev->remote = (VLYNQ_REG_SET*) (pdev->module_base + VLYNQ_REMOTE_REGS_OFFSET); ++ ++ /* Detect faulty int configuration that might induce int pkt looping */ ++ if ( (options & VLYNQ_INIT_LOCAL_INTERRUPTS) && (options & VLYNQ_INIT_REMOTE_INTERRUPTS) ) ++ { ++ /* case when both local and remote are configured */ ++ if((pdev->local_irq.intLocal== VLYNQ_INT_REMOTE ) /* interrupts transfered to remote from local */ ++ && (pdev->remote_irq.intLocal== VLYNQ_INT_REMOTE) /* interrupts transfered from remote to local */ ++ && ((pdev->local_irq.intRemote == VLYNQ_INT_ROOT_ISR) || (pdev->remote_irq.intRemote == VLYNQ_INT_ROOT_ISR)) ) ++ { ++ return (VLYNQ_INT_CONFIG_ERR); ++ } ++ } ++ ++ pdev->state = VLYNQ_DRV_STATE_ININIT; ++ pdev->intCount = 0; ++ pdev->isrCount = 0; ++ ++ /*** Its assumed that the vlynq module has been brought out of reset ++ * before invocation of vlynq_init. Since, this operation is board specific ++ * it must be handled outside this generic driver */ ++ ++ /* Assert reset the remote device, call reset_cb, ++ * reset CB holds Reset according to the device needs. */ ++ VLYNQ_RESETCB(VLYNQ_RESET_ASSERT); ++ ++ /* Handle VLYNQ clock, HW default (Sense On Reset) is ++ * usually input for all the devices. */ ++ if (options & VLYNQ_INIT_CONFIG_CLOCK) ++ { ++ vlynq_configClock(pdev); ++ } ++ ++ /* Call reset_cb again. It will release the remote device ++ * from reset, and wait for a while. */ ++ VLYNQ_RESETCB(VLYNQ_RESET_DEASSERT); ++ ++ if(options & VLYNQ_INIT_CHECK_LINK ) ++ { ++ /* Check for link up during initialization*/ ++ while( counter < 25 ) ++ { ++ /* loop around giving a chance for link status to settle down */ ++ counter++; ++ if(vlynq_link_check(pdev)) ++ { ++ /* Link is up exit loop*/ ++ break; ++ } ++ ++ vlynq_delay(4000); ++ }/*end of while counter loop */ ++ ++ if(!vlynq_link_check(pdev)) ++ { ++ /* Handle this case as abort */ ++ pdev->state = VLYNQ_DRV_STATE_ERROR; ++ VLYNQ_RESETCB( VLYNQ_RESET_INITFAIL); ++ return VLYNQ_LINK_DOWN; ++ }/* end of if not vlynq_link_check conditional block */ ++ ++ }/*end of if options & VLYNQ_INIT_CHECK_LINK conditional block */ ++ ++ ++ if (options & VLYNQ_INIT_LOCAL_MEM_REGIONS) ++ { ++ /* Initialise local memory regions . This initialization lets ++ * the local host access remote device memory regions*/ ++ int i; ++ ++ /* configure the VLYNQ portal window to a PHYSICAL ++ * address of the local CPU */ ++ VLYNQ_ALIGN4(pdev->local_mem.Txmap); ++ VLYNQ_TXMAP_REG = (pdev->local_mem.Txmap); ++ ++ /*This code assumes input parameter is itself a physical address */ ++ for(i=0; i < VLYNQ_MAX_MEMORY_REGIONS ; i++) ++ { ++ /* Physical address on the remote */ ++ map = i+1; ++ VLYNQ_R_RXMAP_SIZE_REG(map) = 0; ++ if( pdev->remote_mem.RxSize[i]) ++ { ++ VLYNQ_ALIGN4(pdev->remote_mem.RxOffset[i]); ++ VLYNQ_ALIGN4(pdev->remote_mem.RxSize[i]); ++ VLYNQ_R_RXMAP_OFFSET_REG(map) = pdev->remote_mem.RxOffset[i]; ++ VLYNQ_R_RXMAP_SIZE_REG(map) = pdev->remote_mem.RxSize[i]; ++ } ++ } ++ } ++ ++ if(options & VLYNQ_INIT_REMOTE_MEM_REGIONS ) ++ { ++ int i; ++ ++ /* Initialise remote memory regions. This initialization lets remote ++ * device access local host memory regions. It configures the VLYNQ portal ++ * window to a PHYSICAL address of the remote */ ++ VLYNQ_ALIGN4(pdev->remote_mem.Txmap); ++ VLYNQ_R_TXMAP_REG = pdev->remote_mem.Txmap; ++ ++ for( i=0; ilocal_mem.RxSize[i]) ++ { ++ VLYNQ_ALIGN4(pdev->local_mem.RxOffset[i]); ++ VLYNQ_ALIGN4(pdev->local_mem.RxSize[i]); ++ VLYNQ_RXMAP_OFFSET_REG(map) = (pdev->local_mem.RxOffset[i]); ++ VLYNQ_RXMAP_SIZE_REG(map) = (pdev->local_mem.RxSize[i]); ++ } ++ } ++ } ++ ++ /* Adapted from original vlynq driver from cable - Calculate VLYNQ bus width */ ++ pdev->width = 3 + VLYNQ_STATUS_FLD_WIDTH(VLYNQ_STATUS_REG) ++ + VLYNQ_STATUS_FLD_WIDTH(VLYNQ_R_STATUS_REG); ++ ++ /* chance to initialize the device, e.g. to boost VLYNQ ++ * clock by modifying pdev->clk_div or and verify the width. */ ++ VLYNQ_RESETCB(VLYNQ_RESET_LINKESTABLISH); ++ ++ /* Handle VLYNQ clock, HW default (Sense On Reset) is ++ * usually input for all the devices. */ ++ if(options & VLYNQ_INIT_CONFIG_CLOCK ) ++ { ++ vlynq_configClock(pdev); ++ } ++ ++ /* last check for link*/ ++ if(options & VLYNQ_INIT_CHECK_LINK ) ++ { ++ /* Final Check for link during initialization*/ ++ while( counter < 25 ) ++ { ++ /* loop around giving a chance for link status to settle down */ ++ counter++; ++ if(vlynq_link_check(pdev)) ++ { ++ /* Link is up exit loop*/ ++ break; ++ } ++ ++ vlynq_delay(4000); ++ }/*end of while counter loop */ ++ ++ if(!vlynq_link_check(pdev)) ++ { ++ /* Handle this case as abort */ ++ pdev->state = VLYNQ_DRV_STATE_ERROR; ++ VLYNQ_RESETCB( VLYNQ_RESET_INITFAIL); ++ return VLYNQ_LINK_DOWN; ++ }/* end of if not vlynq_link_check conditional block */ ++ ++ } /* end of if options & VLYNQ_INIT_CHECK_LINK */ ++ ++ if(options & VLYNQ_INIT_LOCAL_INTERRUPTS ) ++ { ++ /* Configure local interrupt settings */ ++ intSetting = &(pdev->local_irq); ++ ++ /* Map local module status interrupts to interrupt vector*/ ++ val = intSetting->map_vector << VLYNQ_CTL_INTVEC_SHIFT ; ++ ++ /* enable local module status interrupts */ ++ val |= 0x01 << VLYNQ_CTL_INTEN_SHIFT; ++ ++ if ( intSetting->intLocal == VLYNQ_INT_LOCAL ) ++ { ++ /*set the intLocal bit*/ ++ val |= 0x01 << VLYNQ_CTL_INTLOCAL_SHIFT; ++ } ++ ++ /* Irrespective of whether interrupts are handled locally, program ++ * int2Cfg. Error checking for accidental loop(when intLocal=0 and int2Cfg=1 ++ * i.e remote packets are set intPending register->which will result in ++ * same packet being sent out) has been done already ++ */ ++ ++ if (intSetting->intRemote == VLYNQ_INT_ROOT_ISR) ++ { ++ /* Set the int2Cfg register, so that remote interrupt ++ * packets are written to intPending register */ ++ val |= 0x01 << VLYNQ_CTL_INT2CFG_SHIFT; ++ ++ /* Set intPtr register to point to intPending register */ ++ VLYNQ_INT_PTR_REG = VLYNQ_INT_PENDING_REG_PTR ; ++ } ++ else ++ { ++ /*set the interrupt pointer register*/ ++ VLYNQ_INT_PTR_REG = intSetting->intr_ptr; ++ /* Dont bother to modify int2Cfg as it would be zero */ ++ } ++ ++ /** Clear bits related to INT settings in control register **/ ++ VLYNQ_CTRL_REG = VLYNQ_CTRL_REG & (~VLYNQ_CTL_INTFIELDS_CLEAR_MASK); ++ ++ /** Or the bits to be set with Control register **/ ++ VLYNQ_CTRL_REG = VLYNQ_CTRL_REG | val; ++ ++ /* initialise local ICB */ ++ if(vlynqInterruptInit(pdev)==VLYNQ_MEMALLOC_FAIL) ++ return VLYNQ_MEMALLOC_FAIL; ++ ++ /* Install handler for local module status interrupts. By default when ++ * local interrupt setting is initialised, the local module status are ++ * enabled and handler hooked up */ ++ if(vlynq_install_isr(pdev, intSetting->map_vector, vlynq_local_module_isr, ++ pdev, NULL, NULL) == VLYNQ_INVALID_ARG) ++ return VLYNQ_INVALID_ARG; ++ } /* end of init local interrupts */ ++ ++ if(options & VLYNQ_INIT_REMOTE_INTERRUPTS ) ++ { ++ /* Configure remote interrupt settings from configuration */ ++ intSetting = &(pdev->remote_irq); ++ ++ /* Map remote module status interrupts to remote interrupt vector*/ ++ val = intSetting->map_vector << VLYNQ_CTL_INTVEC_SHIFT ; ++ /* enable remote module status interrupts */ ++ val |= 0x01 << VLYNQ_CTL_INTEN_SHIFT; ++ ++ if ( intSetting->intLocal == VLYNQ_INT_LOCAL ) ++ { ++ /*set the intLocal bit*/ ++ val |= 0x01 << VLYNQ_CTL_INTLOCAL_SHIFT; ++ } ++ ++ /* Irrespective of whether interrupts are handled locally, program ++ * int2Cfg. Error checking for accidental loop(when intLocal=0 and int2Cfg=1 ++ * i.e remote packets are set intPending register->which will result in ++ * same packet being sent out) has been done already ++ */ ++ ++ if (intSetting->intRemote == VLYNQ_INT_ROOT_ISR) ++ { ++ /* Set the int2Cfg register, so that remote interrupt ++ * packets are written to intPending register */ ++ val |= 0x01 << VLYNQ_CTL_INT2CFG_SHIFT; ++ /* Set intPtr register to point to intPending register */ ++ VLYNQ_R_INT_PTR_REG = VLYNQ_R_INT_PENDING_REG_PTR ; ++ } ++ else ++ { ++ /*set the interrupt pointer register*/ ++ VLYNQ_R_INT_PTR_REG = intSetting->intr_ptr; ++ /* Dont bother to modify int2Cfg as it would be zero */ ++ } ++ ++ if( (intSetting->intLocal == VLYNQ_INT_REMOTE) && ++ (options & VLYNQ_INIT_LOCAL_INTERRUPTS) && ++ (pdev->local_irq.intRemote == VLYNQ_INT_ROOT_ISR) ) ++ { ++ /* Install handler for remote module status interrupts. By default when ++ * remote interrupts are forwarded to local root_isr then remote_module_isr is ++ * enabled and handler hooked up */ ++ if(vlynq_install_isr(pdev,intSetting->map_vector,vlynq_remote_module_isr, ++ pdev, NULL, NULL) == VLYNQ_INVALID_ARG) ++ return VLYNQ_INVALID_ARG; ++ } + -+ set_except_vector(0, mipsIRQ); -+ write_c0_count(0); ++ ++ /** Clear bits related to INT settings in control register **/ ++ VLYNQ_R_CTRL_REG = VLYNQ_R_CTRL_REG & (~VLYNQ_CTL_INTFIELDS_CLEAR_MASK); ++ ++ /** Or the bits to be set with the remote Control register **/ ++ VLYNQ_R_CTRL_REG = VLYNQ_R_CTRL_REG | val; ++ ++ } /* init remote interrupt settings*/ + -+ printk("calculating r4koff... "); -+ r4k_offset = cal_r4koff(); -+ printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); ++ if(options & VLYNQ_INIT_CLEAR_ERRORS ) ++ { ++ /* Clear errors during initialization */ ++ tmp = VLYNQ_STATUS_REG & (VLYNQ_STS_RERROR_MASK | VLYNQ_STS_LERROR_MASK); ++ VLYNQ_STATUS_REG = tmp; ++ tmp = VLYNQ_R_STATUS_REG & (VLYNQ_STS_RERROR_MASK | VLYNQ_STS_LERROR_MASK); ++ VLYNQ_R_STATUS_REG = tmp; ++ } ++ ++ /* clear int status */ ++ val = VLYNQ_INT_STAT_REG; ++ VLYNQ_INT_STAT_REG = val; ++ ++ /* finish initialization */ ++ pdev->state = VLYNQ_DRV_STATE_RUN; ++ VLYNQ_RESETCB( VLYNQ_RESET_INITOK); ++ return VLYNQ_SUCCESS; + -+ est_freq = 2*r4k_offset*HZ; -+ est_freq += 5000; /* round */ -+ est_freq -= est_freq%10000; -+ printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, -+ (est_freq%1000000)*100/1000000); +} + -+void __init ar7_timer_setup(struct irqaction *irq) ++ ++/* ---------------------------------------------------------------------------- ++ * Function : vlynqInterruptInit() ++ * Description: This local function is used to set up the ICB table for the ++ * VLYNQ_STATUS_REG vlynq module. The input parameter "pdev" points the vlynq ++ * device instance whose ICB is allocated. ++ * Return : returns VLYNQ_SUCCESS or vlynq error for failure ++ * ----------------------------------------------------------------------------- ++ */ ++static int vlynqInterruptInit(VLYNQ_DEV *pdev) +{ -+ /* we are using the cpu counter for timer interrupts */ -+ irq->handler = no_action; /* we use our own handler */ -+ setup_irq(MIPS_CPU_TIMER_IRQ, irq); ++ int i, numslots; ++ ++ /* Memory allocated statically. ++ * Initialise ICB,free list.Indicate primary slot empty. ++ * Intialise intVector <==> map_vector translation table*/ ++ for(i=0; i < VLYNQ_NUM_INT_BITS; i++) ++ { ++ pdev->pIntrCB[i].isr = NULL; ++ pdev->pIntrCB[i].next = NULL; /*nothing chained */ ++ pdev->vector_map[i] = -1; /* indicates unmapped */ ++ } ++ ++ /* In the ICB slots, [VLYNQ_NUM_INT_BITS i.e 32 to ICB array size) are expansion slots ++ * required only when interrupt chaining/sharing is supported. In case ++ * of chained interrupts the list starts from primary slot and the ++ * additional slots are obtained from the common free area */ ++ ++ /* Initialise freelist */ ++ ++ numslots = VLYNQ_NUM_INT_BITS + VLYNQ_IVR_CHAIN_SLOTS; ++ ++ if (numslots > VLYNQ_NUM_INT_BITS) ++ { ++ pdev->freelist = &(pdev->pIntrCB[VLYNQ_NUM_INT_BITS]); ++ ++ for(i = VLYNQ_NUM_INT_BITS; i < (numslots-1) ; i++) ++ { ++ pdev->pIntrCB[i].next = &(pdev->pIntrCB[i+1]); ++ pdev->pIntrCB[i].isr = NULL; ++ } ++ pdev->pIntrCB[i].next=NULL; /* Indicate end of freelist*/ ++ pdev->pIntrCB[i].isr=NULL; ++ } ++ else ++ { ++ pdev->freelist = NULL; ++ } + -+ r4k_cur = (read_c0_count() + r4k_offset); -+ write_c0_compare(r4k_cur); -+ set_c0_status(ALLINTS); ++ /** Reset mapping for IV 0-7 **/ ++ VLYNQ_IVR_03TO00_REG = 0; ++ VLYNQ_IVR_07TO04_REG = 0; ++ ++ return VLYNQ_SUCCESS; +} -diff -urN kernel-base/arch/mips/config-shared.in kernel-current/arch/mips/config-shared.in ---- kernel-base/arch/mips/config-shared.in 2005-07-10 03:00:44.784181376 +0200 -+++ kernel-current/arch/mips/config-shared.in 2005-07-10 06:40:39.589266104 +0200 -@@ -20,6 +20,16 @@ - mainmenu_option next_comment - comment 'Machine selection' - dep_bool 'Support for Acer PICA 1 chipset (EXPERIMENTAL)' CONFIG_ACER_PICA_61 $CONFIG_EXPERIMENTAL -+dep_bool 'Support for Texas Instruments AR7 (EXPERIMENTAL)' CONFIG_AR7 $CONFIG_MIPS32 $CONFIG_EXPERIMENTAL -+if [ "$CONFIG_AR7" = "y" ]; then -+ choice 'Texas Instruments Reference Platform' \ -+ "AR7DB CONFIG_AR7DB \ -+ AR7RD CONFIG_AR7RD \ -+ AR7WRD CONFIG_AR7WRD" AR7DB -+ int 'Texas Instruments AR7 CPU Frequency' CONFIG_AR7_CPU_FREQUENCY 150 -+ int 'Texas Instruments AR7 System Frequency' CONFIG_AR7_SYS_FREQUENCY 125 -+ hex 'Texas Instruments AR7 SDRAM Start' CONFIG_AR7_MEMORY 0x14000000 -+fi - dep_bool 'Support for Alchemy Bosporus board' CONFIG_MIPS_BOSPORUS $CONFIG_MIPS32 - dep_bool 'Support for FIC Multimedia Player board' CONFIG_MIPS_FICMMP $CONFIG_MIPS32 - dep_bool 'Support for Alchemy Mirage board' CONFIG_MIPS_MIRAGE $CONFIG_MIPS32 -@@ -239,6 +249,11 @@ - define_bool CONFIG_NONCOHERENT_IO y - define_bool CONFIG_PC_KEYB y - fi -+if [ "$CONFIG_AR7" = "y" ]; then -+ define_bool CONFIG_NONCOHERENT_IO y -+ define_bool CONFIG_SWAP_IO_SPACE y -+ define_bool CONFIG_AR7_PAGING y -+fi - if [ "$CONFIG_CASIO_E55" = "y" ]; then - define_bool CONFIG_IRQ_CPU y - define_bool CONFIG_NONCOHERENT_IO y -@@ -736,6 +751,7 @@ - mainmenu_option next_comment - comment 'General setup' - if [ "$CONFIG_ACER_PICA_61" = "y" -o \ -+ "$CONFIG_AR7" = "y" -o \ - "$CONFIG_CASIO_E55" = "y" -o \ - "$CONFIG_DDB5074" = "y" -o \ - "$CONFIG_DDB5476" = "y" -o \ -@@ -797,6 +813,7 @@ - bool 'Networking support' CONFIG_NET - - if [ "$CONFIG_ACER_PICA_61" = "y" -o \ -+ "$CONFIG_AR7" = "y" -o \ - "$CONFIG_CASIO_E55" = "y" -o \ - "$CONFIG_DECSTATION" = "y" -o \ - "$CONFIG_IBM_WORKPAD" = "y" -o \ -diff -urN kernel-base/arch/mips/kernel/irq.c kernel-current/arch/mips/kernel/irq.c ---- kernel-base/arch/mips/kernel/irq.c 2005-07-10 03:00:44.784181376 +0200 -+++ kernel-current/arch/mips/kernel/irq.c 2005-07-10 06:40:39.589266104 +0200 -@@ -76,6 +76,7 @@ - * Generic, controller-independent functions: - */ - -+#ifndef CONFIG_AR7 - int get_irq_list(char *buf) - { - int i, j; -@@ -110,6 +111,7 @@ - p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); - return p - buf; - } -+#endif - - #ifdef CONFIG_SMP - int global_irq_holder = NO_PROC_ID; -@@ -525,6 +527,7 @@ - * - */ - -+#ifndef CONFIG_AR7 - int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, -@@ -569,6 +572,7 @@ - kfree(action); - return retval; - } -+#endif - - /** - * free_irq - free an interrupt -@@ -588,6 +592,7 @@ - * the machine. - */ - -+#ifndef CONFIG_AR7 - void free_irq(unsigned int irq, void *dev_id) - { - irq_desc_t *desc; -@@ -629,6 +634,7 @@ - return; - } - } -+#endif - - /* - * IRQ autodetection code.. -diff -urN kernel-base/arch/mips/kernel/mips_ksyms.c kernel-current/arch/mips/kernel/mips_ksyms.c ---- kernel-base/arch/mips/kernel/mips_ksyms.c 2004-02-18 14:36:30.000000000 +0100 -+++ kernel-current/arch/mips/kernel/mips_ksyms.c 2005-07-10 10:08:15.469684456 +0200 -@@ -40,6 +40,10 @@ - extern long __strnlen_user_nocheck_asm(const char *s); - extern long __strnlen_user_asm(const char *s); - -+#ifdef CONFIG_AR7 -+extern int avalanche_request_pacing(int irq_nr, unsigned int blk_num, unsigned int pace_value); -+#endif -+ - EXPORT_SYMBOL(mips_machtype); - #ifdef CONFIG_EISA - EXPORT_SYMBOL(EISA_bus); -@@ -102,4 +106,8 @@ - EXPORT_SYMBOL(ide_ops); - #endif - -+#ifdef CONFIG_AR7 -+EXPORT_SYMBOL_NOVERS(avalanche_request_pacing); -+#endif + - EXPORT_SYMBOL(get_wchan); -diff -urN kernel-base/arch/mips/kernel/setup.c kernel-current/arch/mips/kernel/setup.c ---- kernel-base/arch/mips/kernel/setup.c 2005-07-10 03:00:44.785181224 +0200 -+++ kernel-current/arch/mips/kernel/setup.c 2005-07-10 06:40:39.590265952 +0200 -@@ -109,6 +109,7 @@ - unsigned long isa_slot_offset; - EXPORT_SYMBOL(isa_slot_offset); - -+extern void avalanche_bootmem_init(void); - extern void SetUpBootInfo(void); - extern void load_mmu(void); - extern asmlinkage void start_kernel(void); -@@ -267,6 +268,9 @@ - #endif /* CONFIG_BLK_DEV_INITRD */ - - /* Find the highest page frame number we have available. */ -+#ifdef CONFIG_AR7_PAGING -+ avalanche_bootmem_init(); -+#else - max_pfn = 0; - first_usable_pfn = -1UL; - for (i = 0; i < boot_mem_map.nr_map; i++) { -@@ -377,6 +381,7 @@ - /* Reserve the bootmap memory. */ - reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size); - -+#endif - #ifdef CONFIG_BLK_DEV_INITRD - /* Board specific code should have set up initrd_start and initrd_end */ - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); -@@ -494,6 +499,7 @@ - void hp_setup(void); - void au1x00_setup(void); - void frame_info_init(void); -+ void ar7_setup(void); - - frame_info_init(); - #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) -@@ -691,6 +697,11 @@ - pmc_yosemite_setup(); - break; - #endif -+#ifdef CONFIG_AR7 -+ case MACH_GROUP_UNKNOWN: -+ ar7_setup(); -+ break; -+#endif - default: - panic("Unsupported architecture"); - } -diff -urN kernel-base/arch/mips/kernel/traps.c kernel-current/arch/mips/kernel/traps.c ---- kernel-base/arch/mips/kernel/traps.c 2005-07-10 03:00:44.786181072 +0200 -+++ kernel-current/arch/mips/kernel/traps.c 2005-07-10 06:40:39.591265800 +0200 -@@ -40,6 +40,10 @@ - #include - #include - -+#ifdef CONFIG_AR7 -+#include -+#endif ++/** remember that hooking up of root ISR handler with the interrupt controller ++ * is not done as a part of this driver. Typically, it must be done after ++ * invoking vlynq_init*/ + - extern asmlinkage void handle_mod(void); - extern asmlinkage void handle_tlbl(void); - extern asmlinkage void handle_tlbs(void); -@@ -869,9 +873,15 @@ - - exception_handlers[n] = handler; - if (n == 0 && cpu_has_divec) { -+#ifdef CONFIG_AR7 -+ *(volatile u32 *)(AVALANCHE_VECS_KSEG0+0x200) = 0x08000000 | -+ (0x03ffffff & (handler >> 2)); -+ flush_icache_range(AVALANCHE_VECS_KSEG0+0x200, AVALANCHE_VECS_KSEG0 + 0x204); -+#else - *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | - (0x03ffffff & (handler >> 2)); - flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); -+#endif - } - return (void *)old_handler; - } -@@ -920,14 +930,46 @@ - void __init trap_init(void) - { - extern char except_vec1_generic; -+ extern char except_vec2_generic; - extern char except_vec3_generic, except_vec3_r4000; - extern char except_vec_ejtag_debug; - extern char except_vec4; - unsigned long i; - -+#ifdef CONFIG_AR7 -+ extern char jump_tlb_miss, jump_tlb_miss_unused; -+ extern char jump_cache_error,jump_general_exception; -+ extern char jump_dedicated_interrupt; -+ clear_c0_status(ST0_BEV); -+#endif + - /* Copy the generic exception handler code to it's final destination. */ - memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80); -+ memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); -+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); - -+ memcpy((void *)(KSEG0 + 0x0), &jump_tlb_miss, 0x80); -+ memcpy((void *)(KSEG0 + 0x80), &jump_tlb_miss_unused, 0x80); -+ memcpy((void *)(KSEG0 + 0x100), &jump_cache_error, 0x80); -+ memcpy((void *)(KSEG0 + 0x180), &jump_general_exception, 0x80); -+ memcpy((void *)(KSEG0 + 0x200), &jump_dedicated_interrupt, 0x80); ++ /* ---------------------------------------------------------------------------- ++ * ISR with the SOC interrupt controller. This ISR typically scans ++ * the Int PENDING/SET register in the VLYNQ module and calls the ++ * appropriate ISR associated with the correponding vector number. ++ * ----------------------------------------------------------------------------- ++ */ ++void vlynq_root_isr(void *arg) ++{ ++ int source; /* Bit position of pending interrupt, start from 0 */ ++ unsigned int interrupts, clrInterrupts; ++ VLYNQ_DEV * pdev; ++ VLYNQ_INTR_CNTRL_ICB *entry; + -+#ifdef CONFIG_AR7 -+ memcpy((void *)(AVALANCHE_VECS_KSEG0 + 0x80), &except_vec1_generic, 0x80); -+ memcpy((void *)(AVALANCHE_VECS_KSEG0 + 0x100), &except_vec2_generic, 0x80); -+ memcpy((void *)(AVALANCHE_VECS_KSEG0 + 0x180), &except_vec3_generic, 0x80); -+ flush_icache_range(AVALANCHE_VECS_KSEG0, AVALANCHE_VECS_KSEG0 + 0x200); -+ -+ memcpy((void *)(KSEG0 + 0x0), &jump_tlb_miss, 0x80); -+ memcpy((void *)(KSEG0 + 0x80), &jump_tlb_miss_unused, 0x80); -+ memcpy((void *)(KSEG0 + 0x100), &jump_cache_error, 0x80); -+ memcpy((void *)(KSEG0 + 0x180), &jump_general_exception, 0x80); -+ memcpy((void *)(KSEG0 + 0x200), &jump_dedicated_interrupt, 0x80); -+#else -+ memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80); -+#endif -+ flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x200); -+ - /* - * Setup default vectors - */ -@@ -951,8 +993,12 @@ - * Some MIPS CPUs have a dedicated interrupt vector which reduces the - * interrupt processing overhead. Use it where available. - */ -+#ifdef CONFIG_AR7 -+ memcpy((void *)(AVALANCHE_VECS_KSEG0 + 0x200), &except_vec4, 8); -+#else - if (cpu_has_divec) - memcpy((void *)(KSEG0 + 0x200), &except_vec4, 8); -+#endif - - /* - * Some CPUs can enable/disable for cache parity detection, but does -@@ -991,12 +1037,17 @@ - if (cpu_has_mcheck) - set_except_vector(24, handle_mcheck); - -+memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); -+#ifdef CONFIG_AR7 -+ memcpy((void *)(AVALANCHE_VECS_KSEG0 + 0x180), &except_vec3_generic, 0x80); -+#else - if (cpu_has_vce) - memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); - else if (cpu_has_4kex) - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); - else - memcpy((void *)(KSEG0 + 0x080), &except_vec3_generic, 0x80); -+#endif - - if (current_cpu_data.cputype == CPU_R6000 || - current_cpu_data.cputype == CPU_R6000A) { -@@ -1023,7 +1074,11 @@ - if (board_nmi_handler_setup) - board_nmi_handler_setup(); - -+#ifdef CONFIG_AR7 -+ flush_icache_range(AVALANCHE_VECS_KSEG0, AVALANCHE_VECS_KSEG0 + 0x200); -+#else - flush_icache_range(KSEG0, KSEG0 + 0x400); -+#endif - - per_cpu_trap_init(); - } -diff -urN kernel-base/arch/mips/lib/promlib.c kernel-current/arch/mips/lib/promlib.c ---- kernel-base/arch/mips/lib/promlib.c 2005-07-10 03:00:44.786181072 +0200 -+++ kernel-current/arch/mips/lib/promlib.c 2005-07-10 06:40:39.591265800 +0200 -@@ -1,3 +1,4 @@ -+#ifndef CONFIG_AR7 - #include - #include - -@@ -22,3 +23,4 @@ - } - va_end(args); - } -+#endif -diff -urN kernel-base/arch/mips/Makefile kernel-current/arch/mips/Makefile ---- kernel-base/arch/mips/Makefile 2005-07-10 03:00:44.786181072 +0200 -+++ kernel-current/arch/mips/Makefile 2005-07-10 06:40:39.591265800 +0200 -@@ -369,6 +369,16 @@ - endif - - # -+# Texas Instruments AR7 -+# ++ pdev=(VLYNQ_DEV*)(arg); /*obtain the vlynq device pointer*/ ++ ++ interrupts = VLYNQ_INT_STAT_REG; /* Get the list of pending interrupts */ ++ VLYNQ_INT_STAT_REG = interrupts; /* clear the int CR register */ ++ clrInterrupts = interrupts; /* save them for further analysis */ + -+ifdef CONFIG_AR7 -+LIBS += arch/mips/ar7/ar7.o arch/mips/ar7/ar7/ar7.o -+SUBDIRS += arch/mips/ar7 arch/mips/ar7/ar7 -+LOADADDR += 0x94020000 -+endif ++ debugPrint("vlynq_root_isr: dev %u. INTCR = 0x%08lx\n", pdev->dev_idx, clrInterrupts,0,0,0,0); + -+# - # DECstation family - # - ifdef CONFIG_DECSTATION -diff -urN kernel-base/arch/mips/mm/init.c kernel-current/arch/mips/mm/init.c ---- kernel-base/arch/mips/mm/init.c 2005-07-10 03:00:44.787180920 +0200 -+++ kernel-current/arch/mips/mm/init.c 2005-07-10 07:09:29.914216728 +0200 -@@ -40,8 +40,10 @@ - - mmu_gather_t mmu_gathers[NR_CPUS]; - unsigned long highstart_pfn, highend_pfn; -+#ifndef CONFIG_AR7_PAGING - static unsigned long totalram_pages; - static unsigned long totalhigh_pages; -+#endif - - void pgd_init(unsigned long page) - { -@@ -235,6 +237,7 @@ - #endif - } - -+#ifndef CONFIG_AR7_PAGING - void __init paging_init(void) - { - unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; -@@ -272,6 +275,7 @@ - - free_area_init(zones_size); - } -+#endif - - #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) - #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) -@@ -298,6 +302,7 @@ - return 0; - } - -+#ifndef CONFIG_AR7_PAGING - void __init mem_init(void) - { - unsigned long codesize, reservedpages, datasize, initsize; -@@ -359,6 +364,7 @@ - initsize >> 10, - (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); - } -+#endif - - #ifdef CONFIG_BLK_DEV_INITRD - void free_initrd_mem(unsigned long start, unsigned long end) -@@ -376,6 +382,7 @@ - } - #endif - -+#ifndef CONFIG_AR7_PAGING - extern char __init_begin, __init_end; - extern void prom_free_prom_memory(void) __init; - -@@ -383,7 +390,9 @@ - { - unsigned long addr; - -+#ifndef CONFIG_AR7 - prom_free_prom_memory (); -+#endif - - addr = (unsigned long) &__init_begin; - while (addr < (unsigned long) &__init_end) { -@@ -409,3 +418,4 @@ - - return; - } -+#endif -diff -urN kernel-base/arch/mips/mm/tlb-r4k.c kernel-current/arch/mips/mm/tlb-r4k.c ---- kernel-base/arch/mips/mm/tlb-r4k.c 2005-07-10 03:00:44.787180920 +0200 -+++ kernel-current/arch/mips/mm/tlb-r4k.c 2005-07-10 06:40:39.592265648 +0200 -@@ -20,6 +20,10 @@ - #include - #include - -+#ifdef CONFIG_AR7 -+#include -+#endif ++ /* Scan interrupt bits */ ++ source =0; ++ while( clrInterrupts != 0) ++ { ++ /* test if bit is set? */ ++ if( 0x1ul & clrInterrupts) ++ { ++ entry = &(pdev->pIntrCB[source]); /* Get the ISR entry */ ++ pdev->intCount++; /* update interrupt count */ ++ if(entry->isr != NULL) ++ { ++ do ++ { ++ pdev->isrCount++; /* update isr invocation count */ ++ /* Call the user ISR and update the count for ISR */ ++ entry->isrCount++; ++ entry->isr(entry->arg1, entry->arg2, entry->arg3); ++ if (entry->next == NULL) break; ++ entry = entry->next; ++ ++ } while (entry->isr != NULL); ++ } ++ else ++ { ++ debugPrint(" ISR not installed for vlynq vector:%d\n",source,0,0,0,0,0); ++ } ++ } ++ clrInterrupts >>= 1; /* Next source bit */ ++ ++source; ++ } /* endWhile clrInterrupts != 0 */ ++} + - extern char except_vec0_nevada, except_vec0_r4000, except_vec0_r4600; - - /* CP0 hazard avoidance. */ -@@ -375,7 +379,12 @@ - else if (current_cpu_data.cputype == CPU_R4600) - memcpy((void *)KSEG0, &except_vec0_r4600, 0x80); - else -+#ifdef CONFIG_AR7 -+ memcpy((void *)AVALANCHE_VECS_KSEG0, &except_vec0_r4000, 0x80); -+ flush_icache_range(AVALANCHE_VECS_KSEG0, AVALANCHE_VECS_KSEG0 + 0x80); -+#else - memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); - flush_icache_range(KSEG0, KSEG0 + 0x80); -+#endif - } - } -diff -urN kernel-base/drivers/char/serial.c kernel-current/drivers/char/serial.c ---- kernel-base/drivers/char/serial.c 2005-07-10 03:00:44.789180616 +0200 -+++ kernel-current/drivers/char/serial.c 2005-07-10 06:42:02.902600552 +0200 -@@ -419,7 +419,40 @@ - return 0; - } - --#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_SEAD) -+#if defined(CONFIG_AR7) + -+static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset) ++ /* ---------------------------------------------------------------------------- ++ * Function : vlynq_local__module_isr() ++ * Description: This ISR is attached to the local VLYNQ interrupt vector ++ * by the Vlynq Driver when local interrupts are being handled. i.e. ++ * intLocal=1. This ISR handles local Vlynq module status interrupts only ++ * AS a part of this ISR, user callback in VLYNQ_DEV structure ++ * is invoked. ++ * VLYNQ_DEV is passed as arg1. arg2 and arg3 are unused. ++ * ----------------------------------------------------------------------------- ++ */ ++static void vlynq_local_module_isr(void *arg1,void *arg2, void *arg3) +{ -+ return (inb(info->port + (offset * 4)) & 0xff); -+} ++ VLYNQ_REPORT_CB func; ++ unsigned int dwStatRegVal; ++ VLYNQ_DEV * pdev; + ++ pdev = (VLYNQ_DEV*) arg1; ++ /* Callback function is read from the device pointer that is passed as an argument */ ++ func = pdev->report_cb; ++ ++ /* read local status register */ ++ dwStatRegVal = VLYNQ_STATUS_REG; ++ ++ /* clear pending events */ ++ VLYNQ_STATUS_REG = dwStatRegVal; ++ ++ /* invoke user callback */ ++ if( func != NULL) ++ func( pdev, VLYNQ_LOCAL_DVC, dwStatRegVal); + -+static _INLINE_ unsigned int serial_inp(struct async_struct *info, int offset) -+{ -+#ifdef CONFIG_SERIAL_NOPAUSE_IO -+ return (inb(info->port + (offset * 4)) & 0xff); -+#else -+ return (inb_p(info->port + (offset * 4)) & 0xff); -+#endif +} + -+static _INLINE_ void serial_out(struct async_struct *info, int offset, int value) ++ /* ---------------------------------------------------------------------------- ++ * Function : vlynq_remote_module_isr() ++ * Description: This ISR is attached to the remote VLYNQ interrupt vector ++ * by the Vlynq Driver when remote interrupts are being handled locally. i.e. ++ * intLocal=1. This ISR handles local Vlynq module status interrupts only ++ * AS a part of this ISR, user callback in VLYNQ_DEV structure ++ * is invoked. ++ * The parameters irq,regs ar unused. ++ * ----------------------------------------------------------------------------- ++ */ ++static void vlynq_remote_module_isr(void *arg1,void *arg2, void *arg3) +{ -+ outb(value, info->port + (offset * 4)); ++ VLYNQ_REPORT_CB func; ++ unsigned int dwStatRegVal; ++ VLYNQ_DEV * pdev; ++ ++ ++ pdev = (VLYNQ_DEV*) arg1; ++ ++ /* Callback function is read from the device pointer that is passed as an argument */ ++ func = pdev->report_cb; ++ ++ /* read local status register */ ++ dwStatRegVal = VLYNQ_R_STATUS_REG; ++ ++ /* clear pending events */ ++ VLYNQ_R_STATUS_REG = dwStatRegVal; ++ ++ /* invoke user callback */ ++ if( func != NULL) ++ func( pdev, VLYNQ_REMOTE_DVC, dwStatRegVal); ++ +} + ++/* ---------------------------------------------------------------------------- ++ * Function : vlynq_interrupt_get_count() ++ * Description: This function returns the number of times a particular intr ++ * has been invoked. ++ * ++ * It returns 0, if erroneous map_vector is specified or if the corres isr ++ * has not been registered with VLYNQ. ++ */ ++unsigned int vlynq_interrupt_get_count(VLYNQ_DEV *pdev, ++ unsigned int map_vector) ++{ ++ VLYNQ_INTR_CNTRL_ICB *entry; ++ unsigned int count = 0; + -+static _INLINE_ void serial_outp(struct async_struct *info, int offset, ++ if (map_vector > (VLYNQ_NUM_INT_BITS-1)) ++ return count; ++ ++ entry = &(pdev->pIntrCB[map_vector]); ++ ++ if (entry) ++ count = entry->isrCount; ++ ++ return (count); ++} ++ ++ ++/* ---------------------------------------------------------------------------- ++ * Function : vlynq_install_isr() ++ * Description: This function installs ISR for Vlynq interrupt vector ++ * bits(in IntPending register). This function should be used only when ++ * Vlynq interrupts are being handled locally(remote may be programmed to send ++ * interrupt packets).Also, the int2cfg should be 1 and the least significant ++ * 8 bits of the Interrupt Pointer Register must point to Interrupt ++ * Pending/Set Register). ++ * If host int2cfg=0 and the Interrupt Pointer register contains ++ * the address of the interrupt set register in the interrupt controller ++ * module of the local device , then the ISR for the remote interrupt must be ++ * directly registered with the Interrupt controller and must not use this API ++ * Note: this function simply installs the ISR in ICB It doesnt modify ++ * any register settings ++ */ ++int ++vlynq_install_isr(VLYNQ_DEV *pdev, ++ unsigned int map_vector, ++ VLYNQ_INTR_CNTRL_ISR isr, ++ void *arg1, void *arg2, void *arg3) ++{ ++ VLYNQ_INTR_CNTRL_ICB *entry; ++ ++ if ( (map_vector > (VLYNQ_NUM_INT_BITS-1)) || (isr == NULL) ) ++ return VLYNQ_INVALID_ARG; ++ ++ entry = &(pdev->pIntrCB[map_vector]); ++ ++ if(entry->isr == NULL) ++ { ++ entry->isr = isr; ++ entry->arg1 = arg1; ++ entry->arg2 = arg2; ++ entry->arg3 = arg3; ++ entry->next = NULL; ++ } ++ else ++ { ++ /** No more empty slots,return error */ ++ if(pdev->freelist == NULL) ++ return VLYNQ_MEMALLOC_FAIL; ++ ++ while(entry->next != NULL) ++ { ++ entry = entry->next; ++ } ++ ++ /* Append new node to the chain */ ++ entry->next = pdev->freelist; ++ /* Remove the appended node from freelist */ ++ pdev->freelist = pdev->freelist->next; ++ entry= entry->next; ++ ++ /*** Set the ICB fields ***/ ++ entry->isr = isr; ++ entry->arg1 = arg1; ++ entry->arg2 = arg2; ++ entry->arg3 = arg3; ++ entry->next = NULL; ++ } ++ ++ return VLYNQ_SUCCESS; ++} ++ ++ ++ ++/* ---------------------------------------------------------------------------- ++ * Function : vlynq_uninstall_isr ++ * Description: This function is used to uninstall a previously ++ * registered ISR. In case of shared/chained interrupts, the ++ * void * arg parameter must uniquely identify the ISR to be ++ * uninstalled. ++ * Note: this function simply uninstalls the ISR in ICB ++ * It doesnt modify any register settings ++ */ ++int ++vlynq_uninstall_isr(VLYNQ_DEV *pdev, ++ unsigned int map_vector, ++ void *arg1, void *arg2, void *arg3) ++{ ++ VLYNQ_INTR_CNTRL_ICB *entry,*temp; ++ ++ if (map_vector > (VLYNQ_NUM_INT_BITS-1)) ++ return VLYNQ_INVALID_ARG; ++ ++ entry = &(pdev->pIntrCB[map_vector]); ++ ++ if(entry->isr == NULL ) ++ return VLYNQ_ISR_NON_EXISTENT; ++ ++ if ( (entry->arg1 == arg1) && (entry->arg2 == arg2) && (entry->arg3 == arg3) ) ++ { ++ if(entry->next == NULL) ++ { ++ entry->isr=NULL; ++ return VLYNQ_SUCCESS; ++ } ++ else ++ { ++ temp = entry->next; ++ /* Copy next node in the chain to prim.slot */ ++ entry->isr = temp->isr; ++ entry->arg1 = temp->arg1; ++ entry->arg2 = temp->arg2; ++ entry->arg3 = temp->arg3; ++ entry->next = temp->next; ++ /* Free the just copied node */ ++ temp->isr = NULL; ++ temp->arg1 = NULL; ++ temp->arg2 = NULL; ++ temp->arg3 = NULL; ++ temp->next = pdev->freelist; ++ pdev->freelist = temp; ++ return VLYNQ_SUCCESS; ++ } ++ } ++ else ++ { ++ temp = entry; ++ while ( (entry = temp->next) != NULL) ++ { ++ if ( (entry->arg1 == arg1) && (entry->arg2 == arg2) && (entry->arg3 == arg3) ) ++ { ++ /* remove node from chain */ ++ temp->next = entry->next; ++ /* Add the removed node to freelist */ ++ entry->isr = NULL; ++ entry->arg1 = NULL; ++ entry->arg2 = NULL; ++ entry->arg3 = NULL; ++ entry->next = pdev->freelist; ++ entry->isrCount = 0; ++ pdev->freelist = entry; ++ return VLYNQ_SUCCESS; ++ } ++ temp = entry; ++ } ++ ++ return VLYNQ_ISR_NON_EXISTENT; ++ } ++} ++ ++ ++ ++ ++/* ---------------------------------------------------------------------------- ++ * function : vlynq_interrupt_vector_set() ++ * description:configures interrupt vector mapping,interrupt type ++ * polarity -all in one go. ++ */ ++int ++vlynq_interrupt_vector_set(VLYNQ_DEV *pdev, /* vlynq device */ ++ unsigned int int_vector, /* int vector on vlynq device */ ++ unsigned int map_vector, /* bit for this interrupt */ ++ VLYNQ_DEV_TYPE dev_type, /* local or remote device */ ++ VLYNQ_INTR_POLARITY pol, /* polarity of interrupt */ ++ VLYNQ_INTR_TYPE type) /* pulsed/level interrupt */ ++{ ++ volatile unsigned int * vecreg; ++ unsigned int val=0; ++ unsigned int bytemask=0XFF; ++ ++ /* use the lower 8 bits of val to set the value , shift it to ++ * appropriate byte position in the ivr and write it to the ++ * corresponding register */ ++ ++ /* validate the number of interrupts supported */ ++ if (int_vector >= VLYNQ_IVR_MAXIVR) ++ return VLYNQ_INVALID_ARG; ++ ++ if(map_vector > (VLYNQ_NUM_INT_BITS - 1) ) ++ return VLYNQ_INVALID_ARG; ++ ++ if (dev_type == VLYNQ_LOCAL_DVC) ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector)); ++ } ++ else ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector)); ++ } ++ ++ /* Update the intVector<==> bit position translation table */ ++ pdev->vector_map[map_vector] = int_vector; ++ ++ /* val has been initialised to zero. we only have to turn on appropriate bits*/ ++ if(type == VLYNQ_INTR_PULSED) ++ val |= VLYNQ_IVR_INTTYPE_MASK; ++ ++ if(pol == VLYNQ_INTR_ACTIVE_LOW) ++ val |= VLYNQ_IVR_INTPOL_MASK; ++ ++ val |= map_vector; ++ ++ /** clear the correct byte position and then or val **/ ++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) ); ++ ++ /** write to correct byte position in vecreg*/ ++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ; ++ ++ /* Setting a interrupt vector, leaves the interrupt disabled ++ * which must be enabled subsequently */ ++ ++ return VLYNQ_SUCCESS; ++} ++ ++ ++/* ---------------------------------------------------------------------------- ++ * Function : vlynq_interrupt_vector_cntl() ++ * Description:enables/disable interrupt ++ */ ++int vlynq_interrupt_vector_cntl( VLYNQ_DEV *pdev, ++ unsigned int int_vector, ++ VLYNQ_DEV_TYPE dev_type, ++ unsigned int enable) ++{ ++ volatile unsigned int *vecReg; ++ unsigned int val=0; ++ unsigned int intenMask=0x80; ++ ++ /* validate the number of interrupts supported */ ++ if (int_vector >= VLYNQ_IVR_MAXIVR) ++ return VLYNQ_INVALID_ARG; ++ ++ if (dev_type == VLYNQ_LOCAL_DVC) ++ { ++ vecReg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector)); ++ } ++ else ++ { ++ vecReg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector)); ++ } ++ ++ /** Clear the correct byte position and then or val **/ ++ *vecReg = (*vecReg) & ( ~(intenMask << ( (int_vector %4)*8) ) ); ++ ++ if(enable) ++ { ++ val |= VLYNQ_IVR_INTEN_MASK; ++ /** Write to correct byte position in vecReg*/ ++ *vecReg = (*vecReg) | (val << ( (int_vector % 4)*8) ) ; ++ } ++ ++ return VLYNQ_SUCCESS; ++ ++}/* end of function vlynq_interrupt_vector_cntl */ ++ ++ ++ ++/* ---------------------------------------------------------------------------- ++ * Function : vlynq_interrupt_vector_map() ++ * Description:Configures interrupt vector mapping alone ++ */ ++int ++vlynq_interrupt_vector_map( VLYNQ_DEV *pdev, ++ VLYNQ_DEV_TYPE dev_type, ++ unsigned int int_vector, ++ unsigned int map_vector) ++{ ++ volatile unsigned int * vecreg; ++ unsigned int val=0; ++ unsigned int bytemask=0x1f; /* mask to turn off bits corresponding to int vector */ ++ ++ /* use the lower 8 bits of val to set the value , shift it to ++ * appropriate byte position in the ivr and write it to the ++ * corresponding register */ ++ ++ /* validate the number of interrupts supported */ ++ if (int_vector >= VLYNQ_IVR_MAXIVR) ++ return VLYNQ_INVALID_ARG; ++ ++ if(map_vector > (VLYNQ_NUM_INT_BITS - 1) ) ++ return VLYNQ_INVALID_ARG; ++ ++ if (dev_type == VLYNQ_LOCAL_DVC) ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector)); ++ } ++ else ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector)); ++ } ++ ++ /* Update the intVector<==> bit position translation table */ ++ pdev->vector_map[map_vector] = int_vector; ++ ++ /** val has been initialised to zero. we only have to turn on ++ * appropriate bits*/ ++ val |= map_vector; ++ ++ /** clear the correct byte position and then or val **/ ++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) ); ++ ++ /** write to correct byte position in vecreg*/ ++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ; ++ ++ return VLYNQ_SUCCESS; ++} ++ ++ ++/* ---------------------------------------------------------------------------- ++ * function : vlynq_interrupt_set_polarity() ++ * description:configures interrupt polarity . ++ */ ++int ++vlynq_interrupt_set_polarity( VLYNQ_DEV *pdev , ++ VLYNQ_DEV_TYPE dev_type, ++ unsigned int map_vector, ++ VLYNQ_INTR_POLARITY pol) ++{ ++ volatile unsigned int * vecreg; ++ int int_vector; ++ unsigned int val=0; ++ unsigned int bytemask=0x20; /** mask to turn off bits corresponding to int polarity */ ++ ++ /* get the int_vector from map_vector */ ++ int_vector = pdev->vector_map[map_vector]; ++ ++ if(int_vector == -1) ++ return VLYNQ_INTVEC_MAP_NOT_FOUND; ++ ++ /* use the lower 8 bits of val to set the value , shift it to ++ * appropriate byte position in the ivr and write it to the ++ * corresponding register */ ++ ++ if (dev_type == VLYNQ_LOCAL_DVC) ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector)); ++ } ++ else ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector)); ++ } ++ ++ /* val has been initialised to zero. we only have to turn on ++ * appropriate bits, if need be*/ ++ ++ /** clear the correct byte position and then or val **/ ++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) ); ++ ++ if( pol == VLYNQ_INTR_ACTIVE_LOW) ++ { ++ val |= VLYNQ_IVR_INTPOL_MASK; ++ /** write to correct byte position in vecreg*/ ++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ; ++ } ++ ++ return VLYNQ_SUCCESS; ++} ++ ++int vlynq_interrupt_get_polarity( VLYNQ_DEV *pdev , ++ VLYNQ_DEV_TYPE dev_type, ++ unsigned int map_vector) ++{ ++ volatile unsigned int * vecreg; ++ int int_vector; ++ unsigned int val=0; ++ ++ /* get the int_vector from map_vector */ ++ int_vector = pdev->vector_map[map_vector]; ++ ++ if (map_vector > (VLYNQ_NUM_INT_BITS-1)) ++ return(-1); ++ ++ if(int_vector == -1) ++ return VLYNQ_INTVEC_MAP_NOT_FOUND; ++ ++ /* use the lower 8 bits of val to set the value , shift it to ++ * appropriate byte position in the ivr and write it to the ++ * corresponding register */ ++ ++ if (dev_type == VLYNQ_LOCAL_DVC) ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector)); ++ } ++ else ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector)); ++ } ++ ++ /** read the information into val **/ ++ val = (*vecreg) & ((VLYNQ_IVR_INTPOL_MASK << ( (int_vector %4)*8) ) ); ++ ++ return (val ? (VLYNQ_INTR_ACTIVE_LOW) : (VLYNQ_INTR_ACTIVE_HIGH)); ++} ++ ++ ++/* ---------------------------------------------------------------------------- ++ * function : vlynq_interrupt_set_type() ++ * description:configures interrupt type . ++ */ ++int vlynq_interrupt_set_type( VLYNQ_DEV *pdev, ++ VLYNQ_DEV_TYPE dev_type, ++ unsigned int map_vector, ++ VLYNQ_INTR_TYPE type) ++{ ++ volatile unsigned int * vecreg; ++ unsigned int val=0; ++ int int_vector; ++ ++ /** mask to turn off bits corresponding to interrupt type */ ++ unsigned int bytemask=0x40; ++ ++ /* get the int_vector from map_vector */ ++ int_vector = pdev->vector_map[map_vector]; ++ if(int_vector == -1) ++ return VLYNQ_INTVEC_MAP_NOT_FOUND; ++ ++ /* use the lower 8 bits of val to set the value , shift it to ++ * appropriate byte position in the ivr and write it to the ++ * corresponding register */ ++ if (dev_type == VLYNQ_LOCAL_DVC) ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector)); ++ } ++ else ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector)); ++ } ++ ++ /** val has been initialised to zero. we only have to turn on ++ * appropriate bits if need be*/ ++ ++ /** clear the correct byte position and then or val **/ ++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) ); ++ ++ if( type == VLYNQ_INTR_PULSED) ++ { ++ val |= VLYNQ_IVR_INTTYPE_MASK; ++ /** write to correct byte position in vecreg*/ ++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ; ++ } ++ ++ return VLYNQ_SUCCESS; ++} ++ ++/* ---------------------------------------------------------------------------- ++ * function : vlynq_interrupt_get_type() ++ * description:returns interrupt type . ++ */ ++int vlynq_interrupt_get_type( VLYNQ_DEV *pdev, VLYNQ_DEV_TYPE dev_type, ++ unsigned int map_vector) ++{ ++ volatile unsigned int * vecreg; ++ unsigned int val=0; ++ int int_vector; ++ ++ if (map_vector > (VLYNQ_NUM_INT_BITS-1)) ++ return(-1); ++ ++ /* get the int_vector from map_vector */ ++ int_vector = pdev->vector_map[map_vector]; ++ if(int_vector == -1) ++ return VLYNQ_INTVEC_MAP_NOT_FOUND; ++ ++ /* use the lower 8 bits of val to set the value , shift it to ++ * appropriate byte position in the ivr and write it to the ++ * corresponding register */ ++ if (dev_type == VLYNQ_LOCAL_DVC) ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector)); ++ } ++ else ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector)); ++ } ++ ++ /** Read the correct bit position into val **/ ++ val = (*vecreg) & ((VLYNQ_IVR_INTTYPE_MASK << ( (int_vector %4)*8) ) ); ++ ++ return (val ? (VLYNQ_INTR_PULSED) : (VLYNQ_INTR_LEVEL)); ++} ++ ++/* ---------------------------------------------------------------------------- ++ * function : vlynq_interrupt_enable() ++ * description:Enable interrupt by writing to IVR register. ++ */ ++int vlynq_interrupt_enable( VLYNQ_DEV *pdev, ++ VLYNQ_DEV_TYPE dev_type, ++ unsigned int map_vector) ++{ ++ volatile unsigned int * vecreg; ++ unsigned int val=0; ++ int int_vector; ++ ++ /** mask to turn off bits corresponding to interrupt enable */ ++ unsigned int bytemask=0x80; ++ ++ /* get the int_vector from map_vector */ ++ int_vector = pdev->vector_map[map_vector]; ++ if(int_vector == -1) ++ return VLYNQ_INTVEC_MAP_NOT_FOUND; ++ ++ /* use the lower 8 bits of val to set the value , shift it to ++ * appropriate byte position in the ivr and write it to the ++ * corresponding register */ ++ ++ if (dev_type == VLYNQ_LOCAL_DVC) ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector)); ++ } ++ else ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector)); ++ } ++ ++ /** val has been initialised to zero. we only have to turn on ++ * bit corresponding to interrupt enable*/ ++ val |= VLYNQ_IVR_INTEN_MASK; ++ ++ /** clear the correct byte position and then or val **/ ++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) ); ++ ++ /** write to correct byte position in vecreg*/ ++ *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ; ++ ++ return VLYNQ_SUCCESS; ++} ++ ++ ++/* ---------------------------------------------------------------------------- ++ * function : vlynq_interrupt_disable() ++ * description:Disable interrupt by writing to IVR register. ++ */ ++int ++vlynq_interrupt_disable( VLYNQ_DEV *pdev, ++ VLYNQ_DEV_TYPE dev_type, ++ unsigned int map_vector) ++{ ++ volatile unsigned int * vecreg; ++ int int_vector; ++ ++ /** mask to turn off bits corresponding to interrupt enable */ ++ unsigned int bytemask=0x80; ++ ++ /* get the int_vector from map_vector */ ++ int_vector = pdev->vector_map[map_vector]; ++ if(int_vector == -1) ++ return VLYNQ_INTVEC_MAP_NOT_FOUND; ++ ++ /* use the lower 8 bits of val to set the value , shift it to ++ * appropriate byte position in the ivr and write it to the ++ * corresponding register */ ++ if (dev_type == VLYNQ_LOCAL_DVC) ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector)); ++ } ++ else ++ { ++ vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector)); ++ } ++ ++ /* We disable the interrupt by simply turning off the bit ++ * corresponding to Interrupt enable. ++ * Clear the interrupt enable bit in the correct byte position **/ ++ *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) ); ++ ++ /* Dont have to set any bit positions */ ++ ++ return VLYNQ_SUCCESS; ++ ++} ++ ++ ++ ++ +diff -urN linux.old/drivers/char/serial.c linux.dev/drivers/char/serial.c +--- linux.old/drivers/char/serial.c 2005-10-21 16:43:20.709226000 +0200 ++++ linux.dev/drivers/char/serial.c 2005-11-10 01:10:46.015585250 +0100 +@@ -419,7 +419,40 @@ + return 0; + } + +-#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_SEAD) ++#if defined(CONFIG_AR7) ++ ++static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset) ++{ ++ return (inb(info->port + (offset * 4)) & 0xff); ++} ++ ++ ++static _INLINE_ unsigned int serial_inp(struct async_struct *info, int offset) ++{ ++#ifdef CONFIG_SERIAL_NOPAUSE_IO ++ return (inb(info->port + (offset * 4)) & 0xff); ++#else ++ return (inb_p(info->port + (offset * 4)) & 0xff); ++#endif ++} ++ ++static _INLINE_ void serial_out(struct async_struct *info, int offset, int value) ++{ ++ outb(value, info->port + (offset * 4)); ++} ++ ++ ++static _INLINE_ void serial_outp(struct async_struct *info, int offset, + int value) +{ +#ifdef CONFIG_SERIAL_NOPAUSE_IO @@ -4289,13 +5816,12 @@ diff -urN kernel-base/drivers/char/serial.c kernel-current/drivers/char/serial.c /* -@@ -1728,7 +1763,16 @@ +@@ -1728,7 +1763,15 @@ /* Special case since 134 is really 134.5 */ quot = (2*baud_base / 269); else if (baud) +#ifdef CONFIG_AR7 -+ quot = (CONFIG_AR7_SYS_FREQUENCY*500000) / baud; -+ //quot = get_avalanche_vbus_freq() / baud; ++ quot = (CONFIG_AR7_SYS*500000) / baud; + + if ((quot%16)>7) + quot += 8; @@ -4306,7 +5832,7 @@ diff -urN kernel-base/drivers/char/serial.c kernel-current/drivers/char/serial.c } /* If the quotient is zero refuse the change */ if (!quot && old_termios) { -@@ -5552,8 +5596,10 @@ +@@ -5540,8 +5583,10 @@ state->irq = irq_cannonicalize(state->irq); if (state->hub6) state->io_type = SERIAL_IO_HUB6; @@ -4317,13 +5843,12 @@ diff -urN kernel-base/drivers/char/serial.c kernel-current/drivers/char/serial.c #ifdef CONFIG_MCA if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus) continue; -@@ -6009,7 +6055,16 @@ +@@ -5997,7 +6042,15 @@ info->io_type = state->io_type; info->iomem_base = state->iomem_base; info->iomem_reg_shift = state->iomem_reg_shift; +#ifdef CONFIG_AR7 -+ //quot = get_avalanche_vbus_freq() / baud; -+ quot = (CONFIG_AR7_SYS_FREQUENCY*500000) / baud; ++ quot = (CONFIG_AR7_SYS*500000) / baud; + + if ((quot%16)>7) + quot += 8; @@ -4334,1956 +5859,9713 @@ diff -urN kernel-base/drivers/char/serial.c kernel-current/drivers/char/serial.c cval = cflag & (CSIZE | CSTOPB); #if defined(__powerpc__) || defined(__alpha__) cval >>= 8; -diff -urN kernel-base/include/asm-mips/ar7/ar7.h kernel-current/include/asm-mips/ar7/ar7.h ---- kernel-base/include/asm-mips/ar7/ar7.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/ar7.h 2005-07-10 06:40:39.622261088 +0200 -@@ -0,0 +1,33 @@ +diff -urN linux.old/drivers/char/serial.c.orig linux.dev/drivers/char/serial.c.orig +--- linux.old/drivers/char/serial.c.orig 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/char/serial.c.orig 2005-11-10 01:10:46.051587500 +0100 +@@ -0,0 +1,6054 @@ +/* -+ * $Id$ -+ * Copyright (C) $Date$ $Author$ ++ * linux/drivers/char/serial.c ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, ++ * 1998, 1999 Theodore Ts'o ++ * ++ * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now ++ * much more extensible to support other serial cards based on the ++ * 16450/16550A UART's. Added support for the AST FourPort and the ++ * Accent Async board. ++ * ++ * set_serial_info fixed to set the flags, custom divisor, and uart ++ * type fields. Fix suggested by Michael K. Johnson 12/12/92. ++ * ++ * 11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis ++ * ++ * 03/96: Modularised by Angelo Haritsis ++ * ++ * rs_set_termios fixed to look also for changes of the input ++ * flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. ++ * Bernd Anhäupl 05/17/96. ++ * ++ * 1/97: Extended dumb serial ports are a config option now. ++ * Saves 4k. Michael A. Griffith + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. ++ * 8/97: Fix bug in rs_set_termios with RTS ++ * Stanislav V. Voronyi ++ * ++ * 3/98: Change the IRQ detection, use of probe_irq_o*(), ++ * suppress TIOCSERGWILD and TIOCSERSWILD ++ * Etienne Lorrain ++ * ++ * 4/98: Added changes to support the ARM architecture proposed by ++ * Russell King ++ * ++ * 5/99: Updated to include support for the XR16C850 and ST16C654 ++ * uarts. Stuart MacDonald ++ * ++ * 8/99: Generalized PCI support added. Theodore Ts'o + * -+ * This program is distributed in the hope that 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. ++ * 3/00: Rid circular buffer of redundant xmit_cnt. Fix a ++ * few races on freeing buffers too. ++ * Alan Modra ++ * ++ * 5/00: Support for the RSA-DV II/S card added. ++ * Kiyokazu SUTO + * -+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * 6/00: Remove old-style timer, use timer_list ++ * Andrew Morton + * ++ * 7/00: Support Timedia/Sunix/Exsys PCI cards ++ * ++ * 7/00: fix some returns on failure not using MOD_DEC_USE_COUNT. ++ * Arnaldo Carvalho de Melo ++ * ++ * 10/00: add in optional software flow control for serial console. ++ * Kanoj Sarcar (Modified by Theodore Ts'o) ++ * ++ * 02/02: Fix for AMD Elan bug in transmit irq routine, by ++ * Christer Weinigel , ++ * Robert Schwebel , ++ * Juergen Beisert , ++ * Theodore Ts'o ++ * ++ * 10/00: Added suport for MIPS Atlas board. ++ * 11/00: Hooks for serial kernel debug port support added. ++ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, ++ * carstenl@mips.com ++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + */ + -+#ifndef _AR7_H -+#define _AR7_H -+ -+#include -+#include -+ -+#define AVALANCHE_VECS_KSEG0 (KSEG0ADDR(CONFIG_AR7_MEMORY)) -+ -+#define AR7_UART0_REGS_BASE (KSEG1ADDR(0x08610E00)) -+#define AR7_UART1_REGS_BASE (KSEG1ADDR(0x08610E00)) -+#define AR7_BASE_BAUD ( 3686400 / 16 ) ++static char *serial_version = "5.05c"; ++static char *serial_revdate = "2001-07-08"; + -+#endif -diff -urN kernel-base/include/asm-mips/ar7/avalanche_intc.h kernel-current/include/asm-mips/ar7/avalanche_intc.h ---- kernel-base/include/asm-mips/ar7/avalanche_intc.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/avalanche_intc.h 2005-07-10 06:40:39.622261088 +0200 -@@ -0,0 +1,278 @@ -+ /* -+ * Nitin Dhingra, iamnd@ti.com -+ * Copyright (C) 2000 Texas Instruments Inc. -+ * ++/* ++ * Serial driver configuration section. Here are the various options: + * -+ * ######################################################################## ++ * CONFIG_HUB6 ++ * Enables support for the venerable Bell Technologies ++ * HUB6 card. + * -+ * 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. ++ * CONFIG_SERIAL_MANY_PORTS ++ * Enables support for ports beyond the standard, stupid ++ * COM 1/2/3/4. + * -+ * 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. ++ * CONFIG_SERIAL_MULTIPORT ++ * Enables support for special multiport board support. + * -+ * 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. ++ * CONFIG_SERIAL_SHARE_IRQ ++ * Enables support for multiple serial ports on one IRQ + * -+ * ######################################################################## ++ * CONFIG_SERIAL_DETECT_IRQ ++ * Enable the autodetection of IRQ on standart ports + * -+ * Defines of the Sead board specific address-MAP, registers, etc. ++ * SERIAL_PARANOIA_CHECK ++ * Check the magic number for the async_structure where ++ * ever possible. + * ++ * CONFIG_SERIAL_ACPI ++ * Enable support for serial console port and serial ++ * debug port as defined by the SPCR and DBGP tables in ++ * ACPI 2.0. + */ -+#ifndef _AVALANCHE_INTC_H -+#define _AVALANCHE_INTC_H + -+#define MIPS_EXCEPTION_OFFSET 8 ++#include ++#include ++ ++#undef SERIAL_PARANOIA_CHECK ++#define CONFIG_SERIAL_NOPAUSE_IO ++#define SERIAL_DO_RESTART ++ ++#if 0 ++/* These defines are normally controlled by the autoconf.h */ ++#define CONFIG_SERIAL_MANY_PORTS ++#define CONFIG_SERIAL_SHARE_IRQ ++#define CONFIG_SERIAL_DETECT_IRQ ++#define CONFIG_SERIAL_MULTIPORT ++#define CONFIG_HUB6 ++#endif + -+/****************************************************************************** -+ Avalanche Interrupt number -+******************************************************************************/ -+#define AVINTNUM(x) ((x) - MIPS_EXCEPTION_OFFSET) ++#ifdef CONFIG_PCI ++#define ENABLE_SERIAL_PCI ++#ifndef CONFIG_SERIAL_SHARE_IRQ ++#define CONFIG_SERIAL_SHARE_IRQ ++#endif ++#ifndef CONFIG_SERIAL_MANY_PORTS ++#define CONFIG_SERIAL_MANY_PORTS ++#endif ++#endif + -+/******************************************************************************* -+*Linux Interrupt number -+*******************************************************************************/ -+#define LNXINTNUM(x)((x) + MIPS_EXCEPTION_OFFSET) ++#ifdef CONFIG_SERIAL_ACPI ++#define ENABLE_SERIAL_ACPI ++#endif + ++#if defined(CONFIG_ISAPNP)|| (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE)) ++#ifndef ENABLE_SERIAL_PNP ++#define ENABLE_SERIAL_PNP ++#endif ++#endif + ++/* Set of debugging defines */ + -+#define AVALANCHE_INT_END_PRIMARY (40 + MIPS_EXCEPTION_OFFSET) -+#define AVALANCHE_INT_END_SECONDARY (32 + MIPS_EXCEPTION_OFFSET) ++#undef SERIAL_DEBUG_INTR ++#undef SERIAL_DEBUG_OPEN ++#undef SERIAL_DEBUG_FLOW ++#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT ++#undef SERIAL_DEBUG_PCI ++#undef SERIAL_DEBUG_AUTOCONF + -+#define AVALANCHE_INT_END_PRIMARY_REG1 (31 + MIPS_EXCEPTION_OFFSET) -+#define AVALANCHE_INT_END_PRIMARY_REG2 (39 + MIPS_EXCEPTION_OFFSET) ++/* Sanity checks */ + ++#ifdef CONFIG_SERIAL_MULTIPORT ++#ifndef CONFIG_SERIAL_SHARE_IRQ ++#define CONFIG_SERIAL_SHARE_IRQ ++#endif ++#endif ++ ++#ifdef CONFIG_HUB6 ++#ifndef CONFIG_SERIAL_MANY_PORTS ++#define CONFIG_SERIAL_MANY_PORTS ++#endif ++#ifndef CONFIG_SERIAL_SHARE_IRQ ++#define CONFIG_SERIAL_SHARE_IRQ ++#endif ++#endif ++ ++#ifdef MODULE ++#undef CONFIG_SERIAL_CONSOLE ++#endif + -+#define AVALANCHE_INT_END (AVINTNUM(AVALANCHE_INT_END_PRIMARY) + \ -+ AVINTNUM(AVALANCHE_INT_END_SECONDARY) \ -+ + MIPS_EXCEPTION_OFFSET - 1) /* Suraj, check */ ++#define CONFIG_SERIAL_RSA + ++#define RS_STROBE_TIME (10*HZ) ++#define RS_ISR_PASS_LIMIT 256 + ++#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) ++#define SERIAL_INLINE ++#endif ++ +/* -+ * Avalanche interrupt controller register base (primary) ++ * End of serial driver configuration section. + */ -+#define KSEG1_BASE 0xA0000000 -+#define KSEG_INV_MASK 0x1FFFFFFF /* Inverted mask for kseg address */ -+#define PHYS_ADDR(addr) ((addr) & KSEG_INV_MASK) -+#define PHYS_TO_K1(addr) (PHYS_ADDR(addr)|KSEG1_BASE) + -+#define AVALANCHE_ICTRL_REGS_BASE KSEG1ADDR(0x08612400)// AVALANCHE_INTC_BASE ++#include + -+/****************************************************************************** -+ * Avalanche exception controller register base (secondary) -+ ******************************************************************************/ -+#define AVALANCHE_ECTRL_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0x80) ++#include ++#ifdef LOCAL_HEADERS ++#include "serial_local.h" ++#else ++#include ++#include ++#include ++#include ++#define LOCAL_VERSTRING "" ++#endif + ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if (LINUX_VERSION_CODE >= 131343) ++#include ++#endif ++#if (LINUX_VERSION_CODE >= 131336) ++#include ++#endif ++#include ++#ifdef CONFIG_SERIAL_CONSOLE ++#include ++#endif ++#ifdef ENABLE_SERIAL_PCI ++#include ++#endif ++#ifdef ENABLE_SERIAL_PNP ++#include ++#endif ++#ifdef CONFIG_MAGIC_SYSRQ ++#include ++#endif + -+/****************************************************************************** -+ * Avalanche Interrupt pacing register base (secondary) -+ ******************************************************************************/ -+#define AVALANCHE_IPACE_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0xA0) ++/* ++ * All of the compatibilty code so we can compile serial.c against ++ * older kernels is hidden in serial_compat.h ++ */ ++#if defined(LOCAL_HEADERS) || (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */ ++#include "serial_compat.h" ++#endif + ++#include ++#include ++#include ++#include + ++#if defined(CONFIG_MAC_SERIAL) ++#define SERIAL_DEV_OFFSET ((_machine == _MACH_prep || _machine == _MACH_chrp) ? 0 : 2) ++#else ++#define SERIAL_DEV_OFFSET 0 ++#endif + -+/****************************************************************************** -+ * Avalanche Interrupt Channel Control register base -+ *****************************************************************************/ -+#define AVALANCHE_CHCTRL_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0x200) ++#ifdef SERIAL_INLINE ++#define _INLINE_ inline ++#else ++#define _INLINE_ ++#endif + ++static char *serial_name = "Serial driver"; + -+struct avalanche_ictrl_regs /* Avalanche Interrupt control registers */ -+{ -+ volatile unsigned long intsr1; /* Interrupt Status/Set Register 1 0x00 */ -+ volatile unsigned long intsr2; /* Interrupt Status/Set Register 2 0x04 */ -+ volatile unsigned long unused1; /*0x08 */ -+ volatile unsigned long unused2; /*0x0C */ -+ volatile unsigned long intcr1; /* Interrupt Clear Register 1 0x10 */ -+ volatile unsigned long intcr2; /* Interrupt Clear Register 2 0x14 */ -+ volatile unsigned long unused3; /*0x18 */ -+ volatile unsigned long unused4; /*0x1C */ -+ volatile unsigned long intesr1; /* Interrupt Enable (Set) Register 1 0x20 */ -+ volatile unsigned long intesr2; /* Interrupt Enable (Set) Register 2 0x24 */ -+ volatile unsigned long unused5; /*0x28 */ -+ volatile unsigned long unused6; /*0x2C */ -+ volatile unsigned long intecr1; /* Interrupt Enable Clear Register 1 0x30 */ -+ volatile unsigned long intecr2; /* Interrupt Enable Clear Register 2 0x34 */ -+ volatile unsigned long unused7; /* 0x38 */ -+ volatile unsigned long unused8; /* 0x3c */ -+ volatile unsigned long pintir; /* Priority Interrupt Index Register 0x40 */ -+ volatile unsigned long intmsr; /* Priority Interrupt Mask Index Reg 0x44 */ -+ volatile unsigned long unused9; /* 0x48 */ -+ volatile unsigned long unused10; /* 0x4C */ -+ volatile unsigned long intpolr1; /* Interrupt Polarity Mask register 10x50 */ -+ volatile unsigned long intpolr2; /* Interrupt Polarity Mask register 20x54 */ -+ volatile unsigned long unused11; /* 0x58 */ -+ volatile unsigned long unused12; /*0x5C */ -+ volatile unsigned long inttypr1; /* Interrupt Type Mask register 10x60 */ -+ volatile unsigned long inttypr2; /* Interrupt Type Mask register 20x64 */ -+}; ++static DECLARE_TASK_QUEUE(tq_serial); + -+struct avalanche_exctrl_regs /* Avalanche Exception control registers */ -+{ -+ volatile unsigned long exsr; /* Exceptions Status/Set register 0x80 */ -+ volatile unsigned long reserved; /*0x84 */ -+ volatile unsigned long excr; /* Exceptions Clear Register 0x88 */ -+ volatile unsigned long reserved1; /*0x8c */ -+ volatile unsigned long exiesr; /* Exceptions Interrupt Enable (set) 0x90 */ -+ volatile unsigned long reserved2; /*0x94 */ -+ volatile unsigned long exiecr; /* Exceptions Interrupt Enable(clear)0x98 */ -+}; -+struct avalanche_ipace_regs -+{ ++static struct tty_driver serial_driver, callout_driver; ++static int serial_refcount; + -+ volatile unsigned long ipacep; /* Interrupt pacing register 0xa0 */ -+ volatile unsigned long ipacemap; /*Interrupt Pacing Map Register 0xa4 */ -+ volatile unsigned long ipacemax; /*Interrupt Pacing Max Register 0xa8 */ ++static struct timer_list serial_timer; ++ ++/* serial subtype definitions */ ++#ifndef SERIAL_TYPE_NORMAL ++#define SERIAL_TYPE_NORMAL 1 ++#define SERIAL_TYPE_CALLOUT 2 ++#endif ++ ++/* number of characters left in xmit buffer before we ask for more */ ++#define WAKEUP_CHARS 256 ++ ++/* ++ * IRQ_timeout - How long the timeout should be for each IRQ ++ * should be after the IRQ has been active. ++ */ ++ ++static struct async_struct *IRQ_ports[NR_IRQS]; ++#ifdef CONFIG_SERIAL_MULTIPORT ++static struct rs_multiport_struct rs_multiport[NR_IRQS]; ++#endif ++static int IRQ_timeout[NR_IRQS]; ++#ifdef CONFIG_SERIAL_CONSOLE ++static struct console sercons; ++static int lsr_break_flag; ++#endif ++#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) ++static unsigned long break_pressed; /* break, really ... */ ++#endif ++ ++static unsigned detect_uart_irq (struct serial_state * state); ++static void autoconfig(struct serial_state * state); ++static void change_speed(struct async_struct *info, struct termios *old); ++static void rs_wait_until_sent(struct tty_struct *tty, int timeout); ++ ++/* ++ * Here we define the default xmit fifo size used for each type of ++ * UART ++ */ ++static struct serial_uart_config uart_config[] = { ++ { "unknown", 1, 0 }, ++ { "8250", 1, 0 }, ++ { "16450", 1, 0 }, ++ { "16550", 1, 0 }, ++ { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, ++ { "cirrus", 1, 0 }, /* usurped by cyclades.c */ ++ { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, ++ { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | ++ UART_STARTECH }, ++ { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO}, ++ { "Startech", 1, 0}, /* usurped by cyclades.c */ ++ { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO}, ++ { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | ++ UART_STARTECH }, ++ { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | ++ UART_STARTECH }, ++ { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }, ++ { 0, 0} +}; -+struct avalanche_channel_int_number -+{ -+ volatile unsigned long cintnr0; /* Channel Interrupt Number Register0x200 */ -+ volatile unsigned long cintnr1; /* Channel Interrupt Number Register0x204 */ -+ volatile unsigned long cintnr2; /* Channel Interrupt Number Register0x208 */ -+ volatile unsigned long cintnr3; /* Channel Interrupt Number Register0x20C */ -+ volatile unsigned long cintnr4; /* Channel Interrupt Number Register0x210 */ -+ volatile unsigned long cintnr5; /* Channel Interrupt Number Register0x214 */ -+ volatile unsigned long cintnr6; /* Channel Interrupt Number Register0x218 */ -+ volatile unsigned long cintnr7; /* Channel Interrupt Number Register0x21C */ -+ volatile unsigned long cintnr8; /* Channel Interrupt Number Register0x220 */ -+ volatile unsigned long cintnr9; /* Channel Interrupt Number Register0x224 */ -+ volatile unsigned long cintnr10; /* Channel Interrupt Number Register0x228 */ -+ volatile unsigned long cintnr11; /* Channel Interrupt Number Register0x22C */ -+ volatile unsigned long cintnr12; /* Channel Interrupt Number Register0x230 */ -+ volatile unsigned long cintnr13; /* Channel Interrupt Number Register0x234 */ -+ volatile unsigned long cintnr14; /* Channel Interrupt Number Register0x238 */ -+ volatile unsigned long cintnr15; /* Channel Interrupt Number Register0x23C */ -+ volatile unsigned long cintnr16; /* Channel Interrupt Number Register0x240 */ -+ volatile unsigned long cintnr17; /* Channel Interrupt Number Register0x244 */ -+ volatile unsigned long cintnr18; /* Channel Interrupt Number Register0x248 */ -+ volatile unsigned long cintnr19; /* Channel Interrupt Number Register0x24C */ -+ volatile unsigned long cintnr20; /* Channel Interrupt Number Register0x250 */ -+ volatile unsigned long cintnr21; /* Channel Interrupt Number Register0x254 */ -+ volatile unsigned long cintnr22; /* Channel Interrupt Number Register0x358 */ -+ volatile unsigned long cintnr23; /* Channel Interrupt Number Register0x35C */ -+ volatile unsigned long cintnr24; /* Channel Interrupt Number Register0x260 */ -+ volatile unsigned long cintnr25; /* Channel Interrupt Number Register0x264 */ -+ volatile unsigned long cintnr26; /* Channel Interrupt Number Register0x268 */ -+ volatile unsigned long cintnr27; /* Channel Interrupt Number Register0x26C */ -+ volatile unsigned long cintnr28; /* Channel Interrupt Number Register0x270 */ -+ volatile unsigned long cintnr29; /* Channel Interrupt Number Register0x274 */ -+ volatile unsigned long cintnr30; /* Channel Interrupt Number Register0x278 */ -+ volatile unsigned long cintnr31; /* Channel Interrupt Number Register0x27C */ -+ volatile unsigned long cintnr32; /* Channel Interrupt Number Register0x280 */ -+ volatile unsigned long cintnr33; /* Channel Interrupt Number Register0x284 */ -+ volatile unsigned long cintnr34; /* Channel Interrupt Number Register0x288 */ -+ volatile unsigned long cintnr35; /* Channel Interrupt Number Register0x28C */ -+ volatile unsigned long cintnr36; /* Channel Interrupt Number Register0x290 */ -+ volatile unsigned long cintnr37; /* Channel Interrupt Number Register0x294 */ -+ volatile unsigned long cintnr38; /* Channel Interrupt Number Register0x298 */ -+ volatile unsigned long cintnr39; /* Channel Interrupt Number Register0x29C */ ++ ++#if defined(CONFIG_SERIAL_RSA) && defined(MODULE) ++ ++#define PORT_RSA_MAX 4 ++static int probe_rsa[PORT_RSA_MAX]; ++static int force_rsa[PORT_RSA_MAX]; ++ ++MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); ++MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); ++MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); ++MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA"); ++#endif /* CONFIG_SERIAL_RSA */ ++ ++struct serial_state rs_table[RS_TABLE_SIZE] = { ++ SERIAL_PORT_DFNS /* Defined in serial.h */ +}; + -+struct avalanche_interrupt_line_to_channel ++#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) ++int serial_nr_ports = NR_PORTS; ++ ++#if (defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)) ++#define NR_PCI_BOARDS 8 ++ ++static struct pci_board_inst serial_pci_board[NR_PCI_BOARDS]; ++ ++#ifndef IS_PCI_REGION_IOPORT ++#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \ ++ IORESOURCE_IO) ++#endif ++#ifndef IS_PCI_REGION_IOMEM ++#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \ ++ IORESOURCE_MEM) ++#endif ++#ifndef PCI_IRQ_RESOURCE ++#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start) ++#endif ++#ifndef pci_get_subvendor ++#define pci_get_subvendor(dev) ((dev)->subsystem_vendor) ++#define pci_get_subdevice(dev) ((dev)->subsystem_device) ++#endif ++#endif /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP */ ++ ++#ifndef PREPARE_FUNC ++#define PREPARE_FUNC(dev) (dev->prepare) ++#define ACTIVATE_FUNC(dev) (dev->activate) ++#define DEACTIVATE_FUNC(dev) (dev->deactivate) ++#endif ++ ++#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) ++ ++static struct tty_struct *serial_table[NR_PORTS]; ++static struct termios *serial_termios[NR_PORTS]; ++static struct termios *serial_termios_locked[NR_PORTS]; ++ ++ ++#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) ++#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ ++ kdevname(tty->device), (info->flags), serial_refcount,info->count,tty->count,s) ++#else ++#define DBG_CNT(s) ++#endif ++ ++/* ++ * tmp_buf is used as a temporary buffer by serial_write. We need to ++ * lock it in case the copy_from_user blocks while swapping in a page, ++ * and some other program tries to do a serial write at the same time. ++ * Since the lock will only come under contention when the system is ++ * swapping and available memory is low, it makes sense to share one ++ * buffer across all the serial ports, since it significantly saves ++ * memory if large numbers of serial ports are open. ++ */ ++static unsigned char *tmp_buf; ++#ifdef DECLARE_MUTEX ++static DECLARE_MUTEX(tmp_buf_sem); ++#else ++static struct semaphore tmp_buf_sem = MUTEX; ++#endif ++ ++ ++static inline int serial_paranoia_check(struct async_struct *info, ++ kdev_t device, const char *routine) +{ -+ unsigned long int_line0; /* Start of primary interrupts */ -+ unsigned long int_line1; -+ unsigned long int_line2; -+ unsigned long int_line3; -+ unsigned long int_line4; -+ unsigned long int_line5; -+ unsigned long int_line6; -+ unsigned long int_line7; -+ unsigned long int_line8; -+ unsigned long int_line9; -+ unsigned long int_line10; -+ unsigned long int_line11; -+ unsigned long int_line12; -+ unsigned long int_line13; -+ unsigned long int_line14; -+ unsigned long int_line15; -+ unsigned long int_line16; -+ unsigned long int_line17; -+ unsigned long int_line18; -+ unsigned long int_line19; -+ unsigned long int_line20; -+ unsigned long int_line21; -+ unsigned long int_line22; -+ unsigned long int_line23; -+ unsigned long int_line24; -+ unsigned long int_line25; -+ unsigned long int_line26; -+ unsigned long int_line27; -+ unsigned long int_line28; -+ unsigned long int_line29; -+ unsigned long int_line30; -+ unsigned long int_line31; -+ unsigned long int_line32; -+ unsigned long int_line33; -+ unsigned long int_line34; -+ unsigned long int_line35; -+ unsigned long int_line36; -+ unsigned long int_line37; -+ unsigned long int_line38; -+ unsigned long int_line39; -+}; -+ ++#ifdef SERIAL_PARANOIA_CHECK ++ static const char *badmagic = ++ "Warning: bad magic number for serial struct (%s) in %s\n"; ++ static const char *badinfo = ++ "Warning: null async_struct for (%s) in %s\n"; ++ ++ if (!info) { ++ printk(badinfo, kdevname(device), routine); ++ return 1; ++ } ++ if (info->magic != SERIAL_MAGIC) { ++ printk(badmagic, kdevname(device), routine); ++ return 1; ++ } ++#endif ++ return 0; ++} + -+/* Interrupt Line #'s (Sangam peripherals) */ ++#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_SEAD) + -+/*------------------------------*/ -+/* Sangam primary interrupts */ -+/*------------------------------*/ ++#include + -+#define UNIFIED_SECONDARY_INTERRUPT 0 -+#define AVALANCHE_EXT_INT_0 1 -+#define AVALANCHE_EXT_INT_1 2 -+/* Line #3 Reserved */ -+/* Line #4 Reserved */ -+#define AVALANCHE_TIMER_0_INT 5 -+#define AVALANCHE_TIMER_1_INT 6 -+#define AVALANCHE_UART0_INT 7 -+#define AVALANCHE_UART1_INT 8 -+#define AVALANCHE_PDMA_INT0 9 -+#define AVALANCHE_PDMA_INT1 10 -+/* Line #11 Reserved */ -+/* Line #12 Reserved */ -+/* Line #13 Reserved */ -+/* Line #14 Reserved */ -+#define AVALANCHE_ATM_SAR_INT 15 -+/* Line #16 Reserved */ -+/* Line #17 Reserved */ -+/* Line #18 Reserved */ -+#define AVALANCHE_MAC0_INT 19 -+/* Line #20 Reserved */ -+#define AVALANCHE_VLYNQ0_INT 21 -+#define AVALANCHE_CODEC_WAKE_INT 22 -+/* Line #23 Reserved */ -+#define AVALANCHE_USB_INT 24 -+#define AVALANCHE_VLYNQ1_INT 25 -+/* Line #26 Reserved */ -+/* Line #27 Reserved */ -+#define AVALANCHE_MAC1_INT 28 -+#define AVALANCHE_I2CM_INT 29 -+#define AVALANCHE_PDMA_INT2 30 -+#define AVALANCHE_PDMA_INT3 31 -+/* Line #32 Reserved */ -+/* Line #33 Reserved */ -+/* Line #34 Reserved */ -+/* Line #35 Reserved */ -+/* Line #36 Reserved */ -+#define AVALANCHE_VDMA_VT_RX_INT 37 -+#define AVALANCHE_VDMA_VT_TX_INT 38 -+#define AVALANCHE_ADSLSS_INT 39 ++static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset) ++{ ++ return (*(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) & 0xff); ++} + -+/*-----------------------------------*/ -+/* Sangam Secondary Interrupts */ -+/*-----------------------------------*/ -+#define PRIMARY_INTS 40 ++static _INLINE_ void serial_out(struct async_struct *info, int offset, int value) ++{ ++ *(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) = value; ++} + -+#define EMIF_INT (7 + PRIMARY_INTS) ++#else + ++static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset) ++{ ++ switch (info->io_type) { ++#ifdef CONFIG_HUB6 ++ case SERIAL_IO_HUB6: ++ outb(info->hub6 - 1 + offset, info->port); ++ return inb(info->port+1); ++#endif ++ case SERIAL_IO_MEM: ++ return readb((unsigned long) info->iomem_base + ++ (offset<iomem_reg_shift)); ++ default: ++ return inb(info->port + offset); ++ } ++} + -+extern void avalanche_int_set(int channel, int line); ++static _INLINE_ void serial_out(struct async_struct *info, int offset, ++ int value) ++{ ++ switch (info->io_type) { ++#ifdef CONFIG_HUB6 ++ case SERIAL_IO_HUB6: ++ outb(info->hub6 - 1 + offset, info->port); ++ outb(value, info->port+1); ++ break; ++#endif ++ case SERIAL_IO_MEM: ++ writeb(value, (unsigned long) info->iomem_base + ++ (offset<iomem_reg_shift)); ++ break; ++ default: ++ outb(value, info->port+offset); ++ } ++} ++#endif + + -+#endif /* _AVALANCHE_INTC_H */ -diff -urN kernel-base/include/asm-mips/ar7/avalanche_regs.h kernel-current/include/asm-mips/ar7/avalanche_regs.h ---- kernel-base/include/asm-mips/ar7/avalanche_regs.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/avalanche_regs.h 2005-07-10 09:27:48.638618856 +0200 -@@ -0,0 +1,567 @@ -+/* -+ * $Id$ -+ * Avalanche Register Descriptions -+ * -+ * Jeff Harrell, jharrell@ti.com -+ * 2000 (c) Texas Instruments Inc. ++/* ++ * We used to support using pause I/O for certain machines. We ++ * haven't supported this for a while, but just in case it's badly ++ * needed for certain old 386 machines, I've left these #define's ++ * in.... + */ ++#define serial_inp(info, offset) serial_in(info, offset) ++#define serial_outp(info, offset, value) serial_out(info, offset, value) + -+#ifndef __AVALANCHE_REGS_H -+#define __AVALANCHE_REGS_H -+ -+#include -+#include + -+/*----------------------------------------*/ -+/* Base offsets within the Avalanche ASIC */ -+/*----------------------------------------*/ ++/* ++ * For the 16C950 ++ */ ++void serial_icr_write(struct async_struct *info, int offset, int value) ++{ ++ serial_out(info, UART_SCR, offset); ++ serial_out(info, UART_ICR, value); ++} + -+#define BBIF_SPACE0 (KSEG1ADDR(0x01000000)) -+#define BBIF_SPACE1 (KSEG1ADDR(0x01800000)) -+#define BBIF_CONTROL (KSEG1ADDR(0x02000000)) -+#define ATM_SAR_BASE (KSEG1ADDR(0x03000000)) -+#define USB_MCU_BASE (KSEG1ADDR(0x03400000)) -+#define DES_BASE (KSEG1ADDR(0x08600000)) -+#define ETH_MACA_BASE (KSEG1ADDR(0x08610000)) -+#define ETH_MACB_BASE (KSEG1ADDR(0x08612800)) -+#define MEM_CTRLR_BASE (KSEG1ADDR(0x08610800)) -+#define GPIO_BASE (KSEG1ADDR(0x08610900)) -+#define CLK_CTRL_BASE (KSEG1ADDR(0x08610A00)) -+#define WATCH_DOG_BASE (KSEG1ADDR(0x08610B00)) -+#define TMR1_BASE (KSEG1ADDR(0x08610C00)) -+#define TRM2_BASE (KSEG1ADDR(0x08610D00)) -+#define UARTA_BASE (KSEG1ADDR(0x08610E00)) -+#define UARTB_BASE (KSEG1ADDR(0x08610F00)) -+#define I2C_BASE (KSEG1ADDR(0x08611000)) -+#define DEV_ID_BASE (KSEG1ADDR(0x08611100)) -+#define USB_BASE (KSEG1ADDR(0x08611200)) -+#define PCI_CONFIG_BASE (KSEG1ADDR(0x08611300)) -+#define DMA_BASE (KSEG1ADDR(0x08611400)) -+#define RESET_CTRL_BASE (KSEG1ADDR(0x08611600)) -+#define DSL_IF_BASE (KSEG1ADDR(0x08611B00)) -+#define INT_CTL_BASE (KSEG1ADDR(0x08612400)) -+#define PHY_BASE (KSEG1ADDR(0x1E000000)) ++unsigned int serial_icr_read(struct async_struct *info, int offset) ++{ ++ int value; + -+/*---------------------------------*/ -+/* Device ID, chip version number */ -+/*---------------------------------*/ ++ serial_icr_write(info, UART_ACR, info->ACR | UART_ACR_ICRRD); ++ serial_out(info, UART_SCR, offset); ++ value = serial_in(info, UART_ICR); ++ serial_icr_write(info, UART_ACR, info->ACR); ++ return value; ++} + -+#define AVALANCHE_CHVN (*(volatile unsigned int *)(DEV_ID_BASE+0x14)) -+#define AVALANCHE_DEVID1 (*(volatile unsigned int *)(DEV_ID_BASE+0x18)) -+#define AVALANCHE_DEVID2 (*(volatile unsigned int *)(DEV_ID_BASE+0x1C)) ++/* ++ * ------------------------------------------------------------ ++ * 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; + -+/*----------------------------------*/ -+/* Reset Control VW changed to ptrs */ -+/*----------------------------------*/ ++ if (serial_paranoia_check(info, tty->device, "rs_stop")) ++ return; ++ ++ save_flags(flags); cli(); ++ if (info->IER & UART_IER_THRI) { ++ info->IER &= ~UART_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ } ++ if (info->state->type == PORT_16C950) { ++ info->ACR |= UART_ACR_TXDIS; ++ serial_icr_write(info, UART_ACR, info->ACR); ++ } ++ restore_flags(flags); ++} + -+#define AVALANCHE_PRCR (*(volatile unsigned int *)(RESET_CTRL_BASE + 0x0)) /* Peripheral reset control */ -+#define AVALANCHE_SWRCR (*(volatile unsigned int *)(RESET_CTRL_BASE + 0x4)) /* Software reset control */ -+#define AVALANCHE_RSR (*(volatile unsigned int *)(RESET_CTRL_BASE + 0x8)) /* Reset status register */ ++static void rs_start(struct tty_struct *tty) ++{ ++ struct async_struct *info = (struct async_struct *)tty->driver_data; ++ unsigned long flags; ++ ++ if (serial_paranoia_check(info, tty->device, "rs_start")) ++ return; ++ ++ save_flags(flags); cli(); ++ if (info->xmit.head != info->xmit.tail ++ && info->xmit.buf ++ && !(info->IER & UART_IER_THRI)) { ++ info->IER |= UART_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ } ++ if (info->state->type == PORT_16C950) { ++ info->ACR &= ~UART_ACR_TXDIS; ++ serial_icr_write(info, UART_ACR, info->ACR); ++ } ++ restore_flags(flags); ++} + -+/* reset control bits */ ++/* ++ * ---------------------------------------------------------------------- ++ * ++ * Here starts the interrupt handling routines. All of the following ++ * subroutines are declared as inline and are folded into ++ * rs_interrupt(). They were separated out for readability's sake. ++ * ++ * Note: rs_interrupt() is a "fast" interrupt, which means that it ++ * runs with interrupts turned off. People who may want to modify ++ * rs_interrupt() should try to keep the interrupt handler as fast as ++ * possible. After you are done making modifications, it is not a bad ++ * idea to do: ++ * ++ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c ++ * ++ * and look at the resulting assemble code in serial.s. ++ * ++ * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 ++ * ----------------------------------------------------------------------- ++ */ + -+#define AV_RST_UART0 (1<<0) /* Brings UART0 out of reset */ -+#define AV_RST_UART1 (1<<1) /* Brings UART1 out of reset */ -+#define AV_RST_IICM (1<<2) /* Brings the I2CM out of reset */ -+#define AV_RST_TIMER0 (1<<3) /* Brings Timer 0 out of reset */ -+#define AV_RST_TIMER1 (1<<4) /* Brings Timer 1 out of reset */ -+#define AV_RST_DES (1<<5) /* Brings the DES module out of reset */ -+#define AV_RST_GPIO (1<<6) /* Brings the GPIO module out of reset (see note below) */ +/* -+ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE -+ If you reset the GPIO interface all of the directions (i/o) of the UART B -+ interface pins are inputs and must be reconfigured so as not to lose the -+ serial console interface -+ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE -+*/ -+#define AV_RST_BBIF (1<<7) /* Brings the Broadband interface out of reset */ -+#define AV_RST_USB (1<<8) /* Brings the USB module out of reset */ -+#define AV_RST_SAR (1<<9) /* Brings the SAR out of reset */ -+#define AV_RST_HDLC (1<<10) /* Brings the HDLC module out of reset */ -+#define AV_RST_PCI (1<<16) /* Brings the PCI module out of reset */ -+#define AV_RST_ETH_MAC0 (1<<17) /* Brings the Ethernet MAC0 out of reset */ -+#define AV_RST_PICO_DMA (1<<18) /* Brings the PICO DMA module out of reset */ -+#define AV_RST_BIST (1<<19) /* Brings the BIST module out of reset */ -+#define AV_RST_DSP (1<<20) /* Brings the DSP sub system out of reset */ -+#define AV_RST_ETH_MAC1 (1<<21) /* Brings the Ethernet MAC1 out of reset */ ++ * This routine is used by the interrupt handler to schedule ++ * processing in the software interrupt portion of the driver. ++ */ ++static _INLINE_ void rs_sched_event(struct async_struct *info, ++ int event) ++{ ++ info->event |= 1 << event; ++ queue_task(&info->tqueue, &tq_serial); ++ mark_bh(SERIAL_BH); ++} + -+/*----------------------*/ -+/* Physical interfaces */ -+/*----------------------*/ ++static _INLINE_ void receive_chars(struct async_struct *info, ++ int *status, struct pt_regs * regs) ++{ ++ struct tty_struct *tty = info->tty; ++ unsigned char ch; ++ struct async_icount *icount; ++ int max_count = 256; + -+/* Phy loopback */ -+#define PHY_LOOPBACK 1 ++ icount = &info->state->icount; ++ do { ++ if (tty->flip.count >= TTY_FLIPBUF_SIZE) { ++ tty->flip.tqueue.routine((void *) tty); ++ if (tty->flip.count >= TTY_FLIPBUF_SIZE) { ++ /* no room in flip buffer, discard rx FIFO contents to clear IRQ ++ * *FIXME* Hardware with auto flow control ++ * would benefit from leaving the data in the FIFO and ++ * disabling the rx IRQ until space becomes available. ++ */ ++ do { ++ serial_inp(info, UART_RX); ++ icount->overrun++; ++ *status = serial_inp(info, UART_LSR); ++ } while ((*status & UART_LSR_DR) && (max_count-- > 0)); ++ return; // if TTY_DONT_FLIP is set ++ } ++ } ++ ch = serial_inp(info, UART_RX); ++ *tty->flip.char_buf_ptr = ch; ++ icount->rx++; ++ ++#ifdef SERIAL_DEBUG_INTR ++ printk("DR%02x:%02x...", ch, *status); ++#endif ++ *tty->flip.flag_buf_ptr = 0; ++ if (*status & (UART_LSR_BI | UART_LSR_PE | ++ UART_LSR_FE | UART_LSR_OE)) { ++ /* ++ * For statistics only ++ */ ++ if (*status & UART_LSR_BI) { ++ *status &= ~(UART_LSR_FE | UART_LSR_PE); ++ icount->brk++; ++ /* ++ * We do the SysRQ and SAK checking ++ * here because otherwise the break ++ * may get masked by ignore_status_mask ++ * or read_status_mask. ++ */ ++#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) ++ if (info->line == sercons.index) { ++ if (!break_pressed) { ++ break_pressed = jiffies; ++ goto ignore_char; ++ } ++ break_pressed = 0; ++ } ++#endif ++ if (info->flags & ASYNC_SAK) ++ do_SAK(tty); ++ } else if (*status & UART_LSR_PE) ++ icount->parity++; ++ else if (*status & UART_LSR_FE) ++ icount->frame++; ++ if (*status & UART_LSR_OE) ++ icount->overrun++; ++ ++ /* ++ * Mask off conditions which should be ignored. ++ */ ++ *status &= info->read_status_mask; + ++#ifdef CONFIG_SERIAL_CONSOLE ++ if (info->line == sercons.index) { ++ /* Recover the break flag from console xmit */ ++ *status |= lsr_break_flag; ++ lsr_break_flag = 0; ++ } ++#endif ++ if (*status & (UART_LSR_BI)) { ++#ifdef SERIAL_DEBUG_INTR ++ printk("handling break...."); ++#endif ++ *tty->flip.flag_buf_ptr = TTY_BREAK; ++ } else if (*status & UART_LSR_PE) ++ *tty->flip.flag_buf_ptr = TTY_PARITY; ++ else if (*status & UART_LSR_FE) ++ *tty->flip.flag_buf_ptr = TTY_FRAME; ++ } ++#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) ++ if (break_pressed && info->line == sercons.index) { ++ if (ch != 0 && ++ time_before(jiffies, break_pressed + HZ*5)) { ++ handle_sysrq(ch, regs, NULL, NULL); ++ break_pressed = 0; ++ goto ignore_char; ++ } ++ break_pressed = 0; ++ } ++#endif ++ if ((*status & info->ignore_status_mask) == 0) { ++ tty->flip.flag_buf_ptr++; ++ tty->flip.char_buf_ptr++; ++ tty->flip.count++; ++ } ++ if ((*status & UART_LSR_OE) && ++ (tty->flip.count < TTY_FLIPBUF_SIZE)) { ++ /* ++ * Overrun is special, since it's reported ++ * immediately, and doesn't affect the current ++ * character ++ */ ++ *tty->flip.flag_buf_ptr = TTY_OVERRUN; ++ tty->flip.count++; ++ tty->flip.flag_buf_ptr++; ++ tty->flip.char_buf_ptr++; ++ } ++#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) ++ ignore_char: ++#endif ++ *status = serial_inp(info, UART_LSR); ++ } while ((*status & UART_LSR_DR) && (max_count-- > 0)); ++#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */ ++ tty_flip_buffer_push(tty); ++#else ++ queue_task_irq_off(&tty->flip.tqueue, &tq_timer); ++#endif ++} + -+/* Phy 0 */ -+#define PHY0BASE (PHY_BASE) -+#define PHY0RST (*(volatile unsigned char *) (PHY0BASE)) /* reset */ -+#define PHY0CTRL (*(volatile unsigned char *) (PHY0BASE+0x5)) /* control */ -+#define PHY0RACPCTRL (*(volatile unsigned char *) (PHY0BASE+0x50)) /* RACP control/status */ -+#define PHY0TACPCTRL (*(volatile unsigned char *) (PHY0BASE+0x60)) /* TACP idle/unassigned cell hdr */ -+#define PHY0RACPINT (*(volatile unsigned char *) (PHY0BASE+0x51)) /* RACP interrupt enable/Status */ ++static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) ++{ ++ int count; ++ ++ if (info->x_char) { ++ serial_outp(info, UART_TX, 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_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ return; ++ } ++ ++ count = info->xmit_fifo_size; ++ do { ++ serial_out(info, UART_TX, 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 (--count > 0); ++ ++ 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; + -+/* Phy 1 */ ++ if (info->xmit.head == info->xmit.tail) { ++ info->IER &= ~UART_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ } ++} + -+#define PHY1BASE (PHY_BASE + 0x100000) -+#define PHY1RST (*(volatile unsigned char *) (PHY1BASE)) /* reset */ -+#define PHY1CTRL (*(volatile unsigned char *) (PHY1BASE+0x5)) /* control */ -+#define PHY1RACPCTRL (*(volatile unsigned char *) (PHY1BASE+0x50)) -+#define PHY1TACPCTRL (*(volatile unsigned char *) (PHY1BASE+0x60)) -+#define PHY1RACPINT (*(volatile unsigned char *) (PHY1BASE+0x51)) ++static _INLINE_ void check_modem_status(struct async_struct *info) ++{ ++ int status; ++ struct async_icount *icount; ++ ++ status = serial_in(info, UART_MSR); ++ ++ if (status & UART_MSR_ANY_DELTA) { ++ icount = &info->state->icount; ++ /* update input line counters */ ++ if (status & UART_MSR_TERI) ++ icount->rng++; ++ if (status & UART_MSR_DDSR) ++ icount->dsr++; ++ if (status & UART_MSR_DDCD) { ++ icount->dcd++; ++#ifdef CONFIG_HARD_PPS ++ if ((info->flags & ASYNC_HARDPPS_CD) && ++ (status & UART_MSR_DCD)) ++ hardpps(); ++#endif ++ } ++ if (status & UART_MSR_DCTS) ++ icount->cts++; ++ wake_up_interruptible(&info->delta_msr_wait); ++ } + -+/* Phy 2 */ ++ if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { ++#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) ++ printk("ttys%d CD now %s...", info->line, ++ (status & UART_MSR_DCD) ? "on" : "off"); ++#endif ++ if (status & UART_MSR_DCD) ++ wake_up_interruptible(&info->open_wait); ++ else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && ++ (info->flags & ASYNC_CALLOUT_NOHUP))) { ++#ifdef SERIAL_DEBUG_OPEN ++ printk("doing serial hangup..."); ++#endif ++ if (info->tty) ++ tty_hangup(info->tty); ++ } ++ } ++ if (info->flags & ASYNC_CTS_FLOW) { ++ if (info->tty->hw_stopped) { ++ if (status & UART_MSR_CTS) { ++#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) ++ printk("CTS tx start..."); ++#endif ++ info->tty->hw_stopped = 0; ++ info->IER |= UART_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); ++ return; ++ } ++ } else { ++ if (!(status & UART_MSR_CTS)) { ++#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) ++ printk("CTS tx stop..."); ++#endif ++ info->tty->hw_stopped = 1; ++ info->IER &= ~UART_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ } ++ } ++ } ++} + -+#define PHY2BASE (PHY_BASE + 0x200000) -+#define PHY2RST (*(volatile unsigned char *) (PHY2BASE)) /* reset */ -+#define PHY2CTRL (*(volatile unsigned char *) (PHY2BASE+0x5)) /* control */ -+#define PHY2RACPCTRL (*(volatile unsigned char *) (PHY2BASE+0x50)) -+#define PHY2TACPCTRL (*(volatile unsigned char *) (PHY2BASE+0x60)) -+#define PHY2RACPINT (*(volatile unsigned char *) (PHY2BASE+0x51)) ++#ifdef CONFIG_SERIAL_SHARE_IRQ ++/* ++ * This is the serial driver's generic interrupt routine ++ */ ++static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) ++{ ++ int status, iir; ++ struct async_struct * info; ++ int pass_counter = 0; ++ struct async_struct *end_mark = 0; ++#ifdef CONFIG_SERIAL_MULTIPORT ++ int first_multi = 0; ++ struct rs_multiport_struct *multi; ++#endif + -+/*-------------------*/ -+/* Avalanche ATM SAR */ -+/*-------------------*/ ++#ifdef SERIAL_DEBUG_INTR ++ printk("rs_interrupt(%d)...", irq); ++#endif + -+#define AVSAR_SYSCONFIG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000000)) /* SAR system config register */ -+#define AVSAR_SYSSTATUS (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000004)) /* SAR system status register */ -+#define AVSAR_INT_ENABLE (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000008)) /* SAR interrupt enable register */ -+#define AVSAR_CONN_VPI_VCI (*(volatile unsigned int*)(ATM_SAR_BASE+0x0000000c)) /* VPI/VCI connection config */ -+#define AVSAR_CONN_CONFIG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000010)) /* Connection config register */ -+#define AVSAR_OAM_CONFIG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000018)) /* OAM configuration register */ ++ info = IRQ_ports[irq]; ++ if (!info) ++ return; + -+/* Transmit completion ring registers */ ++#ifdef CONFIG_SERIAL_MULTIPORT ++ multi = &rs_multiport[irq]; ++ if (multi->port_monitor) ++ first_multi = inb(multi->port_monitor); ++#endif + -+#define AVSAR_TCRAPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000100)) -+#define AVSAR_TCRASIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000104)) -+#define AVSAR_TCRAINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000108)) -+#define AVSAR_TCRATOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000010c)) -+#define AVSAR_TCRAFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000110)) -+#define AVSAR_TCRAPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000114)) -+#define AVSAR_TCRAENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000118)) -+#define AVSAR_TCRBPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000011c)) -+#define AVSAR_TCRBSIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000120)) -+#define AVSAR_TCRBINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000124)) -+#define AVSAR_TCRBTOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000128)) -+#define AVSAR_TCRBFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000012c)) -+#define AVSAR_TCRBPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000130)) -+#define AVSAR_TCRBENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000134)) ++ do { ++ if (!info->tty || ++ ((iir=serial_in(info, UART_IIR)) & UART_IIR_NO_INT)) { ++ if (!end_mark) ++ end_mark = info; ++ goto next; ++ } ++#ifdef SERIAL_DEBUG_INTR ++ printk("IIR = %x...", serial_in(info, UART_IIR)); ++#endif ++ end_mark = 0; + -+/* Transmit Queue Packet registers */ -+#define AVSAR_TXQUEUE_PKT0 (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000140)) -+#define AVSAR_TXQUEUE_PKT1 (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000144)) -+#define AVSAR_TXQUEUE_PKT2 (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000148)) -+#define AVSAR_TX_FLUSH (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000014C)) -+/* Receive completion ring registers */ ++ info->last_active = jiffies; + -+#define AVSAR_RCRAPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000200)) -+#define AVSAR_RCRASIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000204)) -+#define AVSAR_RCRAINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000208)) -+#define AVSAR_RCRATOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000020c)) -+#define AVSAR_RCRAFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000210)) -+#define AVSAR_RCRAPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000214)) -+#define AVSAR_RCRAENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000218)) -+#define AVSAR_RCRBPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000021c)) -+#define AVSAR_RCRBSIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000220)) -+#define AVSAR_RCRBINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000224)) -+#define AVSAR_RCRBTOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000228)) -+#define AVSAR_RCRBFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000022c)) -+#define AVSAR_RCRBPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000230)) -+#define AVSAR_RCRBENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000234)) ++ status = serial_inp(info, UART_LSR); ++#ifdef SERIAL_DEBUG_INTR ++ printk("status = %x...", status); ++#endif ++ if (status & UART_LSR_DR) ++ receive_chars(info, &status, regs); ++ check_modem_status(info); ++#ifdef CONFIG_MELAN ++ if ((status & UART_LSR_THRE) || ++ /* for buggy ELAN processors */ ++ ((iir & UART_IIR_ID) == UART_IIR_THRI)) ++ transmit_chars(info, 0); ++#else ++ if (status & UART_LSR_THRE) ++ transmit_chars(info, 0); ++#endif + -+#define AVSAR_RXFBL_ADD0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000240)) /* Rx Free buffer list add 0 */ -+#define AVSAR_RXFBL_ADD1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000244)) /* Rx Free buffer list add 1 */ -+#define AVSAR_RXFBL_ADD2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000248)) /* Rx Free buffer list add 2 */ -+#define AVSAR_RXFBLSIZE_0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x0000028c)) /* Rx Free buffer list size 0 */ -+#define AVSAR_RXFBLSIZE_1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x0000029c)) /* Rx Free buffer list size 1 */ -+#define AVSAR_RXFBLSIZE_2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000002ac)) /* Rx Free buffer list size 2 */ -+#define AVSAR_RXFBLSIZE_3 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000002bc)) /* Rx Free buffer list size 3 */ ++ next: ++ info = info->next_port; ++ if (!info) { ++ info = IRQ_ports[irq]; ++ if (pass_counter++ > RS_ISR_PASS_LIMIT) { ++#if 0 ++ printk("rs loop break\n"); ++#endif ++ break; /* Prevent infinite loops */ ++ } ++ continue; ++ } ++ } while (end_mark != info); ++#ifdef CONFIG_SERIAL_MULTIPORT ++ if (multi->port_monitor) ++ printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n", ++ info->state->irq, first_multi, ++ inb(multi->port_monitor)); ++#endif ++#ifdef SERIAL_DEBUG_INTR ++ printk("end.\n"); ++#endif ++} ++#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */ + + -+#if defined(CONFIG_MIPS_EVM3D) || defined(CONFIG_MIPS_AR5D01) || defined(CONFIG_MIPS_AR5W01) ++/* ++ * This is the serial driver's interrupt routine for a single port ++ */ ++static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) ++{ ++ int status, iir; ++ int pass_counter = 0; ++ struct async_struct * info; ++#ifdef CONFIG_SERIAL_MULTIPORT ++ int first_multi = 0; ++ struct rs_multiport_struct *multi; ++#endif ++ ++#ifdef SERIAL_DEBUG_INTR ++ printk("rs_interrupt_single(%d)...", irq); ++#endif + -+#define AVSAR_SAR_FREQUENCY (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010480)) -+#define AVSAR_OAM_CC_SINK (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010484)) -+#define AVSAR_OAM_AIS_RDI_RX (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010488)) -+#define AVSAR_OAM_CPID0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104E0)) -+#define AVSAR_OAM_LLID0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104F0)) -+#define AVSAR_OAM_CPID1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104E4)) -+#define AVSAR_OAM_LLID1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104F4)) -+#define AVSAR_OAM_CPID2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104E8)) -+#define AVSAR_OAM_LLID2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104F8)) -+#define AVSAR_OAM_CPID3 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104EC)) -+#define AVSAR_OAM_LLID3 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104FC)) -+#define AVSAR_OAM_CORR_TAG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010500)) -+#define AVSAR_OAM_FAR_COUNT (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010520)) -+#define AVSAR_OAM_NEAR_COUNT (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010540)) -+#define AVSAR_OAM_CONFIG_REG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000018)) -+#define AVSAR_FAIRNESS_REG (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104B8)) -+#define AVSAR_UBR_PCR_REG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010490)) ++ info = IRQ_ports[irq]; ++ if (!info || !info->tty) ++ return; + ++#ifdef CONFIG_SERIAL_MULTIPORT ++ multi = &rs_multiport[irq]; ++ if (multi->port_monitor) ++ first_multi = inb(multi->port_monitor); ++#endif ++ ++ iir = serial_in(info, UART_IIR); ++ do { ++ status = serial_inp(info, UART_LSR); ++#ifdef SERIAL_DEBUG_INTR ++ printk("status = %x...", status); ++#endif ++ if (status & UART_LSR_DR) ++ receive_chars(info, &status, regs); ++ check_modem_status(info); ++#ifdef CONFIG_MELAN ++ if ((status & UART_LSR_THRE) || ++ /* For buggy ELAN processors */ ++ ((iir & UART_IIR_ID) == UART_IIR_THRI)) ++ transmit_chars(info, 0); ++#else ++ if (status & UART_LSR_THRE) ++ transmit_chars(info, 0); ++#endif ++ if (pass_counter++ > RS_ISR_PASS_LIMIT) { ++#if SERIAL_DEBUG_INTR ++ printk("rs_single loop break.\n"); ++#endif ++ break; ++ } ++ iir = serial_in(info, UART_IIR); ++#ifdef SERIAL_DEBUG_INTR ++ printk("IIR = %x...", iir); ++#endif ++ } while ((iir & UART_IIR_NO_INT) == 0); ++ info->last_active = jiffies; ++#ifdef CONFIG_SERIAL_MULTIPORT ++ if (multi->port_monitor) ++ printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n", ++ info->state->irq, first_multi, ++ inb(multi->port_monitor)); ++#endif ++#ifdef SERIAL_DEBUG_INTR ++ printk("end.\n"); ++#endif ++} + ++#ifdef CONFIG_SERIAL_MULTIPORT +/* ++ * This is the serial driver's for multiport boards ++ */ ++static void rs_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs) ++{ ++ int status; ++ struct async_struct * info; ++ int pass_counter = 0; ++ int first_multi= 0; ++ struct rs_multiport_struct *multi; ++ ++#ifdef SERIAL_DEBUG_INTR ++ printk("rs_interrupt_multi(%d)...", irq); ++#endif + -+#define OAM_CPID_ADD 0xa30104e0 ++ info = IRQ_ports[irq]; ++ if (!info) ++ return; ++ multi = &rs_multiport[irq]; ++ if (!multi->port1) { ++ /* Should never happen */ ++ printk("rs_interrupt_multi: NULL port1!\n"); ++ return; ++ } ++ if (multi->port_monitor) ++ first_multi = inb(multi->port_monitor); ++ ++ while (1) { ++ if (!info->tty || ++ (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) ++ goto next; + -+#define OAM_LLID_ADD 0xa30104f0 ++ info->last_active = jiffies; + -+#define OAM_LLID_VAL 0xffffffff ++ status = serial_inp(info, UART_LSR); ++#ifdef SERIAL_DEBUG_INTR ++ printk("status = %x...", status); ++#endif ++ if (status & UART_LSR_DR) ++ receive_chars(info, &status, regs); ++ check_modem_status(info); ++ if (status & UART_LSR_THRE) ++ transmit_chars(info, 0); ++ ++ next: ++ info = info->next_port; ++ if (info) ++ continue; + -+#define OAM_CORR_TAG 0xa3010500 ++ info = IRQ_ports[irq]; ++ /* ++ * The user was a bonehead, and misconfigured their ++ * multiport info. Rather than lock up the kernel ++ * in an infinite loop, if we loop too many times, ++ * print a message and break out of the loop. ++ */ ++ if (pass_counter++ > RS_ISR_PASS_LIMIT) { ++ printk("Misconfigured multiport serial info " ++ "for irq %d. Breaking out irq loop\n", irq); ++ break; ++ } ++ if (multi->port_monitor) ++ printk("rs port monitor irq %d: 0x%x, 0x%x\n", ++ info->state->irq, first_multi, ++ inb(multi->port_monitor)); ++ if ((inb(multi->port1) & multi->mask1) != multi->match1) ++ continue; ++ if (!multi->port2) ++ break; ++ if ((inb(multi->port2) & multi->mask2) != multi->match2) ++ continue; ++ if (!multi->port3) ++ break; ++ if ((inb(multi->port3) & multi->mask3) != multi->match3) ++ continue; ++ if (!multi->port4) ++ break; ++ if ((inb(multi->port4) & multi->mask4) != multi->match4) ++ continue; ++ break; ++ } ++#ifdef SERIAL_DEBUG_INTR ++ printk("end.\n"); ++#endif ++} ++#endif + -+#define OAM_FAR_COUNT_ADD 0xa3010520 ++/* ++ * ------------------------------------------------------------------- ++ * Here ends the serial interrupt routines. ++ * ------------------------------------------------------------------- ++ */ + -+#define OAM_NEAR_COUNT_ADD 0xa3010540 ++/* ++ * This routine is used to handle the "bottom half" processing for the ++ * serial driver, known also the "software interrupt" processing. ++ * This processing is done at the kernel interrupt level, after the ++ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This ++ * is where time-consuming activities which can not be done in the ++ * interrupt driver proper are done; the interrupt driver schedules ++ * them using rs_sched_event(), and they get done here. ++ */ ++static void do_serial_bh(void) ++{ ++ run_task_queue(&tq_serial); ++} + -+#define OAM_CONFIG_REG_ADD 0xa3000018 -+*/ ++static void do_softint(void *private_) ++{ ++ struct async_struct *info = (struct async_struct *) private_; ++ struct tty_struct *tty; + ++ tty = info->tty; ++ if (!tty) ++ return; + -+#else /* CONFIG_MIPS_EVM3 || CONFIG_MIPS_ACPEP */ ++ if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { ++ tty_wakeup(tty); ++ ++#ifdef SERIAL_HAVE_POLL_WAIT ++ wake_up_interruptible(&tty->poll_wait); ++#endif ++ } ++} + -+#define AVSAR_SAR_FREQUENCY (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012000)) -+#define AVSAR_OAM_CC_SINK (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012004)) -+#define AVSAR_OAM_AIS_RDI_RX (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012008)) -+#define AVSAR_OAM_CPID (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012300)) ++/* ++ * This subroutine is called when the RS_TIMER goes off. It is used ++ * by the serial driver to handle ports that do not have an interrupt ++ * (irq=0). This doesn't work very well for 16450's, but gives barely ++ * passable results for a 16550A. (Although at the expense of much ++ * CPU overhead). ++ */ ++static void rs_timer(unsigned long dummy) ++{ ++ static unsigned long last_strobe; ++ struct async_struct *info; ++ unsigned int i; ++ unsigned long flags; + -+#endif /* CONFIG_MIPS_EVM3D || CONFIG_MIPS_AR5D01 || CONFIG_MIPS_AR5W01 */ ++ if ((jiffies - last_strobe) >= RS_STROBE_TIME) { ++ for (i=0; i < NR_IRQS; i++) { ++ info = IRQ_ports[i]; ++ if (!info) ++ continue; ++ save_flags(flags); cli(); ++#ifdef CONFIG_SERIAL_SHARE_IRQ ++ if (info->next_port) { ++ do { ++ serial_out(info, UART_IER, 0); ++ info->IER |= UART_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ info = info->next_port; ++ } while (info); ++#ifdef CONFIG_SERIAL_MULTIPORT ++ if (rs_multiport[i].port1) ++ rs_interrupt_multi(i, NULL, NULL); ++ else ++#endif ++ rs_interrupt(i, NULL, NULL); ++ } else ++#endif /* CONFIG_SERIAL_SHARE_IRQ */ ++ rs_interrupt_single(i, NULL, NULL); ++ restore_flags(flags); ++ } ++ } ++ last_strobe = jiffies; ++ mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); + ++ if (IRQ_ports[0]) { ++ save_flags(flags); cli(); ++#ifdef CONFIG_SERIAL_SHARE_IRQ ++ rs_interrupt(0, NULL, NULL); ++#else ++ rs_interrupt_single(0, NULL, NULL); ++#endif ++ restore_flags(flags); + -+#define AVSAR_STATE_RAM (ATM_SAR_BASE + 0x010000) /* SAR state RAM */ -+#define AVSAR_PDSP_BASE (ATM_SAR_BASE + 0x020000) /* SAR PDSP base address */ -+#define AVSAR_TXDMA_BASE (ATM_SAR_BASE + 0x030000) /* Transmit DMA state base */ -+#define AVSAR_TDMASTATE6 0x18 /* Transmit DMA state word 6 */ -+#define AVSAR_RXDMA_BASE (ATM_SAR_BASE + 0x040000) /* Receive DMA state base */ -+#define AVSAR_RDMASTATE0 0x0 /* Receive DMA state word 0 */ ++ mod_timer(&serial_timer, jiffies + IRQ_timeout[0]); ++ } ++} + -+/*------------------------------------------*/ -+/* DSL Interface */ -+/*------------------------------------------*/ ++/* ++ * --------------------------------------------------------------- ++ * Low level utility subroutines for the serial driver: routines to ++ * figure out the appropriate timeout for an interrupt chain, routines ++ * to initialize and startup a serial port, and routines to shutdown a ++ * serial port. Useful stuff like that. ++ * --------------------------------------------------------------- ++ */ + -+#define AVDSL_TX_EN (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000000)) -+#define AVDSL_RX_EN (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000004)) -+#define AVDSL_POLL (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000008)) ++/* ++ * This routine figures out the correct timeout for a particular IRQ. ++ * It uses the smallest timeout of all of the serial ports in a ++ * particular interrupt chain. Now only used for IRQ 0.... ++ */ ++static void figure_IRQ_timeout(int irq) ++{ ++ struct async_struct *info; ++ int timeout = 60*HZ; /* 60 seconds === a long time :-) */ + -+/* Fast */ ++ info = IRQ_ports[irq]; ++ if (!info) { ++ IRQ_timeout[irq] = 60*HZ; ++ return; ++ } ++ while (info) { ++ if (info->timeout < timeout) ++ timeout = info->timeout; ++ info = info->next_port; ++ } ++ if (!irq) ++ timeout = timeout / 2; ++ IRQ_timeout[irq] = (timeout > 3) ? timeout-2 : 1; ++} + -+#define AVDSL_TX_FIFO_ADDR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000000C)) -+#define AVDSL_TX_FIFO_BASE0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000010)) -+#define AVDSL_TX_FIFO_LEN0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000014)) -+#define AVDSL_TX_FIFO_PR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000018)) -+#define AVDSL_RX_FIFO_ADDR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000001C)) -+#define AVDSL_RX_FIFO_BASE0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000020)) -+#define AVDSL_RX_FIFO_LEN0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000024)) -+#define AVDSL_RX_FIFO_PR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000028)) ++#ifdef CONFIG_SERIAL_RSA ++/* Attempts to turn on the RSA FIFO. Returns zero on failure */ ++static int enable_rsa(struct async_struct *info) ++{ ++ unsigned char mode; ++ int result; ++ unsigned long flags; + -+/* Interleaved */ ++ save_flags(flags); cli(); ++ mode = serial_inp(info, UART_RSA_MSR); ++ result = mode & UART_RSA_MSR_FIFO; + -+#define AVDSL_TX_FIFO_ADDR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000002C)) -+#define AVDSL_TX_FIFO_BASE1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000030)) -+#define AVDSL_TX_FIFO_LEN1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000034)) -+#define AVDSL_TX_FIFO_PR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000038)) -+#define AVDSL_RX_FIFO_ADDR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000003C)) -+#define AVDSL_RX_FIFO_BASE1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000040)) -+#define AVDSL_RX_FIFO_LEN1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000044)) -+#define AVDSL_RX_FIFO_PR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000048)) ++ if (!result) { ++ serial_outp(info, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); ++ mode = serial_inp(info, UART_RSA_MSR); ++ result = mode & UART_RSA_MSR_FIFO; ++ } + -+/*------------------------------------------*/ -+/* Broadband I/F */ -+/*------------------------------------------*/ ++ restore_flags(flags); ++ return result; ++} + -+#define AVBBIF_BBIF_CNTRL (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000000)) -+#define AVBBIF_ADDR_TRANS_0 (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000004)) -+#define AVBBIF_ADDR_TRANS_1 (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000008)) -+#define AVBBIF_ADDR_XB_MX_BL (*(volatile unsigned int *)(BBIF_CONTROL + 0x0000000C)) -+#define AVBBIF_INFIFO_LVL (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000010)) -+#define AVBBIF_OUTFIFO_LVL (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000014)) ++/* Attempts to turn off the RSA FIFO. Returns zero on failure */ ++static int disable_rsa(struct async_struct *info) ++{ ++ unsigned char mode; ++ int result; ++ unsigned long flags; + -+#define AVBBIF_DISABLED 0x0 -+#define AVBBIF_LBT4040_INT 0x1 -+#define AVBBIF_XBUS 0x2 -+#define AVBBIF_LBT4040_EXT 0x4 ++ save_flags(flags); cli(); ++ mode = serial_inp(info, UART_RSA_MSR); ++ result = !(mode & UART_RSA_MSR_FIFO); + -+#define AVBBIF_ADDR_MASK0 0xff000000 /* handles upper bits of BBIF 0 address */ -+#define AVBBIF_ADDR_MASK1 0xff800000 /* handles upper bits of BBIF 1 address */ -+#define AVBBIF_TRANS_MASK 0xff000000 -+/*------------------------------------------*/ -+/* GPIO I/F */ -+/*------------------------------------------*/ ++ if (!result) { ++ serial_outp(info, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); ++ mode = serial_inp(info, UART_RSA_MSR); ++ result = !(mode & UART_RSA_MSR_FIFO); ++ } + -+#define GPIO_DATA_INPUT (*(volatile unsigned int *)(GPIO_BASE + 0x00000000)) -+#define GPIO_DATA_OUTPUT (*(volatile unsigned int *)(GPIO_BASE + 0x00000004)) -+#define GPIO_DATA_DIR (*(volatile unsigned int *)(GPIO_BASE + 0x00000008)) /* 0=output 1=input */ -+#define GPIO_DATA_ENABLE (*(volatile unsigned int *)(GPIO_BASE + 0x0000000C)) /* 0=GPIO Mux 1=GPIO */ ++ restore_flags(flags); ++ return result; ++} ++#endif /* CONFIG_SERIAL_RSA */ + -+#define GPIO_0 (1<<21) -+#define GPIO_1 (1<<22) -+#define GPIO_2 (1<<23) -+#define GPIO_3 (1<<24) -+#define EINT_1 (1<<18) ++static int startup(struct async_struct * info) ++{ ++ unsigned long flags; ++ int retval=0; ++ void (*handler)(int, void *, struct pt_regs *); ++ struct serial_state *state= info->state; ++ unsigned long page; ++#ifdef CONFIG_SERIAL_MANY_PORTS ++ unsigned short ICP; ++#endif + -+/* -+ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE -+ If you reset the GPIO interface all of the directions (i/o) of the UART B -+ interface pins are inputs and must be reconfigured so as not to lose the -+ serial console interface -+ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE -+*/ ++ page = get_zeroed_page(GFP_KERNEL); ++ if (!page) ++ return -ENOMEM; + -+/*------------------------------------------*/ -+/* CLK_CTRL */ -+/*------------------------------------------*/ -+#define PERIPH_CLK_CTL (*(volatile unsigned int *)(CLK_CTRL_BASE + 0x00000004)) ++ save_flags(flags); cli(); + -+#define PCLK_0_HALF_VBUS (0<<16) -+#define PCLK_EQ_INPUT (1<<16) -+#define BBIF_CLK_HALF_VBUS (0<<17) -+#define BBIF_CLK_EQ_VBUS (1<<17) -+#define BBIF_CLK_EQ_BBCLK (3<<17) -+#define DSP_MODCLK_DSPCLKI (0<<20) -+#define DSP_MODCLK_REFCLKI (1<<20) -+#define USB_CLK_EQ_USBCLKI (0<<21) -+#define USB_CLK_EQ_REFCLKI (1<<21) ++ if (info->flags & ASYNC_INITIALIZED) { ++ free_page(page); ++ goto errout; ++ } + -+/*------------------------------------------*/ -+/* PCI Control Registers */ -+/*------------------------------------------*/ -+#define PCIC_CONTROL (*(volatile unsigned int *)(PCI_CONFIG_BASE)) -+#define PCIC_CONTROL_CFG_DONE (1<<0) -+#define PCIC_CONTROL_DIS_SLAVE_TO (1<<1) -+#define PCIC_CONTROL_FORCE_DELAY_READ (1<<2) -+#define PCIC_CONTROL_FORCE_DELAY_READ_LINE (1<<3) -+#define PCIC_CONTROL_FORCE_DELAY_READ_MULT (1<<4) -+#define PCIC_CONTROL_MEM_SPACE_EN (1<<5) -+#define PCIC_CONTROL_MEM_MASK (1<<6) -+#define PCIC_CONTROL_IO_SPACE_EN (1<<7) -+#define PCIC_CONTROL_IO_MASK (1<<8) -+/* PCIC_CONTROL_RESERVED (1<<9) */ -+#define PCIC_CONTROL_BASE0_EN (1<<10) -+#define PCIC_CONTROL_BASE1_EN (1<<11) -+#define PCIC_CONTROL_BASE2_EN (1<<12) -+#define PCIC_CONTROL_HOLD_MASTER_WRITE (1<<13) -+#define PCIC_CONTROL_ARBITER_EN (1<<14) -+#define PCIC_INT_SOURCE (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000004)) -+#define PCIC_INT_SOURCE_PWR_MGMT (1<<0) -+#define PCIC_INT_SOURCE_PCI_TARGET (1<<1) -+#define PCIC_INT_SOURCE_PCI_MASTER (1<<2) -+#define PCIC_INT_SOURCE_POWER_WAKEUP (1<<3) -+#define PCIC_INT_SOURCE_PMEIN (1<<4) -+/* PCIC_INT_SOURCE_RESERVED (1<<5) */ -+/* PCIC_INT_SOURCE_RESERVED (1<<6) */ -+#define PCIC_INT_SOURCE_PIC_INTA (1<<7) -+#define PCIC_INT_SOURCE_PIC_INTB (1<<8) -+#define PCIC_INT_SOURCE_PIC_INTC (1<<9) -+#define PCIC_INT_SOURCE_PIC_INTD (1<<10) -+#define PCIC_INT_SOURCE_SOFT_INT0 (1<<11) -+#define PCIC_INT_SOURCE_SOFT_INT1 (1<<12) -+#define PCIC_INT_SOURCE_SOFT_INT2 (1<<13) -+#define PCIC_INT_SOURCE_SOFT_INT3 (1<<14) -+#define PCIC_INT_CLEAR (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000008)) -+#define PCIC_INT_CLEAR_PM (1<<0) -+#define PCIC_INT_CLEAR_PCI_TARGET (1<<1) -+#define PCIC_INT_CLEAR_PCI_MASTER (1<<2) -+/* PCIC_INT_CLEAR_RESERVED (1<<3) */ -+#define PCIC_INT_CLEAR_PMEIN (1<<4) -+/* PCIC_INT_CLEAR_RESERVED (1<<5) */ -+/* PCIC_INT_CLEAR_RESERVED (1<<6) */ -+#define PCIC_INT_CLEAR_PCI_INTA (1<<7) -+#define PCIC_INT_CLEAR_PCI_INTB (1<<8) -+#define PCIC_INT_CLEAR_PCI_INTC (1<<9) -+#define PCIC_INT_CLEAR_PCI_INTD (1<<10) -+#define PCIC_INT_CLEAR_SOFT_INT0 (1<<11) -+#define PCIC_INT_CLEAR_SOFT_INT1 (1<<12) -+#define PCIC_INT_CLEAR_SOFT_INT2 (1<<13) -+#define PCIC_INT_CLEAR_SOFT_INT3 (1<<14) -+#define PCIC_INT_EN_AVAL (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000000c)) -+#define PCIC_INT_EN_AVAL_PM (1<<0) -+#define PCIC_INT_EN_AVAL_PCI_TARGET (1<<1) -+#define PCIC_INT_EN_AVAL_PCI_MASTER (1<<2) -+/* PCIC_INT_EN_AVAL_RESERVED (1<<3) */ -+#define PCIC_INT_EN_AVAL_PMEIN (1<<4) -+/* PCIC_INT_EN_AVAL_RESERVED (1<<5) */ -+/* PCIC_INT_EN_AVAL_RESERVED (1<<6) */ -+#define PCIC_INT_EN_AVAL_PCI_INTA (1<<7) -+#define PCIC_INT_EN_AVAL_PCI_INTB (1<<8) -+#define PCIC_INT_EN_AVAL_PCI_INTC (1<<9) -+#define PCIC_INT_EN_AVAL_PCI_INTD (1<<10) -+#define PCIC_INT_EN_AVAL_SOFT_INT0 (1<<11) -+#define PCIC_INT_EN_AVAL_SOFT_INT1 (1<<12) -+#define PCIC_INT_EN_AVAL_SOFT_INT2 (1<<13) -+#define PCIC_INT_EN_AVAL_SOFT_INT3 (1<<14) -+#define PCIC_INT_EN_PCI (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000010)) -+#define PCIC_INT_EN_PCI_PM (1<<0) -+#define PCIC_INT_EN_PCI_PCI_TARGET (1<<1) -+#define PCIC_INT_EN_PCI_PCI_MASTER (1<<2) -+/* PCIC_INT_EN_PCI_RESERVED (1<<3) */ -+#define PCIC_INT_EN_PCI_PMEIN (1<<4) -+/* PCIC_INT_EN_PCI_RESERVED (1<<5) */ -+/* PCIC_INT_EN_PCI_RESERVED (1<<6) */ -+#define PCIC_INT_EN_PCI_PCI_INTA (1<<7) -+#define PCIC_INT_EN_PCI_PCI_INTB (1<<8) -+#define PCIC_INT_EN_PCI_PCI_INTC (1<<9) -+#define PCIC_INT_EN_PCI_PCI_INTD (1<<10) -+#define PCIC_INT_EN_PCI_SOFT_INT0 (1<<11) -+#define PCIC_INT_EN_PCI_SOFT_INT1 (1<<12) -+#define PCIC_INT_EN_PCI_SOFT_INT2 (1<<13) -+#define PCIC_INT_EN_PCI_SOFT_INT3 (1<<14) -+#define PCIC_INT_SWSET (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000014)) -+#define PCIC_INT_SWSET_SOFT_INT0 (1<<0) -+#define PCIC_INT_SWSET_SOFT_INT1 (1<<1) -+#define PCIC_INT_SWSET_SOFT_INT2 (1<<2) -+#define PCIC_INT_SWSET_SOFT_INT3 (1<<3) -+#define PCIC_PM_CTL (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000018)) -+#define PCIC_PM_CTL_PWR_STATE_MASK (0x02) -+/* PCIC_PM_CTL_RESERVED (1<<2) */ -+/* PCIC_PM_CTL_RESERVED (1<<3) */ -+/* PCIC_PM_CTL_RESERVED (1<<4) */ -+/* PCIC_PM_CTL_RESERVED (1<<5) */ -+/* PCIC_PM_CTL_RESERVED (1<<6) */ -+/* PCIC_PM_CTL_RESERVED (1<<7) */ -+/* PCIC_PM_CTL_RESERVED (1<<8) */ -+/* PCIC_PM_CTL_RESERVED (1<<9) */ -+#define PCIC_PM_CTL_PWR_SUPPORT (1<<10) -+#define PCIC_PM_CTL_PMEIN (1<<11) -+#define PCIC_PM_CTL_CAP_MASK (*(volatile unsigned short int *)(PCI_CONFIG_BASE + 0x0000001a)) -+#define PCIC_PM_CONSUME (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000001c)) -+#define PCIC_PM_CONSUME_D0 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001c)) -+#define PCIC_PM_CONSUME_D1 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001d)) -+#define PCIC_PM_CONSUME_D2 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001e)) -+#define PCIC_PM_CONSUME_D3 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001f)) -+#define PCIC_PM_DISSAPATED (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000020)) -+#define PCIC_PM_DISSAPATED_D0 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000020)) -+#define PCIC_PM_DISSAPATED_D1 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000021)) -+#define PCIC_PM_DISSAPATED_D2 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000022)) -+#define PCIC_PM_DISSAPATED_D3 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000023)) -+#define PCIC_PM_DATA_SCALE (*(volatile unsigned short int *)(PCI_CONFIG_BASE + 0x00000024)) -+#define PCIC_VEND_DEV_ID (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000028)) -+#define PCIC_SUB_VEND_DEV_ID (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000002c)) -+#define PCIC_CLASS_REV_ID (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000030)) -+#define PCIC_MAX_MIN (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000034)) -+#define PCIC_MAST_MEM_AT0 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000003c)) -+#define PCIC_MAST_MEM_AT1 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000040)) -+#define PCIC_MAST_MEM_AT2 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000044)) -+#define PCIC_SLAVE_MASK0 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000004c)) -+#define PCIC_SLAVE_MASK1 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000050)) -+#define PCIC_SLAVE_MASK2 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000054)) -+#define PCIC_SLAVE_BASE_AT0 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000058)) -+#define PCIC_SLAVE_BASE_AT1 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000005c)) -+#define PCIC_SLAVE_BASE_AT2 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000060)) -+#define PCIC_CONF_COMMAND (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000090)) -+#define PCIC_CONF_ADDR (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000094)) -+#define PCIC_CONF_DATA (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000098)) ++ 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; + -+/*------------------------------------------*/ -+/* IIC_INTERFACE */ -+/*------------------------------------------*/ -+#define I2C_DATA_HI (*(volatile unsigned int *)(I2C_BASE + 0x0)) -+#define I2C_DATA_LOW (*(volatile unsigned int *)(I2C_BASE + 0x4)) -+#define I2C_CONFIG (*(volatile unsigned int *)(I2C_BASE + 0x8)) -+#define I2C_DATA_READ (*(volatile unsigned int *)(I2C_BASE + 0xC)) -+#define I2C_CLOCK_DIV (*(volatile unsigned int *)(I2C_BASE + 0x10)) ++#ifdef SERIAL_DEBUG_OPEN ++ printk("starting up ttys%d (irq %d)...", info->line, state->irq); ++#endif + -+#define I2CWRITE 0x200 -+#define I2CREAD 0x300 -+#define I2C_END_BURST 0x400 ++ if (uart_config[state->type].flags & UART_STARTECH) { ++ /* Wake up UART */ ++ serial_outp(info, UART_LCR, 0xBF); ++ serial_outp(info, UART_EFR, UART_EFR_ECB); ++ /* ++ * Turn off LCR == 0xBF so we actually set the IER ++ * register on the XR16C850 ++ */ ++ serial_outp(info, UART_LCR, 0); ++ serial_outp(info, UART_IER, 0); ++ /* ++ * Now reset LCR so we can turn off the ECB bit ++ */ ++ serial_outp(info, UART_LCR, 0xBF); ++ serial_outp(info, UART_EFR, 0); ++ /* ++ * For a XR16C850, we need to set the trigger levels ++ */ ++ if (state->type == PORT_16850) { ++ serial_outp(info, UART_FCTR, UART_FCTR_TRGD | ++ UART_FCTR_RX); ++ serial_outp(info, UART_TRG, UART_TRG_96); ++ serial_outp(info, UART_FCTR, UART_FCTR_TRGD | ++ UART_FCTR_TX); ++ serial_outp(info, UART_TRG, UART_TRG_96); ++ } ++ serial_outp(info, UART_LCR, 0); ++ } + -+/* read bits */ -+#define I2C_READ_ERROR 0x8000 -+#define I2C_READ_COMPLETE 0x4000 -+#define I2C_READ_BUSY 0x2000 ++ if (state->type == PORT_16750) { ++ /* Wake up UART */ ++ serial_outp(info, UART_IER, 0); ++ } + -+/* device types */ -+#define I2C_IO_EXPANDER 0x2 -+#define I2C_RTC 0xd ++ if (state->type == PORT_16C950) { ++ /* Wake up and initialize UART */ ++ info->ACR = 0; ++ serial_outp(info, UART_LCR, 0xBF); ++ serial_outp(info, UART_EFR, UART_EFR_ECB); ++ serial_outp(info, UART_IER, 0); ++ serial_outp(info, UART_LCR, 0); ++ serial_icr_write(info, UART_CSR, 0); /* Reset the UART */ ++ serial_outp(info, UART_LCR, 0xBF); ++ serial_outp(info, UART_EFR, UART_EFR_ECB); ++ serial_outp(info, UART_LCR, 0); ++ } ++ ++#ifdef CONFIG_SERIAL_RSA ++ /* ++ * If this is an RSA port, see if we can kick it up to the ++ * higher speed clock. ++ */ ++ if (state->type == PORT_RSA) { ++ if (state->baud_base != SERIAL_RSA_BAUD_BASE && ++ enable_rsa(info)) ++ state->baud_base = SERIAL_RSA_BAUD_BASE; ++ if (state->baud_base == SERIAL_RSA_BAUD_BASE) ++ serial_outp(info, UART_RSA_FRR, 0); ++ } ++#endif ++ ++ /* ++ * Clear the FIFO buffers and disable them ++ * (they will be reenabled in change_speed()) ++ */ ++ if (uart_config[state->type].flags & UART_CLEAR_FIFO) { ++ serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); ++ serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | ++ UART_FCR_CLEAR_RCVR | ++ UART_FCR_CLEAR_XMIT)); ++ serial_outp(info, UART_FCR, 0); ++ } ++ ++ /* ++ * Clear the interrupt registers. ++ */ ++ (void) serial_inp(info, UART_LSR); ++ (void) serial_inp(info, UART_RX); ++ (void) serial_inp(info, UART_IIR); ++ (void) serial_inp(info, UART_MSR); ++ ++ /* ++ * At this point there's no way the LSR could still be 0xFF; ++ * if it is, then bail out, because there's likely no UART ++ * here. ++ */ ++ if (!(info->flags & ASYNC_BUGGY_UART) && ++ (serial_inp(info, UART_LSR) == 0xff)) { ++ printk("ttyS%d: LSR safety check engaged!\n", state->line); ++ if (capable(CAP_SYS_ADMIN)) { ++ if (info->tty) ++ set_bit(TTY_IO_ERROR, &info->tty->flags); ++ } else ++ retval = -ENODEV; ++ goto errout; ++ } ++ ++ /* ++ * Allocate the IRQ if necessary ++ */ ++ if (state->irq && (!IRQ_ports[state->irq] || ++ !IRQ_ports[state->irq]->next_port)) { ++ if (IRQ_ports[state->irq]) { ++#ifdef CONFIG_SERIAL_SHARE_IRQ ++ free_irq(state->irq, &IRQ_ports[state->irq]); ++#ifdef CONFIG_SERIAL_MULTIPORT ++ if (rs_multiport[state->irq].port1) ++ handler = rs_interrupt_multi; ++ else ++#endif ++ handler = rs_interrupt; ++#else ++ retval = -EBUSY; ++ goto errout; ++#endif /* CONFIG_SERIAL_SHARE_IRQ */ ++ } else ++ handler = rs_interrupt_single; ++ ++ 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); ++ retval = 0; ++ } ++ 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; ++ figure_IRQ_timeout(state->irq); ++ ++ /* ++ * Now, initialize the UART ++ */ ++ serial_outp(info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ ++ ++ info->MCR = 0; ++ if (info->tty->termios->c_cflag & CBAUD) ++ info->MCR = UART_MCR_DTR | UART_MCR_RTS; ++#ifdef CONFIG_SERIAL_MANY_PORTS ++ if (info->flags & ASYNC_FOURPORT) { ++ if (state->irq == 0) ++ info->MCR |= UART_MCR_OUT1; ++ } else ++#endif ++ { ++ if (state->irq != 0) ++ info->MCR |= UART_MCR_OUT2; ++ } ++ info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ ++ serial_outp(info, UART_MCR, info->MCR); ++ ++ /* ++ * Finally, enable interrupts ++ */ ++ info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; ++ serial_outp(info, UART_IER, info->IER); /* enable interrupts */ ++ ++#ifdef CONFIG_SERIAL_MANY_PORTS ++ if (info->flags & ASYNC_FOURPORT) { ++ /* Enable interrupts on the AST Fourport board */ ++ ICP = (info->port & 0xFE0) | 0x01F; ++ outb_p(0x80, ICP); ++ (void) inb_p(ICP); ++ } ++#endif ++ ++ /* ++ * And clear the interrupt registers again for luck. ++ */ ++ (void)serial_inp(info, UART_LSR); ++ (void)serial_inp(info, UART_RX); ++ (void)serial_inp(info, UART_IIR); ++ (void)serial_inp(info, UART_MSR); ++ ++ if (info->tty) ++ clear_bit(TTY_IO_ERROR, &info->tty->flags); ++ info->xmit.head = info->xmit.tail = 0; ++ ++ /* ++ * Set up serial timers... ++ */ ++ mod_timer(&serial_timer, jiffies + 2*HZ/100); ++ ++ /* ++ * Set up the tty->alt_speed kludge ++ */ ++#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ ++ if (info->tty) { ++ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) ++ info->tty->alt_speed = 57600; ++ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) ++ info->tty->alt_speed = 115200; ++ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) ++ info->tty->alt_speed = 230400; ++ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) ++ info->tty->alt_speed = 460800; ++ } ++#endif ++ ++ /* ++ * and set the speed of the serial port ++ */ ++ change_speed(info, 0); ++ ++ info->flags |= ASYNC_INITIALIZED; ++ restore_flags(flags); ++ return 0; ++ ++errout: ++ restore_flags(flags); ++ return retval; ++} ++ ++/* ++ * This routine will shutdown a serial port; interrupts are disabled, and ++ * DTR is dropped if the hangup on close termio flag is on. ++ */ ++static void shutdown(struct async_struct * info) ++{ ++ unsigned long flags; ++ struct serial_state *state; ++ int retval; ++ ++ if (!(info->flags & ASYNC_INITIALIZED)) ++ return; ++ ++ state = info->state; ++ ++#ifdef SERIAL_DEBUG_OPEN ++ printk("Shutting down serial port %d (irq %d)....", info->line, ++ state->irq); ++#endif ++ ++ save_flags(flags); cli(); /* Disable interrupts */ ++ ++ /* ++ * clear delta_msr_wait queue to avoid mem leaks: we may free the irq ++ * here so the queue might never be waken up ++ */ ++ wake_up_interruptible(&info->delta_msr_wait); ++ ++ /* ++ * First unlink the serial port from the IRQ chain... ++ */ ++ if (info->next_port) ++ info->next_port->prev_port = info->prev_port; ++ if (info->prev_port) ++ info->prev_port->next_port = info->next_port; ++ else ++ IRQ_ports[state->irq] = info->next_port; ++ figure_IRQ_timeout(state->irq); ++ ++ /* ++ * Free the IRQ, if necessary ++ */ ++ if (state->irq && (!IRQ_ports[state->irq] || ++ !IRQ_ports[state->irq]->next_port)) { ++ if (IRQ_ports[state->irq]) { ++ free_irq(state->irq, &IRQ_ports[state->irq]); ++ retval = request_irq(state->irq, rs_interrupt_single, ++ SA_SHIRQ, "serial", ++ &IRQ_ports[state->irq]); ++ ++ if (retval) ++ printk("serial shutdown: request_irq: error %d" ++ " Couldn't reacquire IRQ.\n", retval); ++ } else ++ free_irq(state->irq, &IRQ_ports[state->irq]); ++ } ++ ++ if (info->xmit.buf) { ++ unsigned long pg = (unsigned long) info->xmit.buf; ++ info->xmit.buf = 0; ++ free_page(pg); ++ } ++ ++ info->IER = 0; ++ serial_outp(info, UART_IER, 0x00); /* disable all intrs */ ++#ifdef CONFIG_SERIAL_MANY_PORTS ++ if (info->flags & ASYNC_FOURPORT) { ++ /* reset interrupts on the AST Fourport board */ ++ (void) inb((info->port & 0xFE0) | 0x01F); ++ info->MCR |= UART_MCR_OUT1; ++ } else ++#endif ++ info->MCR &= ~UART_MCR_OUT2; ++ info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ ++ ++ /* disable break condition */ ++ serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC); ++ ++ if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) ++ info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); ++ serial_outp(info, UART_MCR, info->MCR); ++ ++ /* disable FIFO's */ ++ serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | ++ UART_FCR_CLEAR_RCVR | ++ UART_FCR_CLEAR_XMIT)); ++ serial_outp(info, UART_FCR, 0); ++ ++#ifdef CONFIG_SERIAL_RSA ++ /* ++ * Reset the RSA board back to 115kbps compat mode. ++ */ ++ if ((state->type == PORT_RSA) && ++ (state->baud_base == SERIAL_RSA_BAUD_BASE && ++ disable_rsa(info))) ++ state->baud_base = SERIAL_RSA_BAUD_BASE_LO; ++#endif ++ ++ ++ (void)serial_in(info, UART_RX); /* read data port to reset things */ ++ ++ if (info->tty) ++ set_bit(TTY_IO_ERROR, &info->tty->flags); ++ ++ if (uart_config[info->state->type].flags & UART_STARTECH) { ++ /* Arrange to enter sleep mode */ ++ serial_outp(info, UART_LCR, 0xBF); ++ serial_outp(info, UART_EFR, UART_EFR_ECB); ++ serial_outp(info, UART_LCR, 0); ++ serial_outp(info, UART_IER, UART_IERX_SLEEP); ++ serial_outp(info, UART_LCR, 0xBF); ++ serial_outp(info, UART_EFR, 0); ++ serial_outp(info, UART_LCR, 0); ++ } ++ if (info->state->type == PORT_16750) { ++ /* Arrange to enter sleep mode */ ++ serial_outp(info, UART_IER, UART_IERX_SLEEP); ++ } ++ info->flags &= ~ASYNC_INITIALIZED; ++ restore_flags(flags); ++} ++ ++#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ ++static int baud_table[] = { ++ 0, 50, 75, 110, 134, 150, 200, 300, ++ 600, 1200, 1800, 2400, 4800, 9600, 19200, ++ 38400, 57600, 115200, 230400, 460800, 0 }; ++ ++static int tty_get_baud_rate(struct tty_struct *tty) ++{ ++ struct async_struct * info = (struct async_struct *)tty->driver_data; ++ unsigned int cflag, i; ++ ++ cflag = tty->termios->c_cflag; ++ ++ i = cflag & CBAUD; ++ if (i & CBAUDEX) { ++ i &= ~CBAUDEX; ++ if (i < 1 || i > 2) ++ tty->termios->c_cflag &= ~CBAUDEX; ++ else ++ i += 15; ++ } ++ if (i == 15) { ++ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) ++ i += 1; ++ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) ++ i += 2; ++ } ++ return baud_table[i]; ++} ++#endif ++ ++/* ++ * This routine is called to set the UART divisor registers to match ++ * the specified baud rate for a serial port. ++ */ ++static void change_speed(struct async_struct *info, ++ struct termios *old_termios) ++{ ++ int quot = 0, baud_base, baud; ++ unsigned cflag, cval, fcr = 0; ++ int bits; ++ unsigned long flags; ++ ++ if (!info->tty || !info->tty->termios) ++ return; ++ cflag = info->tty->termios->c_cflag; ++ if (!CONFIGURED_SERIAL_PORT(info)) ++ return; ++ ++ /* byte size and parity */ ++ switch (cflag & CSIZE) { ++ case CS5: cval = 0x00; bits = 7; break; ++ case CS6: cval = 0x01; bits = 8; break; ++ case CS7: cval = 0x02; bits = 9; break; ++ case CS8: cval = 0x03; bits = 10; break; ++ /* Never happens, but GCC is too dumb to figure it out */ ++ default: cval = 0x00; bits = 7; break; ++ } ++ if (cflag & CSTOPB) { ++ cval |= 0x04; ++ bits++; ++ } ++ if (cflag & PARENB) { ++ cval |= UART_LCR_PARITY; ++ bits++; ++ } ++ if (!(cflag & PARODD)) ++ cval |= UART_LCR_EPAR; ++#ifdef CMSPAR ++ if (cflag & CMSPAR) ++ cval |= UART_LCR_SPAR; ++#endif ++ ++ /* Determine divisor based on baud rate */ ++ baud = tty_get_baud_rate(info->tty); ++ if (!baud) ++ baud = 9600; /* B0 transition handled in rs_set_termios */ ++#ifdef CONFIG_SERIAL_RSA ++ if ((info->state->type == PORT_RSA) && ++ (info->state->baud_base != SERIAL_RSA_BAUD_BASE) && ++ enable_rsa(info)) ++ info->state->baud_base = SERIAL_RSA_BAUD_BASE; ++#endif ++ baud_base = info->state->baud_base; ++ if (info->state->type == PORT_16C950) { ++ if (baud <= baud_base) ++ serial_icr_write(info, UART_TCR, 0); ++ else if (baud <= 2*baud_base) { ++ serial_icr_write(info, UART_TCR, 0x8); ++ baud_base = baud_base * 2; ++ } else if (baud <= 4*baud_base) { ++ serial_icr_write(info, UART_TCR, 0x4); ++ baud_base = baud_base * 4; ++ } else ++ serial_icr_write(info, UART_TCR, 0); ++ } ++ if (baud == 38400 && ++ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) ++ quot = info->state->custom_divisor; ++ else { ++ if (baud == 134) ++ /* Special case since 134 is really 134.5 */ ++ quot = (2*baud_base / 269); ++ else if (baud) ++ quot = baud_base / baud; ++ } ++ /* If the quotient is zero refuse the change */ ++ if (!quot && old_termios) { ++ info->tty->termios->c_cflag &= ~CBAUD; ++ info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); ++ baud = tty_get_baud_rate(info->tty); ++ if (!baud) ++ baud = 9600; ++ if (baud == 38400 && ++ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) ++ quot = info->state->custom_divisor; ++ else { ++ if (baud == 134) ++ /* Special case since 134 is really 134.5 */ ++ quot = (2*baud_base / 269); ++ else if (baud) ++ quot = baud_base / baud; ++ } ++ } ++ /* As a last resort, if the quotient is zero, default to 9600 bps */ ++ if (!quot) ++ quot = baud_base / 9600; ++ /* ++ * Work around a bug in the Oxford Semiconductor 952 rev B ++ * chip which causes it to seriously miscalculate baud rates ++ * when DLL is 0. ++ */ ++ if (((quot & 0xFF) == 0) && (info->state->type == PORT_16C950) && ++ (info->state->revision == 0x5201)) ++ quot++; ++ ++ info->quot = quot; ++ info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); ++ info->timeout += HZ/50; /* Add .02 seconds of slop */ ++ ++ /* Set up FIFO's */ ++ if (uart_config[info->state->type].flags & UART_USE_FIFO) { ++ if ((info->state->baud_base / quot) < 2400) ++ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; ++#ifdef CONFIG_SERIAL_RSA ++ else if (info->state->type == PORT_RSA) ++ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; ++#endif ++ else ++ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; ++ } ++ if (info->state->type == PORT_16750) ++ fcr |= UART_FCR7_64BYTE; ++ ++ /* CTS flow control flag and modem status interrupts */ ++ info->IER &= ~UART_IER_MSI; ++ if (info->flags & ASYNC_HARDPPS_CD) ++ info->IER |= UART_IER_MSI; ++ if (cflag & CRTSCTS) { ++ info->flags |= ASYNC_CTS_FLOW; ++ info->IER |= UART_IER_MSI; ++ } else ++ info->flags &= ~ASYNC_CTS_FLOW; ++ if (cflag & CLOCAL) ++ info->flags &= ~ASYNC_CHECK_CD; ++ else { ++ info->flags |= ASYNC_CHECK_CD; ++ info->IER |= UART_IER_MSI; ++ } ++ serial_out(info, UART_IER, info->IER); ++ ++ /* ++ * Set up parity check flag ++ */ ++#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) ++ ++ info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; ++ if (I_INPCK(info->tty)) ++ info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; ++ if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) ++ info->read_status_mask |= UART_LSR_BI; ++ ++ /* ++ * Characters to ignore ++ */ ++ info->ignore_status_mask = 0; ++ if (I_IGNPAR(info->tty)) ++ info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; ++ if (I_IGNBRK(info->tty)) { ++ info->ignore_status_mask |= UART_LSR_BI; ++ /* ++ * If we're ignore parity and break indicators, ignore ++ * overruns too. (For real raw support). ++ */ ++ if (I_IGNPAR(info->tty)) ++ info->ignore_status_mask |= UART_LSR_OE; ++ } ++ /* ++ * !!! ignore all characters if CREAD is not set ++ */ ++ if ((cflag & CREAD) == 0) ++ info->ignore_status_mask |= UART_LSR_DR; ++ save_flags(flags); cli(); ++ if (uart_config[info->state->type].flags & UART_STARTECH) { ++ serial_outp(info, UART_LCR, 0xBF); ++ serial_outp(info, UART_EFR, ++ (cflag & CRTSCTS) ? UART_EFR_CTS : 0); ++ } ++ serial_outp(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ ++ serial_outp(info, UART_DLL, quot & 0xff); /* LS of divisor */ ++ serial_outp(info, UART_DLM, quot >> 8); /* MS of divisor */ ++ if (info->state->type == PORT_16750) ++ serial_outp(info, UART_FCR, fcr); /* set fcr */ ++ serial_outp(info, UART_LCR, cval); /* reset DLAB */ ++ info->LCR = cval; /* Save LCR */ ++ if (info->state->type != PORT_16750) { ++ if (fcr & UART_FCR_ENABLE_FIFO) { ++ /* emulated UARTs (Lucent Venus 167x) need two steps */ ++ serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); ++ } ++ serial_outp(info, UART_FCR, fcr); /* set fcr */ ++ } ++ restore_flags(flags); ++} ++ ++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 (serial_paranoia_check(info, tty->device, "rs_put_char")) ++ return; ++ ++ 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 (serial_paranoia_check(info, tty->device, "rs_flush_chars")) ++ return; ++ ++ if (info->xmit.head == info->xmit.tail ++ || tty->stopped ++ || tty->hw_stopped ++ || !info->xmit.buf) ++ return; ++ ++ save_flags(flags); cli(); ++ info->IER |= UART_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ restore_flags(flags); ++} ++ ++static int rs_write(struct tty_struct * tty, int from_user, ++ const unsigned char *buf, int count) ++{ ++ int c, ret = 0; ++ struct async_struct *info = (struct async_struct *)tty->driver_data; ++ unsigned long flags; ++ ++ if (serial_paranoia_check(info, tty->device, "rs_write")) ++ return 0; ++ ++ if (!tty || !info->xmit.buf || !tmp_buf) ++ return 0; ++ ++ save_flags(flags); ++ if (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_IER_THRI)) { ++ info->IER |= UART_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ } ++ return ret; ++} ++ ++static int rs_write_room(struct tty_struct *tty) ++{ ++ struct async_struct *info = (struct async_struct *)tty->driver_data; ++ ++ if (serial_paranoia_check(info, tty->device, "rs_write_room")) ++ return 0; ++ 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; ++ ++ if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) ++ return 0; ++ 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; ++ ++ if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) ++ return; ++ save_flags(flags); cli(); ++ info->xmit.head = info->xmit.tail = 0; ++ restore_flags(flags); ++#ifdef SERIAL_HAVE_POLL_WAIT ++ wake_up_interruptible(&tty->poll_wait); ++#endif ++ tty_wakeup(tty); ++} ++ ++/* ++ * 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; ++ ++ if (serial_paranoia_check(info, tty->device, "rs_send_char")) ++ return; ++ ++ info->x_char = ch; ++ if (ch) { ++ /* Make sure transmit interrupts are on */ ++ info->IER |= UART_IER_THRI; ++ serial_out(info, UART_IER, info->IER); ++ } ++} ++ ++/* ++ * ------------------------------------------------------------ ++ * 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) ++{ ++ 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 (serial_paranoia_check(info, tty->device, "rs_throttle")) ++ return; ++ ++ 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); ++} ++ ++static void rs_unthrottle(struct tty_struct * tty) ++{ ++ 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 (serial_paranoia_check(info, tty->device, "rs_unthrottle")) ++ return; ++ ++ 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); ++} ++ ++/* ++ * ------------------------------------------------------------ ++ * rs_ioctl() and friends ++ * ------------------------------------------------------------ ++ */ ++ ++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; ++} ++ ++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].io_type == SERIAL_IO_PORT) && ++ (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; ++#if (LINUX_VERSION_CODE > 0x20100) ++ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; ++#endif ++ info->xmit_fifo_size = state->xmit_fifo_size = ++ new_serial.xmit_fifo_size; ++ ++ if ((state->type != PORT_UNKNOWN) && state->port) { ++#ifdef CONFIG_SERIAL_RSA ++ if (old_state.type == PORT_RSA) ++ release_region(state->port + UART_RSA_BASE, 16); ++ else ++#endif ++ 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) { ++#ifdef CONFIG_SERIAL_RSA ++ if (state->type == PORT_RSA) ++ request_region(state->port + UART_RSA_BASE, ++ 16, "serial_rsa(set)"); ++ else ++#endif ++ request_region(state->port,8,"serial(set)"); ++ } ++ ++ ++check_and_exit: ++ if ((!state->port && !state->iomem_base) || !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 (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ ++ 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; ++#endif ++ change_speed(info, 0); ++ } ++ } else ++ retval = startup(info); ++ return retval; ++} ++ ++ ++/* ++ * get_lsr_info - get line status register info ++ * ++ * Purpose: Let user call ioctl() to get info when the UART physically ++ * is emptied. On bus types like RS485, the transmitter must ++ * release the bus after transmitting. This must be done when ++ * the transmit shift register is empty, not be done when the ++ * transmit holding register is empty. This functionality ++ * allows an RS485 driver to be written in user space. ++ */ ++static int get_lsr_info(struct async_struct * info, unsigned int *value) ++{ ++ unsigned char status; ++ unsigned int result; ++ unsigned long flags; ++ ++ save_flags(flags); cli(); ++ status = serial_in(info, UART_LSR); ++ restore_flags(flags); ++ result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); ++ ++ /* ++ * If we're about to load something into the transmit ++ * register, we'll pretend the transmitter isn't empty to ++ * avoid a race condition (depending on when the transmit ++ * interrupt happens). ++ */ ++ if (info->x_char || ++ ((CIRC_CNT(info->xmit.head, info->xmit.tail, ++ SERIAL_XMIT_SIZE) > 0) && ++ !info->tty->stopped && !info->tty->hw_stopped)) ++ result &= ~TIOCSER_TEMT; ++ ++ if (copy_to_user(value, &result, sizeof(int))) ++ return -EFAULT; ++ return 0; ++} ++ ++ ++static int get_modem_info(struct async_struct * info, unsigned int *value) ++{ ++ unsigned char control, status; ++ unsigned int result; ++ unsigned long flags; ++ ++ control = info->MCR; ++ save_flags(flags); cli(); ++ status = serial_in(info, UART_MSR); ++ restore_flags(flags); ++ result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) ++ | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) ++#ifdef TIOCM_OUT1 ++ | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0) ++ | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0) ++#endif ++ | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) ++ | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) ++ | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) ++ | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); ++ ++ if (copy_to_user(value, &result, sizeof(int))) ++ return -EFAULT; ++ return 0; ++} ++ ++static int set_modem_info(struct async_struct * info, unsigned int cmd, ++ unsigned int *value) ++{ ++ unsigned int arg; ++ unsigned long flags; ++ ++ if (copy_from_user(&arg, value, sizeof(int))) ++ return -EFAULT; ++ ++ switch (cmd) { ++ case TIOCMBIS: ++ if (arg & TIOCM_RTS) ++ info->MCR |= UART_MCR_RTS; ++ if (arg & TIOCM_DTR) ++ info->MCR |= UART_MCR_DTR; ++#ifdef TIOCM_OUT1 ++ if (arg & TIOCM_OUT1) ++ info->MCR |= UART_MCR_OUT1; ++ if (arg & TIOCM_OUT2) ++ info->MCR |= UART_MCR_OUT2; ++#endif ++ if (arg & TIOCM_LOOP) ++ info->MCR |= UART_MCR_LOOP; ++ break; ++ case TIOCMBIC: ++ if (arg & TIOCM_RTS) ++ info->MCR &= ~UART_MCR_RTS; ++ if (arg & TIOCM_DTR) ++ info->MCR &= ~UART_MCR_DTR; ++#ifdef TIOCM_OUT1 ++ if (arg & TIOCM_OUT1) ++ info->MCR &= ~UART_MCR_OUT1; ++ if (arg & TIOCM_OUT2) ++ info->MCR &= ~UART_MCR_OUT2; ++#endif ++ if (arg & TIOCM_LOOP) ++ info->MCR &= ~UART_MCR_LOOP; ++ break; ++ case TIOCMSET: ++ info->MCR = ((info->MCR & ~(UART_MCR_RTS | ++#ifdef TIOCM_OUT1 ++ UART_MCR_OUT1 | ++ UART_MCR_OUT2 | ++#endif ++ UART_MCR_LOOP | ++ UART_MCR_DTR)) ++ | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) ++#ifdef TIOCM_OUT1 ++ | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0) ++ | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0) ++#endif ++ | ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0) ++ | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ save_flags(flags); cli(); ++ info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ ++ serial_out(info, UART_MCR, info->MCR); ++ restore_flags(flags); ++ return 0; ++} ++ ++static int do_autoconfig(struct async_struct * info) ++{ ++ int irq, retval; ++ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ ++ if (info->state->count > 1) ++ return -EBUSY; ++ ++ shutdown(info); ++ ++ autoconfig(info->state); ++ if ((info->state->flags & ASYNC_AUTO_IRQ) && ++ (info->state->port != 0 || info->state->iomem_base != 0) && ++ (info->state->type != PORT_UNKNOWN)) { ++ irq = detect_uart_irq(info->state); ++ if (irq > 0) ++ info->state->irq = irq; ++ } ++ ++ retval = startup(info); ++ if (retval) ++ return retval; ++ return 0; ++} ++ ++/* ++ * rs_break() --- routine which turns the break handling on or off ++ */ ++#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ ++static void send_break( struct async_struct * info, int duration) ++{ ++ if (!CONFIGURED_SERIAL_PORT(info)) ++ return; ++ current->state = TASK_INTERRUPTIBLE; ++ current->timeout = jiffies + duration; ++ cli(); ++ info->LCR |= UART_LCR_SBC; ++ serial_out(info, UART_LCR, info->LCR); ++ schedule(); ++ info->LCR &= ~UART_LCR_SBC; ++ serial_out(info, UART_LCR, info->LCR); ++ sti(); ++} ++#else ++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 (serial_paranoia_check(info, tty->device, "rs_break")) ++ return; ++ ++ if (!CONFIGURED_SERIAL_PORT(info)) ++ return; ++ save_flags(flags); cli(); ++ if (break_state == -1) ++ info->LCR |= UART_LCR_SBC; ++ else ++ info->LCR &= ~UART_LCR_SBC; ++ serial_out(info, UART_LCR, info->LCR); ++ restore_flags(flags); ++} ++#endif ++ ++#ifdef CONFIG_SERIAL_MULTIPORT ++static int get_multiport_struct(struct async_struct * info, ++ struct serial_multiport_struct *retinfo) ++{ ++ struct serial_multiport_struct ret; ++ struct rs_multiport_struct *multi; ++ ++ multi = &rs_multiport[info->state->irq]; ++ ++ ret.port_monitor = multi->port_monitor; ++ ++ ret.port1 = multi->port1; ++ ret.mask1 = multi->mask1; ++ ret.match1 = multi->match1; ++ ++ ret.port2 = multi->port2; ++ ret.mask2 = multi->mask2; ++ ret.match2 = multi->match2; ++ ++ ret.port3 = multi->port3; ++ ret.mask3 = multi->mask3; ++ ret.match3 = multi->match3; ++ ++ ret.port4 = multi->port4; ++ ret.mask4 = multi->mask4; ++ ret.match4 = multi->match4; ++ ++ ret.irq = info->state->irq; ++ ++ if (copy_to_user(retinfo,&ret,sizeof(*retinfo))) ++ return -EFAULT; ++ return 0; ++} ++ ++static int set_multiport_struct(struct async_struct * info, ++ struct serial_multiport_struct *in_multi) ++{ ++ struct serial_multiport_struct new_multi; ++ struct rs_multiport_struct *multi; ++ struct serial_state *state; ++ int was_multi, now_multi; ++ int retval; ++ void (*handler)(int, void *, struct pt_regs *); ++ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ state = info->state; ++ ++ if (copy_from_user(&new_multi, in_multi, ++ sizeof(struct serial_multiport_struct))) ++ return -EFAULT; ++ ++ if (new_multi.irq != state->irq || state->irq == 0 || ++ !IRQ_ports[state->irq]) ++ return -EINVAL; ++ ++ multi = &rs_multiport[state->irq]; ++ was_multi = (multi->port1 != 0); ++ ++ multi->port_monitor = new_multi.port_monitor; ++ ++ if (multi->port1) ++ release_region(multi->port1,1); ++ multi->port1 = new_multi.port1; ++ multi->mask1 = new_multi.mask1; ++ multi->match1 = new_multi.match1; ++ if (multi->port1) ++ request_region(multi->port1,1,"serial(multiport1)"); ++ ++ if (multi->port2) ++ release_region(multi->port2,1); ++ multi->port2 = new_multi.port2; ++ multi->mask2 = new_multi.mask2; ++ multi->match2 = new_multi.match2; ++ if (multi->port2) ++ request_region(multi->port2,1,"serial(multiport2)"); ++ ++ if (multi->port3) ++ release_region(multi->port3,1); ++ multi->port3 = new_multi.port3; ++ multi->mask3 = new_multi.mask3; ++ multi->match3 = new_multi.match3; ++ if (multi->port3) ++ request_region(multi->port3,1,"serial(multiport3)"); ++ ++ if (multi->port4) ++ release_region(multi->port4,1); ++ multi->port4 = new_multi.port4; ++ multi->mask4 = new_multi.mask4; ++ multi->match4 = new_multi.match4; ++ if (multi->port4) ++ request_region(multi->port4,1,"serial(multiport4)"); ++ ++ now_multi = (multi->port1 != 0); ++ ++ if (IRQ_ports[state->irq]->next_port && ++ (was_multi != now_multi)) { ++ free_irq(state->irq, &IRQ_ports[state->irq]); ++ if (now_multi) ++ handler = rs_interrupt_multi; ++ else ++ handler = rs_interrupt; ++ ++ retval = request_irq(state->irq, handler, SA_SHIRQ, ++ "serial", &IRQ_ports[state->irq]); ++ if (retval) { ++ printk("Couldn't reallocate serial interrupt " ++ "driver!!\n"); ++ } ++ } ++ return 0; ++} ++#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 (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ ++ int retval, tmp; ++#endif ++ ++ if (serial_paranoia_check(info, tty->device, "rs_ioctl")) ++ return -ENODEV; ++ ++ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && ++ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && ++ (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { ++ if (tty->flags & (1 << TTY_IO_ERROR)) ++ return -EIO; ++ } ++ ++ switch (cmd) { ++#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ ++ case TCSBRK: /* SVID version: non-zero arg --> no break */ ++ retval = tty_check_change(tty); ++ if (retval) ++ return retval; ++ tty_wait_until_sent(tty, 0); ++ if (signal_pending(current)) ++ return -EINTR; ++ if (!arg) { ++ send_break(info, HZ/4); /* 1/4 second */ ++ if (signal_pending(current)) ++ return -EINTR; ++ } ++ return 0; ++ case TCSBRKP: /* support for POSIX tcsendbreak() */ ++ retval = tty_check_change(tty); ++ if (retval) ++ return retval; ++ tty_wait_until_sent(tty, 0); ++ if (signal_pending(current)) ++ return -EINTR; ++ send_break(info, arg ? arg*(HZ/10) : HZ/4); ++ if (signal_pending(current)) ++ return -EINTR; ++ return 0; ++ case TIOCGSOFTCAR: ++ tmp = C_CLOCAL(tty) ? 1 : 0; ++ if (copy_to_user((void *)arg, &tmp, sizeof(int))) ++ return -EFAULT; ++ return 0; ++ case TIOCSSOFTCAR: ++ if (copy_from_user(&tmp, (void *)arg, sizeof(int))) ++ return -EFAULT; ++ ++ tty->termios->c_cflag = ++ ((tty->termios->c_cflag & ~CLOCAL) | ++ (tmp ? CLOCAL : 0)); ++ return 0; ++#endif ++ 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; ++ ++#ifdef CONFIG_SERIAL_MULTIPORT ++ case TIOCSERGETMULTI: ++ return get_multiport_struct(info, ++ (struct serial_multiport_struct *) arg); ++ case TIOCSERSETMULTI: ++ return set_multiport_struct(info, ++ (struct serial_multiport_struct *) arg); ++#endif ++ ++ /* ++ * 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: ++ 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 */ ++ ++ /* ++ * 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; ++} ++ ++static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) ++{ ++ 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; ++ ++ change_speed(info, old_termios); ++ ++ /* 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); ++ } ++ ++#if 0 ++ /* ++ * No need to wake up processes in open wait, since they ++ * sample the CLOCAL flag once, and don't recheck it. ++ * XXX It's not clear whether the current behavior is correct ++ * or not. Hence, this may change..... ++ */ ++ if (!(old_termios->c_cflag & CLOCAL) && ++ (tty->termios->c_cflag & CLOCAL)) ++ wake_up_interruptible(&info->open_wait); ++#endif ++} ++ ++/* ++ * ------------------------------------------------------------ ++ * 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; ++ ++ if (!info || serial_paranoia_check(info, tty->device, "rs_close")) ++ return; ++ ++ state = info->state; ++ ++ save_flags(flags); cli(); ++ ++ if (tty_hung_up_p(filp)) { ++ DBG_CNT("before DEC-hung"); ++ MOD_DEC_USE_COUNT; ++ 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; ++ } ++ if (state->count) { ++ DBG_CNT("before DEC-2"); ++ MOD_DEC_USE_COUNT; ++ restore_flags(flags); ++ return; ++ } ++ 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 (state->closing_wait != ASYNC_CLOSING_WAIT_NONE) ++ tty_wait_until_sent(tty, state->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); ++ tty_ldisc_flush(tty); ++ tty->closing = 0; ++ info->event = 0; ++ info->tty = 0; ++ if (info->blocked_open) { ++ if (state->close_delay) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(state->close_delay); ++ } ++ wake_up_interruptible(&info->open_wait); ++ } ++ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| ++ ASYNC_CLOSING); ++ wake_up_interruptible(&info->close_wait); ++ MOD_DEC_USE_COUNT; ++} ++ ++/* ++ * rs_wait_until_sent() --- wait until the transmitter is empty ++ */ ++static void rs_wait_until_sent(struct tty_struct *tty, int timeout) ++{ ++ struct async_struct * info = (struct async_struct *)tty->driver_data; ++ unsigned long orig_jiffies, char_time; ++ int lsr; ++ ++ if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) ++ return; ++ ++ 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; ++ } ++#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT ++ printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); ++#endif ++} ++ ++/* ++ * 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; ++ ++ if (serial_paranoia_check(info, tty->device, "rs_hangup")) ++ return; ++ ++ state = info->state; ++ ++ rs_flush_buffer(tty); ++ if (info->flags & ASYNC_CLOSING) ++ return; ++ shutdown(info); ++ info->event = 0; ++ state->count = 0; ++ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); ++ info->tty = 0; ++ wake_up_interruptible(&info->open_wait); ++} ++ ++/* ++ * ------------------------------------------------------------ ++ * rs_open() and friends ++ * ------------------------------------------------------------ ++ */ ++static int block_til_ready(struct tty_struct *tty, struct file * filp, ++ struct async_struct *info) ++{ ++ DECLARE_WAITQUEUE(wait, current); ++ struct serial_state *state = info->state; ++ int retval; ++ int do_clocal = 0, extra_count = 0; ++ unsigned long flags; ++ ++ /* ++ * If the device is in the middle of being closed, then block ++ * until it's done, and then try again. ++ */ ++ if (tty_hung_up_p(filp) || ++ (info->flags & ASYNC_CLOSING)) { ++ if (info->flags & ASYNC_CLOSING) ++ interruptible_sleep_on(&info->close_wait); ++#ifdef SERIAL_DO_RESTART ++ return ((info->flags & ASYNC_HUP_NOTIFY) ? ++ -EAGAIN : -ERESTARTSYS); ++#else ++ return -EAGAIN; ++#endif ++ } ++ ++ /* ++ * If this is a callout device, then just make sure the normal ++ * device isn't being used. ++ */ ++ if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { ++ if (info->flags & ASYNC_NORMAL_ACTIVE) ++ return -EBUSY; ++ if ((info->flags & ASYNC_CALLOUT_ACTIVE) && ++ (info->flags & ASYNC_SESSION_LOCKOUT) && ++ (info->session != current->session)) ++ return -EBUSY; ++ if ((info->flags & ASYNC_CALLOUT_ACTIVE) && ++ (info->flags & ASYNC_PGRP_LOCKOUT) && ++ (info->pgrp != current->pgrp)) ++ return -EBUSY; ++ info->flags |= ASYNC_CALLOUT_ACTIVE; ++ return 0; ++ } ++ ++ /* ++ * If non-blocking mode is set, or the port is not enabled, ++ * then make the check up front and then exit. ++ */ ++ if ((filp->f_flags & O_NONBLOCK) || ++ (tty->flags & (1 << TTY_IO_ERROR))) { ++ if (info->flags & ASYNC_CALLOUT_ACTIVE) ++ return -EBUSY; ++ info->flags |= ASYNC_NORMAL_ACTIVE; ++ return 0; ++ } ++ ++ if (info->flags & ASYNC_CALLOUT_ACTIVE) { ++ if (state->normal_termios.c_cflag & CLOCAL) ++ do_clocal = 1; ++ } else { ++ if (tty->termios->c_cflag & CLOCAL) ++ do_clocal = 1; ++ } ++ ++ /* ++ * Block waiting for the carrier detect and the line to become ++ * free (i.e., not in use by the callout). While we are in ++ * this loop, state->count is dropped by one, so that ++ * rs_close() knows when to free things. We restore it upon ++ * exit, either normal or abnormal. ++ */ ++ retval = 0; ++ add_wait_queue(&info->open_wait, &wait); ++#ifdef SERIAL_DEBUG_OPEN ++ printk("block_til_ready before block: ttys%d, count = %d\n", ++ state->line, state->count); ++#endif ++ save_flags(flags); cli(); ++ if (!tty_hung_up_p(filp)) { ++ extra_count = 1; ++ state->count--; ++ } ++ restore_flags(flags); ++ info->blocked_open++; ++ while (1) { ++ save_flags(flags); cli(); ++ if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && ++ (tty->termios->c_cflag & CBAUD)) ++ serial_out(info, UART_MCR, ++ serial_inp(info, UART_MCR) | ++ (UART_MCR_DTR | UART_MCR_RTS)); ++ restore_flags(flags); ++ set_current_state(TASK_INTERRUPTIBLE); ++ if (tty_hung_up_p(filp) || ++ !(info->flags & ASYNC_INITIALIZED)) { ++#ifdef SERIAL_DO_RESTART ++ if (info->flags & ASYNC_HUP_NOTIFY) ++ retval = -EAGAIN; ++ else ++ retval = -ERESTARTSYS; ++#else ++ retval = -EAGAIN; ++#endif ++ break; ++ } ++ if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && ++ !(info->flags & ASYNC_CLOSING) && ++ (do_clocal || (serial_in(info, UART_MSR) & ++ UART_MSR_DCD))) ++ break; ++ if (signal_pending(current)) { ++ retval = -ERESTARTSYS; ++ break; ++ } ++#ifdef SERIAL_DEBUG_OPEN ++ printk("block_til_ready blocking: ttys%d, count = %d\n", ++ info->line, state->count); ++#endif ++ schedule(); ++ } ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&info->open_wait, &wait); ++ if (extra_count) ++ state->count++; ++ info->blocked_open--; ++#ifdef SERIAL_DEBUG_OPEN ++ printk("block_til_ready after blocking: ttys%d, count = %d\n", ++ info->line, state->count); ++#endif ++ if (retval) ++ return retval; ++ info->flags |= ASYNC_NORMAL_ACTIVE; ++ return 0; ++} ++ ++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; ++ 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; ++} ++ ++/* ++ * 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. ++ * ++ * Note that on failure, we don't decrement the module use count - the tty ++ * later will call rs_close, which will decrement it for us as long as ++ * tty->driver_data is set non-NULL. --rmk ++ */ ++static int rs_open(struct tty_struct *tty, struct file * filp) ++{ ++ struct async_struct *info; ++ int retval, line; ++ unsigned long page; ++ ++ MOD_INC_USE_COUNT; ++ line = MINOR(tty->device) - tty->driver.minor_start; ++ if ((line < 0) || (line >= NR_PORTS)) { ++ MOD_DEC_USE_COUNT; ++ return -ENODEV; ++ } ++ retval = get_async_struct(line, &info); ++ if (retval) { ++ MOD_DEC_USE_COUNT; ++ return retval; ++ } ++ tty->driver_data = info; ++ info->tty = tty; ++ if (serial_paranoia_check(info, tty->device, "rs_open")) ++ return -ENODEV; ++ ++#ifdef SERIAL_DEBUG_OPEN ++ printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, ++ info->state->count); ++#endif ++#if (LINUX_VERSION_CODE > 0x20100) ++ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; ++#endif ++ ++ /* ++ * This relies on lock_kernel() stuff so wants tidying for 2.5 ++ */ ++ 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); ++#ifdef SERIAL_DO_RESTART ++ return ((info->flags & ASYNC_HUP_NOTIFY) ? ++ -EAGAIN : -ERESTARTSYS); ++#else ++ return -EAGAIN; ++#endif ++ } ++ ++ /* ++ * Start up serial port ++ */ ++ retval = startup(info); ++ if (retval) ++ return retval; ++ ++ 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; ++ } ++ ++ 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; ++ change_speed(info, 0); ++ } ++#ifdef CONFIG_SERIAL_CONSOLE ++ if (sercons.cflag && sercons.index == line) { ++ tty->termios->c_cflag = sercons.cflag; ++ sercons.cflag = 0; ++ change_speed(info, 0); ++ } ++#endif ++ info->session = current->session; ++ info->pgrp = current->pgrp; ++ ++#ifdef SERIAL_DEBUG_OPEN ++ printk("rs_open ttys%d successful...", info->line); ++#endif ++ return 0; ++} ++ ++/* ++ * /proc fs routines.... ++ */ ++ ++static inline int line_info(char *buf, struct serial_state *state) ++{ ++ struct async_struct *info = state->info, scr_info; ++ char stat_buf[30], control, status; ++ int ret; ++ unsigned long flags; ++ ++ /* ++ * Return zero characters for ports not claimed by driver. ++ */ ++ if (state->type == PORT_UNKNOWN) { ++ return 0; /* ignore unused ports */ ++ } ++ ++ ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d", ++ state->line, uart_config[state->type].name, ++ (state->port ? state->port : (long)state->iomem_base), ++ state->irq); ++ ++ /* ++ * 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->hub6 = state->hub6; ++ info->io_type = state->io_type; ++ info->iomem_base = state->iomem_base; ++ info->iomem_reg_shift = state->iomem_reg_shift; ++ 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; ++} ++ ++static 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); ++} ++ ++/* ++ * --------------------------------------------------------------------- ++ * rs_init() and friends ++ * ++ * rs_init() is called at boot-time to initialize the serial driver. ++ * --------------------------------------------------------------------- ++ */ ++ ++/* ++ * This routine prints out the appropriate serial driver version ++ * number, and identifies which options were configured into this ++ * driver. ++ */ ++static char serial_options[] __initdata = ++#ifdef CONFIG_HUB6 ++ " HUB-6" ++#define SERIAL_OPT ++#endif ++#ifdef CONFIG_SERIAL_MANY_PORTS ++ " MANY_PORTS" ++#define SERIAL_OPT ++#endif ++#ifdef CONFIG_SERIAL_MULTIPORT ++ " MULTIPORT" ++#define SERIAL_OPT ++#endif ++#ifdef CONFIG_SERIAL_SHARE_IRQ ++ " SHARE_IRQ" ++#define SERIAL_OPT ++#endif ++#ifdef CONFIG_SERIAL_DETECT_IRQ ++ " DETECT_IRQ" ++#define SERIAL_OPT ++#endif ++#ifdef ENABLE_SERIAL_PCI ++ " SERIAL_PCI" ++#define SERIAL_OPT ++#endif ++#ifdef ENABLE_SERIAL_PNP ++ " ISAPNP" ++#define SERIAL_OPT ++#endif ++#ifdef ENABLE_SERIAL_ACPI ++ " SERIAL_ACPI" ++#define SERIAL_OPT ++#endif ++#ifdef SERIAL_OPT ++ " enabled\n"; ++#else ++ " no serial options enabled\n"; ++#endif ++#undef SERIAL_OPT ++ ++static _INLINE_ void show_serial_version(void) ++{ ++ printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name, ++ serial_version, LOCAL_VERSTRING, serial_revdate, ++ serial_options); ++} ++ ++/* ++ * This routine detect the IRQ of a serial port by clearing OUT2 when ++ * no UART interrupt are requested (IER = 0) (*GPL*). This seems to work at ++ * each time, as long as no other device permanently request the IRQ. ++ * If no IRQ is detected, or multiple IRQ appear, this function returns 0. ++ * The variable "state" and the field "state->port" should not be null. ++ */ ++static unsigned detect_uart_irq (struct serial_state * state) ++{ ++ int irq; ++ unsigned long irqs; ++ unsigned char save_mcr, save_ier; ++ struct async_struct scr_info; /* serial_{in,out} because HUB6 */ ++ ++#ifdef CONFIG_SERIAL_MANY_PORTS ++ unsigned char save_ICP=0; /* no warning */ ++ unsigned short ICP=0; ++ ++ if (state->flags & ASYNC_FOURPORT) { ++ ICP = (state->port & 0xFE0) | 0x01F; ++ save_ICP = inb_p(ICP); ++ outb_p(0x80, ICP); ++ (void) inb_p(ICP); ++ } ++#endif ++ scr_info.magic = SERIAL_MAGIC; ++ scr_info.state = state; ++ scr_info.port = state->port; ++ scr_info.flags = state->flags; ++#ifdef CONFIG_HUB6 ++ scr_info.hub6 = state->hub6; ++#endif ++ scr_info.io_type = state->io_type; ++ scr_info.iomem_base = state->iomem_base; ++ scr_info.iomem_reg_shift = state->iomem_reg_shift; ++ ++ /* forget possible initially masked and pending IRQ */ ++ probe_irq_off(probe_irq_on()); ++ save_mcr = serial_inp(&scr_info, UART_MCR); ++ save_ier = serial_inp(&scr_info, UART_IER); ++ serial_outp(&scr_info, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); ++ ++ irqs = probe_irq_on(); ++ serial_outp(&scr_info, UART_MCR, 0); ++ udelay (10); ++ if (state->flags & ASYNC_FOURPORT) { ++ serial_outp(&scr_info, UART_MCR, ++ UART_MCR_DTR | UART_MCR_RTS); ++ } else { ++ serial_outp(&scr_info, UART_MCR, ++ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); ++ } ++ serial_outp(&scr_info, UART_IER, 0x0f); /* enable all intrs */ ++ (void)serial_inp(&scr_info, UART_LSR); ++ (void)serial_inp(&scr_info, UART_RX); ++ (void)serial_inp(&scr_info, UART_IIR); ++ (void)serial_inp(&scr_info, UART_MSR); ++ serial_outp(&scr_info, UART_TX, 0xFF); ++ udelay (20); ++ irq = probe_irq_off(irqs); ++ ++ serial_outp(&scr_info, UART_MCR, save_mcr); ++ serial_outp(&scr_info, UART_IER, save_ier); ++#ifdef CONFIG_SERIAL_MANY_PORTS ++ if (state->flags & ASYNC_FOURPORT) ++ outb_p(save_ICP, ICP); ++#endif ++ return (irq > 0)? irq : 0; ++} ++ ++/* ++ * This is a quickie test to see how big the FIFO is. ++ * It doesn't work at all the time, more's the pity. ++ */ ++static int size_fifo(struct async_struct *info) ++{ ++ unsigned char old_fcr, old_mcr, old_dll, old_dlm; ++ int count; ++ ++ old_fcr = serial_inp(info, UART_FCR); ++ old_mcr = serial_inp(info, UART_MCR); ++ serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO | ++ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); ++ serial_outp(info, UART_MCR, UART_MCR_LOOP); ++ serial_outp(info, UART_LCR, UART_LCR_DLAB); ++ old_dll = serial_inp(info, UART_DLL); ++ old_dlm = serial_inp(info, UART_DLM); ++ serial_outp(info, UART_DLL, 0x01); ++ serial_outp(info, UART_DLM, 0x00); ++ serial_outp(info, UART_LCR, 0x03); ++ for (count = 0; count < 256; count++) ++ serial_outp(info, UART_TX, count); ++ mdelay(20); ++ for (count = 0; (serial_inp(info, UART_LSR) & UART_LSR_DR) && ++ (count < 256); count++) ++ serial_inp(info, UART_RX); ++ serial_outp(info, UART_FCR, old_fcr); ++ serial_outp(info, UART_MCR, old_mcr); ++ serial_outp(info, UART_LCR, UART_LCR_DLAB); ++ serial_outp(info, UART_DLL, old_dll); ++ serial_outp(info, UART_DLM, old_dlm); ++ ++ return count; ++} ++ ++/* ++ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's. ++ * When this function is called we know it is at least a StarTech ++ * 16650 V2, but it might be one of several StarTech UARTs, or one of ++ * its clones. (We treat the broken original StarTech 16650 V1 as a ++ * 16550, and why not? Startech doesn't seem to even acknowledge its ++ * existence.) ++ * ++ * What evil have men's minds wrought... ++ */ ++static void autoconfig_startech_uarts(struct async_struct *info, ++ struct serial_state *state, ++ unsigned long flags) ++{ ++ unsigned char scratch, scratch2, scratch3, scratch4; ++ ++ /* ++ * First we check to see if it's an Oxford Semiconductor UART. ++ * ++ * If we have to do this here because some non-National ++ * Semiconductor clone chips lock up if you try writing to the ++ * LSR register (which serial_icr_read does) ++ */ ++ if (state->type == PORT_16550A) { ++ /* ++ * EFR [4] must be set else this test fails ++ * ++ * This shouldn't be necessary, but Mike Hudson ++ * (Exoray@isys.ca) claims that it's needed for 952 ++ * dual UART's (which are not recommended for new designs). ++ */ ++ info->ACR = 0; ++ serial_out(info, UART_LCR, 0xBF); ++ serial_out(info, UART_EFR, 0x10); ++ serial_out(info, UART_LCR, 0x00); ++ /* Check for Oxford Semiconductor 16C950 */ ++ scratch = serial_icr_read(info, UART_ID1); ++ scratch2 = serial_icr_read(info, UART_ID2); ++ scratch3 = serial_icr_read(info, UART_ID3); ++ ++ if (scratch == 0x16 && scratch2 == 0xC9 && ++ (scratch3 == 0x50 || scratch3 == 0x52 || ++ scratch3 == 0x54)) { ++ state->type = PORT_16C950; ++ state->revision = serial_icr_read(info, UART_REV) | ++ (scratch3 << 8); ++ return; ++ } ++ } ++ ++ /* ++ * We check for a XR16C850 by setting DLL and DLM to 0, and ++ * then reading back DLL and DLM. If DLM reads back 0x10, ++ * then the UART is a XR16C850 and the DLL contains the chip ++ * revision. If DLM reads back 0x14, then the UART is a ++ * XR16C854. ++ * ++ */ ++ ++ /* Save the DLL and DLM */ ++ ++ serial_outp(info, UART_LCR, UART_LCR_DLAB); ++ scratch3 = serial_inp(info, UART_DLL); ++ scratch4 = serial_inp(info, UART_DLM); ++ ++ serial_outp(info, UART_DLL, 0); ++ serial_outp(info, UART_DLM, 0); ++ scratch2 = serial_inp(info, UART_DLL); ++ scratch = serial_inp(info, UART_DLM); ++ serial_outp(info, UART_LCR, 0); ++ ++ if (scratch == 0x10 || scratch == 0x14) { ++ if (scratch == 0x10) ++ state->revision = scratch2; ++ state->type = PORT_16850; ++ return; ++ } ++ ++ /* Restore the DLL and DLM */ ++ ++ serial_outp(info, UART_LCR, UART_LCR_DLAB); ++ serial_outp(info, UART_DLL, scratch3); ++ serial_outp(info, UART_DLM, scratch4); ++ serial_outp(info, UART_LCR, 0); ++ /* ++ * We distinguish between the '654 and the '650 by counting ++ * how many bytes are in the FIFO. I'm using this for now, ++ * since that's the technique that was sent to me in the ++ * serial driver update, but I'm not convinced this works. ++ * I've had problems doing this in the past. -TYT ++ */ ++ if (size_fifo(info) == 64) ++ state->type = PORT_16654; ++ else ++ state->type = PORT_16650V2; ++} ++ ++/* ++ * This routine is called by rs_init() to initialize a specific serial ++ * port. It determines what type of UART chip this serial port is ++ * using: 8250, 16450, 16550, 16550A. The important question is ++ * whether or not this UART is a 16550A or not, since this will ++ * determine whether or not we can use its FIFO features or not. ++ */ ++static void autoconfig(struct serial_state * state) ++{ ++ unsigned char status1, status2, scratch, scratch2, scratch3; ++ unsigned char save_lcr, save_mcr; ++ struct async_struct *info, scr_info; ++ unsigned long flags; ++ ++ state->type = PORT_UNKNOWN; ++ ++#ifdef SERIAL_DEBUG_AUTOCONF ++ printk("Testing ttyS%d (0x%04lx, 0x%04x)...\n", state->line, ++ state->port, (unsigned) state->iomem_base); ++#endif ++ ++ if (!CONFIGURED_SERIAL_PORT(state)) ++ return; ++ ++ info = &scr_info; /* This is just for serial_{in,out} */ ++ ++ info->magic = SERIAL_MAGIC; ++ info->state = state; ++ info->port = state->port; ++ info->flags = state->flags; ++#ifdef CONFIG_HUB6 ++ info->hub6 = state->hub6; ++#endif ++ info->io_type = state->io_type; ++ info->iomem_base = state->iomem_base; ++ info->iomem_reg_shift = state->iomem_reg_shift; ++ ++ save_flags(flags); cli(); ++ ++ if (!(state->flags & ASYNC_BUGGY_UART) && ++ !state->iomem_base) { ++ /* ++ * Do a simple existence test first; if we fail this, ++ * there's no point trying anything else. ++ * ++ * 0x80 is used as a nonsense port to prevent against ++ * false positives due to ISA bus float. The ++ * assumption is that 0x80 is a non-existent port; ++ * which should be safe since include/asm/io.h also ++ * makes this assumption. ++ */ ++ scratch = serial_inp(info, UART_IER); ++ serial_outp(info, UART_IER, 0); ++#ifdef __i386__ ++ outb(0xff, 0x080); ++#endif ++ scratch2 = serial_inp(info, UART_IER); ++ serial_outp(info, UART_IER, 0x0F); ++#ifdef __i386__ ++ outb(0, 0x080); ++#endif ++ scratch3 = serial_inp(info, UART_IER); ++ serial_outp(info, UART_IER, scratch); ++ if (scratch2 || scratch3 != 0x0F) { ++#ifdef SERIAL_DEBUG_AUTOCONF ++ printk("serial: ttyS%d: simple autoconfig failed " ++ "(%02x, %02x)\n", state->line, ++ scratch2, scratch3); ++#endif ++ restore_flags(flags); ++ return; /* We failed; there's nothing here */ ++ } ++ } ++ ++ save_mcr = serial_in(info, UART_MCR); ++ save_lcr = serial_in(info, UART_LCR); ++ ++ /* ++ * Check to see if a UART is really there. Certain broken ++ * internal modems based on the Rockwell chipset fail this ++ * test, because they apparently don't implement the loopback ++ * test mode. So this test is skipped on the COM 1 through ++ * COM 4 ports. This *should* be safe, since no board ++ * manufacturer would be stupid enough to design a board ++ * that conflicts with COM 1-4 --- we hope! ++ */ ++ if (!(state->flags & ASYNC_SKIP_TEST)) { ++ serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A); ++ status1 = serial_inp(info, UART_MSR) & 0xF0; ++ serial_outp(info, UART_MCR, save_mcr); ++ if (status1 != 0x90) { ++#ifdef SERIAL_DEBUG_AUTOCONF ++ printk("serial: ttyS%d: no UART loopback failed\n", ++ state->line); ++#endif ++ restore_flags(flags); ++ return; ++ } ++ } ++ serial_outp(info, UART_LCR, 0xBF); /* set up for StarTech test */ ++ serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */ ++ serial_outp(info, UART_LCR, 0); ++ serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); ++ scratch = serial_in(info, UART_IIR) >> 6; ++ switch (scratch) { ++ case 0: ++ state->type = PORT_16450; ++ break; ++ case 1: ++ state->type = PORT_UNKNOWN; ++ break; ++ case 2: ++ state->type = PORT_16550; ++ break; ++ case 3: ++ state->type = PORT_16550A; ++ break; ++ } ++ if (state->type == PORT_16550A) { ++ /* Check for Startech UART's */ ++ serial_outp(info, UART_LCR, UART_LCR_DLAB); ++ if (serial_in(info, UART_EFR) == 0) { ++ serial_outp(info, UART_EFR, 0xA8); ++ if (serial_in(info, UART_EFR) == 0) { ++ /* We are a NS16552D/Motorola ++ * 8xxx DUART, stop. */ ++ goto out; ++ } ++ state->type = PORT_16650; ++ serial_outp(info, UART_EFR, 0); ++ } else { ++ serial_outp(info, UART_LCR, 0xBF); ++ if (serial_in(info, UART_EFR) == 0) ++ autoconfig_startech_uarts(info, state, flags); ++ } ++ } ++ if (state->type == PORT_16550A) { ++ /* Check for TI 16750 */ ++ serial_outp(info, UART_LCR, save_lcr | UART_LCR_DLAB); ++ serial_outp(info, UART_FCR, ++ UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); ++ scratch = serial_in(info, UART_IIR) >> 5; ++ if (scratch == 7) { ++ /* ++ * If this is a 16750, and not a cheap UART ++ * clone, then it should only go into 64 byte ++ * mode if the UART_FCR7_64BYTE bit was set ++ * while UART_LCR_DLAB was latched. ++ */ ++ serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); ++ serial_outp(info, UART_LCR, 0); ++ serial_outp(info, UART_FCR, ++ UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); ++ scratch = serial_in(info, UART_IIR) >> 5; ++ if (scratch == 6) ++ state->type = PORT_16750; ++ } ++ serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); ++ } ++#if defined(CONFIG_SERIAL_RSA) && defined(MODULE) ++ if (state->type == PORT_16550A) { ++ int i; ++ ++ for (i = 0 ; i < PORT_RSA_MAX ; ++i) { ++ if (!probe_rsa[i] && !force_rsa[i]) ++ break; ++ if (((probe_rsa[i] != state->port) || ++ check_region(state->port + UART_RSA_BASE, 16)) && ++ (force_rsa[i] != state->port)) ++ continue; ++ if (!enable_rsa(info)) ++ continue; ++ state->type = PORT_RSA; ++ state->baud_base = SERIAL_RSA_BAUD_BASE; ++ break; ++ } ++ } ++#endif ++out: ++ serial_outp(info, UART_LCR, save_lcr); ++ if (state->type == PORT_16450) { ++ scratch = serial_in(info, UART_SCR); ++ serial_outp(info, UART_SCR, 0xa5); ++ status1 = serial_in(info, UART_SCR); ++ serial_outp(info, UART_SCR, 0x5a); ++ status2 = serial_in(info, UART_SCR); ++ serial_outp(info, UART_SCR, scratch); ++ ++ if ((status1 != 0xa5) || (status2 != 0x5a)) ++ state->type = PORT_8250; ++ } ++ state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size; ++ ++ if (state->type == PORT_UNKNOWN) { ++ restore_flags(flags); ++ return; ++ } ++ ++ if (info->port) { ++#ifdef CONFIG_SERIAL_RSA ++ if (state->type == PORT_RSA) ++ request_region(info->port + UART_RSA_BASE, 16, ++ "serial_rsa(auto)"); ++ else ++#endif ++ request_region(info->port,8,"serial(auto)"); ++ } ++ ++ /* ++ * Reset the UART. ++ */ ++#ifdef CONFIG_SERIAL_RSA ++ if (state->type == PORT_RSA) ++ serial_outp(info, UART_RSA_FRR, 0); ++#endif ++ serial_outp(info, UART_MCR, save_mcr); ++ serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | ++ UART_FCR_CLEAR_RCVR | ++ UART_FCR_CLEAR_XMIT)); ++ serial_outp(info, UART_FCR, 0); ++ (void)serial_in(info, UART_RX); ++ serial_outp(info, UART_IER, 0); ++ ++ restore_flags(flags); ++} ++ ++int register_serial(struct serial_struct *req); ++void unregister_serial(int line); ++ ++#if (LINUX_VERSION_CODE > 0x20100) ++EXPORT_SYMBOL(register_serial); ++EXPORT_SYMBOL(unregister_serial); ++#else ++static struct symbol_table serial_syms = { ++#include ++ X(register_serial), ++ X(unregister_serial), ++#include ++}; ++#endif ++ ++ ++#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) ++ ++static void __devinit printk_pnp_dev_id(unsigned short vendor, ++ unsigned short device) ++{ ++ printk("%c%c%c%x%x%x%x", ++ 'A' + ((vendor >> 2) & 0x3f) - 1, ++ 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, ++ 'A' + ((vendor >> 8) & 0x1f) - 1, ++ (device >> 4) & 0x0f, ++ device & 0x0f, ++ (device >> 12) & 0x0f, ++ (device >> 8) & 0x0f); ++} ++ ++static _INLINE_ int get_pci_port(struct pci_dev *dev, ++ struct pci_board *board, ++ struct serial_struct *req, ++ int idx) ++{ ++ unsigned long port; ++ int base_idx; ++ int max_port; ++ int offset; ++ ++ base_idx = SPCI_FL_GET_BASE(board->flags); ++ if (board->flags & SPCI_FL_BASE_TABLE) ++ base_idx += idx; ++ ++ if (board->flags & SPCI_FL_REGION_SZ_CAP) { ++ max_port = pci_resource_len(dev, base_idx) / 8; ++ if (idx >= max_port) ++ return 1; ++ } ++ ++ offset = board->first_uart_offset; ++ ++ /* Timedia/SUNIX uses a mixture of BARs and offsets */ ++ /* Ugh, this is ugly as all hell --- TYT */ ++ if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */ ++ switch(idx) { ++ case 0: base_idx=0; ++ break; ++ case 1: base_idx=0; offset=8; ++ break; ++ case 2: base_idx=1; ++ break; ++ case 3: base_idx=1; offset=8; ++ break; ++ case 4: /* BAR 2*/ ++ case 5: /* BAR 3 */ ++ case 6: /* BAR 4*/ ++ case 7: base_idx=idx-2; /* BAR 5*/ ++ } ++ ++ /* Some Titan cards are also a little weird */ ++ if (dev->vendor == PCI_VENDOR_ID_TITAN && ++ (dev->device == PCI_DEVICE_ID_TITAN_400L || ++ dev->device == PCI_DEVICE_ID_TITAN_800L)) { ++ switch (idx) { ++ case 0: base_idx = 1; ++ break; ++ case 1: base_idx = 2; ++ break; ++ default: ++ base_idx = 4; ++ offset = 8 * (idx - 2); ++ } ++ ++ } ++ ++ /* HP's Diva chip puts the 4th/5th serial port further out, and ++ * some serial ports are supposed to be hidden on certain models. ++ */ ++ if (dev->vendor == PCI_VENDOR_ID_HP && ++ dev->device == PCI_DEVICE_ID_HP_SAS) { ++ switch (dev->subsystem_device) { ++ case 0x104B: /* Maestro */ ++ if (idx == 3) idx++; ++ break; ++ case 0x1282: /* Everest / Longs Peak */ ++ if (idx > 0) idx++; ++ if (idx > 2) idx++; ++ break; ++ } ++ if (idx > 2) { ++ offset = 0x18; ++ } ++ } ++ ++ port = pci_resource_start(dev, base_idx) + offset; ++ ++ if ((board->flags & SPCI_FL_BASE_TABLE) == 0) ++ port += idx * (board->uart_offset ? board->uart_offset : 8); ++ ++ if (IS_PCI_REGION_IOPORT(dev, base_idx)) { ++ req->port = port; ++ if (HIGH_BITS_OFFSET) ++ req->port_high = port >> HIGH_BITS_OFFSET; ++ else ++ req->port_high = 0; ++ return 0; ++ } ++ req->io_type = SERIAL_IO_MEM; ++ req->iomem_base = ioremap(port, board->uart_offset); ++ req->iomem_reg_shift = board->reg_shift; ++ req->port = 0; ++ return 0; ++} ++ ++static _INLINE_ int get_pci_irq(struct pci_dev *dev, ++ struct pci_board *board, ++ int idx) ++{ ++ int base_idx; ++ ++ if ((board->flags & SPCI_FL_IRQRESOURCE) == 0) ++ return dev->irq; ++ ++ base_idx = SPCI_FL_GET_IRQBASE(board->flags); ++ if (board->flags & SPCI_FL_IRQ_TABLE) ++ base_idx += idx; ++ ++ return PCI_IRQ_RESOURCE(dev, base_idx); ++} ++ ++/* ++ * Common enabler code shared by both PCI and ISAPNP probes ++ */ ++static void __devinit start_pci_pnp_board(struct pci_dev *dev, ++ struct pci_board *board) ++{ ++ int k, line; ++ struct serial_struct serial_req; ++ int base_baud; ++ ++ if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) { ++ printk("serial: PNP device '"); ++ printk_pnp_dev_id(dev->vendor, dev->device); ++ printk("' prepare failed\n"); ++ return; ++ } ++ ++ if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) { ++ printk("serial: PNP device '"); ++ printk_pnp_dev_id(dev->vendor, dev->device); ++ printk("' activate failed\n"); ++ return; ++ } ++ ++ /* ++ * Run the initialization function, if any ++ */ ++ if (board->init_fn && ((board->init_fn)(dev, board, 1) != 0)) ++ return; ++ ++ /* ++ * Register the serial board in the array if we need to ++ * shutdown the board on a module unload or card removal ++ */ ++ if (DEACTIVATE_FUNC(dev) || board->init_fn) { ++ for (k=0; k < NR_PCI_BOARDS; k++) ++ if (serial_pci_board[k].dev == 0) ++ break; ++ if (k >= NR_PCI_BOARDS) ++ return; ++ serial_pci_board[k].board = *board; ++ serial_pci_board[k].dev = dev; ++ } ++ ++ base_baud = board->base_baud; ++ if (!base_baud) ++ base_baud = BASE_BAUD; ++ memset(&serial_req, 0, sizeof(serial_req)); ++ ++ for (k=0; k < board->num_ports; k++) { ++ serial_req.irq = get_pci_irq(dev, board, k); ++ if (get_pci_port(dev, board, &serial_req, k)) ++ break; ++ serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE; ++#ifdef SERIAL_DEBUG_PCI ++ printk("Setup PCI/PNP port: port %x, irq %d, type %d\n", ++ serial_req.port, serial_req.irq, serial_req.io_type); ++#endif ++ line = register_serial(&serial_req); ++ if (line < 0) ++ break; ++ rs_table[line].baud_base = base_baud; ++ rs_table[line].dev = dev; ++ } ++} ++#endif /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP */ ++ ++#ifdef ENABLE_SERIAL_PCI ++/* ++ * Some PCI serial cards using the PLX 9050 PCI interface chip require ++ * that the card interrupt be explicitly enabled or disabled. This ++ * seems to be mainly needed on card using the PLX which also use I/O ++ * mapped memory. ++ */ ++static int __devinit ++pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable) ++{ ++ u8 data, *p, irq_config; ++ int pci_config; ++ ++ irq_config = 0x41; ++ pci_config = PCI_COMMAND_MEMORY; ++ if (dev->vendor == PCI_VENDOR_ID_PANACOM) ++ irq_config = 0x43; ++ if ((dev->vendor == PCI_VENDOR_ID_PLX) && ++ (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { ++ /* ++ * As the megawolf cards have the int pins active ++ * high, and have 2 UART chips, both ints must be ++ * enabled on the 9050. Also, the UARTS are set in ++ * 16450 mode by default, so we have to enable the ++ * 16C950 'enhanced' mode so that we can use the deep ++ * FIFOs ++ */ ++ irq_config = 0x5b; ++ pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO; ++ } ++ ++ pci_read_config_byte(dev, PCI_COMMAND, &data); ++ ++ if (enable) ++ pci_write_config_byte(dev, PCI_COMMAND, ++ data | pci_config); ++ ++ /* enable/disable interrupts */ ++ p = ioremap(pci_resource_start(dev, 0), 0x80); ++ writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c); ++ iounmap(p); ++ ++ if (!enable) ++ pci_write_config_byte(dev, PCI_COMMAND, ++ data & ~pci_config); ++ return 0; ++} ++ ++ ++/* ++ * SIIG serial cards have an PCI interface chip which also controls ++ * the UART clocking frequency. Each UART can be clocked independently ++ * (except cards equiped with 4 UARTs) and initial clocking settings ++ * are stored in the EEPROM chip. It can cause problems because this ++ * version of serial driver doesn't support differently clocked UART's ++ * on single PCI card. To prevent this, initialization functions set ++ * high frequency clocking for all UART's on given card. It is safe (I ++ * hope) because it doesn't touch EEPROM settings to prevent conflicts ++ * with other OSes (like M$ DOS). ++ * ++ * SIIG support added by Andrey Panin , 10/1999 ++ * ++ * There is two family of SIIG serial cards with different PCI ++ * interface chip and different configuration methods: ++ * - 10x cards have control registers in IO and/or memory space; ++ * - 20x cards have control registers in standard PCI configuration space. ++ * ++ * SIIG initialization functions exported for use by parport_serial.c module. ++ */ ++ ++#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc) ++#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8) ++ ++int __devinit ++pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable) ++{ ++ u16 data, *p; ++ ++ if (!enable) return 0; ++ ++ p = ioremap(pci_resource_start(dev, 0), 0x80); ++ ++ switch (dev->device & 0xfff8) { ++ case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ ++ data = 0xffdf; ++ break; ++ case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */ ++ data = 0xf7ff; ++ break; ++ default: /* 1S1P, 4S */ ++ data = 0xfffb; ++ break; ++ } ++ ++ writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28); ++ iounmap(p); ++ return 0; ++} ++EXPORT_SYMBOL(pci_siig10x_fn); ++ ++#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc) ++#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc) ++ ++int __devinit ++pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable) ++{ ++ u8 data; ++ ++ if (!enable) return 0; ++ ++ /* Change clock frequency for the first UART. */ ++ pci_read_config_byte(dev, 0x6f, &data); ++ pci_write_config_byte(dev, 0x6f, data & 0xef); ++ ++ /* If this card has 2 UART, we have to do the same with second UART. */ ++ if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) || ++ ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) { ++ pci_read_config_byte(dev, 0x73, &data); ++ pci_write_config_byte(dev, 0x73, data & 0xef); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(pci_siig20x_fn); ++ ++/* Added for EKF Intel i960 serial boards */ ++static int __devinit ++pci_inteli960ni_fn(struct pci_dev *dev, ++ struct pci_board *board, ++ int enable) ++{ ++ unsigned long oldval; ++ ++ if (!(pci_get_subdevice(dev) & 0x1000)) ++ return(-1); ++ ++ if (!enable) /* is there something to deinit? */ ++ return(0); ++ ++#ifdef SERIAL_DEBUG_PCI ++ printk(KERN_DEBUG " Subsystem ID %lx (intel 960)\n", ++ (unsigned long) board->subdevice); ++#endif ++ /* is firmware started? */ ++ pci_read_config_dword(dev, 0x44, (void*) &oldval); ++ if (oldval == 0x00001000L) { /* RESET value */ ++ printk(KERN_DEBUG "Local i960 firmware missing"); ++ return(-1); ++ } ++ return(0); ++} ++ ++/* ++ * Timedia has an explosion of boards, and to avoid the PCI table from ++ * growing *huge*, we use this function to collapse some 70 entries ++ * in the PCI table into one, for sanity's and compactness's sake. ++ */ ++static unsigned short timedia_single_port[] = { ++ 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 }; ++static unsigned short timedia_dual_port[] = { ++ 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085, ++ 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, ++ 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, ++ 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079, ++ 0xD079, 0 }; ++static unsigned short timedia_quad_port[] = { ++ 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, ++ 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, ++ 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056, ++ 0xB157, 0 }; ++static unsigned short timedia_eight_port[] = { ++ 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, ++ 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 }; ++static struct timedia_struct { ++ int num; ++ unsigned short *ids; ++} timedia_data[] = { ++ { 1, timedia_single_port }, ++ { 2, timedia_dual_port }, ++ { 4, timedia_quad_port }, ++ { 8, timedia_eight_port }, ++ { 0, 0 } ++}; ++ ++static int __devinit ++pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable) ++{ ++ int i, j; ++ unsigned short *ids; ++ ++ if (!enable) ++ return 0; ++ ++ for (i=0; timedia_data[i].num; i++) { ++ ids = timedia_data[i].ids; ++ for (j=0; ids[j]; j++) { ++ if (pci_get_subdevice(dev) == ids[j]) { ++ board->num_ports = timedia_data[i].num; ++ return 0; ++ } ++ } ++ } ++ return 0; ++} ++ ++/* ++ * HP's Remote Management Console. The Diva chip came in several ++ * different versions. N-class, L2000 and A500 have two Diva chips, each ++ * with 3 UARTs (the third UART on the second chip is unused). Superdome ++ * and Keystone have one Diva chip with 3 UARTs. Some later machines have ++ * one Diva chip, but it has been expanded to 5 UARTs. ++ */ ++static int __devinit ++pci_hp_diva(struct pci_dev *dev, struct pci_board *board, int enable) ++{ ++ if (!enable) ++ return 0; ++ ++ switch (dev->subsystem_device) { ++ case 0x1049: /* Prelude Diva 1 */ ++ case 0x1223: /* Superdome */ ++ case 0x1226: /* Keystone */ ++ case 0x1282: /* Everest / Longs Peak */ ++ board->num_ports = 3; ++ break; ++ case 0x104A: /* Prelude Diva 2 */ ++ board->num_ports = 2; ++ break; ++ case 0x104B: /* Maestro */ ++ board->num_ports = 4; ++ break; ++ case 0x1227: /* Powerbar */ ++ board->num_ports = 1; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int __devinit ++pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable) ++{ ++ __set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout(HZ/10); ++ return 0; ++} ++ ++/* ++ * This is the configuration table for all of the PCI serial boards ++ * which we support. It is directly indexed by the pci_board_num_t enum ++ * value, which is encoded in the pci_device_id PCI probe table's ++ * driver_data member. ++ */ ++enum pci_board_num_t { ++ pbn_b0_1_115200, ++ pbn_default = 0, ++ ++ pbn_b0_2_115200, ++ pbn_b0_4_115200, ++ ++ pbn_b0_1_921600, ++ pbn_b0_2_921600, ++ pbn_b0_4_921600, ++ ++ pbn_b0_bt_1_115200, ++ pbn_b0_bt_2_115200, ++ pbn_b0_bt_1_460800, ++ pbn_b0_bt_2_460800, ++ pbn_b0_bt_2_921600, ++ ++ pbn_b1_1_115200, ++ pbn_b1_2_115200, ++ pbn_b1_4_115200, ++ pbn_b1_8_115200, ++ ++ pbn_b1_2_921600, ++ pbn_b1_4_921600, ++ pbn_b1_8_921600, ++ ++ pbn_b1_2_1382400, ++ pbn_b1_4_1382400, ++ pbn_b1_8_1382400, ++ ++ pbn_b2_1_115200, ++ pbn_b2_8_115200, ++ pbn_b2_4_460800, ++ pbn_b2_8_460800, ++ pbn_b2_16_460800, ++ pbn_b2_4_921600, ++ pbn_b2_8_921600, ++ ++ pbn_b2_bt_1_115200, ++ pbn_b2_bt_2_115200, ++ pbn_b2_bt_4_115200, ++ pbn_b2_bt_2_921600, ++ ++ pbn_panacom, ++ pbn_panacom2, ++ pbn_panacom4, ++ pbn_plx_romulus, ++ pbn_oxsemi, ++ pbn_timedia, ++ pbn_intel_i960, ++ pbn_sgi_ioc3, ++ pbn_hp_diva, ++#ifdef CONFIG_DDB5074 ++ pbn_nec_nile4, ++#endif ++ ++ pbn_dci_pccom4, ++ pbn_dci_pccom8, ++ ++ pbn_xircom_combo, ++ ++ pbn_siig10x_0, ++ pbn_siig10x_1, ++ pbn_siig10x_2, ++ pbn_siig10x_4, ++ pbn_siig20x_0, ++ pbn_siig20x_2, ++ pbn_siig20x_4, ++ ++ pbn_computone_4, ++ pbn_computone_6, ++ pbn_computone_8, ++}; ++ ++static struct pci_board pci_boards[] __devinitdata = { ++ /* ++ * PCI Flags, Number of Ports, Base (Maximum) Baud Rate, ++ * Offset to get to next UART's registers, ++ * Register shift to use for memory-mapped I/O, ++ * Initialization function, first UART offset ++ */ ++ ++ /* Generic serial board, pbn_b0_1_115200, pbn_default */ ++ { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200, ++ pbn_default */ ++ ++ { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */ ++ { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */ ++ ++ { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */ ++ { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */ ++ { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */ ++ ++ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */ ++ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */ ++ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */ ++ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */ ++ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b0_bt_2_921600 */ ++ ++ { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */ ++ { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */ ++ { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */ ++ { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */ ++ ++ { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */ ++ { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */ ++ { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */ ++ ++ { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */ ++ { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */ ++ { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */ ++ ++ { SPCI_FL_BASE2, 1, 115200 }, /* pbn_b2_1_115200 */ ++ { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */ ++ { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */ ++ { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */ ++ { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */ ++ { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */ ++ { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */ ++ ++ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */ ++ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */ ++ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */ ++ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */ ++ ++ { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */ ++ 0x400, 7, pci_plx9050_fn }, ++ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */ ++ 0x400, 7, pci_plx9050_fn }, ++ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */ ++ 0x400, 7, pci_plx9050_fn }, ++ { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */ ++ 0x20, 2, pci_plx9050_fn, 0x03 }, ++ /* This board uses the size of PCI Base region 0 to ++ * signal now many ports are available */ ++ { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */ ++ { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */ ++ 0, 0, pci_timedia_fn }, ++ /* EKF addition for i960 Boards form EKF with serial port */ ++ { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */ ++ 8<<2, 2, pci_inteli960ni_fn, 0x10000}, ++ { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */ ++ 1, 458333, 0, 0, 0, 0x20178 }, ++ { SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0}, /* pbn_hp_diva */ ++#ifdef CONFIG_DDB5074 ++ /* ++ * NEC Vrc-5074 (Nile 4) builtin UART. ++ * Conditionally compiled in since this is a motherboard device. ++ */ ++ { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */ ++ 64, 3, NULL, 0x300 }, ++#endif ++ ++ {SPCI_FL_BASE3, 4, 115200, 8}, /* pbn_dci_pccom4 */ ++ {SPCI_FL_BASE3, 8, 115200, 8}, /* pbn_dci_pccom8 */ ++ ++ { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */ ++ 0, 0, pci_xircom_fn }, ++ ++ { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */ ++ 0, 0, pci_siig10x_fn }, ++ { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */ ++ 0, 0, pci_siig10x_fn }, ++ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */ ++ 0, 0, pci_siig10x_fn }, ++ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */ ++ 0, 0, pci_siig10x_fn }, ++ { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */ ++ 0, 0, pci_siig20x_fn }, ++ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */ ++ 0, 0, pci_siig20x_fn }, ++ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */ ++ 0, 0, pci_siig20x_fn }, ++ ++ { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */ ++ 0x40, 2, NULL, 0x200 }, ++ { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */ ++ 0x40, 2, NULL, 0x200 }, ++ { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */ ++ 0x40, 2, NULL, 0x200 }, ++}; ++ ++/* ++ * Given a complete unknown PCI device, try to use some heuristics to ++ * guess what the configuration might be, based on the pitiful PCI ++ * serial specs. Returns 0 on success, 1 on failure. ++ */ ++static int __devinit serial_pci_guess_board(struct pci_dev *dev, ++ struct pci_board *board) ++{ ++ int num_iomem = 0, num_port = 0, first_port = -1; ++ int i; ++ ++ /* ++ * If it is not a communications device or the programming ++ * interface is greater than 6, give up. ++ * ++ * (Should we try to make guesses for multiport serial devices ++ * later?) ++ */ ++ if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) && ++ ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) || ++ (dev->class & 0xff) > 6) ++ return 1; ++ ++ for (i=0; i < 6; i++) { ++ if (IS_PCI_REGION_IOPORT(dev, i)) { ++ num_port++; ++ if (first_port == -1) ++ first_port = i; ++ } ++ if (IS_PCI_REGION_IOMEM(dev, i)) ++ num_iomem++; ++ } ++ ++ /* ++ * If there is 1 or 0 iomem regions, and exactly one port, use ++ * it. ++ */ ++ if (num_iomem <= 1 && num_port == 1) { ++ board->flags = first_port; ++ return 0; ++ } ++ return 1; ++} ++ ++static int __devinit serial_init_one(struct pci_dev *dev, ++ const struct pci_device_id *ent) ++{ ++ struct pci_board *board, tmp; ++ int rc; ++ ++ board = &pci_boards[ent->driver_data]; ++ ++ rc = pci_enable_device(dev); ++ if (rc) return rc; ++ ++ if (ent->driver_data == pbn_default && ++ serial_pci_guess_board(dev, board)) ++ return -ENODEV; ++ else if (serial_pci_guess_board(dev, &tmp) == 0) { ++ printk(KERN_INFO "Redundant entry in serial pci_table. " ++ "Please send the output of\n" ++ "lspci -vv, this message (%04x,%04x,%04x,%04x)\n" ++ "and the manufacturer and name of " ++ "serial board or modem board\n" ++ "to serial-pci-info@lists.sourceforge.net.\n", ++ dev->vendor, dev->device, ++ pci_get_subvendor(dev), pci_get_subdevice(dev)); ++ } ++ ++ start_pci_pnp_board(dev, board); ++ ++ return 0; ++} ++ ++static void __devexit serial_remove_one(struct pci_dev *dev) ++{ ++ int i; ++ ++ /* ++ * Iterate through all of the ports finding those that belong ++ * to this PCI device. ++ */ ++ for(i = 0; i < NR_PORTS; i++) { ++ if (rs_table[i].dev != dev) ++ continue; ++ unregister_serial(i); ++ rs_table[i].dev = 0; ++ } ++ /* ++ * Now execute any board-specific shutdown procedure ++ */ ++ for (i=0; i < NR_PCI_BOARDS; i++) { ++ struct pci_board_inst *brd = &serial_pci_board[i]; ++ ++ if (serial_pci_board[i].dev != dev) ++ continue; ++ if (brd->board.init_fn) ++ (brd->board.init_fn)(brd->dev, &brd->board, 0); ++ if (DEACTIVATE_FUNC(brd->dev)) ++ (DEACTIVATE_FUNC(brd->dev))(brd->dev); ++ serial_pci_board[i].dev = 0; ++ } ++} ++ ++ ++static struct pci_device_id serial_pci_tbl[] __devinitdata = { ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, ++ pbn_b1_8_1382400 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, ++ pbn_b1_4_1382400 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, ++ pbn_b1_2_1382400 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, ++ pbn_b1_8_1382400 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, ++ pbn_b1_4_1382400 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, ++ pbn_b1_2_1382400 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0, ++ pbn_b1_8_921600 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0, ++ pbn_b1_8_921600 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0, ++ pbn_b1_4_921600 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0, ++ pbn_b1_4_921600 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0, ++ pbn_b1_2_921600 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0, ++ pbn_b1_8_921600 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0, ++ pbn_b1_8_921600 }, ++ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, ++ PCI_SUBVENDOR_ID_CONNECT_TECH, ++ PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0, ++ pbn_b1_4_921600 }, ++ ++ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_bt_1_115200 }, ++ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_bt_2_115200 }, ++ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_bt_4_115200 }, ++ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_bt_2_115200 }, ++ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_bt_4_115200 }, ++ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_8_115200 }, ++ ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_bt_2_115200 }, ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_bt_2_921600 }, ++ /* VScom SPCOM800, from sl@s.pl */ ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_8_921600 }, ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_4_921600 }, ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, ++ PCI_SUBVENDOR_ID_KEYSPAN, ++ PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0, ++ pbn_panacom }, ++ { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_panacom4 }, ++ { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_panacom2 }, ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, ++ PCI_SUBVENDOR_ID_CHASE_PCIFAST, ++ PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0, ++ pbn_b2_4_460800 }, ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, ++ PCI_SUBVENDOR_ID_CHASE_PCIFAST, ++ PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0, ++ pbn_b2_8_460800 }, ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, ++ PCI_SUBVENDOR_ID_CHASE_PCIFAST, ++ PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0, ++ pbn_b2_16_460800 }, ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, ++ PCI_SUBVENDOR_ID_CHASE_PCIFAST, ++ PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0, ++ pbn_b2_16_460800 }, ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, ++ PCI_SUBVENDOR_ID_CHASE_PCIRAS, ++ PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0, ++ pbn_b2_4_460800 }, ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, ++ PCI_SUBVENDOR_ID_CHASE_PCIRAS, ++ PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, ++ pbn_b2_8_460800 }, ++ /* Megawolf Romulus PCI Serial Card, from Mike Hudson */ ++ /* (Exoray@isys.ca) */ ++ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, ++ 0x10b5, 0x106a, 0, 0, ++ pbn_plx_romulus }, ++ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b1_4_115200 }, ++ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b1_2_115200 }, ++ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b1_8_115200 }, ++ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b1_8_115200 }, ++ { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954, ++ PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0, ++ pbn_b0_4_921600 }, ++ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_4_115200 }, ++ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_bt_2_921600 }, ++ ++ /* Digitan DS560-558, from jimd@esoft.com */ ++ { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b1_1_115200 }, ++ ++ /* 3Com US Robotics 56k Voice Internal PCI model 5610 */ ++ { PCI_VENDOR_ID_USR, 0x1008, ++ PCI_ANY_ID, PCI_ANY_ID, }, ++ ++ /* Titan Electronic cards */ ++ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_1_921600 }, ++ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_2_921600 }, ++ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_4_921600 }, ++ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_4_921600 }, ++ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L, ++ PCI_ANY_ID, PCI_ANY_ID, ++ SPCI_FL_BASE1, 1, 921600 }, ++ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L, ++ PCI_ANY_ID, PCI_ANY_ID, ++ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, ++ /* The 400L and 800L have a custom hack in get_pci_port */ ++ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L, ++ PCI_ANY_ID, PCI_ANY_ID, ++ SPCI_FL_BASE_TABLE, 4, 921600 }, ++ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L, ++ PCI_ANY_ID, PCI_ANY_ID, ++ SPCI_FL_BASE_TABLE, 8, 921600 }, ++ ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig10x_0 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig10x_0 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig10x_0 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig10x_2 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig10x_2 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig10x_2 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig10x_4 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig10x_4 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig10x_4 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig20x_0 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig20x_0 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig20x_0 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig20x_2 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig20x_2 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig20x_2 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig20x_4 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig20x_4 }, ++ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_siig20x_4 }, ++ ++ /* Computone devices submitted by Doug McNash dmcnash@computone.com */ ++ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, ++ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4, ++ 0, 0, pbn_computone_4 }, ++ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, ++ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8, ++ 0, 0, pbn_computone_8 }, ++ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, ++ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6, ++ 0, 0, pbn_computone_6 }, ++ ++ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi }, ++ { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, ++ PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia }, ++ ++ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_bt_2_115200 }, ++ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_bt_2_115200 }, ++ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_bt_2_115200 }, ++ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_bt_2_460800 }, ++ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_bt_2_460800 }, ++ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_bt_2_460800 }, ++ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_bt_1_115200 }, ++ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b0_bt_1_460800 }, ++ ++ /* RAStel 2 port modem, gerg@moreton.com.au */ ++ { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_bt_2_115200 }, ++ ++ /* EKF addition for i960 Boards form EKF with serial port */ ++ { PCI_VENDOR_ID_INTEL, 0x1960, ++ 0xE4BF, PCI_ANY_ID, 0, 0, ++ pbn_intel_i960 }, ++ ++ /* Xircom Cardbus/Ethernet combos */ ++ { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_xircom_combo }, ++ ++ /* ++ * Untested PCI modems, sent in from various folks... ++ */ ++ ++ /* Elsa Model 56K PCI Modem, from Andreas Rath */ ++ { PCI_VENDOR_ID_ROCKWELL, 0x1004, ++ 0x1048, 0x1500, 0, 0, ++ pbn_b1_1_115200 }, ++ ++ { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, ++ 0xFF00, 0, 0, 0, ++ pbn_sgi_ioc3 }, ++ ++ /* HP Diva card */ ++ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_SAS, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_hp_diva }, ++ { PCI_VENDOR_ID_HP, 0x1290, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_b2_1_115200 }, ++ ++#ifdef CONFIG_DDB5074 ++ /* ++ * NEC Vrc-5074 (Nile 4) builtin UART. ++ * Conditionally compiled in since this is a motherboard device. ++ */ ++ { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_nec_nile4 }, ++#endif ++ ++ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_dci_pccom4 }, ++ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_dci_pccom8 }, ++ ++ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, }, ++ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_COMMUNICATION_MODEM << 8, 0xffff00, }, ++ { 0, } ++}; ++ ++MODULE_DEVICE_TABLE(pci, serial_pci_tbl); ++ ++static struct pci_driver serial_pci_driver = { ++ name: "serial", ++ probe: serial_init_one, ++ remove: __devexit_p(serial_remove_one), ++ id_table: serial_pci_tbl, ++}; ++ ++ ++/* ++ * Query PCI space for known serial boards ++ * If found, add them to the PCI device space in rs_table[] ++ * ++ * Accept a maximum of eight boards ++ * ++ */ ++static void __devinit probe_serial_pci(void) ++{ ++#ifdef SERIAL_DEBUG_PCI ++ printk(KERN_DEBUG "Entered probe_serial_pci()\n"); ++#endif ++ ++ /* Register call PCI serial devices. Null out ++ * the driver name upon failure, as a signal ++ * not to attempt to unregister the driver later ++ */ ++ if (pci_module_init (&serial_pci_driver) != 0) ++ serial_pci_driver.name = ""; ++ ++#ifdef SERIAL_DEBUG_PCI ++ printk(KERN_DEBUG "Leaving probe_serial_pci() (probe finished)\n"); ++#endif ++ return; ++} ++ ++#endif /* ENABLE_SERIAL_PCI */ ++ ++#ifdef ENABLE_SERIAL_PNP ++ ++struct pnp_board { ++ unsigned short vendor; ++ unsigned short device; ++}; ++ ++static struct pnp_board pnp_devices[] __devinitdata = { ++ /* Archtek America Corp. */ ++ /* Archtek SmartLink Modem 3334BT Plug & Play */ ++ { ISAPNP_VENDOR('A', 'A', 'C'), ISAPNP_DEVICE(0x000F) }, ++ /* Anchor Datacomm BV */ ++ /* SXPro 144 External Data Fax Modem Plug & Play */ ++ { ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0001) }, ++ /* SXPro 288 External Data Fax Modem Plug & Play */ ++ { ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0002) }, ++ /* Rockwell 56K ACF II Fax+Data+Voice Modem */ ++ { ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021) }, ++ /* AZT3005 PnP SOUND DEVICE */ ++ { ISAPNP_VENDOR('A', 'Z', 'T'), ISAPNP_DEVICE(0x4001) }, ++ /* Best Data Products Inc. Smart One 336F PnP Modem */ ++ { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) }, ++ /* Boca Research */ ++ /* Boca Complete Ofc Communicator 14.4 Data-FAX */ ++ { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) }, ++ /* Boca Research 33,600 ACF Modem */ ++ { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x1400) }, ++ /* Boca 33.6 Kbps Internal FD34FSVD */ ++ { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x3400) }, ++ /* Boca 33.6 Kbps Internal FD34FSVD */ ++ { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) }, ++ /* Best Data Products Inc. Smart One 336F PnP Modem */ ++ { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) }, ++ /* Computer Peripherals Inc */ ++ /* EuroViVa CommCenter-33.6 SP PnP */ ++ { ISAPNP_VENDOR('C', 'P', 'I'), ISAPNP_DEVICE(0x4050) }, ++ /* Creative Labs */ ++ /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */ ++ { ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3001) }, ++ /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */ ++ { ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3011) }, ++ /* Creative */ ++ /* Creative Modem Blaster Flash56 DI5601-1 */ ++ { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x1032) }, ++ /* Creative Modem Blaster V.90 DI5660 */ ++ { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x2001) }, ++ /* FUJITSU */ ++ /* Fujitsu 33600 PnP-I2 R Plug & Play */ ++ { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0202) }, ++ /* Fujitsu FMV-FX431 Plug & Play */ ++ { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0205) }, ++ /* Fujitsu 33600 PnP-I4 R Plug & Play */ ++ { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0206) }, ++ /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */ ++ { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0209) }, ++ /* Archtek America Corp. */ ++ /* Archtek SmartLink Modem 3334BT Plug & Play */ ++ { ISAPNP_VENDOR('G', 'V', 'C'), ISAPNP_DEVICE(0x000F) }, ++ /* Hayes */ ++ /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */ ++ { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x0001) }, ++ /* Hayes Optima 336 V.34 + FAX + Voice PnP */ ++ { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000C) }, ++ /* Hayes Optima 336B V.34 + FAX + Voice PnP */ ++ { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000D) }, ++ /* Hayes Accura 56K Ext Fax Modem PnP */ ++ { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5670) }, ++ /* Hayes Accura 56K Ext Fax Modem PnP */ ++ { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5674) }, ++ /* Hayes Accura 56K Fax Modem PnP */ ++ { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5675) }, ++ /* Hayes 288, V.34 + FAX */ ++ { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF000) }, ++ /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */ ++ { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF001) }, ++ /* IBM */ ++ /* IBM Thinkpad 701 Internal Modem Voice */ ++ { ISAPNP_VENDOR('I', 'B', 'M'), ISAPNP_DEVICE(0x0033) }, ++ /* Intertex */ ++ /* Intertex 28k8 33k6 Voice EXT PnP */ ++ { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC801) }, ++ /* Intertex 33k6 56k Voice EXT PnP */ ++ { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC901) }, ++ /* Intertex 28k8 33k6 Voice SP EXT PnP */ ++ { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD801) }, ++ /* Intertex 33k6 56k Voice SP EXT PnP */ ++ { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD901) }, ++ /* Intertex 28k8 33k6 Voice SP INT PnP */ ++ { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF401) }, ++ /* Intertex 28k8 33k6 Voice SP EXT PnP */ ++ { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF801) }, ++ /* Intertex 33k6 56k Voice SP EXT PnP */ ++ { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF901) }, ++ /* Kortex International */ ++ /* KORTEX 28800 Externe PnP */ ++ { ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0x4522) }, ++ /* KXPro 33.6 Vocal ASVD PnP */ ++ { ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0xF661) }, ++ /* Lasat */ ++ /* LASAT Internet 33600 PnP */ ++ { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4040) }, ++ /* Lasat Safire 560 PnP */ ++ { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4540) }, ++ /* Lasat Safire 336 PnP */ ++ { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x5440) }, ++ /* Microcom, Inc. */ ++ /* Microcom TravelPorte FAST V.34 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x281) }, ++ /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */ ++ { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0336) }, ++ /* Microcom DeskPorte FAST EP 28.8 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0339) }, ++ /* Microcom DeskPorte 28.8P Plug & Play */ ++ { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0342) }, ++ /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0500) }, ++ /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0501) }, ++ /* Microcom DeskPorte 28.8S Internal Plug & Play */ ++ { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0502) }, ++ /* Motorola */ ++ /* Motorola BitSURFR Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1105) }, ++ /* Motorola TA210 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1111) }, ++ /* Motorola HMTA 200 (ISDN) Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1114) }, ++ /* Motorola BitSURFR Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1115) }, ++ /* Motorola Lifestyle 28.8 Internal */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1190) }, ++ /* Motorola V.3400 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1501) }, ++ /* Motorola Lifestyle 28.8 V.34 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1502) }, ++ /* Motorola Power 28.8 V.34 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1505) }, ++ /* Motorola ModemSURFR External 28.8 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1509) }, ++ /* Motorola Premier 33.6 Desktop Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150A) }, ++ /* Motorola VoiceSURFR 56K External PnP */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150F) }, ++ /* Motorola ModemSURFR 56K External PnP */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1510) }, ++ /* Motorola ModemSURFR 56K Internal PnP */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1550) }, ++ /* Motorola ModemSURFR Internal 28.8 Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1560) }, ++ /* Motorola Premier 33.6 Internal Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1580) }, ++ /* Motorola OnlineSURFR 28.8 Internal Plug & Play */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15B0) }, ++ /* Motorola VoiceSURFR 56K Internal PnP */ ++ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15F0) }, ++ /* Com 1 */ ++ /* Deskline K56 Phone System PnP */ ++ { ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00A1) }, ++ /* PC Rider K56 Phone System PnP */ ++ { ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00F2) }, ++ /* Pace 56 Voice Internal Plug & Play Modem */ ++ { ISAPNP_VENDOR('P', 'M', 'C'), ISAPNP_DEVICE(0x2430) }, ++ /* Generic */ ++ /* Generic standard PC COM port */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0500) }, ++ /* Generic 16550A-compatible COM port */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0501) }, ++ /* Compaq 14400 Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC000) }, ++ /* Compaq 2400/9600 Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC001) }, ++ /* Dial-Up Networking Serial Cable between 2 PCs */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC031) }, ++ /* Dial-Up Networking Parallel Cable between 2 PCs */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC032) }, ++ /* Standard 9600 bps Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC100) }, ++ /* Standard 14400 bps Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC101) }, ++ /* Standard 28800 bps Modem*/ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC102) }, ++ /* Standard Modem*/ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC103) }, ++ /* Standard 9600 bps Modem*/ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC104) }, ++ /* Standard 14400 bps Modem*/ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC105) }, ++ /* Standard 28800 bps Modem*/ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC106) }, ++ /* Standard Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC107) }, ++ /* Standard 9600 bps Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC108) }, ++ /* Standard 14400 bps Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC109) }, ++ /* Standard 28800 bps Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10A) }, ++ /* Standard Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10B) }, ++ /* Standard 9600 bps Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10C) }, ++ /* Standard 14400 bps Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10D) }, ++ /* Standard 28800 bps Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10E) }, ++ /* Standard Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10F) }, ++ /* Standard PCMCIA Card Modem */ ++ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x2000) }, ++ /* Rockwell */ ++ /* Modular Technology */ ++ /* Rockwell 33.6 DPF Internal PnP */ ++ /* Modular Technology 33.6 Internal PnP */ ++ { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0030) }, ++ /* Kortex International */ ++ /* KORTEX 14400 Externe PnP */ ++ { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0100) }, ++ /* Viking Components, Inc */ ++ /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */ ++ { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x4920) }, ++ /* Rockwell */ ++ /* British Telecom */ ++ /* Modular Technology */ ++ /* Rockwell 33.6 DPF External PnP */ ++ /* BT Prologue 33.6 External PnP */ ++ /* Modular Technology 33.6 External PnP */ ++ { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x00A0) }, ++ /* Viking 56K FAX INT */ ++ { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x0262) }, ++ /* SupraExpress 28.8 Data/Fax PnP modem */ ++ { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1310) }, ++ /* SupraExpress 33.6 Data/Fax PnP modem */ ++ { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1421) }, ++ /* SupraExpress 33.6 Data/Fax PnP modem */ ++ { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1590) }, ++ /* SupraExpress 33.6 Data/Fax PnP modem */ ++ { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1760) }, ++ /* Phoebe Micro */ ++ /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */ ++ { ISAPNP_VENDOR('T', 'E', 'X'), ISAPNP_DEVICE(0x0011) }, ++ /* Archtek America Corp. */ ++ /* Archtek SmartLink Modem 3334BT Plug & Play */ ++ { ISAPNP_VENDOR('U', 'A', 'C'), ISAPNP_DEVICE(0x000F) }, ++ /* 3Com Corp. */ ++ /* Gateway Telepath IIvi 33.6 */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0000) }, ++ /* Sportster Vi 14.4 PnP FAX Voicemail */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0004) }, ++ /* U.S. Robotics 33.6K Voice INT PnP */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0006) }, ++ /* U.S. Robotics 33.6K Voice EXT PnP */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0007) }, ++ /* U.S. Robotics 33.6K Voice INT PnP */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2002) }, ++ /* U.S. Robotics 56K Voice INT PnP */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2070) }, ++ /* U.S. Robotics 56K Voice EXT PnP */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2080) }, ++ /* U.S. Robotics 56K FAX INT */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3031) }, ++ /* U.S. Robotics 56K Voice INT PnP */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3070) }, ++ /* U.S. Robotics 56K Voice EXT PnP */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3080) }, ++ /* U.S. Robotics 56K Voice INT PnP */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3090) }, ++ /* U.S. Robotics 56K Message */ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9100) }, ++ /* U.S. Robotics 56K FAX EXT PnP*/ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9160) }, ++ /* U.S. Robotics 56K FAX INT PnP*/ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9170) }, ++ /* U.S. Robotics 56K Voice EXT PnP*/ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9180) }, ++ /* U.S. Robotics 56K Voice INT PnP*/ ++ { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9190) }, ++ { 0, } ++}; ++ ++static inline void avoid_irq_share(struct pci_dev *dev) ++{ ++ int i, map = 0x1FF8; ++ struct serial_state *state = rs_table; ++ struct isapnp_irq *irq; ++ struct isapnp_resources *res = dev->sysdata; ++ ++ for (i = 0; i < NR_PORTS; i++) { ++ if (state->type != PORT_UNKNOWN) ++ clear_bit(state->irq, &map); ++ state++; ++ } ++ ++ for ( ; res; res = res->alt) ++ for(irq = res->irq; irq; irq = irq->next) ++ irq->map = map; ++} ++ ++static char *modem_names[] __devinitdata = { ++ "MODEM", "Modem", "modem", "FAX", "Fax", "fax", ++ "56K", "56k", "K56", "33.6", "28.8", "14.4", ++ "33,600", "28,800", "14,400", "33.600", "28.800", "14.400", ++ "33600", "28800", "14400", "V.90", "V.34", "V.32", 0 ++}; ++ ++static int __devinit check_name(char *name) ++{ ++ char **tmp = modem_names; ++ ++ while (*tmp) { ++ if (strstr(name, *tmp)) ++ return 1; ++ tmp++; ++ } ++ return 0; ++} ++ ++static inline int check_compatible_id(struct pci_dev *dev) ++{ ++ int i; ++ for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++) ++ if ((dev->vendor_compatible[i] == ++ ISAPNP_VENDOR('P', 'N', 'P')) && ++ (swab16(dev->device_compatible[i]) >= 0xc000) && ++ (swab16(dev->device_compatible[i]) <= 0xdfff)) ++ return 0; ++ return 1; ++} ++ ++/* ++ * Given a complete unknown ISA PnP device, try to use some heuristics to ++ * detect modems. Currently use such heuristic set: ++ * - dev->name or dev->bus->name must contain "modem" substring; ++ * - device must have only one IO region (8 byte long) with base adress ++ * 0x2e8, 0x3e8, 0x2f8 or 0x3f8. ++ * ++ * Such detection looks very ugly, but can detect at least some of numerous ++ * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[] ++ * table. ++ */ ++static int _INLINE_ serial_pnp_guess_board(struct pci_dev *dev, ++ struct pci_board *board) ++{ ++ struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata; ++ struct isapnp_resources *resa; ++ ++ if (!(check_name(dev->name) || check_name(dev->bus->name)) && ++ !(check_compatible_id(dev))) ++ return 1; ++ ++ if (!res || res->next) ++ return 1; ++ ++ for (resa = res->alt; resa; resa = resa->alt) { ++ struct isapnp_port *port; ++ for (port = res->port; port; port = port->next) ++ if ((port->size == 8) && ++ ((port->min == 0x2f8) || ++ (port->min == 0x3f8) || ++ (port->min == 0x2e8) || ++ (port->min == 0x3e8))) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static void __devinit probe_serial_pnp(void) ++{ ++ struct pci_dev *dev = NULL; ++ struct pnp_board *pnp_board; ++ struct pci_board board; ++ ++#ifdef SERIAL_DEBUG_PNP ++ printk("Entered probe_serial_pnp()\n"); ++#endif ++ if (!isapnp_present()) { ++#ifdef SERIAL_DEBUG_PNP ++ printk("Leaving probe_serial_pnp() (no isapnp)\n"); ++#endif ++ return; ++ } ++ ++ isapnp_for_each_dev(dev) { ++ if (dev->active) ++ continue; ++ ++ memset(&board, 0, sizeof(board)); ++ board.flags = SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT; ++ board.num_ports = 1; ++ board.base_baud = 115200; ++ ++ for (pnp_board = pnp_devices; pnp_board->vendor; pnp_board++) ++ if ((dev->vendor == pnp_board->vendor) && ++ (dev->device == pnp_board->device)) ++ break; ++ ++ if (pnp_board->vendor) { ++ /* Special case that's more efficient to hardcode */ ++ if ((pnp_board->vendor == ISAPNP_VENDOR('A', 'K', 'Y') && ++ pnp_board->device == ISAPNP_DEVICE(0x1021))) ++ board.flags |= SPCI_FL_NO_SHIRQ; ++ } else { ++ if (serial_pnp_guess_board(dev, &board)) ++ continue; ++ } ++ ++ if (board.flags & SPCI_FL_NO_SHIRQ) ++ avoid_irq_share(dev); ++ start_pci_pnp_board(dev, &board); ++ } ++ ++#ifdef SERIAL_DEBUG_PNP ++ printk("Leaving probe_serial_pnp() (probe finished)\n"); ++#endif ++ return; ++} ++ ++#endif /* ENABLE_SERIAL_PNP */ ++ ++/* ++ * The serial driver boot-time initialization code! ++ */ ++static int __init rs_init(void) ++{ ++ int i; ++ struct serial_state * state; ++ ++ init_bh(SERIAL_BH, do_serial_bh); ++ init_timer(&serial_timer); ++ serial_timer.function = rs_timer; ++ mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); ++ ++ for (i = 0; i < NR_IRQS; i++) { ++ IRQ_ports[i] = 0; ++ IRQ_timeout[i] = 0; ++#ifdef CONFIG_SERIAL_MULTIPORT ++ memset(&rs_multiport[i], 0, ++ sizeof(struct rs_multiport_struct)); ++#endif ++ } ++ show_serial_version(); ++ ++ /* Initialize the tty_driver structure */ ++ ++ memset(&serial_driver, 0, sizeof(struct tty_driver)); ++ serial_driver.magic = TTY_DRIVER_MAGIC; ++#if (LINUX_VERSION_CODE > 0x20100) ++ serial_driver.driver_name = "serial"; ++#endif ++#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) ++ serial_driver.name = "tts/%d"; ++#else ++ serial_driver.name = "ttyS"; ++#endif ++ serial_driver.major = TTY_MAJOR; ++ serial_driver.minor_start = 64 + SERIAL_DEV_OFFSET; ++ serial_driver.name_base = SERIAL_DEV_OFFSET; ++ serial_driver.num = NR_PORTS; ++ serial_driver.type = TTY_DRIVER_TYPE_SERIAL; ++ serial_driver.subtype = SERIAL_TYPE_NORMAL; ++ serial_driver.init_termios = tty_std_termios; ++ serial_driver.init_termios.c_cflag = ++ B9600 | CS8 | CREAD | HUPCL | CLOCAL; ++ serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; ++ serial_driver.refcount = &serial_refcount; ++ serial_driver.table = serial_table; ++ serial_driver.termios = serial_termios; ++ serial_driver.termios_locked = serial_termios_locked; ++ ++ serial_driver.open = rs_open; ++ serial_driver.close = rs_close; ++ serial_driver.write = rs_write; ++ serial_driver.put_char = rs_put_char; ++ serial_driver.flush_chars = rs_flush_chars; ++ serial_driver.write_room = rs_write_room; ++ serial_driver.chars_in_buffer = rs_chars_in_buffer; ++ serial_driver.flush_buffer = rs_flush_buffer; ++ serial_driver.ioctl = rs_ioctl; ++ serial_driver.throttle = rs_throttle; ++ serial_driver.unthrottle = rs_unthrottle; ++ serial_driver.set_termios = rs_set_termios; ++ serial_driver.stop = rs_stop; ++ serial_driver.start = rs_start; ++ serial_driver.hangup = rs_hangup; ++#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ ++ serial_driver.break_ctl = rs_break; ++#endif ++#if (LINUX_VERSION_CODE >= 131343) ++ serial_driver.send_xchar = rs_send_xchar; ++ serial_driver.wait_until_sent = rs_wait_until_sent; ++ serial_driver.read_proc = rs_read_proc; ++#endif ++ ++ /* ++ * The callout device is just like normal device except for ++ * major number and the subtype code. ++ */ ++ callout_driver = serial_driver; ++#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) ++ callout_driver.name = "cua/%d"; ++#else ++ callout_driver.name = "cua"; ++#endif ++ callout_driver.major = TTYAUX_MAJOR; ++ callout_driver.subtype = SERIAL_TYPE_CALLOUT; ++#if (LINUX_VERSION_CODE >= 131343) ++ callout_driver.read_proc = 0; ++ callout_driver.proc_entry = 0; ++#endif ++ ++ if (tty_register_driver(&serial_driver)) ++ panic("Couldn't register serial driver\n"); ++ if (tty_register_driver(&callout_driver)) ++ panic("Couldn't register callout driver\n"); ++ ++ for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { ++ state->magic = SSTATE_MAGIC; ++ state->line = i; ++ state->type = PORT_UNKNOWN; ++ state->custom_divisor = 0; ++ state->close_delay = 5*HZ/10; ++ state->closing_wait = 30*HZ; ++ state->callout_termios = callout_driver.init_termios; ++ state->normal_termios = serial_driver.init_termios; ++ state->icount.cts = state->icount.dsr = ++ state->icount.rng = state->icount.dcd = 0; ++ state->icount.rx = state->icount.tx = 0; ++ state->icount.frame = state->icount.parity = 0; ++ state->icount.overrun = state->icount.brk = 0; ++ state->irq = irq_cannonicalize(state->irq); ++ if (state->hub6) ++ state->io_type = SERIAL_IO_HUB6; ++ if (state->port && check_region(state->port,8)) ++ continue; ++#ifdef CONFIG_MCA ++ if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus) ++ continue; ++#endif ++ if (state->flags & ASYNC_BOOT_AUTOCONF) ++ autoconfig(state); ++ } ++ for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { ++ if (state->type == PORT_UNKNOWN) ++ continue; ++ if ( (state->flags & ASYNC_BOOT_AUTOCONF) ++ && (state->flags & ASYNC_AUTO_IRQ) ++ && (state->port != 0 || state->iomem_base != 0)) ++ state->irq = detect_uart_irq(state); ++ if (state->io_type == SERIAL_IO_MEM) { ++ printk(KERN_INFO"ttyS%02d%s at 0x%p (irq = %d) is a %s\n", ++ state->line + SERIAL_DEV_OFFSET, ++ (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", ++ state->iomem_base, state->irq, ++ uart_config[state->type].name); ++ } ++ else { ++ printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n", ++ state->line + SERIAL_DEV_OFFSET, ++ (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", ++ state->port, state->irq, ++ uart_config[state->type].name); ++ } ++ tty_register_devfs(&serial_driver, 0, ++ serial_driver.minor_start + state->line); ++ tty_register_devfs(&callout_driver, 0, ++ callout_driver.minor_start + state->line); ++ } ++#ifdef ENABLE_SERIAL_PCI ++ probe_serial_pci(); ++#endif ++#ifdef ENABLE_SERIAL_PNP ++ probe_serial_pnp(); ++#endif ++ return 0; ++} ++ ++/* ++ * This is for use by architectures that know their serial console ++ * attributes only at run time. Not to be invoked after rs_init(). ++ */ ++int __init early_serial_setup(struct serial_struct *req) ++{ ++ int i = req->line; ++ ++ if (i >= NR_IRQS) ++ return(-ENOENT); ++ rs_table[i].magic = 0; ++ rs_table[i].baud_base = req->baud_base; ++ rs_table[i].port = req->port; ++ if (HIGH_BITS_OFFSET) ++ rs_table[i].port += (unsigned long) req->port_high << ++ HIGH_BITS_OFFSET; ++ rs_table[i].irq = req->irq; ++ rs_table[i].flags = req->flags; ++ rs_table[i].close_delay = req->close_delay; ++ rs_table[i].io_type = req->io_type; ++ rs_table[i].hub6 = req->hub6; ++ rs_table[i].iomem_base = req->iomem_base; ++ rs_table[i].iomem_reg_shift = req->iomem_reg_shift; ++ rs_table[i].type = req->type; ++ rs_table[i].xmit_fifo_size = req->xmit_fifo_size; ++ rs_table[i].custom_divisor = req->custom_divisor; ++ rs_table[i].closing_wait = req->closing_wait; ++ return(0); ++} ++ ++/* ++ * register_serial and unregister_serial allows for 16x50 serial ports to be ++ * configured at run-time, to support PCMCIA modems. ++ */ ++ ++/** ++ * register_serial - configure a 16x50 serial port at runtime ++ * @req: request structure ++ * ++ * Configure the serial port specified by the request. If the ++ * port exists and is in use an error is returned. If the port ++ * is not currently in the table it is added. ++ * ++ * The port is then probed and if neccessary the IRQ is autodetected ++ * If this fails an error is returned. ++ * ++ * On success the port is ready to use and the line number is returned. ++ */ ++ ++int register_serial(struct serial_struct *req) ++{ ++ int i; ++ unsigned long flags; ++ struct serial_state *state; ++ struct async_struct *info; ++ unsigned long port; ++ ++ port = req->port; ++ if (HIGH_BITS_OFFSET) ++ port += (unsigned long) req->port_high << HIGH_BITS_OFFSET; ++ ++ save_flags(flags); cli(); ++ for (i = 0; i < NR_PORTS; i++) { ++ if ((rs_table[i].port == port) && ++ (rs_table[i].iomem_base == req->iomem_base)) ++ break; ++ } ++#ifdef __i386__ ++ if (i == NR_PORTS) { ++ for (i = 4; i < NR_PORTS; i++) ++ if ((rs_table[i].type == PORT_UNKNOWN) && ++ (rs_table[i].count == 0)) ++ break; ++ } ++#endif ++ if (i == NR_PORTS) { ++ for (i = 0; i < NR_PORTS; i++) ++ if ((rs_table[i].type == PORT_UNKNOWN) && ++ (rs_table[i].count == 0)) ++ break; ++ } ++ if (i == NR_PORTS) { ++ restore_flags(flags); ++ return -1; ++ } ++ state = &rs_table[i]; ++ if (rs_table[i].count) { ++ restore_flags(flags); ++ printk("Couldn't configure serial #%d (port=%ld,irq=%d): " ++ "device already open\n", i, port, req->irq); ++ return -1; ++ } ++ state->irq = req->irq; ++ state->port = port; ++ state->flags = req->flags; ++ state->io_type = req->io_type; ++ state->iomem_base = req->iomem_base; ++ state->iomem_reg_shift = req->iomem_reg_shift; ++ if (req->baud_base) ++ state->baud_base = req->baud_base; ++ if ((info = state->info) != NULL) { ++ info->port = port; ++ info->flags = req->flags; ++ info->io_type = req->io_type; ++ info->iomem_base = req->iomem_base; ++ info->iomem_reg_shift = req->iomem_reg_shift; ++ } ++ autoconfig(state); ++ if (state->type == PORT_UNKNOWN) { ++ restore_flags(flags); ++ printk("register_serial(): autoconfig failed\n"); ++ return -1; ++ } ++ restore_flags(flags); ++ ++ if ((state->flags & ASYNC_AUTO_IRQ) && CONFIGURED_SERIAL_PORT(state)) ++ state->irq = detect_uart_irq(state); ++ ++ printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n", ++ state->line + SERIAL_DEV_OFFSET, ++ state->iomem_base ? "iomem" : "port", ++ state->iomem_base ? (unsigned long)state->iomem_base : ++ state->port, state->irq, uart_config[state->type].name); ++ tty_register_devfs(&serial_driver, 0, ++ serial_driver.minor_start + state->line); ++ tty_register_devfs(&callout_driver, 0, ++ callout_driver.minor_start + state->line); ++ return state->line + SERIAL_DEV_OFFSET; ++} ++ ++/** ++ * unregister_serial - deconfigure a 16x50 serial port ++ * @line: line to deconfigure ++ * ++ * The port specified is deconfigured and its resources are freed. Any ++ * user of the port is disconnected as if carrier was dropped. Line is ++ * the port number returned by register_serial(). ++ */ ++ ++void unregister_serial(int line) ++{ ++ unsigned long flags; ++ struct serial_state *state = &rs_table[line]; ++ ++ save_flags(flags); cli(); ++ if (state->info && state->info->tty) ++ tty_hangup(state->info->tty); ++ state->type = PORT_UNKNOWN; ++ printk(KERN_INFO "ttyS%02d unloaded\n", state->line); ++ /* These will be hidden, because they are devices that will no longer ++ * be available to the system. (ie, PCMCIA modems, once ejected) ++ */ ++ tty_unregister_devfs(&serial_driver, ++ serial_driver.minor_start + state->line); ++ tty_unregister_devfs(&callout_driver, ++ callout_driver.minor_start + state->line); ++ restore_flags(flags); ++} ++ ++static void __exit rs_fini(void) ++{ ++ unsigned long flags; ++ int e1, e2; ++ int i; ++ struct async_struct *info; ++ ++ /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ ++ del_timer_sync(&serial_timer); ++ save_flags(flags); cli(); ++ remove_bh(SERIAL_BH); ++ if ((e1 = tty_unregister_driver(&serial_driver))) ++ printk("serial: failed to unregister serial driver (%d)\n", ++ e1); ++ if ((e2 = tty_unregister_driver(&callout_driver))) ++ printk("serial: failed to unregister callout driver (%d)\n", ++ e2); ++ restore_flags(flags); ++ ++ for (i = 0; i < NR_PORTS; i++) { ++ if ((info = rs_table[i].info)) { ++ rs_table[i].info = NULL; ++ kfree(info); ++ } ++ if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) { ++#ifdef CONFIG_SERIAL_RSA ++ if (rs_table[i].type == PORT_RSA) ++ release_region(rs_table[i].port + ++ UART_RSA_BASE, 16); ++ else ++#endif ++ release_region(rs_table[i].port, 8); ++ } ++#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) ++ if (rs_table[i].iomem_base) ++ iounmap(rs_table[i].iomem_base); ++#endif ++ } ++#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) ++ for (i=0; i < NR_PCI_BOARDS; i++) { ++ struct pci_board_inst *brd = &serial_pci_board[i]; ++ ++ if (serial_pci_board[i].dev == 0) ++ continue; ++ if (brd->board.init_fn) ++ (brd->board.init_fn)(brd->dev, &brd->board, 0); ++ if (DEACTIVATE_FUNC(brd->dev)) ++ (DEACTIVATE_FUNC(brd->dev))(brd->dev); ++ } ++#endif ++ if (tmp_buf) { ++ unsigned long pg = (unsigned long) tmp_buf; ++ tmp_buf = NULL; ++ free_page(pg); ++ } ++ ++#ifdef ENABLE_SERIAL_PCI ++ if (serial_pci_driver.name[0]) ++ pci_unregister_driver (&serial_pci_driver); ++#endif ++} ++ ++module_init(rs_init); ++module_exit(rs_fini); ++MODULE_DESCRIPTION("Standard/generic (dumb) serial driver"); ++MODULE_AUTHOR("Theodore Ts'o "); ++MODULE_LICENSE("GPL"); ++ ++ ++/* ++ * ------------------------------------------------------------ ++ * Serial console driver ++ * ------------------------------------------------------------ ++ */ ++#ifdef CONFIG_SERIAL_CONSOLE ++ ++#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) ++ ++static struct async_struct async_sercons; ++ ++/* ++ * Wait for transmitter & holding register to empty ++ */ ++static inline void wait_for_xmitr(struct async_struct *info) ++{ ++ unsigned int status, tmout = 1000000; ++ ++ do { ++ status = serial_in(info, UART_LSR); ++ ++ if (status & UART_LSR_BI) ++ lsr_break_flag = UART_LSR_BI; ++ ++ if (--tmout == 0) ++ break; ++ } while((status & BOTH_EMPTY) != BOTH_EMPTY); ++ ++ /* Wait for flow control if necessary */ ++ if (info->flags & ASYNC_CONS_FLOW) { ++ tmout = 1000000; ++ while (--tmout && ++ ((serial_in(info, UART_MSR) & UART_MSR_CTS) == 0)); ++ } ++} ++ ++ ++/* ++ * Print a string to the serial port trying not to disturb ++ * any possible real use of the port... ++ * ++ * The console must be locked when we get here. ++ */ ++static void serial_console_write(struct console *co, const char *s, ++ unsigned count) ++{ ++ static struct async_struct *info = &async_sercons; ++ int ier; ++ unsigned i; ++ ++ /* ++ * First save the IER then disable the interrupts ++ */ ++ ier = serial_in(info, UART_IER); ++ serial_out(info, UART_IER, 0x00); ++ ++ /* ++ * Now, do each character ++ */ ++ for (i = 0; i < count; i++, s++) { ++ wait_for_xmitr(info); ++ ++ /* ++ * Send the character out. ++ * If a LF, also do CR... ++ */ ++ serial_out(info, UART_TX, *s); ++ if (*s == 10) { ++ wait_for_xmitr(info); ++ serial_out(info, UART_TX, 13); ++ } ++ } ++ ++ /* ++ * Finally, Wait for transmitter & holding register to empty ++ * and restore the IER ++ */ ++ wait_for_xmitr(info); ++ serial_out(info, UART_IER, ier); ++} ++ ++static kdev_t serial_console_device(struct console *c) ++{ ++ return MKDEV(TTY_MAJOR, 64 + c->index); ++} ++ ++/* ++ * Setup initial baud/bits/parity/flow control. 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) ++{ ++ static struct async_struct *info; ++ struct serial_state *state; ++ unsigned cval; ++ int baud = 9600; ++ int bits = 8; ++ int parity = 'n'; ++ int doflow = 0; ++ int cflag = CREAD | HUPCL | CLOCAL; ++ int quot = 0; ++ char *s; ++ ++ if (options) { ++ baud = simple_strtoul(options, NULL, 10); ++ s = options; ++ while(*s >= '0' && *s <= '9') ++ s++; ++ if (*s) parity = *s++; ++ if (*s) bits = *s++ - '0'; ++ if (*s) doflow = (*s++ == 'r'); ++ } ++ ++ /* ++ * Now construct a cflag setting. ++ */ ++ switch(baud) { ++ case 1200: ++ cflag |= B1200; ++ break; ++ case 2400: ++ cflag |= B2400; ++ break; ++ case 4800: ++ cflag |= B4800; ++ break; ++ case 19200: ++ cflag |= B19200; ++ break; ++ case 38400: ++ cflag |= B38400; ++ break; ++ case 57600: ++ cflag |= B57600; ++ break; ++ case 115200: ++ cflag |= B115200; ++ break; ++ case 9600: ++ default: ++ cflag |= B9600; ++ /* ++ * Set this to a sane value to prevent a divide error ++ */ ++ baud = 9600; ++ break; ++ } ++ switch(bits) { ++ case 7: ++ cflag |= CS7; ++ break; ++ default: ++ case 8: ++ cflag |= CS8; ++ break; ++ } ++ switch(parity) { ++ case 'o': case 'O': ++ cflag |= PARODD; ++ break; ++ case 'e': case 'E': ++ cflag |= PARENB; ++ break; ++ } ++ co->cflag = cflag; ++ ++ /* ++ * Divisor, bytesize and parity ++ */ ++ state = rs_table + co->index; ++ if (doflow) ++ state->flags |= ASYNC_CONS_FLOW; ++ info = &async_sercons; ++ info->magic = SERIAL_MAGIC; ++ info->state = state; ++ info->port = state->port; ++ info->flags = state->flags; ++#ifdef CONFIG_HUB6 ++ info->hub6 = state->hub6; ++#endif ++ info->io_type = state->io_type; ++ info->iomem_base = state->iomem_base; ++ info->iomem_reg_shift = state->iomem_reg_shift; ++ quot = state->baud_base / baud; ++ cval = cflag & (CSIZE | CSTOPB); ++#if defined(__powerpc__) || defined(__alpha__) ++ cval >>= 8; ++#else /* !__powerpc__ && !__alpha__ */ ++ cval >>= 4; ++#endif /* !__powerpc__ && !__alpha__ */ ++ if (cflag & PARENB) ++ cval |= UART_LCR_PARITY; ++ if (!(cflag & PARODD)) ++ cval |= UART_LCR_EPAR; ++ ++ /* ++ * Disable UART interrupts, set DTR and RTS high ++ * and set speed. ++ */ ++ serial_out(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ ++ serial_out(info, UART_DLL, quot & 0xff); /* LS of divisor */ ++ serial_out(info, UART_DLM, quot >> 8); /* MS of divisor */ ++ serial_out(info, UART_LCR, cval); /* reset DLAB */ ++ serial_out(info, UART_IER, 0); ++ serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); ++ ++ /* ++ * If we read 0xff from the LSR, there is no UART here. ++ */ ++ if (serial_in(info, UART_LSR) == 0xff) ++ return -1; ++ ++ return 0; ++} ++ ++static struct console sercons = { ++ name: "ttyS", ++ write: serial_console_write, ++ device: serial_console_device, ++ setup: serial_console_setup, ++ flags: CON_PRINTBUFFER, ++ index: -1, ++}; ++ ++/* ++ * Register console. ++ */ ++void __init serial_console_init(void) ++{ ++ register_console(&sercons); ++} ++#endif ++ ++/* ++ Local variables: ++ compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" ++ End: ++*/ +diff -urN linux.old/drivers/char/ticfg/Makefile linux.dev/drivers/char/ticfg/Makefile +--- linux.old/drivers/char/ticfg/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/char/ticfg/Makefile 2005-11-10 01:10:46.051587500 +0100 +@@ -0,0 +1,6 @@ ++ ++O_TARGET := ticfg.o ++ ++obj-$(CONFIG_AR7_ADAM2) := adam2_env.o ++ ++include $(TOPDIR)/Rules.make +diff -urN linux.old/drivers/char/ticfg/adam2_env.c linux.dev/drivers/char/ticfg/adam2_env.c +--- linux.old/drivers/char/ticfg/adam2_env.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/drivers/char/ticfg/adam2_env.c 2005-11-10 01:10:46.051587500 +0100 +@@ -0,0 +1,85 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#undef ADAM2_ENV_DEBUG ++ ++#ifdef ADAM2_ENV_DEBUG ++#define DPRINTK(args...) do { printk(args); } while(0); ++#else ++#define DPRINTK(args...) do { } while(0); ++#endif ++ ++#define ADAM2_ENV_DIR "ticfg" ++#define ADAM2_ENV_NAME "env" ++ ++static struct proc_dir_entry *adam2_env_proc_dir; ++static struct proc_dir_entry *adam2_env_proc_ent; ++ ++static int ++adam2_proc_read_env(char *page, char **start, off_t pos, int count, ++ int *eof, void *data) ++{ ++ int len; ++ t_env_var *env; ++ ++ if (pos > 0) ++ return 0; ++ ++ len=0; ++ for (env = prom_iterenv(0); env; env = prom_iterenv(env)) { ++ if (env->val) { ++ /* XXX check for page len */ ++ len += sprintf(page + len, "%s\t%s\n", ++ env->name, env->val); ++ } ++ } ++ ++ *eof=1; ++ return len; ++} ++ ++static int __init ++adam2_env_init(void) ++{ ++ ++ DPRINTK("%s\n", __FUNCTION__); ++ ++ adam2_env_proc_dir = proc_mkdir(ADAM2_ENV_DIR, NULL); ++ if (!adam2_env_proc_dir) { ++ printk(KERN_ERR "%s: Unable to create /proc/%s entry\n", ++ __FUNCTION__, ADAM2_ENV_DIR); ++ return -ENOMEM; ++ } ++ ++ adam2_env_proc_ent = ++ create_proc_entry(ADAM2_ENV_NAME, 0444, adam2_env_proc_dir); ++ if (!adam2_env_proc_ent) { ++ printk(KERN_ERR "%s: Unable to create /proc/%s/%s entry\n", ++ __FUNCTION__, ADAM2_ENV_DIR, ADAM2_ENV_NAME); ++ remove_proc_entry(ADAM2_ENV_DIR, NULL); ++ return -ENOMEM; ++ } ++ adam2_env_proc_ent->read_proc = adam2_proc_read_env; ++ ++ return 0; ++} ++ ++static ++void __exit ++adam2_env_cleanup(void) ++{ ++ remove_proc_entry(ADAM2_ENV_NAME, adam2_env_proc_dir); ++ remove_proc_entry(ADAM2_ENV_DIR, NULL); ++} ++ ++module_init(adam2_env_init); ++module_exit(adam2_env_cleanup); ++ ++MODULE_LICENSE("GPL"); +diff -urN linux.old/include/asm-mips/addrspace.h linux.dev/include/asm-mips/addrspace.h +--- linux.old/include/asm-mips/addrspace.h 2002-11-29 00:53:15.000000000 +0100 ++++ linux.dev/include/asm-mips/addrspace.h 2005-11-10 01:14:16.400733500 +0100 +@@ -11,6 +11,8 @@ + #ifndef __ASM_MIPS_ADDRSPACE_H + #define __ASM_MIPS_ADDRSPACE_H + ++#include ++ + /* + * Configure language + */ +@@ -102,4 +104,11 @@ + #define XKPHYS_TO_PHYS(p) ((p) & TO_PHYS_MASK) + #define PHYS_TO_XKPHYS(cm,a) (0x8000000000000000 | ((cm)<<59) | (a)) + ++#ifdef CONFIG_AR7_MEMORY ++#define PHYS_OFFSET ((unsigned long)(CONFIG_AR7_MEMORY)) ++#else ++#define PHYS_OFFSET (0) ++#endif ++#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT) ++ + #endif /* __ASM_MIPS_ADDRSPACE_H */ +diff -urN linux.old/include/asm-mips/ar7/adam2_env.h linux.dev/include/asm-mips/ar7/adam2_env.h +--- linux.old/include/asm-mips/ar7/adam2_env.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/adam2_env.h 2005-11-10 01:10:46.067588500 +0100 +@@ -0,0 +1,13 @@ ++#ifndef _INCLUDE_ASM_AR7_ADAM2_ENV_H_ ++#define _INCLUDE_ASM_AR7_ADAM2_ENV_H_ ++ ++/* Environment variable */ ++typedef struct { ++ char *name; ++ char *val; ++} t_env_var; ++ ++char *prom_getenv(char *); ++t_env_var *prom_iterenv(t_env_var *); ++ ++#endif /* _INCLUDE_ASM_AR7_ADAM2_ENV_H_ */ +diff -urN linux.old/include/asm-mips/ar7/ar7.h linux.dev/include/asm-mips/ar7/ar7.h +--- linux.old/include/asm-mips/ar7/ar7.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/ar7.h 2005-11-10 01:10:46.067588500 +0100 +@@ -0,0 +1,33 @@ ++/* ++ * $Id$ ++ * Copyright (C) $Date$ $Author$ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#ifndef _AR7_H ++#define _AR7_H ++ ++#include ++#include ++ ++#define AVALANCHE_VECS_KSEG0 (KSEG0ADDR(CONFIG_AR7_MEMORY)) ++ ++#define AR7_UART0_REGS_BASE (KSEG1ADDR(0x08610E00)) ++#define AR7_UART1_REGS_BASE (KSEG1ADDR(0x08610F00)) ++#define AR7_BASE_BAUD ( 3686400 / 16 ) ++ ++#endif +diff -urN linux.old/include/asm-mips/ar7/avalanche_intc.h linux.dev/include/asm-mips/ar7/avalanche_intc.h +--- linux.old/include/asm-mips/ar7/avalanche_intc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/avalanche_intc.h 2005-11-10 01:10:46.067588500 +0100 +@@ -0,0 +1,292 @@ ++ /* ++ * Nitin Dhingra, iamnd@ti.com ++ * Copyright (C) 2000 Texas Instruments Inc. ++ * ++ * ++ * ######################################################################## ++ * ++ * 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. ++ * ++ * ######################################################################## ++ * ++ * Defines of the Sead board specific address-MAP, registers, etc. ++ * ++ */ ++#ifndef _AVALANCHE_INTC_H ++#define _AVALANCHE_INTC_H ++ ++#include ++ ++/* ----- */ ++ ++#define KSEG1_BASE 0xA0000000 ++#define KSEG_INV_MASK 0x1FFFFFFF /* Inverted mask for kseg address */ ++#define PHYS_ADDR(addr) ((addr) & KSEG_INV_MASK) ++#define PHYS_TO_K1(addr) (PHYS_ADDR(addr)|KSEG1_BASE) ++#define AVALANCHE_INTC_BASE PHYS_TO_K1(0x08612400) ++ ++/* ----- */ ++ ++#define MIPS_EXCEPTION_OFFSET 8 ++ ++/****************************************************************************** ++ Avalanche Interrupt number ++******************************************************************************/ ++#define AVINTNUM(x) ((x) - MIPS_EXCEPTION_OFFSET) ++ ++/******************************************************************************* ++*Linux Interrupt number ++*******************************************************************************/ ++#define LNXINTNUM(x)((x) + MIPS_EXCEPTION_OFFSET) ++ ++ ++ ++#define AVALANCHE_INT_END_PRIMARY (40 + MIPS_EXCEPTION_OFFSET) ++#define AVALANCHE_INT_END_SECONDARY (32 + MIPS_EXCEPTION_OFFSET) ++ ++#define AVALANCHE_INT_END_PRIMARY_REG1 (31 + MIPS_EXCEPTION_OFFSET) ++#define AVALANCHE_INT_END_PRIMARY_REG2 (39 + MIPS_EXCEPTION_OFFSET) ++ ++#define AVALANCHE_INTC_END (AVINTNUM(AVALANCHE_INT_END_PRIMARY) + \ ++ AVINTNUM(AVALANCHE_INT_END_SECONDARY) + \ ++ MIPS_EXCEPTION_OFFSET) ++ ++#if defined(CONFIG_AR7_VLYNQ) ++#define AVALANCHE_INT_END_LOW_VLYNQ (AVALANCHE_INTC_END + 32) ++#define AVALANCHE_INT_END_VLYNQ (AVALANCHE_INTC_END + 32 * CONFIG_AR7_VLYNQ_PORTS) ++#define AVALANCHE_INT_END AVALANCHE_INT_END_VLYNQ ++#else ++#define AVALANCHE_INT_END AVALANCHE_INTC_END ++#endif ++ ++ ++/* ++ * Avalanche interrupt controller register base (primary) ++ */ ++#define AVALANCHE_ICTRL_REGS_BASE AVALANCHE_INTC_BASE ++ ++/****************************************************************************** ++ * Avalanche exception controller register base (secondary) ++ ******************************************************************************/ ++#define AVALANCHE_ECTRL_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0x80) ++ ++ ++/****************************************************************************** ++ * Avalanche Interrupt pacing register base (secondary) ++ ******************************************************************************/ ++#define AVALANCHE_IPACE_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0xA0) ++ ++ ++ ++/****************************************************************************** ++ * Avalanche Interrupt Channel Control register base ++ *****************************************************************************/ ++#define AVALANCHE_CHCTRL_REGS_BASE (AVALANCHE_ICTRL_REGS_BASE + 0x200) ++ ++ ++struct avalanche_ictrl_regs /* Avalanche Interrupt control registers */ ++{ ++ volatile unsigned long intsr1; /* Interrupt Status/Set Register 1 0x00 */ ++ volatile unsigned long intsr2; /* Interrupt Status/Set Register 2 0x04 */ ++ volatile unsigned long unused1; /*0x08 */ ++ volatile unsigned long unused2; /*0x0C */ ++ volatile unsigned long intcr1; /* Interrupt Clear Register 1 0x10 */ ++ volatile unsigned long intcr2; /* Interrupt Clear Register 2 0x14 */ ++ volatile unsigned long unused3; /*0x18 */ ++ volatile unsigned long unused4; /*0x1C */ ++ volatile unsigned long intesr1; /* Interrupt Enable (Set) Register 1 0x20 */ ++ volatile unsigned long intesr2; /* Interrupt Enable (Set) Register 2 0x24 */ ++ volatile unsigned long unused5; /*0x28 */ ++ volatile unsigned long unused6; /*0x2C */ ++ volatile unsigned long intecr1; /* Interrupt Enable Clear Register 1 0x30 */ ++ volatile unsigned long intecr2; /* Interrupt Enable Clear Register 2 0x34 */ ++ volatile unsigned long unused7; /* 0x38 */ ++ volatile unsigned long unused8; /* 0x3c */ ++ volatile unsigned long pintir; /* Priority Interrupt Index Register 0x40 */ ++ volatile unsigned long intmsr; /* Priority Interrupt Mask Index Reg 0x44 */ ++ volatile unsigned long unused9; /* 0x48 */ ++ volatile unsigned long unused10; /* 0x4C */ ++ volatile unsigned long intpolr1; /* Interrupt Polarity Mask register 10x50 */ ++ volatile unsigned long intpolr2; /* Interrupt Polarity Mask register 20x54 */ ++ volatile unsigned long unused11; /* 0x58 */ ++ volatile unsigned long unused12; /*0x5C */ ++ volatile unsigned long inttypr1; /* Interrupt Type Mask register 10x60 */ ++ volatile unsigned long inttypr2; /* Interrupt Type Mask register 20x64 */ ++}; ++ ++struct avalanche_exctrl_regs /* Avalanche Exception control registers */ ++{ ++ volatile unsigned long exsr; /* Exceptions Status/Set register 0x80 */ ++ volatile unsigned long reserved; /*0x84 */ ++ volatile unsigned long excr; /* Exceptions Clear Register 0x88 */ ++ volatile unsigned long reserved1; /*0x8c */ ++ volatile unsigned long exiesr; /* Exceptions Interrupt Enable (set) 0x90 */ ++ volatile unsigned long reserved2; /*0x94 */ ++ volatile unsigned long exiecr; /* Exceptions Interrupt Enable(clear)0x98 */ ++}; ++struct avalanche_ipace_regs ++{ ++ ++ volatile unsigned long ipacep; /* Interrupt pacing register 0xa0 */ ++ volatile unsigned long ipacemap; /*Interrupt Pacing Map Register 0xa4 */ ++ volatile unsigned long ipacemax; /*Interrupt Pacing Max Register 0xa8 */ ++}; ++struct avalanche_channel_int_number ++{ ++ volatile unsigned long cintnr0; /* Channel Interrupt Number Register0x200 */ ++ volatile unsigned long cintnr1; /* Channel Interrupt Number Register0x204 */ ++ volatile unsigned long cintnr2; /* Channel Interrupt Number Register0x208 */ ++ volatile unsigned long cintnr3; /* Channel Interrupt Number Register0x20C */ ++ volatile unsigned long cintnr4; /* Channel Interrupt Number Register0x210 */ ++ volatile unsigned long cintnr5; /* Channel Interrupt Number Register0x214 */ ++ volatile unsigned long cintnr6; /* Channel Interrupt Number Register0x218 */ ++ volatile unsigned long cintnr7; /* Channel Interrupt Number Register0x21C */ ++ volatile unsigned long cintnr8; /* Channel Interrupt Number Register0x220 */ ++ volatile unsigned long cintnr9; /* Channel Interrupt Number Register0x224 */ ++ volatile unsigned long cintnr10; /* Channel Interrupt Number Register0x228 */ ++ volatile unsigned long cintnr11; /* Channel Interrupt Number Register0x22C */ ++ volatile unsigned long cintnr12; /* Channel Interrupt Number Register0x230 */ ++ volatile unsigned long cintnr13; /* Channel Interrupt Number Register0x234 */ ++ volatile unsigned long cintnr14; /* Channel Interrupt Number Register0x238 */ ++ volatile unsigned long cintnr15; /* Channel Interrupt Number Register0x23C */ ++ volatile unsigned long cintnr16; /* Channel Interrupt Number Register0x240 */ ++ volatile unsigned long cintnr17; /* Channel Interrupt Number Register0x244 */ ++ volatile unsigned long cintnr18; /* Channel Interrupt Number Register0x248 */ ++ volatile unsigned long cintnr19; /* Channel Interrupt Number Register0x24C */ ++ volatile unsigned long cintnr20; /* Channel Interrupt Number Register0x250 */ ++ volatile unsigned long cintnr21; /* Channel Interrupt Number Register0x254 */ ++ volatile unsigned long cintnr22; /* Channel Interrupt Number Register0x358 */ ++ volatile unsigned long cintnr23; /* Channel Interrupt Number Register0x35C */ ++ volatile unsigned long cintnr24; /* Channel Interrupt Number Register0x260 */ ++ volatile unsigned long cintnr25; /* Channel Interrupt Number Register0x264 */ ++ volatile unsigned long cintnr26; /* Channel Interrupt Number Register0x268 */ ++ volatile unsigned long cintnr27; /* Channel Interrupt Number Register0x26C */ ++ volatile unsigned long cintnr28; /* Channel Interrupt Number Register0x270 */ ++ volatile unsigned long cintnr29; /* Channel Interrupt Number Register0x274 */ ++ volatile unsigned long cintnr30; /* Channel Interrupt Number Register0x278 */ ++ volatile unsigned long cintnr31; /* Channel Interrupt Number Register0x27C */ ++ volatile unsigned long cintnr32; /* Channel Interrupt Number Register0x280 */ ++ volatile unsigned long cintnr33; /* Channel Interrupt Number Register0x284 */ ++ volatile unsigned long cintnr34; /* Channel Interrupt Number Register0x288 */ ++ volatile unsigned long cintnr35; /* Channel Interrupt Number Register0x28C */ ++ volatile unsigned long cintnr36; /* Channel Interrupt Number Register0x290 */ ++ volatile unsigned long cintnr37; /* Channel Interrupt Number Register0x294 */ ++ volatile unsigned long cintnr38; /* Channel Interrupt Number Register0x298 */ ++ volatile unsigned long cintnr39; /* Channel Interrupt Number Register0x29C */ ++}; ++ ++struct avalanche_interrupt_line_to_channel ++{ ++ unsigned long int_line0; /* Start of primary interrupts */ ++ unsigned long int_line1; ++ unsigned long int_line2; ++ unsigned long int_line3; ++ unsigned long int_line4; ++ unsigned long int_line5; ++ unsigned long int_line6; ++ unsigned long int_line7; ++ unsigned long int_line8; ++ unsigned long int_line9; ++ unsigned long int_line10; ++ unsigned long int_line11; ++ unsigned long int_line12; ++ unsigned long int_line13; ++ unsigned long int_line14; ++ unsigned long int_line15; ++ unsigned long int_line16; ++ unsigned long int_line17; ++ unsigned long int_line18; ++ unsigned long int_line19; ++ unsigned long int_line20; ++ unsigned long int_line21; ++ unsigned long int_line22; ++ unsigned long int_line23; ++ unsigned long int_line24; ++ unsigned long int_line25; ++ unsigned long int_line26; ++ unsigned long int_line27; ++ unsigned long int_line28; ++ unsigned long int_line29; ++ unsigned long int_line30; ++ unsigned long int_line31; ++ unsigned long int_line32; ++ unsigned long int_line33; ++ unsigned long int_line34; ++ unsigned long int_line35; ++ unsigned long int_line36; ++ unsigned long int_line37; ++ unsigned long int_line38; ++ unsigned long int_line39; ++}; ++ ++ ++/* Interrupt Line #'s (Sangam peripherals) */ ++ ++/*------------------------------*/ ++/* Sangam primary interrupts */ ++/*------------------------------*/ ++ ++#define UNIFIED_SECONDARY_INTERRUPT 0 ++#define AVALANCHE_EXT_INT_0 1 ++#define AVALANCHE_EXT_INT_1 2 ++/* Line #3 Reserved */ ++/* Line #4 Reserved */ ++#define AVALANCHE_TIMER_0_INT 5 ++#define AVALANCHE_TIMER_1_INT 6 ++#define AVALANCHE_UART0_INT 7 ++#define AVALANCHE_UART1_INT 8 ++#define AVALANCHE_PDMA_INT0 9 ++#define AVALANCHE_PDMA_INT1 10 ++/* Line #11 Reserved */ ++/* Line #12 Reserved */ ++/* Line #13 Reserved */ ++/* Line #14 Reserved */ ++#define AVALANCHE_ATM_SAR_INT 15 ++/* Line #16 Reserved */ ++/* Line #17 Reserved */ ++/* Line #18 Reserved */ ++#define AVALANCHE_MAC0_INT 19 ++/* Line #20 Reserved */ ++#define AVALANCHE_VLYNQ0_INT 21 ++#define AVALANCHE_CODEC_WAKE_INT 22 ++/* Line #23 Reserved */ ++#define AVALANCHE_USB_INT 24 ++#define AVALANCHE_VLYNQ1_INT 25 ++/* Line #26 Reserved */ ++/* Line #27 Reserved */ ++#define AVALANCHE_MAC1_INT 28 ++#define AVALANCHE_I2CM_INT 29 ++#define AVALANCHE_PDMA_INT2 30 ++#define AVALANCHE_PDMA_INT3 31 ++/* Line #32 Reserved */ ++/* Line #33 Reserved */ ++/* Line #34 Reserved */ ++/* Line #35 Reserved */ ++/* Line #36 Reserved */ ++#define AVALANCHE_VDMA_VT_RX_INT 37 ++#define AVALANCHE_VDMA_VT_TX_INT 38 ++#define AVALANCHE_ADSLSS_INT 39 ++ ++/*-----------------------------------*/ ++/* Sangam Secondary Interrupts */ ++/*-----------------------------------*/ ++#define PRIMARY_INTS 40 ++ ++#define EMIF_INT (7 + PRIMARY_INTS) ++ ++ ++extern void avalanche_int_set(int channel, int line); ++ ++ ++#endif /* _AVALANCHE_INTC_H */ +diff -urN linux.old/include/asm-mips/ar7/avalanche_misc.h linux.dev/include/asm-mips/ar7/avalanche_misc.h +--- linux.old/include/asm-mips/ar7/avalanche_misc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/avalanche_misc.h 2005-11-10 01:10:46.067588500 +0100 +@@ -0,0 +1,174 @@ ++#ifndef _AVALANCHE_MISC_H_ ++#define _AVALANCHE_MISC_H_ ++ ++typedef enum AVALANCHE_ERR_t ++{ ++ AVALANCHE_ERR_OK = 0, /* OK or SUCCESS */ ++ AVALANCHE_ERR_ERROR = -1, /* Unspecified/Generic ERROR */ ++ ++ /* Pointers and args */ ++ AVALANCHE_ERR_INVARG = -2, /* Invaild argument to the call */ ++ AVALANCHE_ERR_NULLPTR = -3, /* NULL pointer */ ++ AVALANCHE_ERR_BADPTR = -4, /* Bad (out of mem) pointer */ ++ ++ /* Memory issues */ ++ AVALANCHE_ERR_ALLOC_FAIL = -10, /* allocation failed */ ++ AVALANCHE_ERR_FREE_FAIL = -11, /* free failed */ ++ AVALANCHE_ERR_MEM_CORRUPT = -12, /* corrupted memory */ ++ AVALANCHE_ERR_BUF_LINK = -13, /* buffer linking failed */ ++ ++ /* Device issues */ ++ AVALANCHE_ERR_DEVICE_TIMEOUT = -20, /* device timeout on read/write */ ++ AVALANCHE_ERR_DEVICE_MALFUNC = -21, /* device malfunction */ ++ ++ AVALANCHE_ERR_INVID = -30 /* Invalid ID */ ++ ++} AVALANCHE_ERR; ++ ++/***************************************************************************** ++ * Reset Control Module ++ *****************************************************************************/ ++ ++typedef enum AVALANCHE_RESET_MODULE_tag ++{ ++ RESET_MODULE_UART0 = 0, ++ RESET_MODULE_UART1 = 1, ++ RESET_MODULE_I2C = 2, ++ RESET_MODULE_TIMER0 = 3, ++ RESET_MODULE_TIMER1 = 4, ++ RESET_MODULE_GPIO = 6, ++ RESET_MODULE_ADSLSS = 7, ++ RESET_MODULE_USBS = 8, ++ RESET_MODULE_SAR = 9, ++ RESET_MODULE_VDMA_VT = 11, ++ RESET_MODULE_FSER = 12, ++ RESET_MODULE_VLYNQ1 = 16, ++ RESET_MODULE_EMAC0 = 17, ++ RESET_MODULE_DMA = 18, ++ RESET_MODULE_BIST = 19, ++ RESET_MODULE_VLYNQ0 = 20, ++ RESET_MODULE_EMAC1 = 21, ++ RESET_MODULE_MDIO = 22, ++ RESET_MODULE_ADSLSS_DSP = 23, ++ RESET_MODULE_EPHY = 26 ++} AVALANCHE_RESET_MODULE_T; ++ ++typedef enum AVALANCHE_RESET_CTRL_tag ++{ ++ IN_RESET = 0, ++ OUT_OF_RESET ++} AVALANCHE_RESET_CTRL_T; ++ ++typedef enum AVALANCHE_SYS_RST_MODE_tag ++{ ++ RESET_SOC_WITH_MEMCTRL = 1, /* SW0 bit in SWRCR register */ ++ RESET_SOC_WITHOUT_MEMCTRL = 2 /* SW1 bit in SWRCR register */ ++} AVALANCHE_SYS_RST_MODE_T; ++ ++typedef enum AVALANCHE_SYS_RESET_STATUS_tag ++{ ++ HARDWARE_RESET = 0, ++ SOFTWARE_RESET0, /* Caused by writing 1 to SW0 bit in SWRCR register */ ++ WATCHDOG_RESET, ++ SOFTWARE_RESET1 /* Caused by writing 1 to SW1 bit in SWRCR register */ ++} AVALANCHE_SYS_RESET_STATUS_T; ++ ++AVALANCHE_RESET_CTRL_T avalanche_get_reset_status(AVALANCHE_RESET_MODULE_T reset_module); ++void avalanche_sys_reset(AVALANCHE_SYS_RST_MODE_T mode); ++AVALANCHE_SYS_RESET_STATUS_T avalanche_get_sys_last_reset_status(void); ++ ++typedef int (*REMOTE_VLYNQ_DEV_RESET_CTRL_FN)(unsigned int reset_module, AVALANCHE_RESET_CTRL_T reset_ctrl); ++ ++/***************************************************************************** ++ * Power Control Module ++ *****************************************************************************/ ++ ++typedef enum AVALANCHE_POWER_CTRL_tag ++{ ++ POWER_CTRL_POWER_UP = 0, ++ POWER_CTRL_POWER_DOWN ++} AVALANCHE_POWER_CTRL_T; ++ ++typedef enum AVALANCHE_SYS_POWER_MODE_tag ++{ ++ GLOBAL_POWER_MODE_RUN = 0, /* All system is up */ ++ GLOBAL_POWER_MODE_IDLE, /* MIPS is power down, all peripherals working */ ++ GLOBAL_POWER_MODE_STANDBY, /* Chip in power down, but clock to ADSKL subsystem is running */ ++ GLOBAL_POWER_MODE_POWER_DOWN /* Total chip is powered down */ ++} AVALANCHE_SYS_POWER_MODE_T; ++ ++void avalanche_power_ctrl(unsigned int power_module, AVALANCHE_POWER_CTRL_T power_ctrl); ++AVALANCHE_POWER_CTRL_T avalanche_get_power_status(unsigned int power_module); ++void avalanche_set_global_power_mode(AVALANCHE_SYS_POWER_MODE_T power_mode); ++AVALANCHE_SYS_POWER_MODE_T avalanche_get_global_power_mode(void); ++ ++/***************************************************************************** ++ * Wakeup Control ++ *****************************************************************************/ ++ ++typedef enum AVALANCHE_WAKEUP_INTERRUPT_tag ++{ ++ WAKEUP_INT0 = 1, ++ WAKEUP_INT1 = 2, ++ WAKEUP_INT2 = 4, ++ WAKEUP_INT3 = 8 ++} AVALANCHE_WAKEUP_INTERRUPT_T; ++ ++typedef enum TNETV1050_WAKEUP_CTRL_tag ++{ ++ WAKEUP_DISABLED = 0, ++ WAKEUP_ENABLED ++} AVALANCHE_WAKEUP_CTRL_T; ++ ++typedef enum TNETV1050_WAKEUP_POLARITY_tag ++{ ++ WAKEUP_ACTIVE_HIGH = 0, ++ WAKEUP_ACTIVE_LOW ++} AVALANCHE_WAKEUP_POLARITY_T; ++ ++void avalanche_wakeup_ctrl(AVALANCHE_WAKEUP_INTERRUPT_T wakeup_int, ++ AVALANCHE_WAKEUP_CTRL_T wakeup_ctrl, ++ AVALANCHE_WAKEUP_POLARITY_T wakeup_polarity); ++ ++/***************************************************************************** ++ * GPIO Control ++ *****************************************************************************/ ++ ++typedef enum AVALANCHE_GPIO_PIN_MODE_tag ++{ ++ FUNCTIONAL_PIN = 0, ++ GPIO_PIN = 1 ++} AVALANCHE_GPIO_PIN_MODE_T; ++ ++typedef enum AVALANCHE_GPIO_PIN_DIRECTION_tag ++{ ++ GPIO_OUTPUT_PIN = 0, ++ GPIO_INPUT_PIN = 1 ++} AVALANCHE_GPIO_PIN_DIRECTION_T; ++ ++typedef enum { GPIO_FALSE, GPIO_TRUE } AVALANCHE_GPIO_BOOL_T; ++ ++void avalanche_gpio_init(void); ++int avalanche_gpio_ctrl(unsigned int gpio_pin, ++ AVALANCHE_GPIO_PIN_MODE_T pin_mode, ++ AVALANCHE_GPIO_PIN_DIRECTION_T pin_direction); ++int avalanche_gpio_ctrl_with_link_count(unsigned int gpio_pin, ++ AVALANCHE_GPIO_PIN_MODE_T pin_mode, ++ AVALANCHE_GPIO_PIN_DIRECTION_T pin_direction); ++int avalanche_gpio_out_bit(unsigned int gpio_pin, int value); ++int avalanche_gpio_in_bit(unsigned int gpio_pin); ++int avalanche_gpio_out_value(unsigned int out_val, unsigned int set_mask, unsigned int reg_index); ++int avalanche_gpio_out_value_with_link_count(unsigned int out_val, unsigned int set_mask, unsigned int reg_index); ++int avalanche_gpio_in_value(unsigned int *in_val, unsigned int reg_index); ++ ++unsigned int avalanche_get_chip_version_info(void); ++ ++unsigned int avalanche_get_vbus_freq(void); ++void avalanche_set_vbus_freq(unsigned int); ++ ++ ++typedef int (*SET_MDIX_ON_CHIP_FN_T)(unsigned int base_addr, unsigned int operation); ++int avalanche_set_mdix_on_chip(unsigned int base_addr, unsigned int operation); ++unsigned int avalanche_is_mdix_on_chip(void); ++ ++#endif +diff -urN linux.old/include/asm-mips/ar7/avalanche_regs.h linux.dev/include/asm-mips/ar7/avalanche_regs.h +--- linux.old/include/asm-mips/ar7/avalanche_regs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/avalanche_regs.h 2005-11-10 01:10:46.071588750 +0100 +@@ -0,0 +1,567 @@ ++/* ++ * $Id$ ++ * Avalanche Register Descriptions ++ * ++ * Jeff Harrell, jharrell@ti.com ++ * 2000 (c) Texas Instruments Inc. ++ */ ++ ++#ifndef __AVALANCHE_REGS_H ++#define __AVALANCHE_REGS_H ++ ++#include ++#include ++ ++/*----------------------------------------*/ ++/* Base offsets within the Avalanche ASIC */ ++/*----------------------------------------*/ ++ ++#define BBIF_SPACE0 (KSEG1ADDR(0x01000000)) ++#define BBIF_SPACE1 (KSEG1ADDR(0x01800000)) ++#define BBIF_CONTROL (KSEG1ADDR(0x02000000)) ++#define ATM_SAR_BASE (KSEG1ADDR(0x03000000)) ++#define USB_MCU_BASE (KSEG1ADDR(0x03400000)) ++#define DES_BASE (KSEG1ADDR(0x08600000)) ++#define ETH_MACA_BASE (KSEG1ADDR(0x08610000)) ++#define ETH_MACB_BASE (KSEG1ADDR(0x08612800)) ++#define MEM_CTRLR_BASE (KSEG1ADDR(0x08610800)) ++#define GPIO_BASE (KSEG1ADDR(0x08610900)) ++#define CLK_CTRL_BASE (KSEG1ADDR(0x08610A00)) ++#define WATCH_DOG_BASE (KSEG1ADDR(0x08610B00)) ++#define TMR1_BASE (KSEG1ADDR(0x08610C00)) ++#define TRM2_BASE (KSEG1ADDR(0x08610D00)) ++#define UARTA_BASE (KSEG1ADDR(0x08610E00)) ++#define UARTB_BASE (KSEG1ADDR(0x08610F00)) ++#define I2C_BASE (KSEG1ADDR(0x08611000)) ++#define DEV_ID_BASE (KSEG1ADDR(0x08611100)) ++#define USB_BASE (KSEG1ADDR(0x08611200)) ++#define PCI_CONFIG_BASE (KSEG1ADDR(0x08611300)) ++#define DMA_BASE (KSEG1ADDR(0x08611400)) ++#define RESET_CTRL_BASE (KSEG1ADDR(0x08611600)) ++#define DSL_IF_BASE (KSEG1ADDR(0x08611B00)) ++#define INT_CTL_BASE (KSEG1ADDR(0x08612400)) ++#define PHY_BASE (KSEG1ADDR(0x1E000000)) ++ ++/*---------------------------------*/ ++/* Device ID, chip version number */ ++/*---------------------------------*/ ++ ++#define AVALANCHE_CHVN (*(volatile unsigned int *)(DEV_ID_BASE+0x14)) ++#define AVALANCHE_DEVID1 (*(volatile unsigned int *)(DEV_ID_BASE+0x18)) ++#define AVALANCHE_DEVID2 (*(volatile unsigned int *)(DEV_ID_BASE+0x1C)) ++ ++/*----------------------------------*/ ++/* Reset Control VW changed to ptrs */ ++/*----------------------------------*/ ++ ++#define AVALANCHE_PRCR (*(volatile unsigned int *)(RESET_CTRL_BASE + 0x0)) /* Peripheral reset control */ ++#define AVALANCHE_SWRCR (*(volatile unsigned int *)(RESET_CTRL_BASE + 0x4)) /* Software reset control */ ++#define AVALANCHE_RSR (*(volatile unsigned int *)(RESET_CTRL_BASE + 0x8)) /* Reset status register */ ++ ++/* reset control bits */ ++ ++#define AV_RST_UART0 (1<<0) /* Brings UART0 out of reset */ ++#define AV_RST_UART1 (1<<1) /* Brings UART1 out of reset */ ++#define AV_RST_IICM (1<<2) /* Brings the I2CM out of reset */ ++#define AV_RST_TIMER0 (1<<3) /* Brings Timer 0 out of reset */ ++#define AV_RST_TIMER1 (1<<4) /* Brings Timer 1 out of reset */ ++#define AV_RST_DES (1<<5) /* Brings the DES module out of reset */ ++#define AV_RST_GPIO (1<<6) /* Brings the GPIO module out of reset (see note below) */ ++/* ++ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE ++ If you reset the GPIO interface all of the directions (i/o) of the UART B ++ interface pins are inputs and must be reconfigured so as not to lose the ++ serial console interface ++ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE ++*/ ++#define AV_RST_BBIF (1<<7) /* Brings the Broadband interface out of reset */ ++#define AV_RST_USB (1<<8) /* Brings the USB module out of reset */ ++#define AV_RST_SAR (1<<9) /* Brings the SAR out of reset */ ++#define AV_RST_HDLC (1<<10) /* Brings the HDLC module out of reset */ ++#define AV_RST_PCI (1<<16) /* Brings the PCI module out of reset */ ++#define AV_RST_ETH_MAC0 (1<<17) /* Brings the Ethernet MAC0 out of reset */ ++#define AV_RST_PICO_DMA (1<<18) /* Brings the PICO DMA module out of reset */ ++#define AV_RST_BIST (1<<19) /* Brings the BIST module out of reset */ ++#define AV_RST_DSP (1<<20) /* Brings the DSP sub system out of reset */ ++#define AV_RST_ETH_MAC1 (1<<21) /* Brings the Ethernet MAC1 out of reset */ ++ ++/*----------------------*/ ++/* Physical interfaces */ ++/*----------------------*/ ++ ++/* Phy loopback */ ++#define PHY_LOOPBACK 1 ++ ++ ++/* Phy 0 */ ++#define PHY0BASE (PHY_BASE) ++#define PHY0RST (*(volatile unsigned char *) (PHY0BASE)) /* reset */ ++#define PHY0CTRL (*(volatile unsigned char *) (PHY0BASE+0x5)) /* control */ ++#define PHY0RACPCTRL (*(volatile unsigned char *) (PHY0BASE+0x50)) /* RACP control/status */ ++#define PHY0TACPCTRL (*(volatile unsigned char *) (PHY0BASE+0x60)) /* TACP idle/unassigned cell hdr */ ++#define PHY0RACPINT (*(volatile unsigned char *) (PHY0BASE+0x51)) /* RACP interrupt enable/Status */ ++ ++ ++/* Phy 1 */ ++ ++#define PHY1BASE (PHY_BASE + 0x100000) ++#define PHY1RST (*(volatile unsigned char *) (PHY1BASE)) /* reset */ ++#define PHY1CTRL (*(volatile unsigned char *) (PHY1BASE+0x5)) /* control */ ++#define PHY1RACPCTRL (*(volatile unsigned char *) (PHY1BASE+0x50)) ++#define PHY1TACPCTRL (*(volatile unsigned char *) (PHY1BASE+0x60)) ++#define PHY1RACPINT (*(volatile unsigned char *) (PHY1BASE+0x51)) ++ ++/* Phy 2 */ ++ ++#define PHY2BASE (PHY_BASE + 0x200000) ++#define PHY2RST (*(volatile unsigned char *) (PHY2BASE)) /* reset */ ++#define PHY2CTRL (*(volatile unsigned char *) (PHY2BASE+0x5)) /* control */ ++#define PHY2RACPCTRL (*(volatile unsigned char *) (PHY2BASE+0x50)) ++#define PHY2TACPCTRL (*(volatile unsigned char *) (PHY2BASE+0x60)) ++#define PHY2RACPINT (*(volatile unsigned char *) (PHY2BASE+0x51)) ++ ++/*-------------------*/ ++/* Avalanche ATM SAR */ ++/*-------------------*/ ++ ++#define AVSAR_SYSCONFIG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000000)) /* SAR system config register */ ++#define AVSAR_SYSSTATUS (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000004)) /* SAR system status register */ ++#define AVSAR_INT_ENABLE (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000008)) /* SAR interrupt enable register */ ++#define AVSAR_CONN_VPI_VCI (*(volatile unsigned int*)(ATM_SAR_BASE+0x0000000c)) /* VPI/VCI connection config */ ++#define AVSAR_CONN_CONFIG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000010)) /* Connection config register */ ++#define AVSAR_OAM_CONFIG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000018)) /* OAM configuration register */ ++ ++/* Transmit completion ring registers */ ++ ++#define AVSAR_TCRAPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000100)) ++#define AVSAR_TCRASIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000104)) ++#define AVSAR_TCRAINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000108)) ++#define AVSAR_TCRATOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000010c)) ++#define AVSAR_TCRAFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000110)) ++#define AVSAR_TCRAPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000114)) ++#define AVSAR_TCRAENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000118)) ++#define AVSAR_TCRBPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000011c)) ++#define AVSAR_TCRBSIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000120)) ++#define AVSAR_TCRBINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000124)) ++#define AVSAR_TCRBTOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000128)) ++#define AVSAR_TCRBFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000012c)) ++#define AVSAR_TCRBPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000130)) ++#define AVSAR_TCRBENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000134)) ++ ++/* Transmit Queue Packet registers */ ++#define AVSAR_TXQUEUE_PKT0 (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000140)) ++#define AVSAR_TXQUEUE_PKT1 (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000144)) ++#define AVSAR_TXQUEUE_PKT2 (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000148)) ++#define AVSAR_TX_FLUSH (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000014C)) ++/* Receive completion ring registers */ ++ ++#define AVSAR_RCRAPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000200)) ++#define AVSAR_RCRASIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000204)) ++#define AVSAR_RCRAINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000208)) ++#define AVSAR_RCRATOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000020c)) ++#define AVSAR_RCRAFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000210)) ++#define AVSAR_RCRAPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000214)) ++#define AVSAR_RCRAENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000218)) ++#define AVSAR_RCRBPTR (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000021c)) ++#define AVSAR_RCRBSIZE (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000220)) ++#define AVSAR_RCRBINTTHRESH (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000224)) ++#define AVSAR_RCRBTOTENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000228)) ++#define AVSAR_RCRBFREEENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x0000022c)) ++#define AVSAR_RCRBPENDENT (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000230)) ++#define AVSAR_RCRBENTINC (*(volatile unsigned int *)(ATM_SAR_BASE+0x00000234)) ++ ++#define AVSAR_RXFBL_ADD0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000240)) /* Rx Free buffer list add 0 */ ++#define AVSAR_RXFBL_ADD1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000244)) /* Rx Free buffer list add 1 */ ++#define AVSAR_RXFBL_ADD2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000248)) /* Rx Free buffer list add 2 */ ++#define AVSAR_RXFBLSIZE_0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x0000028c)) /* Rx Free buffer list size 0 */ ++#define AVSAR_RXFBLSIZE_1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x0000029c)) /* Rx Free buffer list size 1 */ ++#define AVSAR_RXFBLSIZE_2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000002ac)) /* Rx Free buffer list size 2 */ ++#define AVSAR_RXFBLSIZE_3 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000002bc)) /* Rx Free buffer list size 3 */ ++ ++ ++#if defined(CONFIG_MIPS_EVM3D) || defined(CONFIG_MIPS_AR5D01) || defined(CONFIG_MIPS_AR5W01) ++ ++#define AVSAR_SAR_FREQUENCY (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010480)) ++#define AVSAR_OAM_CC_SINK (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010484)) ++#define AVSAR_OAM_AIS_RDI_RX (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010488)) ++#define AVSAR_OAM_CPID0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104E0)) ++#define AVSAR_OAM_LLID0 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104F0)) ++#define AVSAR_OAM_CPID1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104E4)) ++#define AVSAR_OAM_LLID1 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104F4)) ++#define AVSAR_OAM_CPID2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104E8)) ++#define AVSAR_OAM_LLID2 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104F8)) ++#define AVSAR_OAM_CPID3 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104EC)) ++#define AVSAR_OAM_LLID3 (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104FC)) ++#define AVSAR_OAM_CORR_TAG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010500)) ++#define AVSAR_OAM_FAR_COUNT (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010520)) ++#define AVSAR_OAM_NEAR_COUNT (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010540)) ++#define AVSAR_OAM_CONFIG_REG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00000018)) ++#define AVSAR_FAIRNESS_REG (*(volatile unsigned int*)(ATM_SAR_BASE+0x000104B8)) ++#define AVSAR_UBR_PCR_REG (*(volatile unsigned int*)(ATM_SAR_BASE+0x00010490)) ++ ++ ++/* ++ ++#define OAM_CPID_ADD 0xa30104e0 ++ ++#define OAM_LLID_ADD 0xa30104f0 ++ ++#define OAM_LLID_VAL 0xffffffff ++ ++#define OAM_CORR_TAG 0xa3010500 ++ ++#define OAM_FAR_COUNT_ADD 0xa3010520 ++ ++#define OAM_NEAR_COUNT_ADD 0xa3010540 ++ ++#define OAM_CONFIG_REG_ADD 0xa3000018 ++*/ ++ ++ ++#else /* CONFIG_MIPS_EVM3 || CONFIG_MIPS_ACPEP */ ++ ++#define AVSAR_SAR_FREQUENCY (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012000)) ++#define AVSAR_OAM_CC_SINK (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012004)) ++#define AVSAR_OAM_AIS_RDI_RX (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012008)) ++#define AVSAR_OAM_CPID (*(volatile unsigned int*)(ATM_SAR_BASE+0x00012300)) ++ ++#endif /* CONFIG_MIPS_EVM3D || CONFIG_MIPS_AR5D01 || CONFIG_MIPS_AR5W01 */ ++ ++ ++#define AVSAR_STATE_RAM (ATM_SAR_BASE + 0x010000) /* SAR state RAM */ ++#define AVSAR_PDSP_BASE (ATM_SAR_BASE + 0x020000) /* SAR PDSP base address */ ++#define AVSAR_TXDMA_BASE (ATM_SAR_BASE + 0x030000) /* Transmit DMA state base */ ++#define AVSAR_TDMASTATE6 0x18 /* Transmit DMA state word 6 */ ++#define AVSAR_RXDMA_BASE (ATM_SAR_BASE + 0x040000) /* Receive DMA state base */ ++#define AVSAR_RDMASTATE0 0x0 /* Receive DMA state word 0 */ ++ ++/*------------------------------------------*/ ++/* DSL Interface */ ++/*------------------------------------------*/ ++ ++#define AVDSL_TX_EN (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000000)) ++#define AVDSL_RX_EN (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000004)) ++#define AVDSL_POLL (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000008)) ++ ++/* Fast */ ++ ++#define AVDSL_TX_FIFO_ADDR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000000C)) ++#define AVDSL_TX_FIFO_BASE0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000010)) ++#define AVDSL_TX_FIFO_LEN0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000014)) ++#define AVDSL_TX_FIFO_PR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000018)) ++#define AVDSL_RX_FIFO_ADDR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000001C)) ++#define AVDSL_RX_FIFO_BASE0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000020)) ++#define AVDSL_RX_FIFO_LEN0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000024)) ++#define AVDSL_RX_FIFO_PR0 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000028)) ++ ++/* Interleaved */ ++ ++#define AVDSL_TX_FIFO_ADDR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000002C)) ++#define AVDSL_TX_FIFO_BASE1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000030)) ++#define AVDSL_TX_FIFO_LEN1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000034)) ++#define AVDSL_TX_FIFO_PR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000038)) ++#define AVDSL_RX_FIFO_ADDR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x0000003C)) ++#define AVDSL_RX_FIFO_BASE1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000040)) ++#define AVDSL_RX_FIFO_LEN1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000044)) ++#define AVDSL_RX_FIFO_PR1 (*(volatile unsigned int *)(DSL_IF_BASE + 0x00000048)) ++ ++/*------------------------------------------*/ ++/* Broadband I/F */ ++/*------------------------------------------*/ ++ ++#define AVBBIF_BBIF_CNTRL (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000000)) ++#define AVBBIF_ADDR_TRANS_0 (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000004)) ++#define AVBBIF_ADDR_TRANS_1 (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000008)) ++#define AVBBIF_ADDR_XB_MX_BL (*(volatile unsigned int *)(BBIF_CONTROL + 0x0000000C)) ++#define AVBBIF_INFIFO_LVL (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000010)) ++#define AVBBIF_OUTFIFO_LVL (*(volatile unsigned int *)(BBIF_CONTROL + 0x00000014)) ++ ++#define AVBBIF_DISABLED 0x0 ++#define AVBBIF_LBT4040_INT 0x1 ++#define AVBBIF_XBUS 0x2 ++#define AVBBIF_LBT4040_EXT 0x4 ++ ++#define AVBBIF_ADDR_MASK0 0xff000000 /* handles upper bits of BBIF 0 address */ ++#define AVBBIF_ADDR_MASK1 0xff800000 /* handles upper bits of BBIF 1 address */ ++#define AVBBIF_TRANS_MASK 0xff000000 ++/*------------------------------------------*/ ++/* GPIO I/F */ ++/*------------------------------------------*/ ++ ++#define GPIO_DATA_INPUT (*(volatile unsigned int *)(GPIO_BASE + 0x00000000)) ++#define GPIO_DATA_OUTPUT (*(volatile unsigned int *)(GPIO_BASE + 0x00000004)) ++#define GPIO_DATA_DIR (*(volatile unsigned int *)(GPIO_BASE + 0x00000008)) /* 0=output 1=input */ ++#define GPIO_DATA_ENABLE (*(volatile unsigned int *)(GPIO_BASE + 0x0000000C)) /* 0=GPIO Mux 1=GPIO */ ++ ++#define GPIO_0 (1<<21) ++#define GPIO_1 (1<<22) ++#define GPIO_2 (1<<23) ++#define GPIO_3 (1<<24) ++#define EINT_1 (1<<18) ++ ++/* ++ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE ++ If you reset the GPIO interface all of the directions (i/o) of the UART B ++ interface pins are inputs and must be reconfigured so as not to lose the ++ serial console interface ++ JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE JAH NOTE ++*/ ++ ++/*------------------------------------------*/ ++/* CLK_CTRL */ ++/*------------------------------------------*/ ++#define PERIPH_CLK_CTL (*(volatile unsigned int *)(CLK_CTRL_BASE + 0x00000004)) ++ ++#define PCLK_0_HALF_VBUS (0<<16) ++#define PCLK_EQ_INPUT (1<<16) ++#define BBIF_CLK_HALF_VBUS (0<<17) ++#define BBIF_CLK_EQ_VBUS (1<<17) ++#define BBIF_CLK_EQ_BBCLK (3<<17) ++#define DSP_MODCLK_DSPCLKI (0<<20) ++#define DSP_MODCLK_REFCLKI (1<<20) ++#define USB_CLK_EQ_USBCLKI (0<<21) ++#define USB_CLK_EQ_REFCLKI (1<<21) ++ ++/*------------------------------------------*/ ++/* PCI Control Registers */ ++/*------------------------------------------*/ ++#define PCIC_CONTROL (*(volatile unsigned int *)(PCI_CONFIG_BASE)) ++#define PCIC_CONTROL_CFG_DONE (1<<0) ++#define PCIC_CONTROL_DIS_SLAVE_TO (1<<1) ++#define PCIC_CONTROL_FORCE_DELAY_READ (1<<2) ++#define PCIC_CONTROL_FORCE_DELAY_READ_LINE (1<<3) ++#define PCIC_CONTROL_FORCE_DELAY_READ_MULT (1<<4) ++#define PCIC_CONTROL_MEM_SPACE_EN (1<<5) ++#define PCIC_CONTROL_MEM_MASK (1<<6) ++#define PCIC_CONTROL_IO_SPACE_EN (1<<7) ++#define PCIC_CONTROL_IO_MASK (1<<8) ++/* PCIC_CONTROL_RESERVED (1<<9) */ ++#define PCIC_CONTROL_BASE0_EN (1<<10) ++#define PCIC_CONTROL_BASE1_EN (1<<11) ++#define PCIC_CONTROL_BASE2_EN (1<<12) ++#define PCIC_CONTROL_HOLD_MASTER_WRITE (1<<13) ++#define PCIC_CONTROL_ARBITER_EN (1<<14) ++#define PCIC_INT_SOURCE (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000004)) ++#define PCIC_INT_SOURCE_PWR_MGMT (1<<0) ++#define PCIC_INT_SOURCE_PCI_TARGET (1<<1) ++#define PCIC_INT_SOURCE_PCI_MASTER (1<<2) ++#define PCIC_INT_SOURCE_POWER_WAKEUP (1<<3) ++#define PCIC_INT_SOURCE_PMEIN (1<<4) ++/* PCIC_INT_SOURCE_RESERVED (1<<5) */ ++/* PCIC_INT_SOURCE_RESERVED (1<<6) */ ++#define PCIC_INT_SOURCE_PIC_INTA (1<<7) ++#define PCIC_INT_SOURCE_PIC_INTB (1<<8) ++#define PCIC_INT_SOURCE_PIC_INTC (1<<9) ++#define PCIC_INT_SOURCE_PIC_INTD (1<<10) ++#define PCIC_INT_SOURCE_SOFT_INT0 (1<<11) ++#define PCIC_INT_SOURCE_SOFT_INT1 (1<<12) ++#define PCIC_INT_SOURCE_SOFT_INT2 (1<<13) ++#define PCIC_INT_SOURCE_SOFT_INT3 (1<<14) ++#define PCIC_INT_CLEAR (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000008)) ++#define PCIC_INT_CLEAR_PM (1<<0) ++#define PCIC_INT_CLEAR_PCI_TARGET (1<<1) ++#define PCIC_INT_CLEAR_PCI_MASTER (1<<2) ++/* PCIC_INT_CLEAR_RESERVED (1<<3) */ ++#define PCIC_INT_CLEAR_PMEIN (1<<4) ++/* PCIC_INT_CLEAR_RESERVED (1<<5) */ ++/* PCIC_INT_CLEAR_RESERVED (1<<6) */ ++#define PCIC_INT_CLEAR_PCI_INTA (1<<7) ++#define PCIC_INT_CLEAR_PCI_INTB (1<<8) ++#define PCIC_INT_CLEAR_PCI_INTC (1<<9) ++#define PCIC_INT_CLEAR_PCI_INTD (1<<10) ++#define PCIC_INT_CLEAR_SOFT_INT0 (1<<11) ++#define PCIC_INT_CLEAR_SOFT_INT1 (1<<12) ++#define PCIC_INT_CLEAR_SOFT_INT2 (1<<13) ++#define PCIC_INT_CLEAR_SOFT_INT3 (1<<14) ++#define PCIC_INT_EN_AVAL (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000000c)) ++#define PCIC_INT_EN_AVAL_PM (1<<0) ++#define PCIC_INT_EN_AVAL_PCI_TARGET (1<<1) ++#define PCIC_INT_EN_AVAL_PCI_MASTER (1<<2) ++/* PCIC_INT_EN_AVAL_RESERVED (1<<3) */ ++#define PCIC_INT_EN_AVAL_PMEIN (1<<4) ++/* PCIC_INT_EN_AVAL_RESERVED (1<<5) */ ++/* PCIC_INT_EN_AVAL_RESERVED (1<<6) */ ++#define PCIC_INT_EN_AVAL_PCI_INTA (1<<7) ++#define PCIC_INT_EN_AVAL_PCI_INTB (1<<8) ++#define PCIC_INT_EN_AVAL_PCI_INTC (1<<9) ++#define PCIC_INT_EN_AVAL_PCI_INTD (1<<10) ++#define PCIC_INT_EN_AVAL_SOFT_INT0 (1<<11) ++#define PCIC_INT_EN_AVAL_SOFT_INT1 (1<<12) ++#define PCIC_INT_EN_AVAL_SOFT_INT2 (1<<13) ++#define PCIC_INT_EN_AVAL_SOFT_INT3 (1<<14) ++#define PCIC_INT_EN_PCI (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000010)) ++#define PCIC_INT_EN_PCI_PM (1<<0) ++#define PCIC_INT_EN_PCI_PCI_TARGET (1<<1) ++#define PCIC_INT_EN_PCI_PCI_MASTER (1<<2) ++/* PCIC_INT_EN_PCI_RESERVED (1<<3) */ ++#define PCIC_INT_EN_PCI_PMEIN (1<<4) ++/* PCIC_INT_EN_PCI_RESERVED (1<<5) */ ++/* PCIC_INT_EN_PCI_RESERVED (1<<6) */ ++#define PCIC_INT_EN_PCI_PCI_INTA (1<<7) ++#define PCIC_INT_EN_PCI_PCI_INTB (1<<8) ++#define PCIC_INT_EN_PCI_PCI_INTC (1<<9) ++#define PCIC_INT_EN_PCI_PCI_INTD (1<<10) ++#define PCIC_INT_EN_PCI_SOFT_INT0 (1<<11) ++#define PCIC_INT_EN_PCI_SOFT_INT1 (1<<12) ++#define PCIC_INT_EN_PCI_SOFT_INT2 (1<<13) ++#define PCIC_INT_EN_PCI_SOFT_INT3 (1<<14) ++#define PCIC_INT_SWSET (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000014)) ++#define PCIC_INT_SWSET_SOFT_INT0 (1<<0) ++#define PCIC_INT_SWSET_SOFT_INT1 (1<<1) ++#define PCIC_INT_SWSET_SOFT_INT2 (1<<2) ++#define PCIC_INT_SWSET_SOFT_INT3 (1<<3) ++#define PCIC_PM_CTL (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000018)) ++#define PCIC_PM_CTL_PWR_STATE_MASK (0x02) ++/* PCIC_PM_CTL_RESERVED (1<<2) */ ++/* PCIC_PM_CTL_RESERVED (1<<3) */ ++/* PCIC_PM_CTL_RESERVED (1<<4) */ ++/* PCIC_PM_CTL_RESERVED (1<<5) */ ++/* PCIC_PM_CTL_RESERVED (1<<6) */ ++/* PCIC_PM_CTL_RESERVED (1<<7) */ ++/* PCIC_PM_CTL_RESERVED (1<<8) */ ++/* PCIC_PM_CTL_RESERVED (1<<9) */ ++#define PCIC_PM_CTL_PWR_SUPPORT (1<<10) ++#define PCIC_PM_CTL_PMEIN (1<<11) ++#define PCIC_PM_CTL_CAP_MASK (*(volatile unsigned short int *)(PCI_CONFIG_BASE + 0x0000001a)) ++#define PCIC_PM_CONSUME (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000001c)) ++#define PCIC_PM_CONSUME_D0 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001c)) ++#define PCIC_PM_CONSUME_D1 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001d)) ++#define PCIC_PM_CONSUME_D2 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001e)) ++#define PCIC_PM_CONSUME_D3 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x0000001f)) ++#define PCIC_PM_DISSAPATED (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000020)) ++#define PCIC_PM_DISSAPATED_D0 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000020)) ++#define PCIC_PM_DISSAPATED_D1 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000021)) ++#define PCIC_PM_DISSAPATED_D2 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000022)) ++#define PCIC_PM_DISSAPATED_D3 (*(volatile unsigned char *)(PCI_CONFIG_BASE + 0x00000023)) ++#define PCIC_PM_DATA_SCALE (*(volatile unsigned short int *)(PCI_CONFIG_BASE + 0x00000024)) ++#define PCIC_VEND_DEV_ID (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000028)) ++#define PCIC_SUB_VEND_DEV_ID (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000002c)) ++#define PCIC_CLASS_REV_ID (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000030)) ++#define PCIC_MAX_MIN (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000034)) ++#define PCIC_MAST_MEM_AT0 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000003c)) ++#define PCIC_MAST_MEM_AT1 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000040)) ++#define PCIC_MAST_MEM_AT2 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000044)) ++#define PCIC_SLAVE_MASK0 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000004c)) ++#define PCIC_SLAVE_MASK1 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000050)) ++#define PCIC_SLAVE_MASK2 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000054)) ++#define PCIC_SLAVE_BASE_AT0 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000058)) ++#define PCIC_SLAVE_BASE_AT1 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x0000005c)) ++#define PCIC_SLAVE_BASE_AT2 (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000060)) ++#define PCIC_CONF_COMMAND (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000090)) ++#define PCIC_CONF_ADDR (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000094)) ++#define PCIC_CONF_DATA (*(volatile unsigned int *)(PCI_CONFIG_BASE + 0x00000098)) ++ ++/*------------------------------------------*/ ++/* IIC_INTERFACE */ ++/*------------------------------------------*/ ++#define I2C_DATA_HI (*(volatile unsigned int *)(I2C_BASE + 0x0)) ++#define I2C_DATA_LOW (*(volatile unsigned int *)(I2C_BASE + 0x4)) ++#define I2C_CONFIG (*(volatile unsigned int *)(I2C_BASE + 0x8)) ++#define I2C_DATA_READ (*(volatile unsigned int *)(I2C_BASE + 0xC)) ++#define I2C_CLOCK_DIV (*(volatile unsigned int *)(I2C_BASE + 0x10)) ++ ++#define I2CWRITE 0x200 ++#define I2CREAD 0x300 ++#define I2C_END_BURST 0x400 ++ ++/* read bits */ ++#define I2C_READ_ERROR 0x8000 ++#define I2C_READ_COMPLETE 0x4000 ++#define I2C_READ_BUSY 0x2000 ++ ++/* device types */ ++#define I2C_IO_EXPANDER 0x2 ++#define I2C_RTC 0xd ++ ++/* device Addresses on I2C bus (EVM3) */ ++#define SEVEN_SEGMENT_DISP 0x23 /* Device type = 0x2, Addr = 3 */ ++#define EVM3_RTC 0xd0 /* Device type = 0xd, Addr = 0 */ ++#define EVM3_RTC_I2C_ADDR 0x0 ++ ++/*------------------------------------------*/ ++/* Ethernet MAC register offset definitions */ ++/*------------------------------------------*/ ++#define VMAC_DMACONFIG(X) (*(volatile unsigned int *)(X + 0x00000000)) ++#define VMAC_INTSTS(X) (*(volatile unsigned int *)(X + 0x00000004)) ++#define VMAC_INTMASK(X) (*(volatile unsigned int *)(X + 0x00000008)) ++ ++#define VMAC_WRAPCLK(X) (*(volatile unsigned int *)(X + 0x00000340)) ++#define VMAC_STATSBASE(X) (*(volatile unsigned int *)(X + 0x00000400)) ++ ++#define VMAC_TCRPTR(X) (*(volatile unsigned int *)(X + 0x00000100)) ++#define VMAC_TCRSIZE(X) (*(volatile unsigned int *)(X + 0x00000104)) ++#define VMAC_TCRINTTHRESH(X) (*(volatile unsigned int *)(X + 0x00000108)) ++#define VMAC_TCRTOTENT(X) (*(volatile unsigned int *)(X + 0x0000010C)) ++#define VMAC_TCRFREEENT(X) (*(volatile unsigned int *)(X + 0x00000110)) ++#define VMAC_TCRPENDENT(X) (*(volatile unsigned int *)(X + 0x00000114)) ++#define VMAC_TCRENTINC(X) (*(volatile unsigned int *)(X + 0x00000118)) ++#define VMAC_TXISRPACE(X) (*(volatile unsigned int *)(X + 0x0000011c)) ++ ++ ++#define VMAC_TDMASTATE0(X) (*(volatile unsigned int *)(X + 0x00000120)) ++#define VMAC_TDMASTATE1(X) (*(volatile unsigned int *)(X + 0x00000124)) ++#define VMAC_TDMASTATE2(X) (*(volatile unsigned int *)(X + 0x00000128)) ++#define VMAC_TDMASTATE3(X) (*(volatile unsigned int *)(X + 0x0000012C)) ++#define VMAC_TDMASTATE4(X) (*(volatile unsigned int *)(X + 0x00000130)) ++#define VMAC_TDMASTATE5(X) (*(volatile unsigned int *)(X + 0x00000134)) ++#define VMAC_TDMASTATE6(X) (*(volatile unsigned int *)(X + 0x00000138)) ++#define VMAC_TDMASTATE7(X) (*(volatile unsigned int *)(X + 0x0000013C)) ++#define VMAC_TXPADDCNT(X) (*(volatile unsigned int *)(X + 0x00000140)) ++#define VMAC_TXPADDSTART(X) (*(volatile unsigned int *)(X + 0x00000144)) ++#define VMAC_TXPADDEND(X) (*(volatile unsigned int *)(X + 0x00000148)) ++#define VMAC_TXQFLUSH(X) (*(volatile unsigned int *)(X + 0x0000014C)) ++ ++#define VMAC_RCRPTR(X) (*(volatile unsigned int *)(X + 0x00000200)) ++#define VMAC_RCRSIZE(X) (*(volatile unsigned int *)(X + 0x00000204)) ++#define VMAC_RCRINTTHRESH(X) (*(volatile unsigned int *)(X + 0x00000208)) ++#define VMAC_RCRTOTENT(X) (*(volatile unsigned int *)(X + 0x0000020C)) ++#define VMAC_RCRFREEENT(X) (*(volatile unsigned int *)(X + 0x00000210)) ++#define VMAC_RCRPENDENT(X) (*(volatile unsigned int *)(X + 0x00000214)) ++#define VMAC_RCRENTINC(X) (*(volatile unsigned int *)(X + 0x00000218)) ++#define VMAC_RXISRPACE(X) (*(volatile unsigned int *)(X + 0x0000021c)) ++ ++#define VMAC_RDMASTATE0(X) (*(volatile unsigned int *)(X + 0x00000220)) ++#define VMAC_RDMASTATE1(X) (*(volatile unsigned int *)(X + 0x00000224)) ++#define VMAC_RDMASTATE2(X) (*(volatile unsigned int *)(X + 0x00000228)) ++#define VMAC_RDMASTATE3(X) (*(volatile unsigned int *)(X + 0x0000022C)) ++#define VMAC_RDMASTATE4(X) (*(volatile unsigned int *)(X + 0x00000230)) ++#define VMAC_RDMASTATE5(X) (*(volatile unsigned int *)(X + 0x00000234)) ++#define VMAC_RDMASTATE6(X) (*(volatile unsigned int *)(X + 0x00000238)) ++#define VMAC_RDMASTATE7(X) (*(volatile unsigned int *)(X + 0x0000023C)) ++#define VMAC_FBLADDCNT(X) (*(volatile unsigned int *)(X + 0x00000240)) ++#define VMAC_FBLADDSTART(X) (*(volatile unsigned int *)(X + 0x00000244)) ++#define VMAC_FBLADDEND(X) (*(volatile unsigned int *)(X + 0x00000248)) ++#define VMAC_RXONOFF(X) (*(volatile unsigned int *)(X + 0x0000024C)) ++ ++#define VMAC_FBL0NEXTD(X) (*(volatile unsigned int *)(X + 0x00000280)) ++#define VMAC_FBL0LASTD(X) (*(volatile unsigned int *)(X + 0x00000284)) ++#define VMAC_FBL0COUNTD(X) (*(volatile unsigned int *)(X + 0x00000288)) ++#define VMAC_FBL0BUFSIZE(X) (*(volatile unsigned int *)(X + 0x0000028C)) ++ ++#define VMAC_MACCONTROL(X) (*(volatile unsigned int *)(X + 0x00000300)) ++#define VMAC_MACSTATUS(X) (*(volatile unsigned int *)(X + 0x00000304)) ++#define VMAC_MACADDRHI(X) (*(volatile unsigned int *)(X + 0x00000308)) ++#define VMAC_MACADDRLO(X) (*(volatile unsigned int *)(X + 0x0000030C)) ++#define VMAC_MACHASH1(X) (*(volatile unsigned int *)(X + 0x00000310)) ++#define VMAC_MACHASH2(X) (*(volatile unsigned int *)(X + 0x00000314)) ++ ++#define VMAC_WRAPCLK(X) (*(volatile unsigned int *)(X + 0x00000340)) ++#define VMAC_BOFTEST(X) (*(volatile unsigned int *)(X + 0x00000344)) ++#define VMAC_PACTEST(X) (*(volatile unsigned int *)(X + 0x00000348)) ++#define VMAC_PAUSEOP(X) (*(volatile unsigned int *)(X + 0x0000034C)) ++ ++#define VMAC_MDIOCONTROL(X) (*(volatile unsigned int *)(X + 0x00000380)) ++#define VMAC_MDIOUSERACCESS(X) (*(volatile unsigned int *)(X +0x00000384)) ++#define VMAC_MDIOACK(X) (*(volatile unsigned int *)(X + 0x00000388)) ++#define VMAC_MDIOLINK(X) (*(volatile unsigned int *)(X + 0x0000038C)) ++#define VMAC_MDIOMACPHY(X) (*(volatile unsigned int *)(X + 0x00000390)) ++ ++#define VMAC_STATS_BASE(X) (X + 0x00000400) ++ ++#endif __AVALANCHE_REGS_H ++ ++ ++ ++ ++ ++ +diff -urN linux.old/include/asm-mips/ar7/avalanche_types.h linux.dev/include/asm-mips/ar7/avalanche_types.h +--- linux.old/include/asm-mips/ar7/avalanche_types.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/avalanche_types.h 2005-11-10 01:10:46.071588750 +0100 +@@ -0,0 +1,126 @@ ++/*------------------------------------------------------------------------------------------*\ ++\*------------------------------------------------------------------------------------------*/ ++#ifndef _avalanche_types_h_ ++#define _avalanche_types_h_ ++ ++/*--- #include ---*/ ++#ifndef TRUE ++#define TRUE 1 ++#endif ++#ifndef FALSE ++#define FALSE 0 ++#endif ++#ifndef NULL ++#define NULL (void *)0 ++#endif ++ ++/*------------------------------------------------------------------------------------------*\ ++ * Typen für Texas GPL Module ++\*------------------------------------------------------------------------------------------*/ ++#ifndef __UINT8_T__ ++typedef unsigned char UINT8; ++#define __UINT8_T__ ++#endif ++ ++#ifndef __UCHAR_T__ ++typedef unsigned char UCHAR; ++#define __UCHAR_T__ ++#endif ++ ++#ifndef __INT8_T__ ++typedef signed char INT8; ++#define __INT8_T__ ++#endif ++ ++#ifndef __UINT16_T__ ++typedef unsigned short UINT16; ++#define __UINT16_T__ ++#endif ++ ++#ifndef __USHORT_T__ ++typedef unsigned short USHORT; ++#define __USHORT_T__ ++#endif ++ ++#ifndef __INT16_T__ ++typedef signed short INT16; ++#define __INT16_T__ ++#endif ++ ++#ifndef __UINT32_T__ ++typedef unsigned int UINT32; ++#define __UINT32_T__ ++#endif ++ ++#ifndef __UINT_T__ ++typedef unsigned int UINT; ++#define __UINT_T__ ++#endif ++ ++#ifndef __INT32_T__ ++typedef signed int INT32; ++#define __INT32_T__ ++#endif ++ ++#ifndef __ULONG_T__ ++typedef unsigned long ULONG; ++#define __ULONG_T__ ++#endif ++ ++#ifndef __BOOL_T__ ++typedef int BOOL; ++#define __BOOL_T__ ++#endif ++ ++#ifndef __STATUS_T__ ++typedef int STATUS; ++#define __STATUS_T__ ++#endif ++ ++/*------------------------------------------------------------------------------------------*\ ++\*------------------------------------------------------------------------------------------*/ ++typedef void (*p_vlynq_intr_cntrl_isr_t)(void *,void *,void *); ++typedef INT32 (*p_vlynq_interrupt_vector_set_t)(void *, UINT32, UINT32, INT32, INT32, INT32); ++typedef INT32 (*p_vlynq_interrupt_vector_cntl_t)(void *, UINT32, INT32, UINT32); ++typedef UINT32 (*p_vlynq_interrupt_get_count_t)(void *, UINT32); ++typedef INT32 (*p_vlynq_install_isr_t)(void *, UINT32, p_vlynq_intr_cntrl_isr_t, void *, void *, void *); ++typedef INT32 (*p_vlynq_uninstall_isr_t)(void *, UINT32, void *, void *, void *); ++typedef void (*p_vlynq_root_isr_t)(void *); ++typedef void (*p_vlynq_delay_t)(UINT32); ++typedef INT32 (*p_vlynq_interrupt_vector_map_t)(void *, INT32, UINT32, UINT32); ++typedef INT32 (*p_vlynq_interrupt_set_polarity_t)(void *, INT32, UINT32, INT32); ++typedef INT32 (*p_vlynq_interrupt_get_polarity_t)(void *, INT32, UINT32); ++typedef INT32 (*p_vlynq_interrupt_set_type_t)(void *, INT32, UINT32, INT32); ++typedef INT32 (*p_vlynq_interrupt_get_type_t)(void *, INT32, UINT32); ++typedef INT32 (*p_vlynq_interrupt_enable_t)(void *, INT32, UINT32); ++typedef INT32 (*p_vlynq_interrupt_disable_t)(void *, INT32, UINT32); ++ ++/*------------------------------------------------------------------------------------------*\ ++\*------------------------------------------------------------------------------------------*/ ++extern p_vlynq_interrupt_vector_set_t p_vlynq_interrupt_vector_set; ++extern p_vlynq_interrupt_vector_cntl_t p_vlynq_interrupt_vector_cntl; ++extern p_vlynq_interrupt_get_count_t p_vlynq_interrupt_get_count; ++extern p_vlynq_install_isr_t p_vlynq_install_isr; ++extern p_vlynq_uninstall_isr_t p_vlynq_uninstall_isr; ++extern p_vlynq_root_isr_t p_vlynq_root_isr; ++extern p_vlynq_delay_t p_vlynq_delay; ++extern p_vlynq_interrupt_vector_map_t p_vlynq_interrupt_vector_map; ++extern p_vlynq_interrupt_set_polarity_t p_vlynq_interrupt_set_polarity; ++extern p_vlynq_interrupt_get_polarity_t p_vlynq_interrupt_get_polarity; ++extern p_vlynq_interrupt_set_type_t p_vlynq_interrupt_set_type; ++extern p_vlynq_interrupt_get_type_t p_vlynq_interrupt_get_type; ++extern p_vlynq_interrupt_enable_t p_vlynq_interrupt_enable; ++extern p_vlynq_interrupt_disable_t p_vlynq_interrupt_disable; ++extern void *p_vlynqDevice0; ++extern void *p_vlynqDevice1; ++ ++/*------------------------------------------------------------------------------------------*\ ++\*------------------------------------------------------------------------------------------*/ ++enum _avalanche_need_ { ++ avalanche_need_vlynq, ++ avalanche_need_auto_mdix ++}; ++ ++int avalanche_need(enum _avalanche_need_); ++ ++#endif /*--- #ifndef _avalanche_types_h_ ---*/ +diff -urN linux.old/include/asm-mips/ar7/if_port.h linux.dev/include/asm-mips/ar7/if_port.h +--- linux.old/include/asm-mips/ar7/if_port.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/if_port.h 2005-11-10 01:10:46.071588750 +0100 +@@ -0,0 +1,26 @@ ++/******************************************************************************* ++ * FILE PURPOSE: Interface port id Header file ++ ******************************************************************************* ++ * FILE NAME: if_port.h ++ * ++ * DESCRIPTION: Header file carrying information about port ids of interfaces ++ * ++ * ++ * (C) Copyright 2003, Texas Instruments, Inc ++ ******************************************************************************/ ++#ifndef _IF_PORT_H_ ++#define _IF_PORT_H_ ++ ++#define AVALANCHE_CPMAC_LOW_PORT_ID 0 ++#define AVALANCHE_CPMAC_HIGH_PORT_ID 1 ++#define AVALANCHE_USB_PORT_ID 2 ++#define AVALANCHE_WLAN_PORT_ID 3 ++ ++ ++#define AVALANCHE_MARVELL_BASE_PORT_ID 4 ++ ++/* The marvell ports occupy port ids from 4 to 8 */ ++/* so the next port id number should start at 9 */ ++ ++ ++#endif /* _IF_PORT_H_ */ +diff -urN linux.old/include/asm-mips/ar7/sangam.h linux.dev/include/asm-mips/ar7/sangam.h +--- linux.old/include/asm-mips/ar7/sangam.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/sangam.h 2005-11-10 01:10:46.071588750 +0100 +@@ -0,0 +1,180 @@ ++#ifndef _SANGAM_H_ ++#define _SANGAM_H_ ++ ++#include ++#include ++ ++/*---------------------------------------------------- ++ * Sangam's Module Base Addresses ++ *--------------------------------------------------*/ ++#define AVALANCHE_ADSL_SUB_SYS_MEM_BASE (KSEG1ADDR(0x01000000)) /* AVALANCHE ADSL Mem Base */ ++#define AVALANCHE_BROADBAND_INTERFACE__BASE (KSEG1ADDR(0x02000000)) /* AVALANCHE BBIF */ ++#define AVALANCHE_ATM_SAR_BASE (KSEG1ADDR(0x03000000)) /* AVALANCHE ATM SAR */ ++#define AVALANCHE_USB_SLAVE_BASE (KSEG1ADDR(0x03400000)) /* AVALANCHE USB SLAVE */ ++#define AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE (KSEG1ADDR(0x04000000)) /* AVALANCHE VLYNQ 0 Mem map */ ++#define AVALANCHE_LOW_CPMAC_BASE (KSEG1ADDR(0x08610000)) /* AVALANCHE CPMAC 0 */ ++#define AVALANCHE_EMIF_CONTROL_BASE (KSEG1ADDR(0x08610800)) /* AVALANCHE EMIF */ ++#define AVALANCHE_GPIO_BASE (KSEG1ADDR(0x08610900)) /* AVALANCHE GPIO */ ++#define AVALANCHE_CLOCK_CONTROL_BASE (KSEG1ADDR(0x08610A00)) /* AVALANCHE Clock Control */ ++#define AVALANCHE_WATCHDOG_TIMER_BASE (KSEG1ADDR(0x08610B00)) /* AVALANCHE Watch Dog Timer */ ++#define AVALANCHE_TIMER0_BASE (KSEG1ADDR(0x08610C00)) /* AVALANCHE Timer 1 */ ++#define AVALANCHE_TIMER1_BASE (KSEG1ADDR(0x08610D00)) /* AVALANCHE Timer 2 */ ++#define AVALANCHE_UART0_REGS_BASE (KSEG1ADDR(0x08610E00)) /* AVALANCHE UART 0 */ ++#define AVALANCHE_UART1_REGS_BASE (KSEG1ADDR(0x08610F00)) /* AVALANCHE UART 0 */ ++#define AVALANCHE_I2C_BASE (KSEG1ADDR(0x08611000)) /* AVALANCHE I2C */ ++#define AVALANCHE_USB_SLAVE_CONTROL_BASE (KSEG1ADDR(0x08611200)) /* AVALANCHE USB DMA */ ++#define AVALANCHE_MCDMA0_CTRL_BASE (KSEG1ADDR(0x08611400)) /* AVALANCHE MC DMA 0 (channels 0-3) */ ++#define AVALANCHE_RESET_CONTROL_BASE (KSEG1ADDR(0x08611600)) /* AVALANCHE Reset Control */ ++#define AVALANCHE_BIST_CONTROL_BASE (KSEG1ADDR(0x08611700)) /* AVALANCHE BIST Control */ ++#define AVALANCHE_LOW_VLYNQ_CONTROL_BASE (KSEG1ADDR(0x08611800)) /* AVALANCHE VLYNQ0 Control */ ++#define AVALANCHE_DEVICE_CONFIG_LATCH_BASE (KSEG1ADDR(0x08611A00)) /* AVALANCHE Device Config Latch */ ++#define AVALANCHE_HIGH_VLYNQ_CONTROL_BASE (KSEG1ADDR(0x08611C00)) /* AVALANCHE VLYNQ1 Control */ ++#define AVALANCHE_MDIO_BASE (KSEG1ADDR(0x08611E00)) /* AVALANCHE MDIO */ ++#define AVALANCHE_FSER_BASE (KSEG1ADDR(0x08612000)) /* AVALANCHE FSER base */ ++#define AVALANCHE_INTC_BASE (KSEG1ADDR(0x08612400)) /* AVALANCHE INTC */ ++#define AVALANCHE_HIGH_CPMAC_BASE (KSEG1ADDR(0x08612800)) /* AVALANCHE CPMAC 1 */ ++#define AVALANCHE_HIGH_VLYNQ_MEM_MAP_BASE (KSEG1ADDR(0x0C000000)) /* AVALANCHE VLYNQ 1 Mem map */ ++ ++#define AVALANCHE_SDRAM_BASE 0x14000000UL ++ ++ ++/*---------------------------------------------------- ++ * Sangam Interrupt Map (Primary Interrupts) ++ *--------------------------------------------------*/ ++ ++#define AVALANCHE_UNIFIED_SECONDARY_INT 0 ++#define AVALANCHE_EXT_INT_0 1 ++#define AVALANCHE_EXT_INT_1 2 ++/* Line# 3 to 4 are reserved */ ++#define AVALANCHE_TIMER_0_INT 5 ++#define AVALANCHE_TIMER_1_INT 6 ++#define AVALANCHE_UART0_INT 7 ++#define AVALANCHE_UART1_INT 8 ++#define AVALANCHE_DMA_INT0 9 ++#define AVALANCHE_DMA_INT1 10 ++/* Line# 11 to 14 are reserved */ ++#define AVALANCHE_ATM_SAR_INT 15 ++/* Line# 16 to 18 are reserved */ ++#define AVALANCHE_LOW_CPMAC_INT 19 ++/* Line# 20 is reserved */ ++#define AVALANCHE_LOW_VLYNQ_INT 21 ++#define AVALANCHE_CODEC_WAKEUP_INT 22 ++/* Line# 23 is reserved */ ++#define AVALANCHE_USB_SLAVE_INT 24 ++#define AVALANCHE_HIGH_VLYNQ_INT 25 ++/* Line# 26 to 27 are reserved */ ++#define AVALANCHE_UNIFIED_PHY_INT 28 ++#define AVALANCHE_I2C_INT 29 ++#define AVALANCHE_DMA_INT2 30 ++#define AVALANCHE_DMA_INT3 31 ++/* Line# 32 is reserved */ ++#define AVALANCHE_HIGH_CPMAC_INT 33 ++/* Line# 34 to 36 is reserved */ ++#define AVALANCHE_VDMA_VT_RX_INT 37 ++#define AVALANCHE_VDMA_VT_TX_INT 38 ++#define AVALANCHE_ADSL_SUB_SYSTEM_INT 39 ++ ++ ++#define AVALANCHE_EMIF_INT 47 ++ ++ ++ ++/*----------------------------------------------------------- ++ * Sangam's Reset Bits ++ *---------------------------------------------------------*/ ++ ++#define AVALANCHE_UART0_RESET_BIT 0 ++#define AVALANCHE_UART1_RESET_BIT 1 ++#define AVALANCHE_I2C_RESET_BIT 2 ++#define AVALANCHE_TIMER0_RESET_BIT 3 ++#define AVALANCHE_TIMER1_RESET_BIT 4 ++/* Reset bit 5 is reserved. */ ++#define AVALANCHE_GPIO_RESET_BIT 6 ++#define AVALANCHE_ADSL_SUB_SYS_RESET_BIT 7 ++#define AVALANCHE_USB_SLAVE_RESET_BIT 8 ++#define AVALANCHE_ATM_SAR_RESET_BIT 9 ++/* Reset bit 10 is reserved. */ ++#define AVALANCHE_VDMA_VT_RESET_BIT 11 ++#define AVALANCHE_FSER_RESET_BIT 12 ++/* Reset bit 13 to 15 are reserved */ ++#define AVALANCHE_HIGH_VLYNQ_RESET_BIT 16 ++#define AVALANCHE_LOW_CPMAC_RESET_BIT 17 ++#define AVALANCHE_MCDMA_RESET_BIT 18 ++#define AVALANCHE_BIST_RESET_BIT 19 ++#define AVALANCHE_LOW_VLYNQ_RESET_BIT 20 ++#define AVALANCHE_HIGH_CPMAC_RESET_BIT 21 ++#define AVALANCHE_MDIO_RESET_BIT 22 ++#define AVALANCHE_ADSL_SUB_SYS_DSP_RESET_BIT 23 ++/* Reset bit 24 to 25 are reserved */ ++#define AVALANCHE_LOW_EPHY_RESET_BIT 26 ++/* Reset bit 27 to 31 are reserved */ ++ ++ ++#define AVALANCHE_POWER_MODULE_USBSP 0 ++#define AVALANCHE_POWER_MODULE_WDTP 1 ++#define AVALANCHE_POWER_MODULE_UT0P 2 ++#define AVALANCHE_POWER_MODULE_UT1P 3 ++#define AVALANCHE_POWER_MODULE_IICP 4 ++#define AVALANCHE_POWER_MODULE_VDMAP 5 ++#define AVALANCHE_POWER_MODULE_GPIOP 6 ++#define AVALANCHE_POWER_MODULE_VLYNQ1P 7 ++#define AVALANCHE_POWER_MODULE_SARP 8 ++#define AVALANCHE_POWER_MODULE_ADSLP 9 ++#define AVALANCHE_POWER_MODULE_EMIFP 10 ++#define AVALANCHE_POWER_MODULE_ADSPP 12 ++#define AVALANCHE_POWER_MODULE_RAMP 13 ++#define AVALANCHE_POWER_MODULE_ROMP 14 ++#define AVALANCHE_POWER_MODULE_DMAP 15 ++#define AVALANCHE_POWER_MODULE_BISTP 16 ++#define AVALANCHE_POWER_MODULE_TIMER0P 18 ++#define AVALANCHE_POWER_MODULE_TIMER1P 19 ++#define AVALANCHE_POWER_MODULE_EMAC0P 20 ++#define AVALANCHE_POWER_MODULE_EMAC1P 22 ++#define AVALANCHE_POWER_MODULE_EPHYP 24 ++#define AVALANCHE_POWER_MODULE_VLYNQ0P 27 ++ ++ ++ ++ ++ ++/* ++ * Sangam board vectors ++ */ ++ ++#define AVALANCHE_VECS (KSEG1ADDR(AVALANCHE_SDRAM_BASE)) ++#define AVALANCHE_VECS_KSEG0 (KSEG0ADDR(AVALANCHE_SDRAM_BASE)) ++ ++/*----------------------------------------------------------------------------- ++ * Sangam's system register. ++ * ++ *---------------------------------------------------------------------------*/ ++#define AVALANCHE_DCL_BOOTCR (KSEG1ADDR(0x08611A00)) ++#define AVALANCHE_EMIF_SDRAM_CFG (AVALANCHE_EMIF_CONTROL_BASE + 0x8) ++#define AVALANCHE_RST_CTRL_PRCR (KSEG1ADDR(0x08611600)) ++#define AVALANCHE_RST_CTRL_SWRCR (KSEG1ADDR(0x08611604)) ++#define AVALANCHE_RST_CTRL_RSR (KSEG1ADDR(0x08611600)) ++ ++#define AVALANCHE_POWER_CTRL_PDCR (KSEG1ADDR(0x08610A00)) ++#define AVALANCHE_WAKEUP_CTRL_WKCR (KSEG1ADDR(0x08610A0C)) ++ ++#define AVALANCHE_GPIO_DATA_IN (AVALANCHE_GPIO_BASE + 0x0) ++#define AVALANCHE_GPIO_DATA_OUT (AVALANCHE_GPIO_BASE + 0x4) ++#define AVALANCHE_GPIO_DIR (AVALANCHE_GPIO_BASE + 0x8) ++#define AVALANCHE_GPIO_ENBL (AVALANCHE_GPIO_BASE + 0xC) ++#define AVALANCHE_CVR (AVALANCHE_GPIO_BASE + 0x14) ++ ++/* ++ * Yamon Prom print address. ++ */ ++#define AVALANCHE_YAMON_FUNCTION_BASE (KSEG1ADDR(0x10000500)) ++#define AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR (AVALANCHE_YAMON_FUNCTION_BASE + 0x4) /* print_count function */ ++#define AVALANCHE_YAMON_PROM_PRINT_ADDR (AVALANCHE_YAMON_FUNCTION_BASE + 0x34) ++ ++#define AVALANCHE_BASE_BAUD ( 3686400 / 16 ) ++ ++#define AVALANCHE_GPIO_PIN_COUNT 32 ++#define AVALANCHE_GPIO_OFF_MAP {0xF34FFFC0} ++ ++#include "sangam_boards.h" ++ ++#endif /*_SANGAM_H_ */ +diff -urN linux.old/include/asm-mips/ar7/sangam_boards.h linux.dev/include/asm-mips/ar7/sangam_boards.h +--- linux.old/include/asm-mips/ar7/sangam_boards.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/sangam_boards.h 2005-11-10 01:10:46.071588750 +0100 +@@ -0,0 +1,77 @@ ++#ifndef _SANGAM_BOARDS_H ++#define _SANGAM_BOARDS_H ++ ++// Let us define board specific information here. ++ ++ ++#if defined(CONFIG_AR7DB) ++ ++#define AFECLK_FREQ 35328000 ++#define REFCLK_FREQ 25000000 ++#define OSC3_FREQ 24000000 ++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 ++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x55555555 ++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 ++ ++#endif ++ ++ ++#if defined(CONFIG_AR7RD) ++#define AFECLK_FREQ 35328000 ++#define REFCLK_FREQ 25000000 ++#define OSC3_FREQ 24000000 ++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 ++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x2 ++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 ++#endif ++ ++ ++#if defined(CONFIG_AR7WI) ++#define AFECLK_FREQ 35328000 ++#define REFCLK_FREQ 25000000 ++#define OSC3_FREQ 24000000 ++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 ++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x2 ++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 ++#endif ++ ++ ++#if defined(CONFIG_AR7V) ++#define AFECLK_FREQ 35328000 ++#define REFCLK_FREQ 25000000 ++#define OSC3_FREQ 24000000 ++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 ++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x2 ++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 ++#endif ++ ++ ++#if defined(CONFIG_AR7WRD) ++#define AFECLK_FREQ 35328000 ++#define REFCLK_FREQ 25000000 ++#define OSC3_FREQ 24000000 ++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 ++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x00010000 ++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 ++#endif ++ ++ ++#if defined(CONFIG_AR7VWI) ++#define AFECLK_FREQ 35328000 ++#define REFCLK_FREQ 25000000 ++#define OSC3_FREQ 24000000 ++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 ++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x00010000 ++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 ++#endif ++ ++ ++#if defined CONFIG_SEAD2 ++#define AVALANCHE_LOW_CPMAC_PHY_MASK 0xAAAAAAAA ++#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x55555555 ++#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0 ++#include ++#endif ++ ++ ++#endif +diff -urN linux.old/include/asm-mips/ar7/tnetd73xx.h linux.dev/include/asm-mips/ar7/tnetd73xx.h +--- linux.old/include/asm-mips/ar7/tnetd73xx.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/tnetd73xx.h 2005-11-10 01:10:46.075589000 +0100 +@@ -0,0 +1,338 @@ ++/****************************************************************************** ++ * FILE PURPOSE: TNETD73xx Common Header File ++ ****************************************************************************** ++ * FILE NAME: tnetd73xx.h ++ * ++ * DESCRIPTION: shared typedef's, constants and API for TNETD73xx ++ * ++ * REVISION HISTORY: ++ * 27 Nov 02 - PSP TII ++ * ++ * (C) Copyright 2002, Texas Instruments, Inc ++ *******************************************************************************/ ++ ++/* ++ * ++ * ++ * These are const, typedef, and api definitions for tnetd73xx. ++ * ++ * NOTES: ++ * 1. This file may be included into both C and Assembly files. ++ * - for .s files, please do #define _ASMLANGUAGE in your ASM file to ++ * avoid C data types (typedefs) below; ++ * - for .c files, you don't have to do anything special. ++ * ++ * 2. This file has a number of sections for each SOC subsystem. When adding ++ * a new constant, find the subsystem you are working on and follow the ++ * name pattern. If you are adding another typedef for your interface, please, ++ * place it with other typedefs and function prototypes. ++ * ++ * 3. Please, DO NOT add any macros or types that are local to a subsystem to avoid ++ * cluttering. Include such items directly into the module's .c file or have a ++ * local .h file to pass data between smaller modules. This file defines only ++ * shared items. ++ */ ++ ++#ifndef __TNETD73XX_H__ ++#define __TNETD73XX_H__ ++ ++#ifndef _ASMLANGUAGE /* This part not for assembly language */ ++ ++extern unsigned int tnetd73xx_mips_freq; ++extern unsigned int tnetd73xx_vbus_freq; ++ ++#include "tnetd73xx_err.h" ++ ++#endif /* _ASMLANGUAGE */ ++ ++ ++/******************************************************************************************* ++* Emerald core specific ++******************************************************************************************** */ ++ ++#ifdef BIG_ENDIAN ++#elif defined(LITTLE_ENDIAN) ++#else ++#error Need to define endianism ++#endif ++ ++#ifndef KSEG_MSK ++#define KSEG_MSK 0xE0000000 /* Most significant 3 bits denote kseg choice */ ++#endif ++ ++#ifndef KSEG_INV_MASK ++#define KSEG_INV_MASK 0x1FFFFFFF /* Inverted mask for kseg address */ ++#endif ++ ++#ifndef KSEG0_BASE ++#define KSEG0_BASE 0x80000000 ++#endif ++ ++#ifndef KSEG1_BASE ++#define KSEG1_BASE 0xA0000000 ++#endif ++ ++#ifndef KSEG0 ++#define KSEG0(addr) (((__u32)(addr) & ~KSEG_MSK) | KSEG0_BASE) ++#endif ++ ++#ifndef KSEG1 ++#define KSEG1(addr) (((__u32)(addr) & ~KSEG_MSK) | KSEG1_BASE) ++#endif ++ ++#ifndef KUSEG ++#define KUSEG(addr) ((__u32)(addr) & ~KSEG_MSK) ++#endif ++ ++#ifndef PHYS_ADDR ++#define PHYS_ADDR(addr) ((addr) & KSEG_INV_MASK) ++#endif ++ ++#ifndef PHYS_TO_K0 ++#define PHYS_TO_K0(addr) (PHYS_ADDR(addr)|KSEG0_BASE) ++#endif ++ ++#ifndef PHYS_TO_K1 ++#define PHYS_TO_K1(addr) (PHYS_ADDR(addr)|KSEG1_BASE) ++#endif ++ ++#ifndef REG8_ADDR ++#define REG8_ADDR(addr) (volatile __u8 *)(PHYS_TO_K1(addr)) ++#define REG8_DATA(addr) (*(volatile __u8 *)(PHYS_TO_K1(addr))) ++#define REG8_WRITE(addr, data) REG8_DATA(addr) = data; ++#define REG8_READ(addr, data) data = (__u8) REG8_DATA(addr); ++#endif ++ ++#ifndef REG16_ADDR ++#define REG16_ADDR(addr) (volatile __u16 *)(PHYS_TO_K1(addr)) ++#define REG16_DATA(addr) (*(volatile __u16 *)(PHYS_TO_K1(addr))) ++#define REG16_WRITE(addr, data) REG16_DATA(addr) = data; ++#define REG16_READ(addr, data) data = (__u16) REG16_DATA(addr); ++#endif ++ ++#ifndef REG32_ADDR ++#define REG32_ADDR(addr) (volatile __u32 *)(PHYS_TO_K1(addr)) ++#define REG32_DATA(addr) (*(volatile __u32 *)(PHYS_TO_K1(addr))) ++#define REG32_WRITE(addr, data) REG32_DATA(addr) = data; ++#define REG32_READ(addr, data) data = (__u32) REG32_DATA(addr); ++#endif ++ ++#ifdef _LINK_KSEG0_ /* Application is linked into KSEG0 space */ ++#define VIRT_ADDR(addr) PHYS_TO_K0(PHYS_ADDR(addr)) ++#endif ++ ++#ifdef _LINK_KSEG1_ /* Application is linked into KSEG1 space */ ++#define VIRT_ADDR(addr) PHYS_TO_K1(PHYS_ADDR(addr)) ++#endif ++ ++#if !defined(_LINK_KSEG0_) && !defined(_LINK_KSEG1_) ++#error You must define _LINK_KSEG0_ or _LINK_KSEG1_ to compile the code. ++#endif ++ ++/* TNETD73XX chip definations */ ++ ++#define FREQ_1MHZ 1000000 ++#define TNETD73XX_MIPS_FREQ tnetd73xx_mips_freq /* CPU clock frequency */ ++#define TNETD73XX_VBUS_FREQ tnetd73xx_vbus_freq /* originally (TNETD73XX_MIPS_FREQ/2) */ ++ ++#ifdef AR7SEAD2 ++#define TNETD73XX_MIPS_FREQ_DEFAULT 25000000 /* 25 Mhz for sead2 board crystal */ ++#else ++#define TNETD73XX_MIPS_FREQ_DEFAULT 125000000 /* 125 Mhz */ ++#endif ++#define TNETD73XX_VBUS_FREQ_DEFAULT (TNETD73XX_MIPS_FREQ_DEFAULT / 2) /* Sync mode */ ++ ++ ++ ++/* Module base addresses */ ++#define TNETD73XX_ADSLSS_BASE PHYS_TO_K1(0x01000000) /* ADSLSS Module */ ++#define TNETD73XX_BBIF_CTRL_BASE PHYS_TO_K1(0x02000000) /* BBIF Control */ ++#define TNETD73XX_ATMSAR_BASE PHYS_TO_K1(0x03000000) /* ATM SAR */ ++#define TNETD73XX_USB_BASE PHYS_TO_K1(0x03400000) /* USB Module */ ++#define TNETD73XX_VLYNQ0_BASE PHYS_TO_K1(0x04000000) /* VLYNQ0 Module */ ++#define TNETD73xx_EMAC0_BASE PHYS_TO_K1(0x08610000) /* EMAC0 Module*/ ++#define TNETD73XX_EMIF_BASE PHYS_TO_K1(0x08610800) /* EMIF Module */ ++#define TNETD73XX_GPIO_BASE PHYS_TO_K1(0x08610900) /* GPIO control */ ++#define TNETD73XX_CLOCK_CTRL_BASE PHYS_TO_K1(0x08610A00) /* Clock Control */ ++#define TNETD73XX_WDTIMER_BASE PHYS_TO_K1(0x08610B00) /* WDTIMER Module */ ++#define TNETD73XX_TIMER0_BASE PHYS_TO_K1(0x08610C00) /* TIMER0 Module */ ++#define TNETD73XX_TIMER1_BASE PHYS_TO_K1(0x08610D00) /* TIMER1 Module */ ++#define TNETD73XX_UARTA_BASE PHYS_TO_K1(0x08610E00) /* UART A */ ++#define TNETD73XX_UARTB_BASE PHYS_TO_K1(0x08610F00) /* UART B */ ++#define TNETD73XX_I2C_BASE PHYS_TO_K1(0x08611000) /* I2C Module */ ++#define TNETD73XX_USB_DMA_BASE PHYS_TO_K1(0x08611200) /* USB Module */ ++#define TNETD73XX_MCDMA_BASE PHYS_TO_K1(0x08611400) /* MC-DMA */ ++#define TNETD73xx_VDMAVT_BASE PHYS_TO_K1(0x08611500) /* VDMAVT Control */ ++#define TNETD73XX_RST_CTRL_BASE PHYS_TO_K1(0x08611600) /* Reset Control */ ++#define TNETD73xx_BIST_CTRL_BASE PHYS_TO_K1(0x08611700) /* BIST Control */ ++#define TNETD73xx_VLYNQ0_CTRL_BASE PHYS_TO_K1(0x08611800) /* VLYNQ0 Control */ ++#define TNETD73XX_DCL_BASE PHYS_TO_K1(0x08611A00) /* Device Configuration Latch */ ++#define TNETD73xx_VLYNQ1_CTRL_BASE PHYS_TO_K1(0x08611C00) /* VLYNQ1 Control */ ++#define TNETD73xx_MDIO_BASE PHYS_TO_K1(0x08611E00) /* MDIO Control */ ++#define TNETD73XX_FSER_BASE PHYS_TO_K1(0x08612000) /* FSER Control */ ++#define TNETD73XX_INTC_BASE PHYS_TO_K1(0x08612400) /* Interrupt Controller */ ++#define TNETD73xx_EMAC1_BASE PHYS_TO_K1(0x08612800) /* EMAC1 Module*/ ++#define TNETD73XX_VLYNQ1_BASE PHYS_TO_K1(0x0C000000) /* VLYNQ1 Module */ ++ ++/* BBIF Registers */ ++#define TNETD73XX_BBIF_ADSLADR (TNETD73XX_BBIF_CTRL_BASE + 0x0) ++ ++/* Device Configuration Latch Registers */ ++#define TNETD73XX_DCL_BOOTCR (TNETD73XX_DCL_BASE + 0x0) ++#define TNETD73XX_DCL_DPLLSELR (TNETD73XX_DCL_BASE + 0x10) ++#define TNETD73XX_DCL_SPEEDCTLR (TNETD73XX_DCL_BASE + 0x14) ++#define TNETD73XX_DCL_SPEEDPWDR (TNETD73XX_DCL_BASE + 0x18) ++#define TNETD73XX_DCL_SPEEDCAPR (TNETD73XX_DCL_BASE + 0x1C) ++ ++/* GPIO Control */ ++#define TNETD73XX_GPIODINR (TNETD73XX_GPIO_BASE + 0x0) ++#define TNETD73XX_GPIODOUTR (TNETD73XX_GPIO_BASE + 0x4) ++#define TNETD73XX_GPIOPDIRR (TNETD73XX_GPIO_BASE + 0x8) ++#define TNETD73XX_GPIOENR (TNETD73XX_GPIO_BASE + 0xC) ++#define TNETD73XX_CVR (TNETD73XX_GPIO_BASE + 0x14) ++#define TNETD73XX_DIDR1 (TNETD73XX_GPIO_BASE + 0x18) ++#define TNETD73XX_DIDR2 (TNETD73XX_GPIO_BASE + 0x1C) ++ ++/* Reset Control */ ++#define TNETD73XX_RST_CTRL_PRCR (TNETD73XX_RST_CTRL_BASE + 0x0) ++#define TNETD73XX_RST_CTRL_SWRCR (TNETD73XX_RST_CTRL_BASE + 0x4) ++#define TNETD73XX_RST_CTRL_RSR (TNETD73XX_RST_CTRL_BASE + 0x8) ++ ++/* Power Control */ ++#define TNETD73XX_POWER_CTRL_PDCR (TNETD73XX_CLOCK_CTRL_BASE + 0x0) ++#define TNETD73XX_POWER_CTRL_PCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x4) ++#define TNETD73XX_POWER_CTRL_PDUCR (TNETD73XX_CLOCK_CTRL_BASE + 0x8) ++#define TNETD73XX_POWER_CTRL_WKCR (TNETD73XX_CLOCK_CTRL_BASE + 0xC) ++ ++/* Clock Control */ ++#define TNETD73XX_CLK_CTRL_SCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x20) ++#define TNETD73XX_CLK_CTRL_SCLKPLLCR (TNETD73XX_CLOCK_CTRL_BASE + 0x30) ++#define TNETD73XX_CLK_CTRL_MCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x40) ++#define TNETD73XX_CLK_CTRL_MCLKPLLCR (TNETD73XX_CLOCK_CTRL_BASE + 0x50) ++#define TNETD73XX_CLK_CTRL_UCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x60) ++#define TNETD73XX_CLK_CTRL_UCLKPLLCR (TNETD73XX_CLOCK_CTRL_BASE + 0x70) ++#define TNETD73XX_CLK_CTRL_ACLKCR0 (TNETD73XX_CLOCK_CTRL_BASE + 0x80) ++#define TNETD73XX_CLK_CTRL_ACLKPLLCR0 (TNETD73XX_CLOCK_CTRL_BASE + 0x90) ++#define TNETD73XX_CLK_CTRL_ACLKCR1 (TNETD73XX_CLOCK_CTRL_BASE + 0xA0) ++#define TNETD73XX_CLK_CTRL_ACLKPLLCR1 (TNETD73XX_CLOCK_CTRL_BASE + 0xB0) ++ ++/* EMIF control */ ++#define TNETD73XX_EMIF_SDRAM_CFG ( TNETD73XX_EMIF_BASE + 0x08 ) ++ ++/* UART */ ++#ifdef AR7SEAD2 ++#define TNETD73XX_UART_FREQ 3686400 ++#else ++#define TNETD73XX_UART_FREQ TNETD73XX_VBUS_FREQ ++#endif ++ ++/* Interrupt Controller */ ++ ++/* Primary interrupts */ ++#define TNETD73XX_INTC_UNIFIED_SECONDARY 0 /* Unified secondary interrupt */ ++#define TNETD73XX_INTC_EXTERNAL0 1 /* External Interrupt Line 0 */ ++#define TNETD73XX_INTC_EXTERNAL1 2 /* External Interrupt Line 1 */ ++#define TNETD73XX_INTC_RESERVED3 3 /* Reserved */ ++#define TNETD73XX_INTC_RESERVED4 4 /* Reserved */ ++#define TNETD73XX_INTC_TIMER0 5 /* TIMER 0 int */ ++#define TNETD73XX_INTC_TIMER1 6 /* TIMER 1 int */ ++#define TNETD73XX_INTC_UART0 7 /* UART 0 int */ ++#define TNETD73XX_INTC_UART1 8 /* UART 1 int */ ++#define TNETD73XX_INTC_MCDMA0 9 /* MCDMA 0 int */ ++#define TNETD73XX_INTC_MCDMA1 10 /* MCDMA 1 int */ ++#define TNETD73XX_INTC_RESERVED11 11 /* Reserved */ ++#define TNETD73XX_INTC_RESERVED12 12 /* Reserved */ ++#define TNETD73XX_INTC_RESERVED13 13 /* Reserved */ ++#define TNETD73XX_INTC_RESERVED14 14 /* Reserved */ ++#define TNETD73XX_INTC_ATMSAR 15 /* ATM SAR int */ ++#define TNETD73XX_INTC_RESERVED16 16 /* Reserved */ ++#define TNETD73XX_INTC_RESERVED17 17 /* Reserved */ ++#define TNETD73XX_INTC_RESERVED18 18 /* Reserved */ ++#define TNETD73XX_INTC_EMAC0 19 /* EMAC 0 int */ ++#define TNETD73XX_INTC_RESERVED20 20 /* Reserved */ ++#define TNETD73XX_INTC_VLYNQ0 21 /* VLYNQ 0 int */ ++#define TNETD73XX_INTC_CODEC 22 /* CODEC int */ ++#define TNETD73XX_INTC_RESERVED23 23 /* Reserved */ ++#define TNETD73XX_INTC_USBSLAVE 24 /* USB Slave int */ ++#define TNETD73XX_INTC_VLYNQ1 25 /* VLYNQ 1 int */ ++#define TNETD73XX_INTC_RESERVED26 26 /* Reserved */ ++#define TNETD73XX_INTC_RESERVED27 27 /* Reserved */ ++#define TNETD73XX_INTC_ETH_PHY 28 /* Ethernet PHY */ ++#define TNETD73XX_INTC_I2C 29 /* I2C int */ ++#define TNETD73XX_INTC_MCDMA2 30 /* MCDMA 2 int */ ++#define TNETD73XX_INTC_MCDMA3 31 /* MCDMA 3 int */ ++#define TNETD73XX_INTC_RESERVED32 32 /* Reserved */ ++#define TNETD73XX_INTC_EMAC1 33 /* EMAC 1 int */ ++#define TNETD73XX_INTC_RESERVED34 34 /* Reserved */ ++#define TNETD73XX_INTC_RESERVED35 35 /* Reserved */ ++#define TNETD73XX_INTC_RESERVED36 36 /* Reserved */ ++#define TNETD73XX_INTC_VDMAVTRX 37 /* VDMAVTRX */ ++#define TNETD73XX_INTC_VDMAVTTX 38 /* VDMAVTTX */ ++#define TNETD73XX_INTC_ADSLSS 39 /* ADSLSS */ ++ ++/* Secondary interrupts */ ++#define TNETD73XX_INTC_SEC0 40 /* Secondary */ ++#define TNETD73XX_INTC_SEC1 41 /* Secondary */ ++#define TNETD73XX_INTC_SEC2 42 /* Secondary */ ++#define TNETD73XX_INTC_SEC3 43 /* Secondary */ ++#define TNETD73XX_INTC_SEC4 44 /* Secondary */ ++#define TNETD73XX_INTC_SEC5 45 /* Secondary */ ++#define TNETD73XX_INTC_SEC6 46 /* Secondary */ ++#define TNETD73XX_INTC_EMIF 47 /* EMIF */ ++#define TNETD73XX_INTC_SEC8 48 /* Secondary */ ++#define TNETD73XX_INTC_SEC9 49 /* Secondary */ ++#define TNETD73XX_INTC_SEC10 50 /* Secondary */ ++#define TNETD73XX_INTC_SEC11 51 /* Secondary */ ++#define TNETD73XX_INTC_SEC12 52 /* Secondary */ ++#define TNETD73XX_INTC_SEC13 53 /* Secondary */ ++#define TNETD73XX_INTC_SEC14 54 /* Secondary */ ++#define TNETD73XX_INTC_SEC15 55 /* Secondary */ ++#define TNETD73XX_INTC_SEC16 56 /* Secondary */ ++#define TNETD73XX_INTC_SEC17 57 /* Secondary */ ++#define TNETD73XX_INTC_SEC18 58 /* Secondary */ ++#define TNETD73XX_INTC_SEC19 59 /* Secondary */ ++#define TNETD73XX_INTC_SEC20 60 /* Secondary */ ++#define TNETD73XX_INTC_SEC21 61 /* Secondary */ ++#define TNETD73XX_INTC_SEC22 62 /* Secondary */ ++#define TNETD73XX_INTC_SEC23 63 /* Secondary */ ++#define TNETD73XX_INTC_SEC24 64 /* Secondary */ ++#define TNETD73XX_INTC_SEC25 65 /* Secondary */ ++#define TNETD73XX_INTC_SEC26 66 /* Secondary */ ++#define TNETD73XX_INTC_SEC27 67 /* Secondary */ ++#define TNETD73XX_INTC_SEC28 68 /* Secondary */ ++#define TNETD73XX_INTC_SEC29 69 /* Secondary */ ++#define TNETD73XX_INTC_SEC30 70 /* Secondary */ ++#define TNETD73XX_INTC_SEC31 71 /* Secondary */ ++ ++/* These ugly macros are to access the -1 registers, like config1 */ ++#define MFC0_SEL1_OPCODE(dst, src)\ ++ .word (0x40000000 | ((dst)<<16) | ((src)<<11) | 1);\ ++ nop; \ ++ nop; \ ++ nop ++ ++#define MTC0_SEL1_OPCODE(dst, src)\ ++ .word (0x40800000 | ((dst)<<16) | ((src)<<11) | 1);\ ++ nop; \ ++ nop; \ ++ nop ++ ++ ++/* Below are Jade core specific */ ++#define CFG0_4K_IL_MASK 0x00380000 ++#define CFG0_4K_IL_SHIFT 19 ++#define CFG0_4K_IA_MASK 0x00070000 ++#define CFG0_4K_IA_SHIFT 16 ++#define CFG0_4K_IS_MASK 0x01c00000 ++#define CFG0_4K_IS_SHIFT 22 ++ ++#define CFG0_4K_DL_MASK 0x00001c00 ++#define CFG0_4K_DL_SHIFT 10 ++#define CFG0_4K_DA_MASK 0x00000380 ++#define CFG0_4K_DA_SHIFT 7 ++#define CFG0_4K_DS_MASK 0x0000E000 ++#define CFG0_4K_DS_SHIFT 13 ++ ++ ++ ++#endif /* __TNETD73XX_H_ */ +diff -urN linux.old/include/asm-mips/ar7/tnetd73xx_err.h linux.dev/include/asm-mips/ar7/tnetd73xx_err.h +--- linux.old/include/asm-mips/ar7/tnetd73xx_err.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/tnetd73xx_err.h 2005-11-10 01:10:46.075589000 +0100 +@@ -0,0 +1,42 @@ ++/****************************************************************************** ++ * FILE PURPOSE: TNETD73xx Error Definations Header File ++ ****************************************************************************** ++ * FILE NAME: tnetd73xx_err.h ++ * ++ * DESCRIPTION: Error definations for TNETD73XX ++ * ++ * REVISION HISTORY: ++ * 27 Nov 02 - PSP TII ++ * ++ * (C) Copyright 2002, Texas Instruments, Inc ++ *******************************************************************************/ ++ ++ ++#ifndef __TNETD73XX_ERR_H__ ++#define __TNETD73XX_ERR_H__ ++ ++typedef enum TNETD73XX_ERR_t ++{ ++ TNETD73XX_ERR_OK = 0, /* OK or SUCCESS */ ++ TNETD73XX_ERR_ERROR = -1, /* Unspecified/Generic ERROR */ ++ ++ /* Pointers and args */ ++ TNETD73XX_ERR_INVARG = -2, /* Invaild argument to the call */ ++ TNETD73XX_ERR_NULLPTR = -3, /* NULL pointer */ ++ TNETD73XX_ERR_BADPTR = -4, /* Bad (out of mem) pointer */ ++ ++ /* Memory issues */ ++ TNETD73XX_ERR_ALLOC_FAIL = -10, /* allocation failed */ ++ TNETD73XX_ERR_FREE_FAIL = -11, /* free failed */ ++ TNETD73XX_ERR_MEM_CORRUPT = -12, /* corrupted memory */ ++ TNETD73XX_ERR_BUF_LINK = -13, /* buffer linking failed */ ++ ++ /* Device issues */ ++ TNETD73XX_ERR_DEVICE_TIMEOUT = -20, /* device timeout on read/write */ ++ TNETD73XX_ERR_DEVICE_MALFUNC = -21, /* device malfunction */ ++ ++ TNETD73XX_ERR_INVID = -30 /* Invalid ID */ ++ ++} TNETD73XX_ERR; ++ ++#endif /* __TNETD73XX_ERR_H__ */ +diff -urN linux.old/include/asm-mips/ar7/tnetd73xx_misc.h linux.dev/include/asm-mips/ar7/tnetd73xx_misc.h +--- linux.old/include/asm-mips/ar7/tnetd73xx_misc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/tnetd73xx_misc.h 2005-11-10 01:10:46.075589000 +0100 +@@ -0,0 +1,239 @@ ++/****************************************************************************** ++ * FILE PURPOSE: TNETD73xx Misc modules API Header ++ ****************************************************************************** ++ * FILE NAME: tnetd73xx_misc.h ++ * ++ * DESCRIPTION: Clock Control, Reset Control, Power Management, GPIO ++ * FSER Modules API ++ * As per TNETD73xx specifications ++ * ++ * REVISION HISTORY: ++ * 27 Nov 02 - Sharath Kumar PSP TII ++ * 14 Feb 03 - Anant Gole PSP TII ++ * ++ * (C) Copyright 2002, Texas Instruments, Inc ++ *******************************************************************************/ ++ ++#ifndef __TNETD73XX_MISC_H__ ++#define __TNETD73XX_MISC_H__ ++ ++/***************************************************************************** ++ * Reset Control Module ++ *****************************************************************************/ ++ ++typedef enum TNETD73XX_RESET_MODULE_tag ++{ ++ RESET_MODULE_UART0 = 0, ++ RESET_MODULE_UART1 = 1, ++ RESET_MODULE_I2C = 2, ++ RESET_MODULE_TIMER0 = 3, ++ RESET_MODULE_TIMER1 = 4, ++ RESET_MODULE_GPIO = 6, ++ RESET_MODULE_ADSLSS = 7, ++ RESET_MODULE_USBS = 8, ++ RESET_MODULE_SAR = 9, ++ RESET_MODULE_VDMA_VT = 11, ++ RESET_MODULE_FSER = 12, ++ RESET_MODULE_VLYNQ1 = 16, ++ RESET_MODULE_EMAC0 = 17, ++ RESET_MODULE_DMA = 18, ++ RESET_MODULE_BIST = 19, ++ RESET_MODULE_VLYNQ0 = 20, ++ RESET_MODULE_EMAC1 = 21, ++ RESET_MODULE_MDIO = 22, ++ RESET_MODULE_ADSLSS_DSP = 23, ++ RESET_MODULE_EPHY = 26 ++} TNETD73XX_RESET_MODULE_T; ++ ++typedef enum TNETD73XX_RESET_CTRL_tag ++{ ++ IN_RESET = 0, ++ OUT_OF_RESET ++} TNETD73XX_RESET_CTRL_T; ++ ++typedef enum TNETD73XX_SYS_RST_MODE_tag ++{ ++ RESET_SOC_WITH_MEMCTRL = 1, /* SW0 bit in SWRCR register */ ++ RESET_SOC_WITHOUT_MEMCTRL = 2 /* SW1 bit in SWRCR register */ ++} TNETD73XX_SYS_RST_MODE_T; ++ ++typedef enum TNETD73XX_SYS_RESET_STATUS_tag ++{ ++ HARDWARE_RESET = 0, ++ SOFTWARE_RESET0, /* Caused by writing 1 to SW0 bit in SWRCR register */ ++ WATCHDOG_RESET, ++ SOFTWARE_RESET1 /* Caused by writing 1 to SW1 bit in SWRCR register */ ++} TNETD73XX_SYS_RESET_STATUS_T; ++ ++void tnetd73xx_reset_ctrl(TNETD73XX_RESET_MODULE_T reset_module, ++ TNETD73XX_RESET_CTRL_T reset_ctrl); ++TNETD73XX_RESET_CTRL_T tnetd73xx_get_reset_status(TNETD73XX_RESET_MODULE_T reset_module); ++void tnetd73xx_sys_reset(TNETD73XX_SYS_RST_MODE_T mode); ++TNETD73XX_SYS_RESET_STATUS_T tnetd73xx_get_sys_last_reset_status(void); ++ ++/***************************************************************************** ++ * Power Control Module ++ *****************************************************************************/ ++ ++typedef enum TNETD73XX_POWER_MODULE_tag ++{ ++ POWER_MODULE_USBSP = 0, ++ POWER_MODULE_WDTP = 1, ++ POWER_MODULE_UT0P = 2, ++ POWER_MODULE_UT1P = 3, ++ POWER_MODULE_IICP = 4, ++ POWER_MODULE_VDMAP = 5, ++ POWER_MODULE_GPIOP = 6, ++ POWER_MODULE_VLYNQ1P = 7, ++ POWER_MODULE_SARP = 8, ++ POWER_MODULE_ADSLP = 9, ++ POWER_MODULE_EMIFP = 10, ++ POWER_MODULE_ADSPP = 12, ++ POWER_MODULE_RAMP = 13, ++ POWER_MODULE_ROMP = 14, ++ POWER_MODULE_DMAP = 15, ++ POWER_MODULE_BISTP = 16, ++ POWER_MODULE_TIMER0P = 18, ++ POWER_MODULE_TIMER1P = 19, ++ POWER_MODULE_EMAC0P = 20, ++ POWER_MODULE_EMAC1P = 22, ++ POWER_MODULE_EPHYP = 24, ++ POWER_MODULE_VLYNQ0P = 27, ++} TNETD73XX_POWER_MODULE_T; ++ ++typedef enum TNETD73XX_POWER_CTRL_tag ++{ ++ POWER_CTRL_POWER_UP = 0, ++ POWER_CTRL_POWER_DOWN ++} TNETD73XX_POWER_CTRL_T; ++ ++typedef enum TNETD73XX_SYS_POWER_MODE_tag ++{ ++ GLOBAL_POWER_MODE_RUN = 0, /* All system is up */ ++ GLOBAL_POWER_MODE_IDLE, /* MIPS is power down, all peripherals working */ ++ GLOBAL_POWER_MODE_STANDBY, /* Chip in power down, but clock to ADSKL subsystem is running */ ++ GLOBAL_POWER_MODE_POWER_DOWN /* Total chip is powered down */ ++} TNETD73XX_SYS_POWER_MODE_T; ++ ++void tnetd73xx_power_ctrl(TNETD73XX_POWER_MODULE_T power_module, TNETD73XX_POWER_CTRL_T power_ctrl); ++TNETD73XX_POWER_CTRL_T tnetd73xx_get_pwr_status(TNETD73XX_POWER_MODULE_T power_module); ++void tnetd73xx_set_global_pwr_mode(TNETD73XX_SYS_POWER_MODE_T power_mode); ++TNETD73XX_SYS_POWER_MODE_T tnetd73xx_get_global_pwr_mode(void); ++ ++/***************************************************************************** ++ * Wakeup Control ++ *****************************************************************************/ ++ ++typedef enum TNETD73XX_WAKEUP_INTERRUPT_tag ++{ ++ WAKEUP_INT0 = 1, ++ WAKEUP_INT1 = 2, ++ WAKEUP_INT2 = 4, ++ WAKEUP_INT3 = 8 ++} TNETD73XX_WAKEUP_INTERRUPT_T; ++ ++typedef enum TNETD73XX_WAKEUP_CTRL_tag ++{ ++ WAKEUP_DISABLED = 0, ++ WAKEUP_ENABLED ++} TNETD73XX_WAKEUP_CTRL_T; ++ ++typedef enum TNETD73XX_WAKEUP_POLARITY_tag ++{ ++ WAKEUP_ACTIVE_HIGH = 0, ++ WAKEUP_ACTIVE_LOW ++} TNETD73XX_WAKEUP_POLARITY_T; ++ ++void tnetd73xx_wakeup_ctrl(TNETD73XX_WAKEUP_INTERRUPT_T wakeup_int, ++ TNETD73XX_WAKEUP_CTRL_T wakeup_ctrl, ++ TNETD73XX_WAKEUP_POLARITY_T wakeup_polarity); ++ ++/***************************************************************************** ++ * FSER Control ++ *****************************************************************************/ ++ ++typedef enum TNETD73XX_FSER_MODE_tag ++{ ++ FSER_I2C = 0, ++ FSER_UART = 1 ++} TNETD73XX_FSER_MODE_T; ++ ++void tnetd73xx_fser_ctrl(TNETD73XX_FSER_MODE_T fser_mode); ++ ++/***************************************************************************** ++ * Clock Control ++ *****************************************************************************/ ++ ++#define CLK_MHZ(x) ( (x) * 1000000 ) ++ ++typedef enum TNETD73XX_CLKC_ID_tag ++{ ++ CLKC_SYS = 0, ++ CLKC_MIPS, ++ CLKC_USB, ++ CLKC_ADSLSS ++} TNETD73XX_CLKC_ID_T; + -+/* device Addresses on I2C bus (EVM3) */ -+#define SEVEN_SEGMENT_DISP 0x23 /* Device type = 0x2, Addr = 3 */ -+#define EVM3_RTC 0xd0 /* Device type = 0xd, Addr = 0 */ -+#define EVM3_RTC_I2C_ADDR 0x0 ++void tnetd73xx_clkc_init(__u32 afeclk, __u32 refclk, __u32 xtal3in); ++TNETD73XX_ERR tnetd73xx_clkc_set_freq(TNETD73XX_CLKC_ID_T clk_id, __u32 output_freq); ++__u32 tnetd73xx_clkc_get_freq(TNETD73XX_CLKC_ID_T clk_id); + -+/*------------------------------------------*/ -+/* Ethernet MAC register offset definitions */ -+/*------------------------------------------*/ -+#define VMAC_DMACONFIG(X) (*(volatile unsigned int *)(X + 0x00000000)) -+#define VMAC_INTSTS(X) (*(volatile unsigned int *)(X + 0x00000004)) -+#define VMAC_INTMASK(X) (*(volatile unsigned int *)(X + 0x00000008)) ++/***************************************************************************** ++ * GPIO Control ++ *****************************************************************************/ + -+#define VMAC_WRAPCLK(X) (*(volatile unsigned int *)(X + 0x00000340)) -+#define VMAC_STATSBASE(X) (*(volatile unsigned int *)(X + 0x00000400)) -+ -+#define VMAC_TCRPTR(X) (*(volatile unsigned int *)(X + 0x00000100)) -+#define VMAC_TCRSIZE(X) (*(volatile unsigned int *)(X + 0x00000104)) -+#define VMAC_TCRINTTHRESH(X) (*(volatile unsigned int *)(X + 0x00000108)) -+#define VMAC_TCRTOTENT(X) (*(volatile unsigned int *)(X + 0x0000010C)) -+#define VMAC_TCRFREEENT(X) (*(volatile unsigned int *)(X + 0x00000110)) -+#define VMAC_TCRPENDENT(X) (*(volatile unsigned int *)(X + 0x00000114)) -+#define VMAC_TCRENTINC(X) (*(volatile unsigned int *)(X + 0x00000118)) -+#define VMAC_TXISRPACE(X) (*(volatile unsigned int *)(X + 0x0000011c)) ++typedef enum TNETD73XX_GPIO_PIN_tag ++{ ++ GPIO_UART0_RD = 0, ++ GPIO_UART0_TD = 1, ++ GPIO_UART0_RTS = 2, ++ GPIO_UART0_CTS = 3, ++ GPIO_FSER_CLK = 4, ++ GPIO_FSER_D = 5, ++ GPIO_EXT_AFE_SCLK = 6, ++ GPIO_EXT_AFE_TX_FS = 7, ++ GPIO_EXT_AFE_TXD = 8, ++ GPIO_EXT_AFE_RS_FS = 9, ++ GPIO_EXT_AFE_RXD1 = 10, ++ GPIO_EXT_AFE_RXD0 = 11, ++ GPIO_EXT_AFE_CDIN = 12, ++ GPIO_EXT_AFE_CDOUT = 13, ++ GPIO_EPHY_SPEED100 = 14, ++ GPIO_EPHY_LINKON = 15, ++ GPIO_EPHY_ACTIVITY = 16, ++ GPIO_EPHY_FDUPLEX = 17, ++ GPIO_EINT0 = 18, ++ GPIO_EINT1 = 19, ++ GPIO_MBSP0_TCLK = 20, ++ GPIO_MBSP0_RCLK = 21, ++ GPIO_MBSP0_RD = 22, ++ GPIO_MBSP0_TD = 23, ++ GPIO_MBSP0_RFS = 24, ++ GPIO_MBSP0_TFS = 25, ++ GPIO_MII_DIO = 26, ++ GPIO_MII_DCLK = 27, ++} TNETD73XX_GPIO_PIN_T; + ++typedef enum TNETD73XX_GPIO_PIN_MODE_tag ++{ ++ FUNCTIONAL_PIN = 0, ++ GPIO_PIN = 1 ++} TNETD73XX_GPIO_PIN_MODE_T; + -+#define VMAC_TDMASTATE0(X) (*(volatile unsigned int *)(X + 0x00000120)) -+#define VMAC_TDMASTATE1(X) (*(volatile unsigned int *)(X + 0x00000124)) -+#define VMAC_TDMASTATE2(X) (*(volatile unsigned int *)(X + 0x00000128)) -+#define VMAC_TDMASTATE3(X) (*(volatile unsigned int *)(X + 0x0000012C)) -+#define VMAC_TDMASTATE4(X) (*(volatile unsigned int *)(X + 0x00000130)) -+#define VMAC_TDMASTATE5(X) (*(volatile unsigned int *)(X + 0x00000134)) -+#define VMAC_TDMASTATE6(X) (*(volatile unsigned int *)(X + 0x00000138)) -+#define VMAC_TDMASTATE7(X) (*(volatile unsigned int *)(X + 0x0000013C)) -+#define VMAC_TXPADDCNT(X) (*(volatile unsigned int *)(X + 0x00000140)) -+#define VMAC_TXPADDSTART(X) (*(volatile unsigned int *)(X + 0x00000144)) -+#define VMAC_TXPADDEND(X) (*(volatile unsigned int *)(X + 0x00000148)) -+#define VMAC_TXQFLUSH(X) (*(volatile unsigned int *)(X + 0x0000014C)) ++typedef enum TNETD73XX_GPIO_PIN_DIRECTION_tag ++{ ++ GPIO_OUTPUT_PIN = 0, ++ GPIO_INPUT_PIN = 1 ++} TNETD73XX_GPIO_PIN_DIRECTION_T; + -+#define VMAC_RCRPTR(X) (*(volatile unsigned int *)(X + 0x00000200)) -+#define VMAC_RCRSIZE(X) (*(volatile unsigned int *)(X + 0x00000204)) -+#define VMAC_RCRINTTHRESH(X) (*(volatile unsigned int *)(X + 0x00000208)) -+#define VMAC_RCRTOTENT(X) (*(volatile unsigned int *)(X + 0x0000020C)) -+#define VMAC_RCRFREEENT(X) (*(volatile unsigned int *)(X + 0x00000210)) -+#define VMAC_RCRPENDENT(X) (*(volatile unsigned int *)(X + 0x00000214)) -+#define VMAC_RCRENTINC(X) (*(volatile unsigned int *)(X + 0x00000218)) -+#define VMAC_RXISRPACE(X) (*(volatile unsigned int *)(X + 0x0000021c)) ++void tnetd73xx_gpio_init(void); ++void tnetd73xx_gpio_ctrl(TNETD73XX_GPIO_PIN_T gpio_pin, ++ TNETD73XX_GPIO_PIN_MODE_T pin_mode, ++ TNETD73XX_GPIO_PIN_DIRECTION_T pin_direction); ++void tnetd73xx_gpio_out(TNETD73XX_GPIO_PIN_T gpio_pin, int value); ++int tnetd73xx_gpio_in(TNETD73XX_GPIO_PIN_T gpio_pin); + -+#define VMAC_RDMASTATE0(X) (*(volatile unsigned int *)(X + 0x00000220)) -+#define VMAC_RDMASTATE1(X) (*(volatile unsigned int *)(X + 0x00000224)) -+#define VMAC_RDMASTATE2(X) (*(volatile unsigned int *)(X + 0x00000228)) -+#define VMAC_RDMASTATE3(X) (*(volatile unsigned int *)(X + 0x0000022C)) -+#define VMAC_RDMASTATE4(X) (*(volatile unsigned int *)(X + 0x00000230)) -+#define VMAC_RDMASTATE5(X) (*(volatile unsigned int *)(X + 0x00000234)) -+#define VMAC_RDMASTATE6(X) (*(volatile unsigned int *)(X + 0x00000238)) -+#define VMAC_RDMASTATE7(X) (*(volatile unsigned int *)(X + 0x0000023C)) -+#define VMAC_FBLADDCNT(X) (*(volatile unsigned int *)(X + 0x00000240)) -+#define VMAC_FBLADDSTART(X) (*(volatile unsigned int *)(X + 0x00000244)) -+#define VMAC_FBLADDEND(X) (*(volatile unsigned int *)(X + 0x00000248)) -+#define VMAC_RXONOFF(X) (*(volatile unsigned int *)(X + 0x0000024C)) -+ -+#define VMAC_FBL0NEXTD(X) (*(volatile unsigned int *)(X + 0x00000280)) -+#define VMAC_FBL0LASTD(X) (*(volatile unsigned int *)(X + 0x00000284)) -+#define VMAC_FBL0COUNTD(X) (*(volatile unsigned int *)(X + 0x00000288)) -+#define VMAC_FBL0BUFSIZE(X) (*(volatile unsigned int *)(X + 0x0000028C)) -+ -+#define VMAC_MACCONTROL(X) (*(volatile unsigned int *)(X + 0x00000300)) -+#define VMAC_MACSTATUS(X) (*(volatile unsigned int *)(X + 0x00000304)) -+#define VMAC_MACADDRHI(X) (*(volatile unsigned int *)(X + 0x00000308)) -+#define VMAC_MACADDRLO(X) (*(volatile unsigned int *)(X + 0x0000030C)) -+#define VMAC_MACHASH1(X) (*(volatile unsigned int *)(X + 0x00000310)) -+#define VMAC_MACHASH2(X) (*(volatile unsigned int *)(X + 0x00000314)) -+ -+#define VMAC_WRAPCLK(X) (*(volatile unsigned int *)(X + 0x00000340)) -+#define VMAC_BOFTEST(X) (*(volatile unsigned int *)(X + 0x00000344)) -+#define VMAC_PACTEST(X) (*(volatile unsigned int *)(X + 0x00000348)) -+#define VMAC_PAUSEOP(X) (*(volatile unsigned int *)(X + 0x0000034C)) -+ -+#define VMAC_MDIOCONTROL(X) (*(volatile unsigned int *)(X + 0x00000380)) -+#define VMAC_MDIOUSERACCESS(X) (*(volatile unsigned int *)(X +0x00000384)) -+#define VMAC_MDIOACK(X) (*(volatile unsigned int *)(X + 0x00000388)) -+#define VMAC_MDIOLINK(X) (*(volatile unsigned int *)(X + 0x0000038C)) -+#define VMAC_MDIOMACPHY(X) (*(volatile unsigned int *)(X + 0x00000390)) ++/* TNETD73XX Revision */ ++__u32 tnetd73xx_get_revision(void); + -+#define VMAC_STATS_BASE(X) (X + 0x00000400) ++#endif /* __TNETD73XX_MISC_H__ */ +diff -urN linux.old/include/asm-mips/ar7/vlynq.h linux.dev/include/asm-mips/ar7/vlynq.h +--- linux.old/include/asm-mips/ar7/vlynq.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/vlynq.h 2005-11-10 01:10:46.095590250 +0100 +@@ -0,0 +1,610 @@ ++/*************************************************************************** ++**+----------------------------------------------------------------------+** ++**| **** |** ++**| **** |** ++**| ******o*** |** ++**| ********_///_**** |** ++**| ***** /_//_/ **** |** ++**| ** ** (__/ **** |** ++**| ********* |** ++**| **** |** ++**| *** |** ++**| |** ++**| Copyright (c) 2003 Texas Instruments Incorporated |** ++**| ALL RIGHTS RESERVED |** ++**| |** ++**| Permission is hereby granted to licensees of Texas Instruments |** ++**| Incorporated (TI) products to use this computer program for the sole |** ++**| purpose of implementing a licensee product based on TI products. |** ++**| No other rights to reproduce, use, or disseminate this computer |** ++**| program, whether in part or in whole, are granted. |** ++**| |** ++**| TI makes no representation or warranties with respect to the |** ++**| performance of this computer program, and specifically disclaims |** ++**| any responsibility for any damages, special or consequential, |** ++**| connected with the use of this program. |** ++**| |** ++**+----------------------------------------------------------------------+** ++***************************************************************************/ ++ ++/********************************************************************************* ++ * ------------------------------------------------------------------------------ ++ * Module : vlynq_hal.h ++ * Description : ++ * This header file provides the set of functions exported by the ++ * VLYNQ HAL. This file is included from the SOC specific VLYNQ driver wrapper. ++ * ------------------------------------------------------------------------------ ++ *********************************************************************************/ ++ ++#ifndef _VLYNQ_HAL_H_ ++#define _VLYNQ_HAL_H_ ++ ++/* Enable/Disable debug feature */ ++#undef VLYNQ_DEBUG ++ ++#ifdef VLYNQ_DEBUG /* This needs to be OS abstracted - for testing use vxworks/linux calls */ ++#define debugPrint(format,args...) ++#else ++#define debugPrint(format,args...) ++#endif + -+#endif __AVALANCHE_REGS_H ++ /* number of VLYNQ memory regions supported */ ++#define VLYNQ_MAX_MEMORY_REGIONS 0x04 ++ ++ /* Max.number of external interrupt inputs supported by VLYNQ module */ ++#define VLYNQ_IVR_MAXIVR 0x08 + ++#define VLYNQ_CLK_DIV_MAX 0x08 ++#define VLYNQ_CLK_DIV_MIN 0x01 + + ++/*** the total number of entries allocated for ICB would be ++ * 32(for 32 bits in IntPending register) + VLYNQ_IVR_CHAIN_SLOTS*/ ++#define VLYNQ_IVR_CHAIN_SLOTS 10 + + ++/* Error defines */ ++#define VLYNQ_SUCCESS 0 + -diff -urN kernel-base/include/asm-mips/ar7/if_port.h kernel-current/include/asm-mips/ar7/if_port.h ---- kernel-base/include/asm-mips/ar7/if_port.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/if_port.h 2005-07-10 06:40:39.623260936 +0200 -@@ -0,0 +1,26 @@ -+/******************************************************************************* -+ * FILE PURPOSE: Interface port id Header file -+ ******************************************************************************* -+ * FILE NAME: if_port.h -+ * -+ * DESCRIPTION: Header file carrying information about port ids of interfaces -+ * -+ * -+ * (C) Copyright 2003, Texas Instruments, Inc -+ ******************************************************************************/ -+#ifndef _IF_PORT_H_ -+#define _IF_PORT_H_ ++#define VLYNQ_ERRCODE_BASE 0 /* Chosen by system */ ++#define VLYNQ_INVALID_ARG -(VLYNQ_ERRCODE_BASE+1) ++#define VLYNQ_INVALID_DRV_STATE -(VLYNQ_ERRCODE_BASE+2) ++#define VLYNQ_INT_CONFIG_ERR -(VLYNQ_ERRCODE_BASE+3) ++#define VLYNQ_LINK_DOWN -(VLYNQ_ERRCODE_BASE+4) ++#define VLYNQ_MEMALLOC_FAIL -(VLYNQ_ERRCODE_BASE+5) ++#define VLYNQ_ISR_NON_EXISTENT -(VLYNQ_ERRCODE_BASE+6) ++#define VLYNQ_INTVEC_MAP_NOT_FOUND -(VLYNQ_ERRCODE_BASE+7) + -+#define AVALANCHE_CPMAC_LOW_PORT_ID 0 -+#define AVALANCHE_CPMAC_HIGH_PORT_ID 1 -+#define AVALANCHE_USB_PORT_ID 2 -+#define AVALANCHE_WLAN_PORT_ID 3 ++/* Vlynq Defines and Macros */ + ++#define VLYNQ_NUM_INT_BITS 32 /* 32 bit interrupt staus register */ + -+#define AVALANCHE_MARVELL_BASE_PORT_ID 4 ++/* Base address of module */ ++#define VLYNQ_BASE (pdev->module_base) + -+/* The marvell ports occupy port ids from 4 to 8 */ -+/* so the next port id number should start at 9 */ ++#define VLYNQ_REMOTE_REGS_OFFSET 0x0080 + ++#define VLYNQ_REV_OFFSET 0x0000 ++#define VLYNQ_CTRL_OFFSET 0x0004 ++#define VLYNQ_STATUS_OFFSET 0x0008 ++#define VLYNQ_INT_STAT_OFFSET 0x0010 ++#define VLYNQ_INT_PEND_OFFSET 0x0014 ++#define VLYNQ_INT_PTR_OFFSET 0x0018 ++#define VLYNQ_TXMAP_OFFSET 0x001c + -+#endif /* _IF_PORT_H_ */ -diff -urN kernel-base/include/asm-mips/ar7/ledapp.h kernel-current/include/asm-mips/ar7/ledapp.h ---- kernel-base/include/asm-mips/ar7/ledapp.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/ledapp.h 2005-07-10 08:26:11.663644480 +0200 -@@ -0,0 +1,59 @@ -+#ifndef __LED_APP__ -+#define __LED_APP__ -+ -+#define CONF_FILE "/etc/led.conf" -+#define LED_PROC_FILE "/proc/led_mod/led" -+ -+#define CONFIG_LED_MODULE -+ -+#define MAX_MOD_ID 25 -+#define MAX_STATE_ID 25 -+#define MAX_LED_ID 25 -+ -+#define MOD_ADSL 1 -+#define DEF_ADSL_IDLE 1 -+#define DEF_ADSL_TRAINING 2 -+#define DEF_ADSL_SYNC 3 -+#define DEF_ADSL_ACTIVITY 4 -+ -+#define MOD_WAN 2 -+#define DEF_WAN_IDLE 1 -+#define DEF_WAN_NEGOTIATE 2 -+#define DEF_WAN_SESSION 3 -+ -+#define MOD_LAN 3 -+#define DEF_LAN_IDLE 1 -+#define DEF_LAN_LINK_UP 2 -+#define DEF_LAN_ACTIVITY 3 -+ -+#define MOD_WLAN 4 -+#define DEF_WLAN_IDLE 1 -+#define DEF_WLAN_LINK_UP 2 -+#define DEF_WLAN_ACTIVITY 3 -+ -+#define MOD_USB 5 -+#define DEF_USB_IDLE 1 -+#define DEF_USB_LINK_UP 2 -+#define DEF_USB_ACTIVITY 3 -+ -+#define MOD_ETH 6 -+#define DEF_ETH_IDLE 1 -+#define DEF_ETH_LINK_UP 2 -+#define DEF_ETH_ACTIVITY 3 -+ -+typedef struct config_elem{ -+ unsigned char name; -+ unsigned char state; -+ unsigned char mode; -+ unsigned char led; -+ int param; -+}config_elem_t; -+ -+typedef struct led_reg{ -+ unsigned int param; -+ void (*init)(unsigned long param); -+ void (*onfunc)(unsigned long param); -+ void (*offfunc)(unsigned long param); -+}led_reg_t; -+ -+#endif -diff -urN kernel-base/include/asm-mips/ar7/sangam_boards.h kernel-current/include/asm-mips/ar7/sangam_boards.h ---- kernel-base/include/asm-mips/ar7/sangam_boards.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/sangam_boards.h 2005-07-10 06:40:39.623260936 +0200 -@@ -0,0 +1,77 @@ -+#ifndef _SANGAM_BOARDS_H -+#define _SANGAM_BOARDS_H ++#define VLYNQ_RX0MAP_SIZE_REG_OFFSET 0x0020 ++#define VLYNQ_RX0MAP_OFFSET_REG_OFFSET 0x0024 + -+// Let us define board specific information here. ++#define VLYNQ_CHIP_VER_OFFSET 0x0040 ++#define VLYNQ_IVR_REGS_OFFSET 0x0060 + ++#define VLYNQ_INT_PENDING_REG_PTR 0x14 ++#define VLYNQ_R_INT_PENDING_REG_PTR VLYNQ_REMOTE_REGS_OFFSET + 0x14 + -+#if defined(CONFIG_AR7DB) ++#define VLYNQ_REV_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_REV_OFFSET)) ++#define VLYNQ_CTRL_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_CTRL_OFFSET)) ++#define VLYNQ_STATUS_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_STATUS_OFFSET)) ++#define VLYNQ_INT_STAT_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_INT_STAT_OFFSET)) ++#define VLYNQ_INT_PEND_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_INT_PEND_OFFSET)) ++#define VLYNQ_INT_PTR_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_INT_PTR_OFFSET)) ++#define VLYNQ_TXMAP_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_TXMAP_OFFSET)) + -+#define AFECLK_FREQ 35328000 -+#define REFCLK_FREQ 25000000 -+#define OSC3_FREQ 24000000 -+#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 -+#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x55555555 -+#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 ++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/ ++#define VLYNQ_RXMAP_SIZE_REG(map) \ ++ *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_RX0MAP_SIZE_REG_OFFSET+( (map-1)<<3))) ++ ++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/ ++#define VLYNQ_RXMAP_OFFSET_REG(map) \ ++ *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_RX0MAP_OFFSET_REG_OFFSET+( (map-1)<<3))) + -+#endif ++#define VLYNQ_CHIP_VER_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_CHIP_VER_OFFSET)) + ++/* 0 =< ivr <= 31; currently ivr < VLYNQ_IVR_MAXIVR=8) */ ++#define VLYNQ_IVR_OFFSET(ivr) \ ++ (VLYNQ_BASE + VLYNQ_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3) ) + -+#if defined(CONFIG_AR7RD) -+#define AFECLK_FREQ 35328000 -+#define REFCLK_FREQ 25000000 -+#define OSC3_FREQ 24000000 -+#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 -+#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x2 -+#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 -+#endif ++#define VLYNQ_IVR_03TO00_REG *((volatile unsigned int*) (VLYNQ_IVR_OFFSET(0)) ) ++#define VLYNQ_IVR_07TO04_REG *((volatile unsigned int*) (VLYNQ_IVR_OFFSET(4)) ) ++/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/ + ++#define VLYNQ_IVR_INTEN(ivr) (((unsigned int)(0x80)) << ((((unsigned)(ivr)) % 4) * 8)) ++#define VLYNQ_IVR_INTTYPE(ivr) (((unsigned int)(0x40)) << ((((unsigned)(ivr)) % 4) * 8)) ++#define VLYNQ_IVR_INTPOL(ivr) (((unsigned int)(0x20)) << ((((unsigned)(ivr)) % 4) * 8)) ++#define VLYNQ_IVR_INTVEC(ivr) (((unsigned int)(0x1F)) << ((((unsigned)(ivr)) % 4) * 8)) ++#define VLYNQ_IVR_INTALL(ivr) (((unsigned int)(0xFF)) << ((((unsigned)(ivr)) % 4) * 8)) + -+#if defined(CONFIG_AR7WI) -+#define AFECLK_FREQ 35328000 -+#define REFCLK_FREQ 25000000 -+#define OSC3_FREQ 24000000 -+#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 -+#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x2 -+#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 -+#endif + + -+#if defined(CONFIG_AR7V) -+#define AFECLK_FREQ 35328000 -+#define REFCLK_FREQ 25000000 -+#define OSC3_FREQ 24000000 -+#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 -+#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x2 -+#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 -+#endif ++/********************************* ++ * Remote VLYNQ register set * ++ *********************************/ + ++#define VLYNQ_R_REV_OFFSET 0x0080 ++#define VLYNQ_R_CTRL_OFFSET 0x0084 ++#define VLYNQ_R_STATUS_OFFSET 0x0088 ++#define VLYNQ_R_INT_STAT_OFFSET 0x0090 ++#define VLYNQ_R_INT_PEND_OFFSET 0x0094 ++#define VLYNQ_R_INT_PTR_OFFSET 0x0098 ++#define VLYNQ_R_TXMAP_OFFSET 0x009c + -+#if defined(CONFIG_AR7WRD) -+#define AFECLK_FREQ 35328000 -+#define REFCLK_FREQ 25000000 -+#define OSC3_FREQ 24000000 -+#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 -+#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x00010000 -+#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 -+#endif ++#define VLYNQ_R_RX0MAP_SIZE_REG_OFFSET 0x00A0 ++#define VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET 0x00A4 + ++#define VLYNQ_R_CHIP_VER_OFFSET 0x00C0 ++#define VLYNQ_R_IVR_REGS_OFFSET 0x00E0 + -+#if defined(CONFIG_AR7VWI) -+#define AFECLK_FREQ 35328000 -+#define REFCLK_FREQ 25000000 -+#define OSC3_FREQ 24000000 -+#define AVALANCHE_LOW_CPMAC_PHY_MASK 0x80000000 -+#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x00010000 -+#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0x80000000 -+#endif ++#define VLYNQ_R_REV_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_REV_OFFSET)) ++#define VLYNQ_R_CTRL_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_CTRL_OFFSET)) ++#define VLYNQ_R_STATUS_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_STATUS_OFFSET)) ++#define VLYNQ_R_INT_STAT_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_INT_STAT_OFFSET)) ++#define VLYNQ_R_INT_PEND_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_INT_PEND_OFFSET)) ++#define VLYNQ_R_INT_PTR_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_INT_PTR_OFFSET)) ++#define VLYNQ_R_TXMAP_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_TXMAP_OFFSET)) + ++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/ ++#define VLYNQ_R_RXMAP_SIZE_REG(map) \ ++ *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_SIZE_REG_OFFSET + ((map-1)<<3))) ++ ++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/ ++#define VLYNQ_R_RXMAP_OFFSET_REG(map) \ ++ *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET + ((map-1)<<3))) + -+#if defined CONFIG_SEAD2 -+#define AVALANCHE_LOW_CPMAC_PHY_MASK 0xAAAAAAAA -+#define AVALANCHE_HIGH_CPMAC_PHY_MASK 0x55555555 -+#define AVALANCHE_LOW_CPMAC_MDIX_MASK 0 -+#include -+#endif ++#define VLYNQ_R_CHIP_VER_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_CHIP_VER_OFFSET) + ++#define VLYNQ_R_IVR_OFFSET(ivr) \ ++ (VLYNQ_BASE + VLYNQ_R_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3)) ++ + -+#endif -diff -urN kernel-base/include/asm-mips/ar7/sangam.h kernel-current/include/asm-mips/ar7/sangam.h ---- kernel-base/include/asm-mips/ar7/sangam.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/sangam.h 2005-07-10 06:40:39.624260784 +0200 -@@ -0,0 +1,180 @@ -+#ifndef _SANGAM_H_ -+#define _SANGAM_H_ ++/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/ ++#define VLYNQ_R_IVR_03TO00_REG *((volatile unsigned int*) (VLYNQ_R_IVR_OFFSET(0)) ) ++#define VLYNQ_R_IVR_07TO04_REG *((volatile unsigned int*) (VLYNQ_R_IVR_OFFSET(4)) ) + -+#include -+#include + -+/*---------------------------------------------------- -+ * Sangam's Module Base Addresses -+ *--------------------------------------------------*/ -+#define AVALANCHE_ADSL_SUB_SYS_MEM_BASE (KSEG1ADDR(0x01000000)) /* AVALANCHE ADSL Mem Base */ -+#define AVALANCHE_BROADBAND_INTERFACE__BASE (KSEG1ADDR(0x02000000)) /* AVALANCHE BBIF */ -+#define AVALANCHE_ATM_SAR_BASE (KSEG1ADDR(0x03000000)) /* AVALANCHE ATM SAR */ -+#define AVALANCHE_USB_SLAVE_BASE (KSEG1ADDR(0x03400000)) /* AVALANCHE USB SLAVE */ -+#define AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE (KSEG1ADDR(0x04000000)) /* AVALANCHE VLYNQ 0 Mem map */ -+#define AVALANCHE_LOW_CPMAC_BASE (KSEG1ADDR(0x08610000)) /* AVALANCHE CPMAC 0 */ -+#define AVALANCHE_EMIF_CONTROL_BASE (KSEG1ADDR(0x08610800)) /* AVALANCHE EMIF */ -+#define AVALANCHE_GPIO_BASE (KSEG1ADDR(0x08610900)) /* AVALANCHE GPIO */ -+#define AVALANCHE_CLOCK_CONTROL_BASE (KSEG1ADDR(0x08610A00)) /* AVALANCHE Clock Control */ -+#define AVALANCHE_WATCHDOG_TIMER_BASE (KSEG1ADDR(0x08610B00)) /* AVALANCHE Watch Dog Timer */ -+#define AVALANCHE_TIMER0_BASE (KSEG1ADDR(0x08610C00)) /* AVALANCHE Timer 1 */ -+#define AVALANCHE_TIMER1_BASE (KSEG1ADDR(0x08610D00)) /* AVALANCHE Timer 2 */ -+#define AVALANCHE_UART0_REGS_BASE (KSEG1ADDR(0x08610E00)) /* AVALANCHE UART 0 */ -+#define AVALANCHE_UART1_REGS_BASE (KSEG1ADDR(0x08610F00)) /* AVALANCHE UART 0 */ -+#define AVALANCHE_I2C_BASE (KSEG1ADDR(0x08611000)) /* AVALANCHE I2C */ -+#define AVALANCHE_USB_SLAVE_CONTROL_BASE (KSEG1ADDR(0x08611200)) /* AVALANCHE USB DMA */ -+#define AVALANCHE_MCDMA0_CTRL_BASE (KSEG1ADDR(0x08611400)) /* AVALANCHE MC DMA 0 (channels 0-3) */ -+#define AVALANCHE_RESET_CONTROL_BASE (KSEG1ADDR(0x08611600)) /* AVALANCHE Reset Control */ -+#define AVALANCHE_BIST_CONTROL_BASE (KSEG1ADDR(0x08611700)) /* AVALANCHE BIST Control */ -+#define AVALANCHE_LOW_VLYNQ_CONTROL_BASE (KSEG1ADDR(0x08611800)) /* AVALANCHE VLYNQ0 Control */ -+#define AVALANCHE_DEVICE_CONFIG_LATCH_BASE (KSEG1ADDR(0x08611A00)) /* AVALANCHE Device Config Latch */ -+#define AVALANCHE_HIGH_VLYNQ_CONTROL_BASE (KSEG1ADDR(0x08611C00)) /* AVALANCHE VLYNQ1 Control */ -+#define AVALANCHE_MDIO_BASE (KSEG1ADDR(0x08611E00)) /* AVALANCHE MDIO */ -+#define AVALANCHE_FSER_BASE (KSEG1ADDR(0x08612000)) /* AVALANCHE FSER base */ -+#define AVALANCHE_INTC_BASE (KSEG1ADDR(0x08612400)) /* AVALANCHE INTC */ -+#define AVALANCHE_HIGH_CPMAC_BASE (KSEG1ADDR(0x08612800)) /* AVALANCHE CPMAC 1 */ -+#define AVALANCHE_HIGH_VLYNQ_MEM_MAP_BASE (KSEG1ADDR(0x0C000000)) /* AVALANCHE VLYNQ 1 Mem map */ ++/****End of remote register set definition******/ ++ + -+#define AVALANCHE_SDRAM_BASE 0x14000000UL ++/*** Masks for individual register fields ***/ + ++#define VLYNQ_MODULE_ID_MASK 0xffff0000 ++#define VLYNQ_MAJOR_REV_MASK 0x0000ff00 ++#define VLYNQ_MINOR_REV_MASK 0x000000ff + -+/*---------------------------------------------------- -+ * Sangam Interrupt Map (Primary Interrupts) -+ *--------------------------------------------------*/ ++ ++#define VLYNQ_CTL_ILOOP_MASK 0x00000002 ++#define VLYNQ_CTL_INT2CFG_MASK 0x00000080 ++#define VLYNQ_CTL_INTVEC_MASK 0x00001f00 ++#define VLYNQ_CTL_INTEN_MASK 0x00002000 ++#define VLYNQ_CTL_INTLOCAL_MASK 0x00004000 ++#define VLYNQ_CTL_CLKDIR_MASK 0x00008000 ++#define VLYNQ_CTL_CLKDIV_MASK 0x00070000 ++#define VLYNQ_CTL_MODE_MASK 0x00e00000 ++ ++ ++#define VLYNQ_STS_LINK_MASK 0x00000001 /* Link is active */ ++#define VLYNQ_STS_MPEND_MASK 0x00000002 /* Pending master requests */ ++#define VLYNQ_STS_SPEND_MASK 0x00000004 /* Pending slave requests */ ++#define VLYNQ_STS_NFEMPTY0_MASK 0x00000008 /* Master data FIFO not empty */ ++#define VLYNQ_STS_NFEMPTY1_MASK 0x00000010 /* Master command FIFO not empty */ ++#define VLYNQ_STS_NFEMPTY2_MASK 0x00000020 /* Slave data FIFO not empty */ ++#define VLYNQ_STS_NFEMPTY3_MASK 0x00000040 /* Slave command FIFO not empty */ ++#define VLYNQ_STS_LERROR_MASK 0x00000080 /* Local error, w/c */ ++#define VLYNQ_STS_RERROR_MASK 0x00000100 /* remote error w/c */ ++#define VLYNQ_STS_OFLOW_MASK 0x00000200 ++#define VLYNQ_STS_IFLOW_MASK 0x00000400 ++#define VLYNQ_STS_MODESUP_MASK 0x00E00000 /* Highest mode supported */ ++#define VLYNQ_STS_SWIDTH_MASK 0x07000000 /* Used for reading the width of VLYNQ bus */ ++#define VLYNQ_STS_DEBUG_MASK 0xE0000000 ++ ++#define VLYNQ_CTL_INTVEC_SHIFT 0x08 ++#define VLYNQ_CTL_INTEN_SHIFT 0x0D ++#define VLYNQ_CTL_INT2CFG_SHIFT 0x07 ++#define VLYNQ_CTL_INTLOCAL_SHIFT 0x0E ++ ++#define VLYNQ_CTL_INTFIELDS_CLEAR_MASK 0x7F80 ++ ++#define VLYNQ_CHIPVER_DEVREV_MASK 0xffff0000 ++#define VLYNQ_CHIPVER_DEVID_MASK 0x0000ffff ++ ++#define VLYNQ_IVR_INTEN_MASK 0x80 ++#define VLYNQ_IVR_INTTYPE_MASK 0x40 ++#define VLYNQ_IVR_INTPOL_MASK 0x20 ++ ++ ++/**** Helper macros ****/ ++ ++#define VLYNQ_RESETCB(arg) \ ++ if( pdev->reset_cb != NULL) \ ++ { \ ++ (pdev->reset_cb)(pdev, (arg)); \ ++ } ++ ++#define VLYNQ_STATUS_FLD_WIDTH(sts) (((sts) & VLYNQ_STS_SWIDTH_MASK) >> 24 ) ++#define VLYNQ_CTL_INTVEC(x) (((x) & 31) << 8 ) + -+#define AVALANCHE_UNIFIED_SECONDARY_INT 0 -+#define AVALANCHE_EXT_INT_0 1 -+#define AVALANCHE_EXT_INT_1 2 -+/* Line# 3 to 4 are reserved */ -+#define AVALANCHE_TIMER_0_INT 5 -+#define AVALANCHE_TIMER_1_INT 6 -+#define AVALANCHE_UART0_INT 7 -+#define AVALANCHE_UART1_INT 8 -+#define AVALANCHE_DMA_INT0 9 -+#define AVALANCHE_DMA_INT1 10 -+/* Line# 11 to 14 are reserved */ -+#define AVALANCHE_ATM_SAR_INT 15 -+/* Line# 16 to 18 are reserved */ -+#define AVALANCHE_LOW_CPMAC_INT 19 -+/* Line# 20 is reserved */ -+#define AVALANCHE_LOW_VLYNQ_INT 21 -+#define AVALANCHE_CODEC_WAKEUP_INT 22 -+/* Line# 23 is reserved */ -+#define AVALANCHE_USB_SLAVE_INT 24 -+#define AVALANCHE_HIGH_VLYNQ_INT 25 -+/* Line# 26 to 27 are reserved */ -+#define AVALANCHE_UNIFIED_PHY_INT 28 -+#define AVALANCHE_I2C_INT 29 -+#define AVALANCHE_DMA_INT2 30 -+#define AVALANCHE_DMA_INT3 31 -+/* Line# 32 is reserved */ -+#define AVALANCHE_HIGH_CPMAC_INT 33 -+/* Line# 34 to 36 is reserved */ -+#define AVALANCHE_VDMA_VT_RX_INT 37 -+#define AVALANCHE_VDMA_VT_TX_INT 38 -+#define AVALANCHE_ADSL_SUB_SYSTEM_INT 39 ++#define VLYNQ_INRANGE(x,hi,lo) (((x) <= (hi)) && ((x) >= (lo))) ++#define VLYNQ_OUTRANGE(x,hi,lo) (((x) > (hi)) || ((x) < (lo))) + ++#define VLYNQ_ALIGN4(x) (x)=(x)&(~3) + -+#define AVALANCHE_EMIF_INT 47 + ++/************************************* ++ * Enums * ++ *************************************/ + ++/* Initialization options define what operations are ++ * undertaken during vlynq module initialization */ ++typedef enum ++{ ++ /* Init host local memory regions.This allows ++ * local host access remote memory regions */ ++ VLYNQ_INIT_LOCAL_MEM_REGIONS = 0x01, ++ /* Init host remote memory regions.This allows ++ * remote device access local memory regions */ ++ VLYNQ_INIT_REMOTE_MEM_REGIONS =0x02, ++ /* Init local interrupt config*/ ++ VLYNQ_INIT_LOCAL_INTERRUPTS =0x04, ++ /* Init remote interrupt config*/ ++ VLYNQ_INIT_REMOTE_INTERRUPTS =0x08, ++ /* Check link during initialization*/ ++ VLYNQ_INIT_CHECK_LINK =0x10, ++ /* configure clock during init */ ++ VLYNQ_INIT_CONFIG_CLOCK =0x20, ++ /* Clear errors during init */ ++ VLYNQ_INIT_CLEAR_ERRORS =0x40, ++ /* All options */ ++ VLYNQ_INIT_PERFORM_ALL =0x7F ++}VLYNQ_INIT_OPTIONS; ++ ++ ++/* VLYNQ_DEV_TYPE identifies local or remote device */ ++typedef enum ++{ ++ VLYNQ_LOCAL_DVC = 0, /* vlynq local device (SOC's vlynq module) */ ++ VLYNQ_REMOTE_DVC = 1 /* vlynq remote device (remote vlynq module) */ ++}VLYNQ_DEV_TYPE; + -+/*----------------------------------------------------------- -+ * Sangam's Reset Bits -+ *---------------------------------------------------------*/ + -+#define AVALANCHE_UART0_RESET_BIT 0 -+#define AVALANCHE_UART1_RESET_BIT 1 -+#define AVALANCHE_I2C_RESET_BIT 2 -+#define AVALANCHE_TIMER0_RESET_BIT 3 -+#define AVALANCHE_TIMER1_RESET_BIT 4 -+/* Reset bit 5 is reserved. */ -+#define AVALANCHE_GPIO_RESET_BIT 6 -+#define AVALANCHE_ADSL_SUB_SYS_RESET_BIT 7 -+#define AVALANCHE_USB_SLAVE_RESET_BIT 8 -+#define AVALANCHE_ATM_SAR_RESET_BIT 9 -+/* Reset bit 10 is reserved. */ -+#define AVALANCHE_VDMA_VT_RESET_BIT 11 -+#define AVALANCHE_FSER_RESET_BIT 12 -+/* Reset bit 13 to 15 are reserved */ -+#define AVALANCHE_HIGH_VLYNQ_RESET_BIT 16 -+#define AVALANCHE_LOW_CPMAC_RESET_BIT 17 -+#define AVALANCHE_MCDMA_RESET_BIT 18 -+#define AVALANCHE_BIST_RESET_BIT 19 -+#define AVALANCHE_LOW_VLYNQ_RESET_BIT 20 -+#define AVALANCHE_HIGH_CPMAC_RESET_BIT 21 -+#define AVALANCHE_MDIO_RESET_BIT 22 -+#define AVALANCHE_ADSL_SUB_SYS_DSP_RESET_BIT 23 -+/* Reset bit 24 to 25 are reserved */ -+#define AVALANCHE_LOW_EPHY_RESET_BIT 26 -+/* Reset bit 27 to 31 are reserved */ ++/* VLYNQ_CLK_SOURCE identifies the vlynq module clock source */ ++typedef enum ++{ ++ VLYNQ_CLK_SOURCE_NONE = 0, /* do not initialize clock generator*/ ++ VLYNQ_CLK_SOURCE_LOCAL = 1, /* clock is generated by local machine */ ++ VLYNQ_CLK_SOURCE_REMOTE = 2 /* clock is generated by remote machine */ ++}VLYNQ_CLK_SOURCE; + + -+#define AVALANCHE_POWER_MODULE_USBSP 0 -+#define AVALANCHE_POWER_MODULE_WDTP 1 -+#define AVALANCHE_POWER_MODULE_UT0P 2 -+#define AVALANCHE_POWER_MODULE_UT1P 3 -+#define AVALANCHE_POWER_MODULE_IICP 4 -+#define AVALANCHE_POWER_MODULE_VDMAP 5 -+#define AVALANCHE_POWER_MODULE_GPIOP 6 -+#define AVALANCHE_POWER_MODULE_VLYNQ1P 7 -+#define AVALANCHE_POWER_MODULE_SARP 8 -+#define AVALANCHE_POWER_MODULE_ADSLP 9 -+#define AVALANCHE_POWER_MODULE_EMIFP 10 -+#define AVALANCHE_POWER_MODULE_ADSPP 12 -+#define AVALANCHE_POWER_MODULE_RAMP 13 -+#define AVALANCHE_POWER_MODULE_ROMP 14 -+#define AVALANCHE_POWER_MODULE_DMAP 15 -+#define AVALANCHE_POWER_MODULE_BISTP 16 -+#define AVALANCHE_POWER_MODULE_TIMER0P 18 -+#define AVALANCHE_POWER_MODULE_TIMER1P 19 -+#define AVALANCHE_POWER_MODULE_EMAC0P 20 -+#define AVALANCHE_POWER_MODULE_EMAC1P 22 -+#define AVALANCHE_POWER_MODULE_EPHYP 24 -+#define AVALANCHE_POWER_MODULE_VLYNQ0P 27 ++/* VLYNQ_DRV_STATE indicates the current driver state */ ++typedef enum ++{ ++ VLYNQ_DRV_STATE_UNINIT = 0, /* driver is uninitialized */ ++ VLYNQ_DRV_STATE_ININIT = 1, /* VLYNQ is being initialized */ ++ VLYNQ_DRV_STATE_RUN = 2, /* VLYNQ is running properly */ ++ VLYNQ_DRV_STATE_HOLD = 3, /* driver stopped temporarily */ ++ VLYNQ_DRV_STATE_ERROR = 4 /* driver stopped on unrecoverable error */ ++}VLYNQ_DRV_STATE; + + ++/* VLYNQ_BUS_WIDTH identifies the vlynq module bus width */ ++typedef enum ++{ ++ VLYNQ_BUS_WIDTH_3 = 3, ++ VLYNQ_BUS_WIDTH_5 = 5, ++ VLYNQ_BUS_WIDTH_7 = 7, ++ VLYNQ_BUS_WIDTH_9 = 9 ++}VLYNQ_BUS_WIDTH; + + ++/* VLYNQ_LOCAL_INT_CONFIG indicates whether the local vlynq ++ * interrupts are processed by the host or passed on to the ++ * remote device. ++ */ ++typedef enum ++{ ++ VLYNQ_INT_REMOTE = 0, /* Interrupt packets sent to remote, intlocal=0 */ ++ VLYNQ_INT_LOCAL = 1 /* Interrupts are handled locally, intlocal=1 */ ++}VLYNQ_LOCAL_INT_CONFIG; + -+/* -+ * Sangam board vectors ++ ++/* VLYNQ_REMOTE_INT_CONFIG indicates whether the remote ++ * interrupts are to be handled by the SOC system ISR ++ * or via the vlynq root ISR + */ ++typedef enum ++{ ++ VLYNQ_INT_ROOT_ISR = 0, /* remote ints handled via vlynq root ISR */ ++ VLYNQ_INT_SYSTEM_ISR = 1 /* remote ints handled via system ISR */ ++}VLYNQ_REMOTE_INT_CONFIG; + -+#define AVALANCHE_VECS (KSEG1ADDR(AVALANCHE_SDRAM_BASE)) -+#define AVALANCHE_VECS_KSEG0 (KSEG0ADDR(AVALANCHE_SDRAM_BASE)) + -+/*----------------------------------------------------------------------------- -+ * Sangam's system register. -+ * -+ *---------------------------------------------------------------------------*/ -+#define AVALANCHE_DCL_BOOTCR (KSEG1ADDR(0x08611A00)) -+#define AVALANCHE_EMIF_SDRAM_CFG (AVALANCHE_EMIF_CONTROL_BASE + 0x8) -+#define AVALANCHE_RST_CTRL_PRCR (KSEG1ADDR(0x08611600)) -+#define AVALANCHE_RST_CTRL_SWRCR (KSEG1ADDR(0x08611604)) -+#define AVALANCHE_RST_CTRL_RSR (KSEG1ADDR(0x08611600)) ++/* VLYNQ_INTR_POLARITY - vlynq interrupt polarity setting */ ++typedef enum ++{ ++ VLYNQ_INTR_ACTIVE_HIGH = 0, ++ VLYNQ_INTR_ACTIVE_LOW = 1 ++}VLYNQ_INTR_POLARITY; + -+#define AVALANCHE_POWER_CTRL_PDCR (KSEG1ADDR(0x08610A00)) -+#define AVALANCHE_WAKEUP_CTRL_WKCR (KSEG1ADDR(0x08610A0C)) + -+#define AVALANCHE_GPIO_DATA_IN (AVALANCHE_GPIO_BASE + 0x0) -+#define AVALANCHE_GPIO_DATA_OUT (AVALANCHE_GPIO_BASE + 0x4) -+#define AVALANCHE_GPIO_DIR (AVALANCHE_GPIO_BASE + 0x8) -+#define AVALANCHE_GPIO_ENBL (AVALANCHE_GPIO_BASE + 0xC) -+#define AVALANCHE_CVR (AVALANCHE_GPIO_BASE + 0x14) ++/* VLYNQ_INTR_TYPE - vlynq interrupt type */ ++typedef enum ++{ ++ VLYNQ_INTR_LEVEL = 0, ++ VLYNQ_INTR_PULSED = 1 ++}VLYNQ_INTR_TYPE; + -+/* -+ * Yamon Prom print address. -+ */ -+#define AVALANCHE_YAMON_FUNCTION_BASE (KSEG1ADDR(0x10000500)) -+#define AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR (AVALANCHE_YAMON_FUNCTION_BASE + 0x4) /* print_count function */ -+#define AVALANCHE_YAMON_PROM_PRINT_ADDR (AVALANCHE_YAMON_FUNCTION_BASE + 0x34) + -+#define AVALANCHE_BASE_BAUD ( 3686400 / 16 ) ++/* VLYNQ_RESET_MODE - vlynq reset mode */ ++typedef enum ++{ ++ VLYNQ_RESET_ASSERT, /* hold device in reset state */ ++ VLYNQ_RESET_DEASSERT, /* release device from reset state */ ++ VLYNQ_RESET_INITFAIL, /* handle the device in case driver initialization fails */ ++ VLYNQ_RESET_LINKESTABLISH, /* handle the device in case driver established link */ ++ VLYNQ_RESET_INITFAIL2, /* Driver initialization failed but VLYNQ link exist. */ ++ VLYNQ_RESET_INITOK /* Driver initialization finished OK. */ ++}VLYNQ_RESET_MODE; ++ + -+#define AVALANCHE_GPIO_PIN_COUNT 32 -+#define AVALANCHE_GPIO_OFF_MAP {0xF34FFFC0} + -+#include "sangam_boards.h" ++/************************************* ++ * Typedefs * ++ *************************************/ + -+#endif /*_SANGAM_H_ */ -diff -urN kernel-base/include/asm-mips/ar7/tnetd73xx_err.h kernel-current/include/asm-mips/ar7/tnetd73xx_err.h ---- kernel-base/include/asm-mips/ar7/tnetd73xx_err.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/tnetd73xx_err.h 2005-07-10 09:34:36.482617144 +0200 -@@ -0,0 +1,42 @@ -+/****************************************************************************** -+ * FILE PURPOSE: TNETD73xx Error Definations Header File -+ ****************************************************************************** -+ * FILE NAME: tnetd73xx_err.h -+ * -+ * DESCRIPTION: Error definations for TNETD73XX -+ * -+ * REVISION HISTORY: -+ * 27 Nov 02 - PSP TII -+ * -+ * (C) Copyright 2002, Texas Instruments, Inc -+ *******************************************************************************/ ++struct VLYNQ_DEV_t; /*forward declaration*/ + -+ -+#ifndef __TNETD73XX_ERR_H__ -+#define __TNETD73XX_ERR_H__ ++/*--------Function Pointers defintions -----------*/ + -+typedef enum TNETD73XX_ERR_t -+{ -+ TNETD73XX_ERR_OK = 0, /* OK or SUCCESS */ -+ TNETD73XX_ERR_ERROR = -1, /* Unspecified/Generic ERROR */ ++/* prototype for interrupt handler definition */ ++typedef void (*VLYNQ_INTR_CNTRL_ISR)(void *arg1,void *arg2,void *arg3); + -+ /* Pointers and args */ -+ TNETD73XX_ERR_INVARG = -2, /* Invaild argument to the call */ -+ TNETD73XX_ERR_NULLPTR = -3, /* NULL pointer */ -+ TNETD73XX_ERR_BADPTR = -4, /* Bad (out of mem) pointer */ ++typedef void ++(*VLYNQ_RESET_REMOTE)(struct VLYNQ_DEV_t *pDev, VLYNQ_RESET_MODE mode); + -+ /* Memory issues */ -+ TNETD73XX_ERR_ALLOC_FAIL = -10, /* allocation failed */ -+ TNETD73XX_ERR_FREE_FAIL = -11, /* free failed */ -+ TNETD73XX_ERR_MEM_CORRUPT = -12, /* corrupted memory */ -+ TNETD73XX_ERR_BUF_LINK = -13, /* buffer linking failed */ ++typedef void ++(*VLYNQ_REPORT_CB)( struct VLYNQ_DEV_t *pDev, /* This VLYNQ */ ++ VLYNQ_DEV_TYPE aSrcDvc, /* Event Cause -local/remote? */ ++ unsigned int dwStatRegVal); /* Value of the relevant status register */ + -+ /* Device issues */ -+ TNETD73XX_ERR_DEVICE_TIMEOUT = -20, /* device timeout on read/write */ -+ TNETD73XX_ERR_DEVICE_MALFUNC = -21, /* device malfunction */ + -+ TNETD73XX_ERR_INVID = -30 /* Invalid ID */ ++/*-------Structure Definitions------------*/ + -+} TNETD73XX_ERR; ++typedef struct VLYNQ_MEMORY_MAP_t ++{ ++ unsigned int Txmap; ++ unsigned int RxOffset[VLYNQ_MAX_MEMORY_REGIONS]; ++ unsigned int RxSize[VLYNQ_MAX_MEMORY_REGIONS]; ++}VLYNQ_MEMORY_MAP; + -+#endif /* __TNETD73XX_ERR_H__ */ -diff -urN kernel-base/include/asm-mips/ar7/tnetd73xx.h kernel-current/include/asm-mips/ar7/tnetd73xx.h ---- kernel-base/include/asm-mips/ar7/tnetd73xx.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/tnetd73xx.h 2005-07-10 09:51:18.910224984 +0200 -@@ -0,0 +1,338 @@ -+/****************************************************************************** -+ * FILE PURPOSE: TNETD73xx Common Header File -+ ****************************************************************************** -+ * FILE NAME: tnetd73xx.h -+ * -+ * DESCRIPTION: shared typedef's, constants and API for TNETD73xx -+ * -+ * REVISION HISTORY: -+ * 27 Nov 02 - PSP TII -+ * -+ * (C) Copyright 2002, Texas Instruments, Inc -+ *******************************************************************************/ + -+/* -+ * -+ * -+ * These are const, typedef, and api definitions for tnetd73xx. -+ * -+ * NOTES: -+ * 1. This file may be included into both C and Assembly files. -+ * - for .s files, please do #define _ASMLANGUAGE in your ASM file to -+ * avoid C data types (typedefs) below; -+ * - for .c files, you don't have to do anything special. -+ * -+ * 2. This file has a number of sections for each SOC subsystem. When adding -+ * a new constant, find the subsystem you are working on and follow the -+ * name pattern. If you are adding another typedef for your interface, please, -+ * place it with other typedefs and function prototypes. -+ * -+ * 3. Please, DO NOT add any macros or types that are local to a subsystem to avoid -+ * cluttering. Include such items directly into the module's .c file or have a -+ * local .h file to pass data between smaller modules. This file defines only -+ * shared items. ++/**VLYNQ_INTERRUPT_CNTRL - defines the vlynq module interrupt ++ * settings in vlynq Control register */ ++typedef struct VLYNQ_INTERRUPT_CNTRL_t ++{ ++ /* vlynq interrupts handled by host or remote - maps to ++ * intLocal bit in vlynq control register */ ++ VLYNQ_LOCAL_INT_CONFIG intLocal; ++ ++ /* remote interrupts handled by vlynq isr or host system ++ * interrupt controller - maps to the int2Cfg in vlynq ++ * control register */ ++ VLYNQ_REMOTE_INT_CONFIG intRemote; ++ ++ /* bit in pending/set register used for module interrupts*/ ++ unsigned int map_vector; ++ ++ /* used only if remote interrupts are to be handled by system ISR*/ ++ unsigned int intr_ptr; ++ ++}VLYNQ_INTERRUPT_CNTRL; ++ ++ ++/* VLYNQ_INTR_CNTRL_ICB - defines the Interrupt control block which hold ++ * the interrupt dispatch table. The vlynq_root_isr() indexes into this ++ * table to identify the ISR to be invoked + */ ++typedef struct VLYNQ_INTR_CNTRL_ICB_t ++{ ++ VLYNQ_INTR_CNTRL_ISR isr; /* Clear errors during initialization */ ++ void *arg1 ; /* Arg 1 for the ISR */ ++ void *arg2 ; /* Arg 2 for the ISR */ ++ void *arg3 ; /* Arg 3 for the ISR */ ++ unsigned int isrCount; /* number of ISR invocations so far */ ++ struct VLYNQ_INTR_CNTRL_ICB_t *next; ++}VLYNQ_INTR_CNTRL_ICB; ++ ++/* overlay of vlynq register set */ ++typedef struct VLYNQ_REG_SET_t ++{ ++ unsigned int revision; /*offset : 0x00 */ ++ unsigned int control; /* 0x04*/ ++ unsigned int status; /* 0x08*/ ++ unsigned int pad1; /* 0x0c*/ ++ unsigned int intStatus; /*0x10*/ ++ unsigned int intPending; /*0x14*/ ++ unsigned int intPtr; /*0x18*/ ++ unsigned int txMap; /*0x1C*/ ++ unsigned int rxSize1; /*0x20*/ ++ unsigned int rxOffset1; /*0x24*/ ++ unsigned int rxSize2; /*0x28*/ ++ unsigned int rxOffset2; /*0x2C*/ ++ unsigned int rxSize3; /*0x30*/ ++ unsigned int rxOffset3; /*0x34*/ ++ unsigned int rxSize4; /*0x38*/ ++ unsigned int rxOffset4; /*0x3C*/ ++ unsigned int chipVersion; /*0x40*/ ++ unsigned int pad2[8]; ++ unsigned int ivr30; /*0x60*/ ++ unsigned int ivr74; /*0x64*/ ++ unsigned int pad3[7]; ++}VLYNQ_REG_SET; ++ + -+#ifndef __TNETD73XX_H__ -+#define __TNETD73XX_H__ ++typedef struct VLYNQ_DEV_t ++{ ++ /** module index:1,2,3... used for debugging purposes */ ++ unsigned int dev_idx; ++ ++ /*VLYNQ module base address */ ++ unsigned int module_base; ++ ++ /* clock source selection */ ++ VLYNQ_CLK_SOURCE clk_source; ++ ++ /* Clock Divider.Val=1 to 8. VLYNQ_clk = VBUSCLK/clk_div */ ++ unsigned int clk_div; ++ ++ /* State of the VLYNQ driver, set to VLYNQ_DRV_STATE_UNINIT, when initializing */ ++ VLYNQ_DRV_STATE state; ++ ++ /* Valid VLYNQ bus width, filled by driver */ ++ VLYNQ_BUS_WIDTH width; ++ ++ /* local memory mapping */ ++ VLYNQ_MEMORY_MAP local_mem; ++ ++ /* remote memory mapping */ ++ VLYNQ_MEMORY_MAP remote_mem; ++ ++ /* Local module interrupt params */ ++ VLYNQ_INTERRUPT_CNTRL local_irq; ++ ++ /* remote module interrupt params */ ++ VLYNQ_INTERRUPT_CNTRL remote_irq; ++ ++ /*** ICB related fields **/ ++ ++ /* Sizeof of ICB = VLYNQ_NUM_INT_BITS(for 32 bits in IntPending) + ++ * expansion slots for shared interrupts*/ ++ VLYNQ_INTR_CNTRL_ICB pIntrCB[VLYNQ_NUM_INT_BITS + VLYNQ_IVR_CHAIN_SLOTS]; ++ VLYNQ_INTR_CNTRL_ICB *freelist; ++ ++ /* table holding mapping between intVector and the bit position the interrupt ++ * is mapped to(mapVector)*/ ++ char vector_map[32]; ++ ++ /* user callback for vlynq events, NULL if unused */ ++ VLYNQ_REPORT_CB report_cb; ++ ++ /* user callback for resetting/realeasing remote device */ ++ VLYNQ_RESET_REMOTE reset_cb; + -+#ifndef _ASMLANGUAGE /* This part not for assembly language */ ++ /*** Handles provided for direct access to register set if need be ++ * Must be intialized to point to appropriate address during ++ * vlynq_init */ ++ volatile VLYNQ_REG_SET * local; ++ volatile VLYNQ_REG_SET * remote; + -+extern unsigned int tnetd73xx_mips_freq; -+extern unsigned int tnetd73xx_vbus_freq; ++ unsigned int intCount; /* number of interrupts generated so far */ ++ unsigned int isrCount; /* number of ISR invocations so far */ ++}VLYNQ_DEV; + -+#include "tnetd73xx_err.h" + -+#endif /* _ASMLANGUAGE */ ++typedef struct VLYNQ_ISR_ARGS_t ++{ ++ int irq; ++ void * arg; ++ void * regset; ++}VLYNQ_ISR_ARGS; + + -+/******************************************************************************************* -+* Emerald core specific -+******************************************************************************************** */ ++/**************************************** ++ * Function Prototypes * ++ * API exported by generic vlynq driver * ++ ****************************************/ ++/* Initialization function */ ++int vlynq_init( VLYNQ_DEV *pdev, VLYNQ_INIT_OPTIONS options); + -+#ifdef BIG_ENDIAN -+#elif defined(LITTLE_ENDIAN) -+#else -+#error Need to define endianism -+#endif ++/* Check vlynq link */ ++unsigned int vlynq_link_check( VLYNQ_DEV * pdev); + -+#ifndef KSEG_MSK -+#define KSEG_MSK 0xE0000000 /* Most significant 3 bits denote kseg choice */ -+#endif ++/* Set interrupt vector in local or remote device */ ++int vlynq_interrupt_vector_set( VLYNQ_DEV *pdev, ++ unsigned int int_vector, ++ unsigned int map_vector, ++ VLYNQ_DEV_TYPE dev, ++ VLYNQ_INTR_POLARITY pol, ++ VLYNQ_INTR_TYPE type); + -+#ifndef KSEG_INV_MASK -+#define KSEG_INV_MASK 0x1FFFFFFF /* Inverted mask for kseg address */ -+#endif + -+#ifndef KSEG0_BASE -+#define KSEG0_BASE 0x80000000 -+#endif ++int vlynq_interrupt_vector_cntl( VLYNQ_DEV *pdev, ++ unsigned int int_vector, ++ VLYNQ_DEV_TYPE dev, ++ unsigned int enable); + -+#ifndef KSEG1_BASE -+#define KSEG1_BASE 0xA0000000 -+#endif ++unsigned int vlynq_interrupt_get_count( VLYNQ_DEV *pdev, ++ unsigned int map_vector); ++ ++int vlynq_install_isr( VLYNQ_DEV *pdev, ++ unsigned int map_vector, ++ VLYNQ_INTR_CNTRL_ISR isr, ++ void *arg1, void *arg2, void *arg3); ++ ++int vlynq_uninstall_isr( VLYNQ_DEV *pdev, ++ unsigned int map_vector, ++ void *arg1, void *arg2, void *arg3); ++ ++ ++void vlynq_root_isr(void *arg); ++ ++void vlynq_delay(unsigned int clktime); ++ ++/* The following functions, provide better granularity in setting ++ * interrupt parameters. (for better support of linux INT Controller) ++ * Note: The interrupt source is identified by "map_vector"- the bit ++ * position in interrupt status register*/ ++ ++int vlynq_interrupt_vector_map(VLYNQ_DEV * pdev, ++ VLYNQ_DEV_TYPE dev, ++ unsigned int int_vector, ++ unsigned int map_vector); ++ ++int vlynq_interrupt_set_polarity(VLYNQ_DEV * pdev, ++ VLYNQ_DEV_TYPE dev, ++ unsigned int map_vector, ++ VLYNQ_INTR_POLARITY pol); ++ ++int vlynq_interrupt_get_polarity( VLYNQ_DEV *pdev , ++ VLYNQ_DEV_TYPE dev_type, ++ unsigned int map_vector); ++ ++int vlynq_interrupt_set_type(VLYNQ_DEV * pdev, ++ VLYNQ_DEV_TYPE dev, ++ unsigned int map_vector, ++ VLYNQ_INTR_TYPE type); ++ ++int vlynq_interrupt_get_type( VLYNQ_DEV *pdev, ++ VLYNQ_DEV_TYPE dev_type, ++ unsigned int map_vector); ++ ++int vlynq_interrupt_enable(VLYNQ_DEV* pdev, ++ VLYNQ_DEV_TYPE dev, ++ unsigned int map_vector); ++ ++int vlynq_interrupt_disable(VLYNQ_DEV * pdev, ++ VLYNQ_DEV_TYPE dev, ++ unsigned int map_vector); ++ ++ ++ ++ + -+#ifndef KSEG0 -+#define KSEG0(addr) (((__u32)(addr) & ~KSEG_MSK) | KSEG0_BASE) ++#endif /* _VLYNQ_HAL_H_ */ +diff -urN linux.old/include/asm-mips/ar7/vlynq_hal.h linux.dev/include/asm-mips/ar7/vlynq_hal.h +--- linux.old/include/asm-mips/ar7/vlynq_hal.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/vlynq_hal.h 2005-11-10 01:10:46.095590250 +0100 +@@ -0,0 +1,606 @@ ++/*************************************************************************** ++**+----------------------------------------------------------------------+** ++**| **** |** ++**| **** |** ++**| ******o*** |** ++**| ********_///_**** |** ++**| ***** /_//_/ **** |** ++**| ** ** (__/ **** |** ++**| ********* |** ++**| **** |** ++**| *** |** ++**| |** ++**| Copyright (c) 2003 Texas Instruments Incorporated |** ++**| ALL RIGHTS RESERVED |** ++**| |** ++**| Permission is hereby granted to licensees of Texas Instruments |** ++**| Incorporated (TI) products to use this computer program for the sole |** ++**| purpose of implementing a licensee product based on TI products. |** ++**| No other rights to reproduce, use, or disseminate this computer |** ++**| program, whether in part or in whole, are granted. |** ++**| |** ++**| TI makes no representation or warranties with respect to the |** ++**| performance of this computer program, and specifically disclaims |** ++**| any responsibility for any damages, special or consequential, |** ++**| connected with the use of this program. |** ++**| |** ++**+----------------------------------------------------------------------+** ++***************************************************************************/ ++ ++/********************************************************************************* ++ * ------------------------------------------------------------------------------ ++ * Module : vlynq_hal.h ++ * Description : ++ * This header file provides the set of functions exported by the ++ * VLYNQ HAL. This file is included from the SOC specific VLYNQ driver wrapper. ++ * ------------------------------------------------------------------------------ ++ *********************************************************************************/ ++ ++#ifndef _VLYNQ_HAL_H_ ++#define _VLYNQ_HAL_H_ ++ ++#include ++#include ++ ++#ifndef PRIVATE ++#define PRIVATE static +#endif + -+#ifndef KSEG1 -+#define KSEG1(addr) (((__u32)(addr) & ~KSEG_MSK) | KSEG1_BASE) ++#ifndef GLOBAL ++#define GLOBAL +#endif + -+#ifndef KUSEG -+#define KUSEG(addr) ((__u32)(addr) & ~KSEG_MSK) -+#endif ++/* Enable/Disable debug feature */ ++#undef VLYNQ_DEBUG + -+#ifndef PHYS_ADDR -+#define PHYS_ADDR(addr) ((addr) & KSEG_INV_MASK) ++#ifdef VLYNQ_DEBUG /* This needs to be OS abstracted - for testing use vxworks/linux calls */ ++#define debugPrint(format,args...) ++#else ++#define debugPrint(format,args...) +#endif + -+#ifndef PHYS_TO_K0 -+#define PHYS_TO_K0(addr) (PHYS_ADDR(addr)|KSEG0_BASE) -+#endif ++/* Error defines */ ++#define VLYNQ_SUCCESS 0 + -+#ifndef PHYS_TO_K1 -+#define PHYS_TO_K1(addr) (PHYS_ADDR(addr)|KSEG1_BASE) -+#endif ++#define VLYNQ_ERRCODE_BASE 0 /* Chosen by system */ ++#define VLYNQ_INVALID_ARG -(VLYNQ_ERRCODE_BASE+1) ++#define VLYNQ_INVALID_DRV_STATE -(VLYNQ_ERRCODE_BASE+2) ++#define VLYNQ_INT_CONFIG_ERR -(VLYNQ_ERRCODE_BASE+3) ++#define VLYNQ_LINK_DOWN -(VLYNQ_ERRCODE_BASE+4) ++#define VLYNQ_MEMALLOC_FAIL -(VLYNQ_ERRCODE_BASE+5) ++#define VLYNQ_ISR_NON_EXISTENT -(VLYNQ_ERRCODE_BASE+6) ++#define VLYNQ_INTVEC_MAP_NOT_FOUND -(VLYNQ_ERRCODE_BASE+7) + -+#ifndef REG8_ADDR -+#define REG8_ADDR(addr) (volatile __u8 *)(PHYS_TO_K1(addr)) -+#define REG8_DATA(addr) (*(volatile __u8 *)(PHYS_TO_K1(addr))) -+#define REG8_WRITE(addr, data) REG8_DATA(addr) = data; -+#define REG8_READ(addr, data) data = (__u8) REG8_DATA(addr); -+#endif ++/* Vlynq Defines and Macros */ + -+#ifndef REG16_ADDR -+#define REG16_ADDR(addr) (volatile __u16 *)(PHYS_TO_K1(addr)) -+#define REG16_DATA(addr) (*(volatile __u16 *)(PHYS_TO_K1(addr))) -+#define REG16_WRITE(addr, data) REG16_DATA(addr) = data; -+#define REG16_READ(addr, data) data = (__u16) REG16_DATA(addr); -+#endif ++#define VLYNQ_NUM_INT_BITS 32 /* 32 bit interrupt staus register */ + -+#ifndef REG32_ADDR -+#define REG32_ADDR(addr) (volatile __u32 *)(PHYS_TO_K1(addr)) -+#define REG32_DATA(addr) (*(volatile __u32 *)(PHYS_TO_K1(addr))) -+#define REG32_WRITE(addr, data) REG32_DATA(addr) = data; -+#define REG32_READ(addr, data) data = (__u32) REG32_DATA(addr); -+#endif ++/* Base address of module */ ++#define VLYNQ_BASE (pdev->module_base) + -+#ifdef _LINK_KSEG0_ /* Application is linked into KSEG0 space */ -+#define VIRT_ADDR(addr) PHYS_TO_K0(PHYS_ADDR(addr)) -+#endif ++#define VLYNQ_REMOTE_REGS_OFFSET 0x0080 + -+#ifdef _LINK_KSEG1_ /* Application is linked into KSEG1 space */ -+#define VIRT_ADDR(addr) PHYS_TO_K1(PHYS_ADDR(addr)) -+#endif ++#define VLYNQ_REV_OFFSET 0x0000 ++#define VLYNQ_CTRL_OFFSET 0x0004 ++#define VLYNQ_STATUS_OFFSET 0x0008 ++#define VLYNQ_INT_STAT_OFFSET 0x0010 ++#define VLYNQ_INT_PEND_OFFSET 0x0014 ++#define VLYNQ_INT_PTR_OFFSET 0x0018 ++#define VLYNQ_TXMAP_OFFSET 0x001c + -+#if !defined(_LINK_KSEG0_) && !defined(_LINK_KSEG1_) -+#error You must define _LINK_KSEG0_ or _LINK_KSEG1_ to compile the code. -+#endif ++#define VLYNQ_RX0MAP_SIZE_REG_OFFSET 0x0020 ++#define VLYNQ_RX0MAP_OFFSET_REG_OFFSET 0x0024 + -+/* TNETD73XX chip definations */ ++#define VLYNQ_CHIP_VER_OFFSET 0x0040 ++#define VLYNQ_IVR_REGS_OFFSET 0x0060 + -+#define FREQ_1MHZ 1000000 -+#define TNETD73XX_MIPS_FREQ tnetd73xx_mips_freq /* CPU clock frequency */ -+#define TNETD73XX_VBUS_FREQ tnetd73xx_vbus_freq /* originally (TNETD73XX_MIPS_FREQ/2) */ ++#define VLYNQ_INT_PENDING_REG_PTR 0x14 ++#define VLYNQ_R_INT_PENDING_REG_PTR VLYNQ_REMOTE_REGS_OFFSET + 0x14 + -+#ifdef AR7SEAD2 -+#define TNETD73XX_MIPS_FREQ_DEFAULT 25000000 /* 25 Mhz for sead2 board crystal */ -+#else -+#define TNETD73XX_MIPS_FREQ_DEFAULT 125000000 /* 125 Mhz */ -+#endif -+#define TNETD73XX_VBUS_FREQ_DEFAULT (TNETD73XX_MIPS_FREQ_DEFAULT / 2) /* Sync mode */ ++#define VLYNQ_REV_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_REV_OFFSET)) ++#define VLYNQ_CTRL_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_CTRL_OFFSET)) ++#define VLYNQ_STATUS_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_STATUS_OFFSET)) ++#define VLYNQ_INT_STAT_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_INT_STAT_OFFSET)) ++#define VLYNQ_INT_PEND_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_INT_PEND_OFFSET)) ++#define VLYNQ_INT_PTR_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_INT_PTR_OFFSET)) ++#define VLYNQ_TXMAP_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_TXMAP_OFFSET)) + ++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/ ++#define VLYNQ_RXMAP_SIZE_REG(map) \ ++ *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_RX0MAP_SIZE_REG_OFFSET+( (map-1)<<3))) ++ ++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/ ++#define VLYNQ_RXMAP_OFFSET_REG(map) \ ++ *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_RX0MAP_OFFSET_REG_OFFSET+( (map-1)<<3))) + ++#define VLYNQ_CHIP_VER_REG *((volatile UINT32 *)(VLYNQ_BASE+VLYNQ_CHIP_VER_OFFSET)) + -+/* Module base addresses */ -+#define TNETD73XX_ADSLSS_BASE PHYS_TO_K1(0x01000000) /* ADSLSS Module */ -+#define TNETD73XX_BBIF_CTRL_BASE PHYS_TO_K1(0x02000000) /* BBIF Control */ -+#define TNETD73XX_ATMSAR_BASE PHYS_TO_K1(0x03000000) /* ATM SAR */ -+#define TNETD73XX_USB_BASE PHYS_TO_K1(0x03400000) /* USB Module */ -+#define TNETD73XX_VLYNQ0_BASE PHYS_TO_K1(0x04000000) /* VLYNQ0 Module */ -+#define TNETD73xx_EMAC0_BASE PHYS_TO_K1(0x08610000) /* EMAC0 Module*/ -+#define TNETD73XX_EMIF_BASE PHYS_TO_K1(0x08610800) /* EMIF Module */ -+#define TNETD73XX_GPIO_BASE PHYS_TO_K1(0x08610900) /* GPIO control */ -+#define TNETD73XX_CLOCK_CTRL_BASE PHYS_TO_K1(0x08610A00) /* Clock Control */ -+#define TNETD73XX_WDTIMER_BASE PHYS_TO_K1(0x08610B00) /* WDTIMER Module */ -+#define TNETD73XX_TIMER0_BASE PHYS_TO_K1(0x08610C00) /* TIMER0 Module */ -+#define TNETD73XX_TIMER1_BASE PHYS_TO_K1(0x08610D00) /* TIMER1 Module */ -+#define TNETD73XX_UARTA_BASE PHYS_TO_K1(0x08610E00) /* UART A */ -+#define TNETD73XX_UARTB_BASE PHYS_TO_K1(0x08610F00) /* UART B */ -+#define TNETD73XX_I2C_BASE PHYS_TO_K1(0x08611000) /* I2C Module */ -+#define TNETD73XX_USB_DMA_BASE PHYS_TO_K1(0x08611200) /* USB Module */ -+#define TNETD73XX_MCDMA_BASE PHYS_TO_K1(0x08611400) /* MC-DMA */ -+#define TNETD73xx_VDMAVT_BASE PHYS_TO_K1(0x08611500) /* VDMAVT Control */ -+#define TNETD73XX_RST_CTRL_BASE PHYS_TO_K1(0x08611600) /* Reset Control */ -+#define TNETD73xx_BIST_CTRL_BASE PHYS_TO_K1(0x08611700) /* BIST Control */ -+#define TNETD73xx_VLYNQ0_CTRL_BASE PHYS_TO_K1(0x08611800) /* VLYNQ0 Control */ -+#define TNETD73XX_DCL_BASE PHYS_TO_K1(0x08611A00) /* Device Configuration Latch */ -+#define TNETD73xx_VLYNQ1_CTRL_BASE PHYS_TO_K1(0x08611C00) /* VLYNQ1 Control */ -+#define TNETD73xx_MDIO_BASE PHYS_TO_K1(0x08611E00) /* MDIO Control */ -+#define TNETD73XX_FSER_BASE PHYS_TO_K1(0x08612000) /* FSER Control */ -+#define TNETD73XX_INTC_BASE PHYS_TO_K1(0x08612400) /* Interrupt Controller */ -+#define TNETD73xx_EMAC1_BASE PHYS_TO_K1(0x08612800) /* EMAC1 Module*/ -+#define TNETD73XX_VLYNQ1_BASE PHYS_TO_K1(0x0C000000) /* VLYNQ1 Module */ ++/* 0 =< ivr <= 31; currently ivr < VLYNQ_IVR_MAXIVR=8) */ ++#define VLYNQ_IVR_OFFSET(ivr) \ ++ (VLYNQ_BASE + VLYNQ_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3) ) + -+/* BBIF Registers */ -+#define TNETD73XX_BBIF_ADSLADR (TNETD73XX_BBIF_CTRL_BASE + 0x0) ++#define VLYNQ_IVR_03TO00_REG *((volatile UINT32*) (VLYNQ_IVR_OFFSET(0)) ) ++#define VLYNQ_IVR_07TO04_REG *((volatile UINT32*) (VLYNQ_IVR_OFFSET(4)) ) ++/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/ + -+/* Device Configuration Latch Registers */ -+#define TNETD73XX_DCL_BOOTCR (TNETD73XX_DCL_BASE + 0x0) -+#define TNETD73XX_DCL_DPLLSELR (TNETD73XX_DCL_BASE + 0x10) -+#define TNETD73XX_DCL_SPEEDCTLR (TNETD73XX_DCL_BASE + 0x14) -+#define TNETD73XX_DCL_SPEEDPWDR (TNETD73XX_DCL_BASE + 0x18) -+#define TNETD73XX_DCL_SPEEDCAPR (TNETD73XX_DCL_BASE + 0x1C) ++#define VLYNQ_IVR_INTEN(ivr) (((UINT32)(0x80)) << ((((unsigned)(ivr)) % 4) * 8)) ++#define VLYNQ_IVR_INTTYPE(ivr) (((UINT32)(0x40)) << ((((unsigned)(ivr)) % 4) * 8)) ++#define VLYNQ_IVR_INTPOL(ivr) (((UINT32)(0x20)) << ((((unsigned)(ivr)) % 4) * 8)) ++#define VLYNQ_IVR_INTVEC(ivr) (((UINT32)(0x1F)) << ((((unsigned)(ivr)) % 4) * 8)) ++#define VLYNQ_IVR_INTALL(ivr) (((UINT32)(0xFF)) << ((((unsigned)(ivr)) % 4) * 8)) + -+/* GPIO Control */ -+#define TNETD73XX_GPIODINR (TNETD73XX_GPIO_BASE + 0x0) -+#define TNETD73XX_GPIODOUTR (TNETD73XX_GPIO_BASE + 0x4) -+#define TNETD73XX_GPIOPDIRR (TNETD73XX_GPIO_BASE + 0x8) -+#define TNETD73XX_GPIOENR (TNETD73XX_GPIO_BASE + 0xC) -+#define TNETD73XX_CVR (TNETD73XX_GPIO_BASE + 0x14) -+#define TNETD73XX_DIDR1 (TNETD73XX_GPIO_BASE + 0x18) -+#define TNETD73XX_DIDR2 (TNETD73XX_GPIO_BASE + 0x1C) + -+/* Reset Control */ -+#define TNETD73XX_RST_CTRL_PRCR (TNETD73XX_RST_CTRL_BASE + 0x0) -+#define TNETD73XX_RST_CTRL_SWRCR (TNETD73XX_RST_CTRL_BASE + 0x4) -+#define TNETD73XX_RST_CTRL_RSR (TNETD73XX_RST_CTRL_BASE + 0x8) + -+/* Power Control */ -+#define TNETD73XX_POWER_CTRL_PDCR (TNETD73XX_CLOCK_CTRL_BASE + 0x0) -+#define TNETD73XX_POWER_CTRL_PCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x4) -+#define TNETD73XX_POWER_CTRL_PDUCR (TNETD73XX_CLOCK_CTRL_BASE + 0x8) -+#define TNETD73XX_POWER_CTRL_WKCR (TNETD73XX_CLOCK_CTRL_BASE + 0xC) ++/********************************* ++ * Remote VLYNQ register set * ++ *********************************/ + -+/* Clock Control */ -+#define TNETD73XX_CLK_CTRL_SCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x20) -+#define TNETD73XX_CLK_CTRL_SCLKPLLCR (TNETD73XX_CLOCK_CTRL_BASE + 0x30) -+#define TNETD73XX_CLK_CTRL_MCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x40) -+#define TNETD73XX_CLK_CTRL_MCLKPLLCR (TNETD73XX_CLOCK_CTRL_BASE + 0x50) -+#define TNETD73XX_CLK_CTRL_UCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x60) -+#define TNETD73XX_CLK_CTRL_UCLKPLLCR (TNETD73XX_CLOCK_CTRL_BASE + 0x70) -+#define TNETD73XX_CLK_CTRL_ACLKCR0 (TNETD73XX_CLOCK_CTRL_BASE + 0x80) -+#define TNETD73XX_CLK_CTRL_ACLKPLLCR0 (TNETD73XX_CLOCK_CTRL_BASE + 0x90) -+#define TNETD73XX_CLK_CTRL_ACLKCR1 (TNETD73XX_CLOCK_CTRL_BASE + 0xA0) -+#define TNETD73XX_CLK_CTRL_ACLKPLLCR1 (TNETD73XX_CLOCK_CTRL_BASE + 0xB0) ++#define VLYNQ_R_REV_OFFSET 0x0080 ++#define VLYNQ_R_CTRL_OFFSET 0x0084 ++#define VLYNQ_R_STATUS_OFFSET 0x0088 ++#define VLYNQ_R_INT_STAT_OFFSET 0x0090 ++#define VLYNQ_R_INT_PEND_OFFSET 0x0094 ++#define VLYNQ_R_INT_PTR_OFFSET 0x0098 ++#define VLYNQ_R_TXMAP_OFFSET 0x009c + -+/* EMIF control */ -+#define TNETD73XX_EMIF_SDRAM_CFG ( TNETD73XX_EMIF_BASE + 0x08 ) ++#define VLYNQ_R_RX0MAP_SIZE_REG_OFFSET 0x00A0 ++#define VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET 0x00A4 + -+/* UART */ -+#ifdef AR7SEAD2 -+#define TNETD73XX_UART_FREQ 3686400 -+#else -+#define TNETD73XX_UART_FREQ TNETD73XX_VBUS_FREQ -+#endif ++#define VLYNQ_R_CHIP_VER_OFFSET 0x00C0 ++#define VLYNQ_R_IVR_REGS_OFFSET 0x00E0 + -+/* Interrupt Controller */ ++#define VLYNQ_R_REV_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_REV_OFFSET)) ++#define VLYNQ_R_CTRL_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_CTRL_OFFSET)) ++#define VLYNQ_R_STATUS_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_STATUS_OFFSET)) ++#define VLYNQ_R_INT_STAT_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_INT_STAT_OFFSET)) ++#define VLYNQ_R_INT_PEND_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_INT_PEND_OFFSET)) ++#define VLYNQ_R_INT_PTR_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_INT_PTR_OFFSET)) ++#define VLYNQ_R_TXMAP_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_TXMAP_OFFSET)) + -+/* Primary interrupts */ -+#define TNETD73XX_INTC_UNIFIED_SECONDARY 0 /* Unified secondary interrupt */ -+#define TNETD73XX_INTC_EXTERNAL0 1 /* External Interrupt Line 0 */ -+#define TNETD73XX_INTC_EXTERNAL1 2 /* External Interrupt Line 1 */ -+#define TNETD73XX_INTC_RESERVED3 3 /* Reserved */ -+#define TNETD73XX_INTC_RESERVED4 4 /* Reserved */ -+#define TNETD73XX_INTC_TIMER0 5 /* TIMER 0 int */ -+#define TNETD73XX_INTC_TIMER1 6 /* TIMER 1 int */ -+#define TNETD73XX_INTC_UART0 7 /* UART 0 int */ -+#define TNETD73XX_INTC_UART1 8 /* UART 1 int */ -+#define TNETD73XX_INTC_MCDMA0 9 /* MCDMA 0 int */ -+#define TNETD73XX_INTC_MCDMA1 10 /* MCDMA 1 int */ -+#define TNETD73XX_INTC_RESERVED11 11 /* Reserved */ -+#define TNETD73XX_INTC_RESERVED12 12 /* Reserved */ -+#define TNETD73XX_INTC_RESERVED13 13 /* Reserved */ -+#define TNETD73XX_INTC_RESERVED14 14 /* Reserved */ -+#define TNETD73XX_INTC_ATMSAR 15 /* ATM SAR int */ -+#define TNETD73XX_INTC_RESERVED16 16 /* Reserved */ -+#define TNETD73XX_INTC_RESERVED17 17 /* Reserved */ -+#define TNETD73XX_INTC_RESERVED18 18 /* Reserved */ -+#define TNETD73XX_INTC_EMAC0 19 /* EMAC 0 int */ -+#define TNETD73XX_INTC_RESERVED20 20 /* Reserved */ -+#define TNETD73XX_INTC_VLYNQ0 21 /* VLYNQ 0 int */ -+#define TNETD73XX_INTC_CODEC 22 /* CODEC int */ -+#define TNETD73XX_INTC_RESERVED23 23 /* Reserved */ -+#define TNETD73XX_INTC_USBSLAVE 24 /* USB Slave int */ -+#define TNETD73XX_INTC_VLYNQ1 25 /* VLYNQ 1 int */ -+#define TNETD73XX_INTC_RESERVED26 26 /* Reserved */ -+#define TNETD73XX_INTC_RESERVED27 27 /* Reserved */ -+#define TNETD73XX_INTC_ETH_PHY 28 /* Ethernet PHY */ -+#define TNETD73XX_INTC_I2C 29 /* I2C int */ -+#define TNETD73XX_INTC_MCDMA2 30 /* MCDMA 2 int */ -+#define TNETD73XX_INTC_MCDMA3 31 /* MCDMA 3 int */ -+#define TNETD73XX_INTC_RESERVED32 32 /* Reserved */ -+#define TNETD73XX_INTC_EMAC1 33 /* EMAC 1 int */ -+#define TNETD73XX_INTC_RESERVED34 34 /* Reserved */ -+#define TNETD73XX_INTC_RESERVED35 35 /* Reserved */ -+#define TNETD73XX_INTC_RESERVED36 36 /* Reserved */ -+#define TNETD73XX_INTC_VDMAVTRX 37 /* VDMAVTRX */ -+#define TNETD73XX_INTC_VDMAVTTX 38 /* VDMAVTTX */ -+#define TNETD73XX_INTC_ADSLSS 39 /* ADSLSS */ ++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/ ++#define VLYNQ_R_RXMAP_SIZE_REG(map) \ ++ *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_SIZE_REG_OFFSET + ((map-1)<<3))) ++ ++/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/ ++#define VLYNQ_R_RXMAP_OFFSET_REG(map) \ ++ *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET + ((map-1)<<3))) + -+/* Secondary interrupts */ -+#define TNETD73XX_INTC_SEC0 40 /* Secondary */ -+#define TNETD73XX_INTC_SEC1 41 /* Secondary */ -+#define TNETD73XX_INTC_SEC2 42 /* Secondary */ -+#define TNETD73XX_INTC_SEC3 43 /* Secondary */ -+#define TNETD73XX_INTC_SEC4 44 /* Secondary */ -+#define TNETD73XX_INTC_SEC5 45 /* Secondary */ -+#define TNETD73XX_INTC_SEC6 46 /* Secondary */ -+#define TNETD73XX_INTC_EMIF 47 /* EMIF */ -+#define TNETD73XX_INTC_SEC8 48 /* Secondary */ -+#define TNETD73XX_INTC_SEC9 49 /* Secondary */ -+#define TNETD73XX_INTC_SEC10 50 /* Secondary */ -+#define TNETD73XX_INTC_SEC11 51 /* Secondary */ -+#define TNETD73XX_INTC_SEC12 52 /* Secondary */ -+#define TNETD73XX_INTC_SEC13 53 /* Secondary */ -+#define TNETD73XX_INTC_SEC14 54 /* Secondary */ -+#define TNETD73XX_INTC_SEC15 55 /* Secondary */ -+#define TNETD73XX_INTC_SEC16 56 /* Secondary */ -+#define TNETD73XX_INTC_SEC17 57 /* Secondary */ -+#define TNETD73XX_INTC_SEC18 58 /* Secondary */ -+#define TNETD73XX_INTC_SEC19 59 /* Secondary */ -+#define TNETD73XX_INTC_SEC20 60 /* Secondary */ -+#define TNETD73XX_INTC_SEC21 61 /* Secondary */ -+#define TNETD73XX_INTC_SEC22 62 /* Secondary */ -+#define TNETD73XX_INTC_SEC23 63 /* Secondary */ -+#define TNETD73XX_INTC_SEC24 64 /* Secondary */ -+#define TNETD73XX_INTC_SEC25 65 /* Secondary */ -+#define TNETD73XX_INTC_SEC26 66 /* Secondary */ -+#define TNETD73XX_INTC_SEC27 67 /* Secondary */ -+#define TNETD73XX_INTC_SEC28 68 /* Secondary */ -+#define TNETD73XX_INTC_SEC29 69 /* Secondary */ -+#define TNETD73XX_INTC_SEC30 70 /* Secondary */ -+#define TNETD73XX_INTC_SEC31 71 /* Secondary */ ++#define VLYNQ_R_CHIP_VER_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_CHIP_VER_OFFSET) + -+/* These ugly macros are to access the -1 registers, like config1 */ -+#define MFC0_SEL1_OPCODE(dst, src)\ -+ .word (0x40000000 | ((dst)<<16) | ((src)<<11) | 1);\ -+ nop; \ -+ nop; \ -+ nop ++#define VLYNQ_R_IVR_OFFSET(ivr) \ ++ (VLYNQ_BASE + VLYNQ_R_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3)) ++ + -+#define MTC0_SEL1_OPCODE(dst, src)\ -+ .word (0x40800000 | ((dst)<<16) | ((src)<<11) | 1);\ -+ nop; \ -+ nop; \ -+ nop ++/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/ ++#define VLYNQ_R_IVR_03TO00_REG *((volatile UINT32*) (VLYNQ_R_IVR_OFFSET(0)) ) ++#define VLYNQ_R_IVR_07TO04_REG *((volatile UINT32*) (VLYNQ_R_IVR_OFFSET(4)) ) + + -+/* Below are Jade core specific */ -+#define CFG0_4K_IL_MASK 0x00380000 -+#define CFG0_4K_IL_SHIFT 19 -+#define CFG0_4K_IA_MASK 0x00070000 -+#define CFG0_4K_IA_SHIFT 16 -+#define CFG0_4K_IS_MASK 0x01c00000 -+#define CFG0_4K_IS_SHIFT 22 ++/****End of remote register set definition******/ + -+#define CFG0_4K_DL_MASK 0x00001c00 -+#define CFG0_4K_DL_SHIFT 10 -+#define CFG0_4K_DA_MASK 0x00000380 -+#define CFG0_4K_DA_SHIFT 7 -+#define CFG0_4K_DS_MASK 0x0000E000 -+#define CFG0_4K_DS_SHIFT 13 + ++/*** Masks for individual register fields ***/ + ++#define VLYNQ_MODULE_ID_MASK 0xffff0000 ++#define VLYNQ_MAJOR_REV_MASK 0x0000ff00 ++#define VLYNQ_MINOR_REV_MASK 0x000000ff + -+#endif /* __TNETD73XX_H_ */ -diff -urN kernel-base/include/asm-mips/ar7/tnetd73xx_misc.h kernel-current/include/asm-mips/ar7/tnetd73xx_misc.h ---- kernel-base/include/asm-mips/ar7/tnetd73xx_misc.h 1970-01-01 01:00:00.000000000 +0100 -+++ kernel-current/include/asm-mips/ar7/tnetd73xx_misc.h 2005-07-10 09:53:49.418344272 +0200 -@@ -0,0 +1,239 @@ -+/****************************************************************************** -+ * FILE PURPOSE: TNETD73xx Misc modules API Header -+ ****************************************************************************** -+ * FILE NAME: tnetd73xx_misc.h -+ * -+ * DESCRIPTION: Clock Control, Reset Control, Power Management, GPIO -+ * FSER Modules API -+ * As per TNETD73xx specifications -+ * -+ * REVISION HISTORY: -+ * 27 Nov 02 - Sharath Kumar PSP TII -+ * 14 Feb 03 - Anant Gole PSP TII -+ * -+ * (C) Copyright 2002, Texas Instruments, Inc -+ *******************************************************************************/ ++ ++#define VLYNQ_CTL_ILOOP_MASK 0x00000002 ++#define VLYNQ_CTL_INT2CFG_MASK 0x00000080 ++#define VLYNQ_CTL_INTVEC_MASK 0x00001f00 ++#define VLYNQ_CTL_INTEN_MASK 0x00002000 ++#define VLYNQ_CTL_INTLOCAL_MASK 0x00004000 ++#define VLYNQ_CTL_CLKDIR_MASK 0x00008000 ++#define VLYNQ_CTL_CLKDIV_MASK 0x00070000 ++#define VLYNQ_CTL_MODE_MASK 0x00e00000 ++ ++ ++#define VLYNQ_STS_LINK_MASK 0x00000001 /* Link is active */ ++#define VLYNQ_STS_MPEND_MASK 0x00000002 /* Pending master requests */ ++#define VLYNQ_STS_SPEND_MASK 0x00000004 /* Pending slave requests */ ++#define VLYNQ_STS_NFEMPTY0_MASK 0x00000008 /* Master data FIFO not empty */ ++#define VLYNQ_STS_NFEMPTY1_MASK 0x00000010 /* Master command FIFO not empty */ ++#define VLYNQ_STS_NFEMPTY2_MASK 0x00000020 /* Slave data FIFO not empty */ ++#define VLYNQ_STS_NFEMPTY3_MASK 0x00000040 /* Slave command FIFO not empty */ ++#define VLYNQ_STS_LERROR_MASK 0x00000080 /* Local error, w/c */ ++#define VLYNQ_STS_RERROR_MASK 0x00000100 /* remote error w/c */ ++#define VLYNQ_STS_OFLOW_MASK 0x00000200 ++#define VLYNQ_STS_IFLOW_MASK 0x00000400 ++#define VLYNQ_STS_MODESUP_MASK 0x00E00000 /* Highest mode supported */ ++#define VLYNQ_STS_SWIDTH_MASK 0x07000000 /* Used for reading the width of VLYNQ bus */ ++#define VLYNQ_STS_DEBUG_MASK 0xE0000000 ++ ++#define VLYNQ_CTL_INTVEC_SHIFT 0x08 ++#define VLYNQ_CTL_INTEN_SHIFT 0x0D ++#define VLYNQ_CTL_INT2CFG_SHIFT 0x07 ++#define VLYNQ_CTL_INTLOCAL_SHIFT 0x0E ++ ++#define VLYNQ_CTL_INTFIELDS_CLEAR_MASK 0x7F80 ++ ++#define VLYNQ_CHIPVER_DEVREV_MASK 0xffff0000 ++#define VLYNQ_CHIPVER_DEVID_MASK 0x0000ffff ++ ++#define VLYNQ_IVR_INTEN_MASK 0x80 ++#define VLYNQ_IVR_INTTYPE_MASK 0x40 ++#define VLYNQ_IVR_INTPOL_MASK 0x20 ++ ++ ++/**** Helper macros ****/ ++ ++#define VLYNQ_RESETCB(arg) \ ++ if( pdev->reset_cb != NULL) \ ++ { \ ++ (pdev->reset_cb)(pdev, (arg)); \ ++ } ++ ++#define VLYNQ_STATUS_FLD_WIDTH(sts) (((sts) & VLYNQ_STS_SWIDTH_MASK) >> 24 ) ++#define VLYNQ_CTL_INTVEC(x) (((x) & 31) << 8 ) ++ ++#define VLYNQ_INRANGE(x,hi,lo) (((x) <= (hi)) && ((x) >= (lo))) ++#define VLYNQ_OUTRANGE(x,hi,lo) (((x) > (hi)) || ((x) < (lo))) ++ ++#define VLYNQ_ALIGN4(x) (x)=(x)&(~3) ++ ++ ++/************************************* ++ * Enums * ++ *************************************/ ++ ++/* Initialization options define what operations are ++ * undertaken during vlynq module initialization */ ++typedef enum ++{ ++ /* Init host local memory regions.This allows ++ * local host access remote memory regions */ ++ VLYNQ_INIT_LOCAL_MEM_REGIONS = 0x01, ++ /* Init host remote memory regions.This allows ++ * remote device access local memory regions */ ++ VLYNQ_INIT_REMOTE_MEM_REGIONS =0x02, ++ /* Init local interrupt config*/ ++ VLYNQ_INIT_LOCAL_INTERRUPTS =0x04, ++ /* Init remote interrupt config*/ ++ VLYNQ_INIT_REMOTE_INTERRUPTS =0x08, ++ /* Check link during initialization*/ ++ VLYNQ_INIT_CHECK_LINK =0x10, ++ /* configure clock during init */ ++ VLYNQ_INIT_CONFIG_CLOCK =0x20, ++ /* Clear errors during init */ ++ VLYNQ_INIT_CLEAR_ERRORS =0x40, ++ /* All options */ ++ VLYNQ_INIT_PERFORM_ALL =0x7F ++}VLYNQ_INIT_OPTIONS; ++ ++ ++/* VLYNQ_DEV_TYPE identifies local or remote device */ ++typedef enum ++{ ++ VLYNQ_LOCAL_DVC = 0, /* vlynq local device (SOC's vlynq module) */ ++ VLYNQ_REMOTE_DVC = 1 /* vlynq remote device (remote vlynq module) */ ++}VLYNQ_DEV_TYPE; ++ ++ ++/* VLYNQ_CLK_SOURCE identifies the vlynq module clock source */ ++typedef enum ++{ ++ VLYNQ_CLK_SOURCE_NONE = 0, /* do not initialize clock generator*/ ++ VLYNQ_CLK_SOURCE_LOCAL = 1, /* clock is generated by local machine */ ++ VLYNQ_CLK_SOURCE_REMOTE = 2 /* clock is generated by remote machine */ ++}VLYNQ_CLK_SOURCE; + -+#ifndef __TNETD73XX_MISC_H__ -+#define __TNETD73XX_MISC_H__ + -+/***************************************************************************** -+ * Reset Control Module -+ *****************************************************************************/ -+ -+typedef enum TNETD73XX_RESET_MODULE_tag ++/* VLYNQ_DRV_STATE indicates the current driver state */ ++typedef enum +{ -+ RESET_MODULE_UART0 = 0, -+ RESET_MODULE_UART1 = 1, -+ RESET_MODULE_I2C = 2, -+ RESET_MODULE_TIMER0 = 3, -+ RESET_MODULE_TIMER1 = 4, -+ RESET_MODULE_GPIO = 6, -+ RESET_MODULE_ADSLSS = 7, -+ RESET_MODULE_USBS = 8, -+ RESET_MODULE_SAR = 9, -+ RESET_MODULE_VDMA_VT = 11, -+ RESET_MODULE_FSER = 12, -+ RESET_MODULE_VLYNQ1 = 16, -+ RESET_MODULE_EMAC0 = 17, -+ RESET_MODULE_DMA = 18, -+ RESET_MODULE_BIST = 19, -+ RESET_MODULE_VLYNQ0 = 20, -+ RESET_MODULE_EMAC1 = 21, -+ RESET_MODULE_MDIO = 22, -+ RESET_MODULE_ADSLSS_DSP = 23, -+ RESET_MODULE_EPHY = 26 -+} TNETD73XX_RESET_MODULE_T; ++ VLYNQ_DRV_STATE_UNINIT = 0, /* driver is uninitialized */ ++ VLYNQ_DRV_STATE_ININIT = 1, /* VLYNQ is being initialized */ ++ VLYNQ_DRV_STATE_RUN = 2, /* VLYNQ is running properly */ ++ VLYNQ_DRV_STATE_HOLD = 3, /* driver stopped temporarily */ ++ VLYNQ_DRV_STATE_ERROR = 4 /* driver stopped on unrecoverable error */ ++}VLYNQ_DRV_STATE; + -+typedef enum TNETD73XX_RESET_CTRL_tag ++ ++/* VLYNQ_BUS_WIDTH identifies the vlynq module bus width */ ++typedef enum +{ -+ IN_RESET = 0, -+ OUT_OF_RESET -+} TNETD73XX_RESET_CTRL_T; ++ VLYNQ_BUS_WIDTH_3 = 3, ++ VLYNQ_BUS_WIDTH_5 = 5, ++ VLYNQ_BUS_WIDTH_7 = 7, ++ VLYNQ_BUS_WIDTH_9 = 9 ++}VLYNQ_BUS_WIDTH; + -+typedef enum TNETD73XX_SYS_RST_MODE_tag ++ ++/* VLYNQ_LOCAL_INT_CONFIG indicates whether the local vlynq ++ * interrupts are processed by the host or passed on to the ++ * remote device. ++ */ ++typedef enum +{ -+ RESET_SOC_WITH_MEMCTRL = 1, /* SW0 bit in SWRCR register */ -+ RESET_SOC_WITHOUT_MEMCTRL = 2 /* SW1 bit in SWRCR register */ -+} TNETD73XX_SYS_RST_MODE_T; ++ VLYNQ_INT_REMOTE = 0, /* Interrupt packets sent to remote, intlocal=0 */ ++ VLYNQ_INT_LOCAL = 1 /* Interrupts are handled locally, intlocal=1 */ ++}VLYNQ_LOCAL_INT_CONFIG; + -+typedef enum TNETD73XX_SYS_RESET_STATUS_tag ++ ++/* VLYNQ_REMOTE_INT_CONFIG indicates whether the remote ++ * interrupts are to be handled by the SOC system ISR ++ * or via the vlynq root ISR ++ */ ++typedef enum +{ -+ HARDWARE_RESET = 0, -+ SOFTWARE_RESET0, /* Caused by writing 1 to SW0 bit in SWRCR register */ -+ WATCHDOG_RESET, -+ SOFTWARE_RESET1 /* Caused by writing 1 to SW1 bit in SWRCR register */ -+} TNETD73XX_SYS_RESET_STATUS_T; ++ VLYNQ_INT_ROOT_ISR = 0, /* remote ints handled via vlynq root ISR */ ++ VLYNQ_INT_SYSTEM_ISR = 1 /* remote ints handled via system ISR */ ++}VLYNQ_REMOTE_INT_CONFIG; + -+void tnetd73xx_reset_ctrl(TNETD73XX_RESET_MODULE_T reset_module, -+ TNETD73XX_RESET_CTRL_T reset_ctrl); -+TNETD73XX_RESET_CTRL_T tnetd73xx_get_reset_status(TNETD73XX_RESET_MODULE_T reset_module); -+void tnetd73xx_sys_reset(TNETD73XX_SYS_RST_MODE_T mode); -+TNETD73XX_SYS_RESET_STATUS_T tnetd73xx_get_sys_last_reset_status(void); -+ -+/***************************************************************************** -+ * Power Control Module -+ *****************************************************************************/ + -+typedef enum TNETD73XX_POWER_MODULE_tag ++/* VLYNQ_INTR_POLARITY - vlynq interrupt polarity setting */ ++typedef enum +{ -+ POWER_MODULE_USBSP = 0, -+ POWER_MODULE_WDTP = 1, -+ POWER_MODULE_UT0P = 2, -+ POWER_MODULE_UT1P = 3, -+ POWER_MODULE_IICP = 4, -+ POWER_MODULE_VDMAP = 5, -+ POWER_MODULE_GPIOP = 6, -+ POWER_MODULE_VLYNQ1P = 7, -+ POWER_MODULE_SARP = 8, -+ POWER_MODULE_ADSLP = 9, -+ POWER_MODULE_EMIFP = 10, -+ POWER_MODULE_ADSPP = 12, -+ POWER_MODULE_RAMP = 13, -+ POWER_MODULE_ROMP = 14, -+ POWER_MODULE_DMAP = 15, -+ POWER_MODULE_BISTP = 16, -+ POWER_MODULE_TIMER0P = 18, -+ POWER_MODULE_TIMER1P = 19, -+ POWER_MODULE_EMAC0P = 20, -+ POWER_MODULE_EMAC1P = 22, -+ POWER_MODULE_EPHYP = 24, -+ POWER_MODULE_VLYNQ0P = 27, -+} TNETD73XX_POWER_MODULE_T; ++ VLYNQ_INTR_ACTIVE_HIGH = 0, ++ VLYNQ_INTR_ACTIVE_LOW = 1 ++}VLYNQ_INTR_POLARITY; + -+typedef enum TNETD73XX_POWER_CTRL_tag ++ ++/* VLYNQ_INTR_TYPE - vlynq interrupt type */ ++typedef enum +{ -+ POWER_CTRL_POWER_UP = 0, -+ POWER_CTRL_POWER_DOWN -+} TNETD73XX_POWER_CTRL_T; ++ VLYNQ_INTR_LEVEL = 0, ++ VLYNQ_INTR_PULSED = 1 ++}VLYNQ_INTR_TYPE; + -+typedef enum TNETD73XX_SYS_POWER_MODE_tag ++ ++/* VLYNQ_RESET_MODE - vlynq reset mode */ ++typedef enum +{ -+ GLOBAL_POWER_MODE_RUN = 0, /* All system is up */ -+ GLOBAL_POWER_MODE_IDLE, /* MIPS is power down, all peripherals working */ -+ GLOBAL_POWER_MODE_STANDBY, /* Chip in power down, but clock to ADSKL subsystem is running */ -+ GLOBAL_POWER_MODE_POWER_DOWN /* Total chip is powered down */ -+} TNETD73XX_SYS_POWER_MODE_T; ++ VLYNQ_RESET_ASSERT, /* hold device in reset state */ ++ VLYNQ_RESET_DEASSERT, /* release device from reset state */ ++ VLYNQ_RESET_INITFAIL, /* handle the device in case driver initialization fails */ ++ VLYNQ_RESET_LINKESTABLISH, /* handle the device in case driver established link */ ++ VLYNQ_RESET_INITFAIL2, /* Driver initialization failed but VLYNQ link exist. */ ++ VLYNQ_RESET_INITOK /* Driver initialization finished OK. */ ++}VLYNQ_RESET_MODE; ++ + -+void tnetd73xx_power_ctrl(TNETD73XX_POWER_MODULE_T power_module, TNETD73XX_POWER_CTRL_T power_ctrl); -+TNETD73XX_POWER_CTRL_T tnetd73xx_get_pwr_status(TNETD73XX_POWER_MODULE_T power_module); -+void tnetd73xx_set_global_pwr_mode(TNETD73XX_SYS_POWER_MODE_T power_mode); -+TNETD73XX_SYS_POWER_MODE_T tnetd73xx_get_global_pwr_mode(void); + -+/***************************************************************************** -+ * Wakeup Control -+ *****************************************************************************/ ++/************************************* ++ * Typedefs * ++ *************************************/ + -+typedef enum TNETD73XX_WAKEUP_INTERRUPT_tag -+{ -+ WAKEUP_INT0 = 1, -+ WAKEUP_INT1 = 2, -+ WAKEUP_INT2 = 4, -+ WAKEUP_INT3 = 8 -+} TNETD73XX_WAKEUP_INTERRUPT_T; ++struct VLYNQ_DEV_t; /*forward declaration*/ + -+typedef enum TNETD73XX_WAKEUP_CTRL_tag -+{ -+ WAKEUP_DISABLED = 0, -+ WAKEUP_ENABLED -+} TNETD73XX_WAKEUP_CTRL_T; ++/*--------Function Pointers defintions -----------*/ + -+typedef enum TNETD73XX_WAKEUP_POLARITY_tag -+{ -+ WAKEUP_ACTIVE_HIGH = 0, -+ WAKEUP_ACTIVE_LOW -+} TNETD73XX_WAKEUP_POLARITY_T; ++/* prototype for interrupt handler definition */ ++typedef void (*VLYNQ_INTR_CNTRL_ISR)(void *arg1,void *arg2,void *arg3); + -+void tnetd73xx_wakeup_ctrl(TNETD73XX_WAKEUP_INTERRUPT_T wakeup_int, -+ TNETD73XX_WAKEUP_CTRL_T wakeup_ctrl, -+ TNETD73XX_WAKEUP_POLARITY_T wakeup_polarity); ++typedef void ++(*VLYNQ_RESET_REMOTE)(struct VLYNQ_DEV_t *pDev, VLYNQ_RESET_MODE mode); + -+/***************************************************************************** -+ * FSER Control -+ *****************************************************************************/ -+ -+typedef enum TNETD73XX_FSER_MODE_tag -+{ -+ FSER_I2C = 0, -+ FSER_UART = 1 -+} TNETD73XX_FSER_MODE_T; ++typedef void ++(*VLYNQ_REPORT_CB)( struct VLYNQ_DEV_t *pDev, /* This VLYNQ */ ++ VLYNQ_DEV_TYPE aSrcDvc, /* Event Cause -local/remote? */ ++ UINT32 dwStatRegVal); /* Value of the relevant status register */ + -+void tnetd73xx_fser_ctrl(TNETD73XX_FSER_MODE_T fser_mode); + -+/***************************************************************************** -+ * Clock Control -+ *****************************************************************************/ ++/*-------Structure Definitions------------*/ + -+#define CLK_MHZ(x) ( (x) * 1000000 ) ++typedef struct VLYNQ_MEMORY_MAP_t ++{ ++ UINT32 Txmap; ++ UINT32 RxOffset[VLYNQ_MAX_MEMORY_REGIONS]; ++ UINT32 RxSize[VLYNQ_MAX_MEMORY_REGIONS]; ++}VLYNQ_MEMORY_MAP; + -+typedef enum TNETD73XX_CLKC_ID_tag ++ ++/**VLYNQ_INTERRUPT_CNTRL - defines the vlynq module interrupt ++ * settings in vlynq Control register */ ++typedef struct VLYNQ_INTERRUPT_CNTRL_t +{ -+ CLKC_SYS = 0, -+ CLKC_MIPS, -+ CLKC_USB, -+ CLKC_ADSLSS -+} TNETD73XX_CLKC_ID_T; ++ /* vlynq interrupts handled by host or remote - maps to ++ * intLocal bit in vlynq control register */ ++ VLYNQ_LOCAL_INT_CONFIG intLocal; ++ ++ /* remote interrupts handled by vlynq isr or host system ++ * interrupt controller - maps to the int2Cfg in vlynq ++ * control register */ ++ VLYNQ_REMOTE_INT_CONFIG intRemote; ++ ++ /* bit in pending/set register used for module interrupts*/ ++ UINT32 map_vector; ++ ++ /* used only if remote interrupts are to be handled by system ISR*/ ++ UINT32 intr_ptr; + -+void tnetd73xx_clkc_init(__u32 afeclk, __u32 refclk, __u32 xtal3in); -+TNETD73XX_ERR tnetd73xx_clkc_set_freq(TNETD73XX_CLKC_ID_T clk_id, __u32 output_freq); -+__u32 tnetd73xx_clkc_get_freq(TNETD73XX_CLKC_ID_T clk_id); ++}VLYNQ_INTERRUPT_CNTRL; + -+/***************************************************************************** -+ * GPIO Control -+ *****************************************************************************/ + -+typedef enum TNETD73XX_GPIO_PIN_tag ++/* VLYNQ_INTR_CNTRL_ICB - defines the Interrupt control block which hold ++ * the interrupt dispatch table. The vlynq_root_isr() indexes into this ++ * table to identify the ISR to be invoked ++ */ ++typedef struct VLYNQ_INTR_CNTRL_ICB_t +{ -+ GPIO_UART0_RD = 0, -+ GPIO_UART0_TD = 1, -+ GPIO_UART0_RTS = 2, -+ GPIO_UART0_CTS = 3, -+ GPIO_FSER_CLK = 4, -+ GPIO_FSER_D = 5, -+ GPIO_EXT_AFE_SCLK = 6, -+ GPIO_EXT_AFE_TX_FS = 7, -+ GPIO_EXT_AFE_TXD = 8, -+ GPIO_EXT_AFE_RS_FS = 9, -+ GPIO_EXT_AFE_RXD1 = 10, -+ GPIO_EXT_AFE_RXD0 = 11, -+ GPIO_EXT_AFE_CDIN = 12, -+ GPIO_EXT_AFE_CDOUT = 13, -+ GPIO_EPHY_SPEED100 = 14, -+ GPIO_EPHY_LINKON = 15, -+ GPIO_EPHY_ACTIVITY = 16, -+ GPIO_EPHY_FDUPLEX = 17, -+ GPIO_EINT0 = 18, -+ GPIO_EINT1 = 19, -+ GPIO_MBSP0_TCLK = 20, -+ GPIO_MBSP0_RCLK = 21, -+ GPIO_MBSP0_RD = 22, -+ GPIO_MBSP0_TD = 23, -+ GPIO_MBSP0_RFS = 24, -+ GPIO_MBSP0_TFS = 25, -+ GPIO_MII_DIO = 26, -+ GPIO_MII_DCLK = 27, -+} TNETD73XX_GPIO_PIN_T; ++ VLYNQ_INTR_CNTRL_ISR isr; /* Clear errors during initialization */ ++ void *arg1 ; /* Arg 1 for the ISR */ ++ void *arg2 ; /* Arg 2 for the ISR */ ++ void *arg3 ; /* Arg 3 for the ISR */ ++ UINT32 isrCount; /* number of ISR invocations so far */ ++ struct VLYNQ_INTR_CNTRL_ICB_t *next; ++}VLYNQ_INTR_CNTRL_ICB; ++ ++/* overlay of vlynq register set */ ++typedef struct VLYNQ_REG_SET_t ++{ ++ UINT32 revision; /*offset : 0x00 */ ++ UINT32 control; /* 0x04*/ ++ UINT32 status; /* 0x08*/ ++ UINT32 pad1; /* 0x0c*/ ++ UINT32 intStatus; /*0x10*/ ++ UINT32 intPending; /*0x14*/ ++ UINT32 intPtr; /*0x18*/ ++ UINT32 txMap; /*0x1C*/ ++ UINT32 rxSize1; /*0x20*/ ++ UINT32 rxOffset1; /*0x24*/ ++ UINT32 rxSize2; /*0x28*/ ++ UINT32 rxOffset2; /*0x2C*/ ++ UINT32 rxSize3; /*0x30*/ ++ UINT32 rxOffset3; /*0x34*/ ++ UINT32 rxSize4; /*0x38*/ ++ UINT32 rxOffset4; /*0x3C*/ ++ UINT32 chipVersion; /*0x40*/ ++ UINT32 pad2[8]; ++ UINT32 ivr30; /*0x60*/ ++ UINT32 ivr74; /*0x64*/ ++ UINT32 pad3[7]; ++}VLYNQ_REG_SET; ++ + -+typedef enum TNETD73XX_GPIO_PIN_MODE_tag ++typedef struct VLYNQ_DEV_t +{ -+ FUNCTIONAL_PIN = 0, -+ GPIO_PIN = 1 -+} TNETD73XX_GPIO_PIN_MODE_T; ++ /** module index:1,2,3... used for debugging purposes */ ++ UINT32 dev_idx; ++ ++ /*VLYNQ module base address */ ++ UINT32 module_base; ++ ++ /* clock source selection */ ++ VLYNQ_CLK_SOURCE clk_source; ++ ++ /* Clock Divider.Val=1 to 8. VLYNQ_clk = VBUSCLK/clk_div */ ++ UINT32 clk_div; ++ ++ /* State of the VLYNQ driver, set to VLYNQ_DRV_STATE_UNINIT, when initializing */ ++ VLYNQ_DRV_STATE state; ++ ++ /* Valid VLYNQ bus width, filled by driver */ ++ VLYNQ_BUS_WIDTH width; ++ ++ /* local memory mapping */ ++ VLYNQ_MEMORY_MAP local_mem; ++ ++ /* remote memory mapping */ ++ VLYNQ_MEMORY_MAP remote_mem; ++ ++ /* Local module interrupt params */ ++ VLYNQ_INTERRUPT_CNTRL local_irq; ++ ++ /* remote module interrupt params */ ++ VLYNQ_INTERRUPT_CNTRL remote_irq; ++ ++ /*** ICB related fields **/ ++ ++ /* Sizeof of ICB = VLYNQ_NUM_INT_BITS(for 32 bits in IntPending) + ++ * expansion slots for shared interrupts*/ ++ VLYNQ_INTR_CNTRL_ICB pIntrCB[VLYNQ_NUM_INT_BITS + VLYNQ_IVR_CHAIN_SLOTS]; ++ VLYNQ_INTR_CNTRL_ICB *freelist; ++ ++ /* table holding mapping between intVector and the bit position the interrupt ++ * is mapped to(mapVector)*/ ++ INT8 vector_map[32]; ++ ++ /* user callback for vlynq events, NULL if unused */ ++ VLYNQ_REPORT_CB report_cb; ++ ++ /* user callback for resetting/realeasing remote device */ ++ VLYNQ_RESET_REMOTE reset_cb; + -+typedef enum TNETD73XX_GPIO_PIN_DIRECTION_tag ++ /*** Handles provided for direct access to register set if need be ++ * Must be intialized to point to appropriate address during ++ * vlynq_init */ ++ volatile VLYNQ_REG_SET * local; ++ volatile VLYNQ_REG_SET * remote; ++ ++ UINT32 intCount; /* number of interrupts generated so far */ ++ UINT32 isrCount; /* number of ISR invocations so far */ ++}VLYNQ_DEV; ++ ++ ++typedef struct VLYNQ_ISR_ARGS_t +{ -+ GPIO_OUTPUT_PIN = 0, -+ GPIO_INPUT_PIN = 1 -+} TNETD73XX_GPIO_PIN_DIRECTION_T; -+ -+void tnetd73xx_gpio_init(void); -+void tnetd73xx_gpio_ctrl(TNETD73XX_GPIO_PIN_T gpio_pin, -+ TNETD73XX_GPIO_PIN_MODE_T pin_mode, -+ TNETD73XX_GPIO_PIN_DIRECTION_T pin_direction); -+void tnetd73xx_gpio_out(TNETD73XX_GPIO_PIN_T gpio_pin, int value); -+int tnetd73xx_gpio_in(TNETD73XX_GPIO_PIN_T gpio_pin); ++ int irq; ++ void * arg; ++ void * regset; ++}VLYNQ_ISR_ARGS; + -+/* TNETD73XX Revision */ -+__u32 tnetd73xx_get_revision(void); + -+#endif /* __TNETD73XX_MISC_H__ */ -diff -urN kernel-base/include/asm-mips/io.h kernel-current/include/asm-mips/io.h ---- kernel-base/include/asm-mips/io.h 2005-07-10 03:00:44.797179400 +0200 -+++ kernel-current/include/asm-mips/io.h 2005-07-10 06:40:39.624260784 +0200 -@@ -63,8 +63,12 @@ ++/**************************************** ++ * Function Prototypes * ++ * API exported by generic vlynq driver * ++ ****************************************/ ++/* Initialization function */ ++GLOBAL INT32 vlynq_init( VLYNQ_DEV *pdev, VLYNQ_INIT_OPTIONS options); ++ ++/* Check vlynq link */ ++GLOBAL UINT32 vlynq_link_check( VLYNQ_DEV * pdev); ++ ++/* Set interrupt vector in local or remote device */ ++GLOBAL INT32 vlynq_interrupt_vector_set( VLYNQ_DEV *pdev, ++ UINT32 int_vector, ++ UINT32 map_vector, ++ VLYNQ_DEV_TYPE dev, ++ VLYNQ_INTR_POLARITY pol, ++ VLYNQ_INTR_TYPE type); ++ ++ ++GLOBAL INT32 vlynq_interrupt_vector_cntl( VLYNQ_DEV *pdev, ++ UINT32 int_vector, ++ VLYNQ_DEV_TYPE dev, ++ UINT32 enable); ++ ++GLOBAL UINT32 vlynq_interrupt_get_count( VLYNQ_DEV *pdev, ++ UINT32 map_vector); ++ ++GLOBAL INT32 vlynq_install_isr( VLYNQ_DEV *pdev, ++ UINT32 map_vector, ++ VLYNQ_INTR_CNTRL_ISR isr, ++ void *arg1, void *arg2, void *arg3); ++ ++GLOBAL INT32 vlynq_uninstall_isr( VLYNQ_DEV *pdev, ++ UINT32 map_vector, ++ void *arg1, void *arg2, void *arg3); ++ ++ ++GLOBAL void vlynq_root_isr(void *arg); ++ ++GLOBAL void vlynq_delay(UINT32 clktime); ++ ++/* The following functions, provide better granularity in setting ++ * interrupt parameters. (for better support of linux INT Controller) ++ * Note: The interrupt source is identified by "map_vector"- the bit ++ * position in interrupt status register*/ ++ ++GLOBAL INT32 vlynq_interrupt_vector_map(VLYNQ_DEV * pdev, ++ VLYNQ_DEV_TYPE dev, ++ UINT32 int_vector, ++ UINT32 map_vector); ++ ++GLOBAL INT32 vlynq_interrupt_set_polarity(VLYNQ_DEV * pdev, ++ VLYNQ_DEV_TYPE dev, ++ UINT32 map_vector, ++ VLYNQ_INTR_POLARITY pol); ++ ++GLOBAL INT32 vlynq_interrupt_get_polarity( VLYNQ_DEV *pdev , ++ VLYNQ_DEV_TYPE dev_type, ++ UINT32 map_vector); ++ ++GLOBAL INT32 vlynq_interrupt_set_type(VLYNQ_DEV * pdev, ++ VLYNQ_DEV_TYPE dev, ++ UINT32 map_vector, ++ VLYNQ_INTR_TYPE type); ++ ++GLOBAL INT32 vlynq_interrupt_get_type( VLYNQ_DEV *pdev, ++ VLYNQ_DEV_TYPE dev_type, ++ UINT32 map_vector); ++ ++GLOBAL INT32 vlynq_interrupt_enable(VLYNQ_DEV* pdev, ++ VLYNQ_DEV_TYPE dev, ++ UINT32 map_vector); ++ ++GLOBAL INT32 vlynq_interrupt_disable(VLYNQ_DEV * pdev, ++ VLYNQ_DEV_TYPE dev, ++ UINT32 map_vector); ++ ++ ++ ++ ++ ++#endif /* _VLYNQ_HAL_H_ */ +diff -urN linux.old/include/asm-mips/ar7/vlynq_hal_params.h linux.dev/include/asm-mips/ar7/vlynq_hal_params.h +--- linux.old/include/asm-mips/ar7/vlynq_hal_params.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux.dev/include/asm-mips/ar7/vlynq_hal_params.h 2005-11-10 01:10:46.095590250 +0100 +@@ -0,0 +1,50 @@ ++/*************************************************************************** ++**+----------------------------------------------------------------------+** ++**| **** |** ++**| **** |** ++**| ******o*** |** ++**| ********_///_**** |** ++**| ***** /_//_/ **** |** ++**| ** ** (__/ **** |** ++**| ********* |** ++**| **** |** ++**| *** |** ++**| |** ++**| Copyright (c) 2003 Texas Instruments Incorporated |** ++**| ALL RIGHTS RESERVED |** ++**| |** ++**| Permission is hereby granted to licensees of Texas Instruments |** ++**| Incorporated (TI) products to use this computer program for the sole |** ++**| purpose of implementing a licensee product based on TI products. |** ++**| No other rights to reproduce, use, or disseminate this computer |** ++**| program, whether in part or in whole, are granted. |** ++**| |** ++**| TI makes no representation or warranties with respect to the |** ++**| performance of this computer program, and specifically disclaims |** ++**| any responsibility for any damages, special or consequential, |** ++**| connected with the use of this program. |** ++**| |** ++**+----------------------------------------------------------------------+** ++***************************************************************************/ ++ ++/* This file defines Vlynq module parameters*/ ++ ++#ifndef _VLYNQ_HAL_PARAMS_H ++#define _VLYNQ_HAL_PARAMS_H ++ ++ /* number of VLYNQ memory regions supported */ ++#define VLYNQ_MAX_MEMORY_REGIONS 0x04 ++ ++ /* Max.number of external interrupt inputs supported by VLYNQ module */ ++#define VLYNQ_IVR_MAXIVR 0x08 ++ ++#define VLYNQ_CLK_DIV_MAX 0x08 ++#define VLYNQ_CLK_DIV_MIN 0x01 ++ ++ ++/*** the total number of entries allocated for ICB would be ++ * 32(for 32 bits in IntPending register) + VLYNQ_IVR_CHAIN_SLOTS*/ ++#define VLYNQ_IVR_CHAIN_SLOTS 10 ++ ++ ++#endif /* _VLYNQ_HAL_PARAMS_H */ +diff -urN linux.old/include/asm-mips/io.h linux.dev/include/asm-mips/io.h +--- linux.old/include/asm-mips/io.h 2003-08-25 13:44:43.000000000 +0200 ++++ linux.dev/include/asm-mips/io.h 2005-11-10 01:14:16.400733500 +0100 +@@ -61,9 +61,9 @@ + * Change "struct page" to physical address. + */ #ifdef CONFIG_64BIT_PHYS_ADDR - #define page_to_phys(page) ((u64)(page - mem_map) << PAGE_SHIFT) +-#define page_to_phys(page) ((u64)(page - mem_map) << PAGE_SHIFT) ++#define page_to_phys(page) (((u64)(page - mem_map) << PAGE_SHIFT) + PHYS_OFFSET) #else -+#ifdef CONFIG_AR7_PAGING -+#define page_to_phys(page) (((page - mem_map) << PAGE_SHIFT) + CONFIG_AR7_MEMORY) -+#else - #define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT) +-#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT) ++#define page_to_phys(page) (((page - mem_map) << PAGE_SHIFT) + PHYS_OFFSET) #endif -+#endif #define IO_SPACE_LIMIT 0xffff - -diff -urN kernel-base/include/asm-mips/irq.h kernel-current/include/asm-mips/irq.h ---- kernel-base/include/asm-mips/irq.h 2005-07-10 03:00:44.798179248 +0200 -+++ kernel-current/include/asm-mips/irq.h 2005-07-10 06:40:39.624260784 +0200 -@@ -14,7 +14,12 @@ +diff -urN linux.old/include/asm-mips/irq.h linux.dev/include/asm-mips/irq.h +--- linux.old/include/asm-mips/irq.h 2003-08-25 13:44:43.000000000 +0200 ++++ linux.dev/include/asm-mips/irq.h 2005-11-10 01:12:43.950955750 +0100 +@@ -14,7 +14,20 @@ #include #include +#ifdef CONFIG_AR7 -+#include -+#define NR_IRQS AVALANCHE_INT_END + 1 ++/* MIPS has 8 irqs ++ * AR7 has 40 primary and 32 secondary irqs ++ * vlynq0 has 32 irqs ++ * vlynq1 has 32 irqs ++ */ ++#ifdef CONFIG_AR7_VLYNQ ++#define NR_IRQS (80 + 32 * CONFIG_AR7_VLYNQ_PORTS) ++#else ++#define NR_IRQS 80 ++#endif +#else #define NR_IRQS 128 /* Largest number of ints of all machines. */ +#endif #ifdef CONFIG_I8259 static inline int irq_cannonicalize(int irq) -diff -urN kernel-base/include/asm-mips/page.h kernel-current/include/asm-mips/page.h ---- kernel-base/include/asm-mips/page.h 2005-07-10 03:00:44.798179248 +0200 -+++ kernel-current/include/asm-mips/page.h 2005-07-10 06:40:39.625260632 +0200 -@@ -129,7 +129,11 @@ +diff -urN linux.old/include/asm-mips/mips-boards/prom.h linux.dev/include/asm-mips/mips-boards/prom.h +--- linux.old/include/asm-mips/mips-boards/prom.h 2001-09-09 19:43:02.000000000 +0200 ++++ linux.dev/include/asm-mips/mips-boards/prom.h 2005-11-10 01:14:16.436735750 +0100 +@@ -33,7 +33,7 @@ + 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 unsigned long 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); +diff -urN linux.old/include/asm-mips/page.h linux.dev/include/asm-mips/page.h +--- linux.old/include/asm-mips/page.h 2004-02-18 14:36:32.000000000 +0100 ++++ linux.dev/include/asm-mips/page.h 2005-11-10 01:14:16.436735750 +0100 +@@ -12,6 +12,7 @@ + + #include + #include ++#include + + #ifdef __KERNEL__ + +@@ -129,7 +130,7 @@ #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) -+#ifdef CONFIG_AR7_PAGING -+#define virt_to_page(kaddr) phys_to_page(__pa(kaddr)) -+#else - #define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT)) -+#endif +-#define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT)) ++#define virt_to_page(kaddr) (mem_map + ((__pa(kaddr)-PHYS_OFFSET) >> PAGE_SHIFT)) #define VALID_PAGE(page) ((page - mem_map) < max_mapnr) #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ -diff -urN kernel-base/include/asm-mips/pgtable-32.h kernel-current/include/asm-mips/pgtable-32.h ---- kernel-base/include/asm-mips/pgtable-32.h 2005-07-10 03:00:44.798179248 +0200 -+++ kernel-current/include/asm-mips/pgtable-32.h 2005-07-10 06:40:39.625260632 +0200 -@@ -108,7 +108,18 @@ +diff -urN linux.old/include/asm-mips/pgtable-32.h linux.dev/include/asm-mips/pgtable-32.h +--- linux.old/include/asm-mips/pgtable-32.h 2004-02-18 14:36:32.000000000 +0100 ++++ linux.dev/include/asm-mips/pgtable-32.h 2005-11-10 01:14:16.436735750 +0100 +@@ -108,7 +108,7 @@ * and a page entry and page directory to the page they refer to. */ -#ifdef CONFIG_CPU_VR41XX -+#if defined(CONFIG_AR7_PAGING) -+#define mk_pte(page, pgprot) \ -+({ \ -+ pte_t __pte; \ -+ \ -+ pte_val(__pte) = ((phys_t)(page - mem_map) << (PAGE_SHIFT) | \ -+ CONFIG_AR7_MEMORY) | \ -+ pgprot_val(pgprot); \ -+ \ -+ __pte; \ -+}) -+#elif defined(CONFIG_CPU_VR41XX) ++#if defined(CONFIG_CPU_VR41XX) #define mk_pte(page, pgprot) \ ({ \ pte_t __pte; \ -@@ -130,6 +141,7 @@ +@@ -123,13 +123,14 @@ + ({ \ + pte_t __pte; \ + \ +- pte_val(__pte) = ((phys_t)(page - mem_map) << PAGE_SHIFT) | \ +- pgprot_val(pgprot); \ ++ pte_val(__pte) = (((phys_t)(page - mem_map) << PAGE_SHIFT) + \ ++ PHYS_OFFSET) | pgprot_val(pgprot); \ + \ + __pte; \ }) #endif @@ -6291,27 +15573,32 @@ diff -urN kernel-base/include/asm-mips/pgtable-32.h kernel-current/include/asm-m static inline pte_t mk_pte_phys(phys_t physpage, pgprot_t pgprot) { #ifdef CONFIG_CPU_VR41XX -@@ -175,7 +187,10 @@ +@@ -175,12 +176,12 @@ set_pte(ptep, __pte(0)); } -#ifdef CONFIG_CPU_VR41XX -+#if defined(CONFIG_AR7_PAGING) -+#define phys_to_page(phys) (mem_map + (((phys)-CONFIG_AR7_MEMORY) >> PAGE_SHIFT)) -+#define pte_page(x) phys_to_page(pte_val(x)) -+#elif defined(CONFIG_CPU_VR41XX) ++#if defined(CONFIG_CPU_VR41XX) #define pte_page(x) (mem_map+((unsigned long)(((x).pte_low >> (PAGE_SHIFT+2))))) #define __mk_pte(page_nr,pgprot) __pte(((page_nr) << (PAGE_SHIFT+2)) | pgprot_val(pgprot)) #else -diff -urN kernel-base/include/asm-mips/serial.h kernel-current/include/asm-mips/serial.h ---- kernel-base/include/asm-mips/serial.h 2005-07-10 03:00:44.799179096 +0200 -+++ kernel-current/include/asm-mips/serial.h 2005-07-10 06:40:39.625260632 +0200 -@@ -65,6 +65,15 @@ +-#define pte_page(x) (mem_map+((unsigned long)(((x).pte_low >> PAGE_SHIFT)))) +-#define __mk_pte(page_nr,pgprot) __pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot)) ++#define pte_page(x) (mem_map+((unsigned long)((((x).pte_low-PHYS_OFFSET) >> PAGE_SHIFT)))) ++#define __mk_pte(page_nr,pgprot) __pte((((page_nr) << PAGE_SHIFT)+PHYS_OFFSET)|pgprot_val(pgprot)) + #endif + + #endif +diff -urN linux.old/include/asm-mips/serial.h linux.dev/include/asm-mips/serial.h +--- linux.old/include/asm-mips/serial.h 2005-01-19 15:10:12.000000000 +0100 ++++ linux.dev/include/asm-mips/serial.h 2005-11-10 01:14:16.436735750 +0100 +@@ -65,6 +65,16 @@ #define C_P(card,port) (((card)<<6|(port)<<3) + 1) +#ifdef CONFIG_AR7 +#include ++#include +#define AR7_SERIAL_PORT_DEFNS \ + { 0, AR7_BASE_BAUD, AR7_UART0_REGS_BASE, LNXINTNUM(AVALANCHE_UART0_INT), STD_COM_FLAGS }, \ + { 0, AR7_BASE_BAUD, AR7_UART1_REGS_BASE, LNXINTNUM(AVALANCHE_UART1_INT), STD_COM_FLAGS }, @@ -6322,7 +15609,7 @@ diff -urN kernel-base/include/asm-mips/serial.h kernel-current/include/asm-mips/ #ifdef CONFIG_MIPS_JAZZ #define _JAZZ_SERIAL_INIT(int, base) \ { .baud_base = JAZZ_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS, \ -@@ -468,6 +477,7 @@ +@@ -468,6 +478,7 @@ #endif #define SERIAL_PORT_DFNS \ @@ -6330,15 +15617,3 @@ diff -urN kernel-base/include/asm-mips/serial.h kernel-current/include/asm-mips/ ATLAS_SERIAL_PORT_DEFNS \ AU1000_SERIAL_PORT_DEFNS \ COBALT_SERIAL_PORT_DEFNS \ -diff -urN kernel-base/Makefile kernel-current/Makefile ---- kernel-base/Makefile 2005-07-10 03:00:44.799179096 +0200 -+++ kernel-current/Makefile 2005-07-10 06:40:39.626260480 +0200 -@@ -91,7 +91,7 @@ - - CPPFLAGS := -D__KERNEL__ -I$(HPATH) - --CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ -+CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -Os \ - -fno-strict-aliasing -fno-common - ifndef CONFIG_FRAME_POINTER - CFLAGS += -fomit-frame-pointer