diff -urN linux.old/Makefile linux.dev/Makefile --- linux.old/Makefile 2005-10-21 16:43:16.316951500 +0200 +++ linux.dev/Makefile 2005-10-21 16:45:42.294074500 +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 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-10-21 16:45:42.134064500 +0200 @@ -369,6 +369,16 @@ endif # +# Texas Instruments AR7 +# + +ifdef CONFIG_AR7 +LIBS += arch/mips/ar7/ar7.o +SUBDIRS += arch/mips/ar7 +LOADADDR += 0x94020000 +endif + +# # 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-10-21 17:02:14.507635750 +0200 @@ -0,0 +1,14 @@ +.S.s: + $(CPP) $(AFLAGS) $< -o $*.s + +.S.o: + $(CC) $(AFLAGS) -c $< -o $*.o + +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 mipsIRQ.o reset.o init.o psp_env.o memory.o printf.o cmdline.o time.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-10-21 16:45:42.090061750 +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 + +#include + +extern int prom_argc; +extern int *_prom_argv; + +/* + * 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)])) + +char arcs_cmdline[CL_SIZE]; + +char * __init prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + + +void __init prom_init_cmdline(void) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); +#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 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-10-21 17:02:14.507635750 +0200 @@ -0,0 +1,199 @@ +/* + * 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 + +#include +#include +#include + +#include + +int prom_argc; +int *_prom_argv, *_prom_envp; + +/* max # of Adam2 environment variables */ +#define MAX_ENV_ENTRY 80 + +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 *prom_psp_getenv(char *envname); + +static inline char *prom_adam2_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; + t_env_var *env = (t_env_var *) local_envp; + + if (strcmp("bootloader", envname) == 0) + return "Adam2"; + + i = strlen(envname); + while (env->name) { + if(strncmp(envname, env->name, i) == 0) { + return(env->val); + } + env++; + } + + return NULL; +} + +/* 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; +} + +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); +} + +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 */ +} + +static inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ + int i; + + for (i = 0; i < 6; i++) { + unsigned char num; + + if((*str == '.') || (*str == ':')) + str++; + num = str2hexnum(*str++) << 4; + num |= (str2hexnum(*str++)); + ea[i] = num; + } +} + +int get_ethernet_addr(char *ethernet_addr) +{ + char *ethaddr_str; + + 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)); + } + + return 0; +} + +struct psbl_rec { + unsigned int psbl_size; + unsigned int env_base; + unsigned int env_size; + unsigned int ffs_base; + unsigned int ffs_size; +}; + +static const char psp_env_version[] = "TIENV0.8"; + +int __init prom_init(int argc, char **argv, char **envp) +{ + int i; + + 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); + + prom_argc = argc; + _prom_argv = (int *)argv; + _prom_envp = (int *)envp; + + if(strcmp(psp_env, psp_env_version) == 0) { + /* PSPBOOT */ + + 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 + */ + + 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(); + + return 0; +} 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-10-21 17:02:14.507635750 +0200 @@ -0,0 +1,925 @@ +/* + * 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 +#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}}; + + +unsigned long spurious_count = 0; + +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 */ + +extern asmlinkage void mipsIRQ(void); + +#ifdef CONFIG_AR7_VLYNQ +#include +extern VLYNQ_DEV vlynqDevice0, vlynqDevice1; +#endif + +/* + * 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) + * + */ + + +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 +}; + +/* + This remaps interrupts to exist on other channels than the default + channels. essentially we can use the line # as the index for this + array + */ + + +static unsigned long line_to_channel[AVINTNUM(AVALANCHE_INT_END_PRIMARY)]; +unsigned long uni_secondary_interrupt = 0; + +static struct irqaction r4ktimer_action = { + NULL, 0, 0, "R4000 timer/counter", NULL, NULL, +}; + +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 */ +}; + +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; + + if(irq_nr >= AVALANCHE_INT_END) + { + printk(KERN_ERR "%s: whee, invalid irq_nr %d\n", + __FUNCTION__, irq_nr); + panic("IRQ, you lose..."); + } + + save_and_cli(flags); + + + if(irq_nr < MIPS_EXCEPTION_OFFSET) + { + /* disable mips exception */ + + int_bit = read_c0_status() & ~(1 << (8+irq_nr)); + change_c0_status(ST0_IM,int_bit); + restore_flags(flags); + return; + } + +#if defined (CONFIG_AR7_VLYNQ) + /* Vlynq irq_nr are 72-145 in the system and are placed after + * the interrupts managed by the interrupt controller. + */ + if(irq_nr >= AVALANCHE_INTC_END) + { + if(irq_nr >= AVALANCHE_INT_END_LOW_VLYNQ) + /* Vlynq interrupts 32-63 */ + vlynq_interrupt_disable(&vlynqDevice1,VLYNQ_REMOTE_DVC, + irq_nr-AVALANCHE_INT_END_LOW_VLYNQ); + else + /* Vlynq interupts 0-31 */ + vlynq_interrupt_disable(&vlynqDevice0,VLYNQ_REMOTE_DVC, + irq_nr-AVALANCHE_INTC_END); + + goto ret_from_disable_irq; + } +#endif + + /* 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); /*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 */ + + /* primary interrupt #'s 0-31 */ + + if(chan_nr <= AVINTNUM(AVALANCHE_INT_END_PRIMARY_REG1)) + avalanche_hw0_icregs->intecr1 = (1 << chan_nr); + + /* 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))); + + else /* secondary interrupt #'s 0-31 */ + avalanche_hw0_ecregs->exiecr = (1 << (chan_nr - AVINTNUM(AVALANCHE_INT_END_PRIMARY))); + +#if defined (CONFIG_AR7_VLYNQ) +ret_from_disable_irq: +#endif + + restore_flags(flags); +} + +void enable_avalanche_irq(unsigned int irq_nr) +{ + unsigned long flags; + unsigned long chan_nr=0; + unsigned long int_bit=0; + + if(irq_nr > AVALANCHE_INT_END) { + printk(KERN_ERR "%s: whee, invalid irq_nr %d\n", + __FUNCTION__, irq_nr); + panic("IRQ, you lose..."); + } + + save_and_cli(flags); + + + if(irq_nr < MIPS_EXCEPTION_OFFSET) + { + /* Enable MIPS exceptions */ + int_bit = read_c0_status(); + change_c0_status(ST0_IM,int_bit | (1<<(8+irq_nr))); + restore_flags(flags); + return; + } + +#if defined (CONFIG_AR7_VLYNQ) + /* Vlynq irq_nr are 80-143 in the system and are placed after + * the interrupts managed by the interrupt controller. + */ + if(irq_nr >= AVALANCHE_INTC_END) + { + if(irq_nr >= AVALANCHE_INT_END_LOW_VLYNQ) + /* Vlynq interrupts 32-63 */ + vlynq_interrupt_enable(&vlynqDevice1,VLYNQ_REMOTE_DVC, + irq_nr-AVALANCHE_INT_END_LOW_VLYNQ); + else + /* Vlynq interupts 0-31 */ + vlynq_interrupt_enable(&vlynqDevice0,VLYNQ_REMOTE_DVC, + irq_nr-AVALANCHE_INTC_END); + + goto ret_from_enable_irq; + } +#endif + + /* 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)]; + + /* 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); + + /* 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))); + +#if defined (CONFIG_AR7_VLYNQ) +ret_from_enable_irq: +#endif + + 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; + + for (i = 0; i < MIPS_EXCEPTION_OFFSET; i++, num++) + { + 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"); + } + + + for (i = 0; i < AVINTNUM(AVALANCHE_INT_END); i++,num++) + { + 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"); + + } + + 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; + + 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) + { + irq_action[irq] = action; + enable_avalanche_irq(irq); + return 0; + } + + 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; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction *action; + + if (irq > AVALANCHE_INT_END) { + printk(KERN_ERR "Trying to free IRQ%d\n",irq); + return; + } + + if(irq < MIPS_EXCEPTION_OFFSET) + { + action = irq_action[irq]; + irq_action[irq] = NULL; + irq_desc_ti[irq].action = NULL; + disable_avalanche_irq(irq); + kfree(action); + return; + } + + 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); +} + +#ifdef CONFIG_KGDB +extern void breakpoint(void); +extern int remote_debug; +#endif + + +//void init_IRQ(void) __init; +void __init init_IRQ(void) +{ + 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 */ + + + // avalanche_hw0_ipaceregs->ipacep = (2*get_avalanche_vbus_freq()/1000000)*4; + /* hack for speeding up the pacing. */ + printk(KERN_INFO "the pacing pre-scalar has been set as 600.\n"); + avalanche_hw0_ipaceregs->ipacep = 600; + /* Channel to line mapping, Line to Channel mapping */ + + for(i = 0; i < 40; i++) + avalanche_int_set(i,i); + + /* Now safe to set the exception vector. */ + set_except_vector(0, mipsIRQ); + + /* 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++) + { + 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; + } + +#ifdef CONFIG_KGDB + if (remote_debug) + { + set_debug_traps(); + breakpoint(); + } +#endif +} + +void avalanche_hw0_irqdispatch(struct pt_regs *regs) +{ + 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) + { + 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; + + if(chan_nr == uni_secondary_interrupt) + { + status = avalanche_hw0_ecregs->exsr; + for(i=0; i < AVINTNUM(AVALANCHE_INT_END_SECONDARY); i++) + { + if (status & 1<excr = 1 << i; + break; + } + } + 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 */ + + if(secondary) + action = hw0_irq_action_secondary[irq]; + else + action = hw0_irq_action_primary[irq]; + + /* if action == NULL, then we don't have a handler for the irq */ + + if ( action == NULL ) { + printk(KERN_ERR "No handler for hw0 irq: %i\n", irq); + return; + } + + irq_enter(cpu,irq); + if(secondary) + { + kstat.irqs[0][(irq + AVINTNUM(AVALANCHE_INT_END_PRIMARY)) + 8]++; + action->handler((irq + AVALANCHE_INT_END_PRIMARY), action->dev_id, regs); + } + else + { + kstat.irqs[0][irq + 8]++; + action->handler(LNXINTNUM(irq), action->dev_id, regs); + } + + irq_exit(cpu,irq); + + if(softirq_pending(cpu)) + do_softirq(); + + return; +} + +void avalanche_int_set(int channel, int line) +{ + switch(channel) + { + 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(KERN_ERR "Error: Unknown Avalanche interrupt channel\n"); + } + + line_to_channel[line] = channel; /* Suraj check */ + + if (channel == UNIFIED_SECONDARY_INTERRUPT) + uni_secondary_interrupt = line; + +} + + +#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) +{ + 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; + + save_and_cli(flags); + + /* 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); + + /* setup the new values */ + avalanche_hw0_ipaceregs->ipacemap |= ((AVINTNUM(irq_nr)) << blk_offset); + avalanche_hw0_ipaceregs->ipacemax |= ((0x80 | pace_value) << blk_offset); + + restore_flags(flags); + + return(0); +} + +/* Sets the trigger type: edge or level */ +int avalanche_intr_type_set(unsigned int irq_nr, unsigned long type_val) +{ + unsigned long flags; + unsigned long chan_nr=0; + + printk(KERN_NOTICE "AVALANCHE_INT_END_PRIMARY %d\n", + AVALANCHE_INT_END_PRIMARY); + printk(KERN_NOTICE "AVALANCHE_INT_END_SECONDARY %d\n", + AVALANCHE_INT_END_SECONDARY); + printk(KERN_NOTICE "AVALANCHE_INT_END %d\n", AVALANCHE_INT_END); + printk(KERN_NOTICE "AVALANCHE_INTC_END %d\n", AVALANCHE_INTC_END); + if(irq_nr < MIPS_EXCEPTION_OFFSET || + irq_nr >= AVALANCHE_INT_END) + { + printk(KERN_ERR "%s: whee, invalid irq_nr %d\n", + __FUNCTION__, irq_nr); + panic("IRQ, you lose..."); + return(-1); + } + + if(type_val > 1) + { + printk(KERN_ERR "Not a valid polarity value.\n"); + return(-1); + } + +#if defined (CONFIG_AR7_VLYNQ) + /* Vlynq irq_nr are 80-143 in the system and are placed after the interrupts + * managed by the interrupt controller. + */ + if(irq_nr >= AVALANCHE_INTC_END) + { + /* Type values for VLYNQ are INTC are different. */ + if(irq_nr >= AVALANCHE_INT_END_LOW_VLYNQ) + /* Vlynq interrupts 32-63 */ + vlynq_interrupt_set_type(&vlynqDevice1, VLYNQ_REMOTE_DVC, + irq_nr - AVALANCHE_INT_END_LOW_VLYNQ, !type_val); + else + /* Vlynq interupts 0-31 */ + vlynq_interrupt_set_type(&vlynqDevice0, VLYNQ_REMOTE_DVC, + irq_nr - AVALANCHE_INTC_END, !type_val); + + goto ret_from_set_type; + } +#endif + + irq_nr = AVINTNUM(irq_nr); + + chan_nr = line_to_channel[AVINTNUM(irq_nr)]; + + save_and_cli(flags); + + /* primary interrupt #'s 0-31 */ + if(chan_nr < AVALANCHE_INT_END_PRIMARY_REG1) + { + if(type_val) + avalanche_hw0_icregs->inttypr1 |= (1 << chan_nr); + else + avalanche_hw0_icregs->inttypr1 &= ~(1 << chan_nr); + } + /* primary interrupt #'s 32 throuth 39 */ + else + { + if(type_val) + avalanche_hw0_icregs->inttypr2 |= + (1 << (chan_nr - AVALANCHE_INT_END_PRIMARY_REG1)); + else + avalanche_hw0_icregs->inttypr2 &= + ~(1 << (chan_nr - AVALANCHE_INT_END_PRIMARY_REG1)); + } + + restore_flags(flags); + +#if defined (CONFIG_AR7_VLYNQ) +ret_from_set_type: +#endif + + return(0); +} + + +int avalanche_intr_polarity_set(unsigned int irq_nr, unsigned long polarity_val) +{ + unsigned long flags; + unsigned long chan_nr=0; + + if(irq_nr < MIPS_EXCEPTION_OFFSET || + irq_nr >= AVALANCHE_INT_END) + { + printk(KERN_ERR "%s: whee, invalid irq_nr %d\n", + __FUNCTION__, irq_nr); +#if defined (CONFIG_AR7_VLYNQ) + printk(KERN_ERR "Not one of the primary or vlynq avalanche interrupts.\n"); +#else + printk(KERN_ERR "Not one of the primary avalanche interrupts\n"); +#endif + panic("IRQ, you lose..."); + return(-1); + } + + if(polarity_val > 1) + { + printk(KERN_ERR "Not a valid polarity value.\n"); + return(-1); + } + + +#if defined (CONFIG_AR7_VLYNQ) + /* Vlynq irq_nr are 80-143 in the system and are placed after the interrupts + * managed by the interrupt controller. + */ + if(irq_nr >= AVALANCHE_INTC_END) + { + if(irq_nr >= AVALANCHE_INT_END_LOW_VLYNQ) + /* Vlynq interrupts 32-63 */ + vlynq_interrupt_set_polarity(&vlynqDevice1, VLYNQ_REMOTE_DVC, + irq_nr - AVALANCHE_INT_END_LOW_VLYNQ, polarity_val); + else + /* Vlynq interupts 0-31 */ + vlynq_interrupt_set_polarity(&vlynqDevice0, VLYNQ_REMOTE_DVC, + irq_nr - AVALANCHE_INTC_END, polarity_val); + goto ret_from_set_polarity; + } +#endif + + irq_nr = AVINTNUM(irq_nr); + + chan_nr = line_to_channel[irq_nr]; + + save_and_cli(flags); + + /* primary interrupt #'s 0-31 */ + if(chan_nr < AVALANCHE_INT_END_PRIMARY_REG1) + { + if(polarity_val) + avalanche_hw0_icregs->intpolr1 |= (1 << chan_nr); + else + avalanche_hw0_icregs->intpolr1 &= ~(1 << chan_nr); + } + /* primary interrupt #'s 32 throuth 39 */ + else + { + if(polarity_val) + avalanche_hw0_icregs->intpolr2 |= + (1 << (chan_nr - AVALANCHE_INT_END_PRIMARY_REG1)); + else + avalanche_hw0_icregs->intpolr2 &= + ~(1 << (chan_nr - AVALANCHE_INT_END_PRIMARY_REG1)); + } + + restore_flags(flags); + +#if defined (CONFIG_AR7_VLYNQ) +ret_from_set_polarity: +#endif + + return(0); +} + +EXPORT_SYMBOL(avalanche_intr_polarity_set); +EXPORT_SYMBOL(avalanche_intr_type_set); 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-10-21 16:45:42.090061750 +0200 @@ -0,0 +1,131 @@ +/* + * 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 + +#include +#include +#include + +enum yamon_memtypes { + yamon_dontuse, + yamon_prom, + yamon_free, +}; +struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; + +/* References to section boundaries */ +extern char _end; + +#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) + + +struct prom_pmemblock * __init prom_getmdesc(void) +{ + char *memsize_str; + unsigned int memsize; + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x02000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + + memset(mdesc, 0, sizeof(mdesc)); + + mdesc[0].type = yamon_dontuse; + mdesc[0].base = 0x00000000; + mdesc[0].size = CONFIG_AR7_MEMORY; + + mdesc[1].type = yamon_prom; + mdesc[1].base = CONFIG_AR7_MEMORY; + mdesc[1].size = 0x00020000; + + mdesc[2].type = yamon_free; + mdesc[2].base = CONFIG_AR7_MEMORY + 0x00020000; + mdesc[2].size = (memsize + CONFIG_AR7_MEMORY) - mdesc[2].base; + + return &mdesc[0]; +} + +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; + } +} + +void __init prom_meminit(void) +{ + struct prom_pmemblock *p; + + p = prom_getmdesc(); + + while (p->size) { + long type; + unsigned long base, size; + + type = prom_memtype_classify (p->type); + base = p->base; + size = p->size; + + add_memory_region(base, size, type); + p++; + } +} + +void __init prom_free_prom_memory (void) +{ +#if 0 + int i; + unsigned long freed = 0; + unsigned long addr; + + for (i = 0; i < boot_mem_map.nr_map; i++) { + if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) + continue; + + addr = boot_mem_map.map[i].addr; + while (addr < boot_mem_map.map[i].addr + + boot_mem_map.map[i].size) { + ClearPageReserved(virt_to_page(__va(addr))); + set_page_count(virt_to_page(__va(addr)), 1); + free_page((unsigned long)__va(addr)); + addr += PAGE_SIZE; + freed += PAGE_SIZE; + } + } + printk("Freeing prom memory: %ldkb freed\n", freed >> 10); +#endif +} diff -urN linux.old/arch/mips/ar7/mipsIRQ.S linux.dev/arch/mips/ar7/mipsIRQ.S --- linux.old/arch/mips/ar7/mipsIRQ.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.dev/arch/mips/ar7/mipsIRQ.S 2005-10-21 16:45:42.118063500 +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 + +#include +#include +#include +#include + +/* A lot of complication here is taken away because: + * + * 1) We handle one interrupt and return, sitting in a loop and moving across + * all the pending IRQ bits in the cause register is _NOT_ the answer, the + * common case is one pending IRQ so optimize in that direction. + * + * 2) We need not check against bits in the status register IRQ mask, that + * would make this routine slow as hell. + * + * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in + * between like BSD spl() brain-damage. + * + * Furthermore, the IRQs on the MIPS board look basically (barring software + * IRQs which we don't use at all and all external interrupt sources are + * combined together on hardware interrupt 0 (MIPS IRQ 2)) like: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Combined hardware interrupt (hw0) + * 3 Hardware (ignored) + * 4 Hardware (ignored) + * 5 Hardware (ignored) + * 6 Hardware (ignored) + * 7 R4k timer (what we use) + * + * Note: On the SEAD board thing are a little bit different. + * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired + * wired to UART1. + * + * We handle the IRQ according to _our_ priority which is: + * + * Highest ---- R4k Timer + * Lowest ---- Combined hardware interrupt + * + * then we just return, if multiple IRQs are pending then we will just take + * another exception, big deal. + */ + +.text +.set noreorder +.set noat + .align 5 +NESTED(mipsIRQ, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + + mfc0 s0, CP0_CAUSE # get irq bits + + /* First we check for r4k counter/timer IRQ. */ + andi a0, s0, CAUSEF_IP7 + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt + + /* Wheee, a timer interrupt. */ + move a0, sp + jal ar7_timer_interrupt + nop + + j ret_from_irq + nop + + 1: + beq a0, zero, 1f # delay slot, check hw3 interrupt + nop + + /* Wheee, combined hardware level zero interrupt. */ + jal avalanche_hw0_irqdispatch + move a0, sp # delay slot + + j ret_from_irq + nop # delay slot + + 1: + /* + * Here by mistake? This is possible, what can happen is that by the + * time we take the exception the IRQ pin goes low, so just leave if + * this is the case. + */ + move a1,s0 + 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 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-10-21 16:45:42.122063750 +0200 @@ -0,0 +1,319 @@ +#include +#include +#include +#include + +#define TRUE 1 + +static unsigned int avalanche_vbus_freq; + +REMOTE_VLYNQ_DEV_RESET_CTRL_FN p_remote_vlynq_dev_reset_ctrl = NULL; + +/***************************************************************************** + * Reset Control Module. + *****************************************************************************/ +void avalanche_reset_ctrl(unsigned int module_reset_bit, + AVALANCHE_RESET_CTRL_T reset_ctrl) +{ + volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR; + + if(module_reset_bit >= 32 && module_reset_bit < 64) + return; + + if(module_reset_bit >= 64) + { + if(p_remote_vlynq_dev_reset_ctrl) + return(p_remote_vlynq_dev_reset_ctrl(module_reset_bit - 64, reset_ctrl)); + else + return; + } + + if(reset_ctrl == OUT_OF_RESET) + *reset_reg |= 1 << module_reset_bit; + else + *reset_reg &= ~(1 << module_reset_bit); +} + +AVALANCHE_RESET_CTRL_T avalanche_get_reset_status(unsigned int module_reset_bit) +{ + volatile unsigned int *reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_PRCR; + + return (((*reset_reg) & (1 << module_reset_bit)) ? OUT_OF_RESET : IN_RESET ); +} + +void avalanche_sys_reset(AVALANCHE_SYS_RST_MODE_T mode) +{ + volatile unsigned int *sw_reset_reg = (unsigned int*) AVALANCHE_RST_CTRL_SWRCR; + *sw_reset_reg = mode; +} + +#define AVALANCHE_RST_CTRL_RSR_MASK 0x3 + +AVALANCHE_SYS_RESET_STATUS_T avalanche_get_sys_last_reset_status() +{ + volatile unsigned int *sys_reset_status = (unsigned int*) AVALANCHE_RST_CTRL_RSR; + + return ( (AVALANCHE_SYS_RESET_STATUS_T) (*sys_reset_status & AVALANCHE_RST_CTRL_RSR_MASK) ); +} + + +/***************************************************************************** + * Power Control Module + *****************************************************************************/ +#define AVALANCHE_GLOBAL_POWER_DOWN_MASK 0x3FFFFFFF /* bit 31, 30 masked */ +#define AVALANCHE_GLOBAL_POWER_DOWN_BIT 30 /* shift to bit 30, 31 */ + + +void avalanche_power_ctrl(unsigned int module_power_bit, AVALANCHE_POWER_CTRL_T power_ctrl) +{ + volatile unsigned int *power_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR; + + if (power_ctrl == POWER_CTRL_POWER_DOWN) + /* power down the module */ + *power_reg |= (1 << module_power_bit); + else + /* power on the 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; + + return (((*power_status_reg) & (1 << module_power_bit)) ? POWER_CTRL_POWER_DOWN : POWER_CTRL_POWER_UP); +} + +void avalanche_set_global_power_mode(AVALANCHE_SYS_POWER_MODE_T power_mode) +{ + volatile unsigned int *power_status_reg = (unsigned int*)AVALANCHE_POWER_CTRL_PDCR; + + *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((AVALANCHE_SYS_POWER_MODE_T) (((*power_status_reg) & (~AVALANCHE_GLOBAL_POWER_DOWN_MASK)) + >> AVALANCHE_GLOBAL_POWER_DOWN_BIT)); +} + +/***************************************************************************** + * 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) +{ + 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); + + if(pin_mode == GPIO_PIN) + { + *gpio_ctrl |= (1 << gpio_pin); + + 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); + + return (0); +} + +/**************************************************************************** + * FUNCTION: avalanche_gpio_out + ***************************************************************************/ +int avalanche_gpio_out_bit(unsigned int gpio_pin, int value) +{ + 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); + + return(0); +} + +/**************************************************************************** + * 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); + + 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; + + if(reg_index > 0) + return(-1); + + spin_lock_irqsave(&closeLock, closeFlag); + *gpio_out &= ~out_mask; + *gpio_out |= out_val; + spin_unlock_irqrestore(&closeLock, closeFlag); + + return(0); +} + +/**************************************************************************** + * FUNCTION: avalanche_gpio_in_value + ***************************************************************************/ +int avalanche_gpio_in_value(unsigned int* in_val, unsigned int reg_index) +{ + spinlock_t closeLock; + unsigned int closeFlag; + volatile unsigned int *gpio_in = (unsigned int*) AVALANCHE_GPIO_DATA_IN; + + if(reg_index > 0) + return(-1); + + 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_reg |= wakeup_int; + else + /* disable wakeup */ + *wakeup_status_reg &= (~wakeup_int); + + /* set polarity */ + if (wakeup_polarity == WAKEUP_ACTIVE_LOW) + *wakeup_status_reg |= (wakeup_int << AVALANCHE_WAKEUP_POLARITY_BIT); + else + *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; +} + +unsigned int avalanche_get_vbus_freq() +{ + return(avalanche_vbus_freq); +} + +unsigned int avalanche_get_chip_version_info() +{ + return(*(volatile unsigned int*)AVALANCHE_CVR); +} + +SET_MDIX_ON_CHIP_FN_T p_set_mdix_on_chip_fn = NULL; + +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); +} + +unsigned int avalanche_is_mdix_on_chip(void) +{ + return(p_set_mdix_on_chip_fn ? 1:0); +} + +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-10-21 16:45:42.122063750 +0200 @@ -0,0 +1,65 @@ +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ + +#include + + +/* 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 + +#ifdef CONFIG_MIPS_TNETV1050SDB +#define TNETV1050SDB +#define DUAL_FLASH +#endif + +#ifdef CONFIG_MIPS_AR7DB +#define TNETD73XX_BOARD +#define AR7DB +#endif + +#ifdef CONFIG_MIPS_AR7RD +#define TNETD73XX_BOARD +#define AR7RD +#endif + +#ifdef CONFIG_AR7WRD +#define TNETD73XX_BOARD +#define AR7WRD +#endif + +#ifdef CONFIG_MIPS_AR7VWI +#define TNETD73XX_BOARD +#define AR7VWi +#endif + +/* Merging from the DEV_DSL-PSPL4.3.2.7_Patch release. */ +#ifdef CONFIG_MIPS_AR7VW +#define TNETD73XX_BOARD +#define AR7WRD +#endif + +#ifdef CONFIG_MIPS_AR7WI +#define TNETD73XX_BOARD +#define AR7Wi +#endif + +#ifdef CONFIG_MIPS_AR7V +#define TNETD73XX_BOARD +#define AR7V +#endif + +#ifdef CONFIG_MIPS_AR7V +#define TNETD73XX_BOARD +#define AR7V +#endif + +#ifdef CONFIG_MIPS_WA1130 +#define AVALANCHE +#define WLAN +#endif + +#endif diff -urN linux.old/arch/mips/ar7/printf.c linux.dev/arch/mips/ar7/printf.c --- linux.old/arch/mips/ar7/printf.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.dev/arch/mips/ar7/printf.c 2005-10-21 16:45:42.122063750 +0200 @@ -0,0 +1,53 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#define AVALANCHE_YAMON_FUNCTION_BASE (KSEG1ADDR(0x10000500)) +#define AVALANCHE_YAMON_PROM_PRINT_COUNT_ADDR (AVALANCHE_YAMON_FUNCTION_BASE + 0x4) + +static char ppbuf[1024]; + +void (*prom_print_str)(unsigned int out, char *s, int len); + +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; + + va_start(args, fmt); + vsprintf(ppbuf, fmt, args); + len = strlen(ppbuf); + + prom_print_str(1, ppbuf, len); + + va_end(args); + 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-10-21 16:45:42.122063750 +0200 @@ -0,0 +1,350 @@ +#include +#include +#include +#include +#include +#include + +#include "platform.h" + +#define ENV_CELL_SIZE 16 + +/* 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) + +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. + */ + + env_vars_end +} ENV_VARS; + + +struct env_description { + ENV_VARS idx; + char *nm; + char *alias; +}; + +#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; + + /* 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; + } + + /* 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; +} + +extern int *_prom_envp; + +/* 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. + */ + +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)); + + 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)); + } + + return NULL; +} + +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; + + env_var++; /* skip signature */ + + 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); + + return NULL; +} + +static inline char *get_value(struct env_variable* env_var) +{ + unsigned char *name; + unsigned char *value; + unsigned short chksum; + int i; + + chksum = env_var->varNum + env_var->ctrl + env_var->numCells; + + 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; + + for (i = 0; i < strlen(value); i++) + chksum += value[i]; + + chksum += env_var->chksum; + chksum = ~(chksum); + + if(chksum != 0) { + return NULL; + } + + return value; +} + +struct psbl_rec { + unsigned int psbl_size; + unsigned int env_base; + unsigned int env_size; + unsigned int ffs_base; + unsigned int ffs_size; +}; + +char *prom_psp_getenv(char *envname) +{ + struct env_variable* env_var; + char *value; + + if (strcmp("bootloader", envname) == 0) + return "PSPBoot"; + + if (!(env_var = get_var(envname))) + return NULL; + + value = get_value(env_var); + + 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-10-21 16:45:42.122063750 +0200 @@ -0,0 +1,56 @@ +/* + * 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 MIPS boards. + * + */ +#include + +#include +#include + +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) +{ + volatile unsigned int *softres_reg = (void *)(KSEG1ADDR(0x08611600 + 0x4)); + + *softres_reg = 1; +} + +static void ar7_machine_halt(void) +{ + +} + +static void ar7_machine_power_off(void) +{ + +} + +void ar7_reboot_setup(void) +{ + _machine_restart = ar7_machine_restart; + _machine_halt = ar7_machine_halt; + _machine_power_off = ar7_machine_power_off; +} 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-10-21 16:45:42.122063750 +0200 @@ -0,0 +1,120 @@ +/* + * 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. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_KGDB +extern void rs_kgdb_hook(int); +int remote_debug = 0; +#endif + +extern struct rtc_ops no_rtc_ops; + +extern void ar7_reboot_setup(void); + +extern void ar7_time_init(void); +extern void ar7_timer_setup(struct irqaction *irq); + +const char *get_system_type(void) +{ + return "Texas Instruments AR7"; +} + +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 + +#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 + + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "nofpu")) != NULL) + cpu_data[0].options &= ~MIPS_CPU_FPU; + + rtc_ops = &no_rtc_ops; + + ar7_reboot_setup(); + + board_time_init = ar7_time_init; + board_timer_setup = ar7_timer_setup; +} diff -urN linux.old/arch/mips/ar7/time.c linux.dev/arch/mips/ar7/time.c --- linux.old/arch/mips/ar7/time.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.dev/arch/mips/ar7/time.c 2005-10-21 16:45:42.126064000 +0200 @@ -0,0 +1,124 @@ +/* + * 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 + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +extern asmlinkage void mipsIRQ(void); + +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 */ + +#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) +{ + write_c0_compare(newval); +} + +void ar7_timer_interrupt(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + irq_enter(cpu, MIPS_CPU_TIMER_IRQ); + + if (r4k_offset == 0) + goto null; + + do { + kstat.irqs[cpu][MIPS_CPU_TIMER_IRQ]++; + do_timer(regs); + r4k_cur += r4k_offset; + ack_r4ktimer(r4k_cur); + + } while (((unsigned long)read_c0_count() + - r4k_cur) < 0x7fffffff); + + irq_exit(cpu, MIPS_CPU_TIMER_IRQ); + + if (softirq_pending(cpu)) + do_softirq(); + + return; + +null: + ack_r4ktimer(0); +} + +/* + * Figure out the r4k offset, the amount to increment the compare + * register for each time tick. + */ +static unsigned long __init cal_r4koff(void) +{ + return ((CONFIG_AR7_CPU*500000)/HZ); +} + +void __init ar7_time_init(void) +{ + unsigned long flags; + unsigned int est_freq; + + set_except_vector(0, mipsIRQ); + write_c0_count(0); + + printk("calculating r4koff... "); + r4k_offset = cal_r4koff(); + printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + + est_freq = 2*r4k_offset*HZ; + est_freq += 5000; /* round */ + est_freq -= est_freq%10000; + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + (est_freq%1000000)*100/1000000); +} + +void __init ar7_timer_setup(struct irqaction *irq) +{ + /* 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); + + r4k_cur = (read_c0_count() + r4k_offset); + write_c0_compare(r4k_cur); + set_c0_status(ALLINTS); +} 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-10-21 16:45:42.126064000 +0200 @@ -0,0 +1,924 @@ +/****************************************************************************** + * 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 + *******************************************************************************/ + +#define LITTLE_ENDIAN +#define _LINK_KSEG0_ + +#include +#include +#include + +/* TNETD73XX Revision */ +u32 tnetd73xx_get_revision(void) +{ + /* Read Chip revision register - This register is from GPIO module */ + return ( (u32) REG32_DATA(TNETD73XX_CVR)); +} + +/***************************************************************************** + * Reset Control Module + *****************************************************************************/ + + +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); +} + + +TNETD73XX_RESET_CTRL_T tnetd73xx_get_reset_status (TNETD73XX_RESET_MODULE_T reset_module) +{ + u32 reset_status; + + REG32_READ(TNETD73XX_RST_CTRL_PRCR, reset_status); + return ( (reset_status & (1 << reset_module)) ? OUT_OF_RESET : IN_RESET ); +} + +void tnetd73xx_sys_reset(TNETD73XX_SYS_RST_MODE_T mode) +{ + REG32_WRITE(TNETD73XX_RST_CTRL_SWRCR, mode); +} + +#define TNETD73XX_RST_CTRL_RSR_MASK 0x3 + +TNETD73XX_SYS_RESET_STATUS_T tnetd73xx_get_sys_last_reset_status() +{ + 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) ); +} + + +/***************************************************************************** + * 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) +{ + 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)); + } + + /* write to the reset register */ + REG32_WRITE(TNETD73XX_POWER_CTRL_PDCR, power_status); +} + +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 ); +} + +void tnetd73xx_set_global_pwr_mode(TNETD73XX_SYS_POWER_MODE_T power_mode) +{ + u32 power_status; + + /* read current power down control register */ + REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); + + power_status &= TNETD73XX_GLOBAL_POWER_DOWN_MASK; + power_status |= ( power_mode << TNETD73XX_GLOBAL_POWER_DOWN_BIT); + + /* 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; + + /* read current power down control register */ + REG32_READ(TNETD73XX_POWER_CTRL_PDCR, power_status); + + power_status &= (~TNETD73XX_GLOBAL_POWER_DOWN_MASK); + power_status = ( power_status >> TNETD73XX_GLOBAL_POWER_DOWN_BIT); + + return ( (TNETD73XX_SYS_POWER_MODE_T) power_status ); +} + + +/***************************************************************************** + * Wakeup Control + *****************************************************************************/ + +#define TNETD73XX_WAKEUP_POLARITY_BIT 16 + +void tnetd73xx_wakeup_ctrl(TNETD73XX_WAKEUP_INTERRUPT_T wakeup_int, + TNETD73XX_WAKEUP_CTRL_T wakeup_ctrl, + TNETD73XX_WAKEUP_POLARITY_T wakeup_polarity) +{ + u32 wakeup_status; + + /* read the wakeup control register */ + REG32_READ(TNETD73XX_POWER_CTRL_WKCR, wakeup_status); + + /* enable/disable */ + if (wakeup_ctrl == WAKEUP_ENABLED) + { + /* enable wakeup */ + wakeup_status |= wakeup_int; + } + else + { + /* disable wakeup */ + wakeup_status &= (~wakeup_int); + } + + /* set polarity */ + if (wakeup_polarity == WAKEUP_ACTIVE_LOW) + { + wakeup_status |= (wakeup_int << TNETD73XX_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); +} + + +/***************************************************************************** + * FSER Control + *****************************************************************************/ + +void tnetd73xx_fser_ctrl(TNETD73XX_FSER_MODE_T fser_mode) +{ + REG32_WRITE(TNETD73XX_FSER_BASE, fser_mode); +} + +/***************************************************************************** + * Clock Control + *****************************************************************************/ + +#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) ) + +#define CLKC_CLKCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x20 + (0x20 * (x))) +#define CLKC_CLKPLLCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x30 + (0x20 * (x))) + +#define CLKC_PRE_DIVIDER 0x0000001F +#define CLKC_POST_DIVIDER 0x001F0000 + +#define CLKC_PLL_STATUS 0x1 +#define CLKC_PLL_FACTOR 0x0000F000 + +#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 + +#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 + +#define USB_SYSPLL_SELECT 0x00000000 +#define USB_REFCLKI_SELECT 0x00040000 +#define USB_XTAL3IN_SELECT 0x00080000 +#define USB_MIPSPLL_SELECT 0x000C0000 + +#define ADSLSS_AFECLKI_SELECT 0x00000000 +#define ADSLSS_REFCLKI_SELECT 0x00400000 +#define ADSLSS_XTAL3IN_SELECT 0x00800000 +#define ADSLSS_MIPSPLL_SELECT 0x00C00000 + +#define SYS_MAX CLK_MHZ(150) +#define SYS_MIN CLK_MHZ(1) + +#define MIPS_SYNC_MAX SYS_MAX +#define MIPS_ASYNC_MAX CLK_MHZ(160) +#define MIPS_MIN CLK_MHZ(1) + +#define USB_MAX CLK_MHZ(100) +#define USB_MIN CLK_MHZ(1) + +#define ADSL_MAX CLK_MHZ(180) +#define ADSL_MIN CLK_MHZ(1) + +#define PLL_MUL_MAXFACTOR 15 +#define MAX_DIV_VALUE 32 +#define MIN_DIV_VALUE 1 + +#define MIN_PLL_INP_FREQ CLK_MHZ(8) +#define MAX_PLL_INP_FREQ CLK_MHZ(100) + +#define DIVIDER_LOCK_TIME 10100 +#define PLL_LOCK_TIME 10100 * 75 + + + + /**************************************************************************** + * 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) +{ + + u32 choice; + + afeclk_inp = afeclk; + refclk_inp = refclk; + xtal_inp = xtal3in; + + choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & MIPS_PLL_SELECT; + switch(choice) + { + case MIPS_AFECLKI_SELECT: + clk_src[CLKC_MIPS] = &afeclk_inp; + break; + + 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; + + } + + 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; + + } + + + choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & ADSLSS_PLL_SELECT; + switch(choice) + { + case ADSLSS_AFECLKI_SELECT: + clk_src[CLKC_ADSLSS] = &afeclk_inp; + break; + + 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; + + } + + + choice = REG32_DATA(TNETD73XX_DCL_BOOTCR) & USB_PLL_SELECT; + switch(choice) + { + case USB_SYSPLL_SELECT: + clk_src[CLKC_USB] = &sys_pll_out ; + break; + + 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; + + } +} + + + +/**************************************************************************** + * 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; + + 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; + + 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; + } + + + base_freq = get_base_frequency(clk_id); + + + /* check for minimum base frequency value */ + if( base_freq < MIN_PLL_INP_FREQ) + { + return TNETD73XX_ERR_ERROR; + } + + get_val(output_freq, base_freq, &multiplier, ÷r); + + /* check multiplier range */ + if( (multiplier > PLL_MUL_MAXFACTOR) || (multiplier <= 0) ) + { + return TNETD73XX_ERR_ERROR; + } + + /* check divider value */ + if( divider == 0 ) + { + return TNETD73XX_ERR_ERROR; + } + + /*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); + + /*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; + } + + } + + /* compute predivider and postdivider values */ + prediv = compute_prediv (divider, min_prediv, max_prediv); + postdiv = CEIL(divider,prediv); + + /*return fail if postdivider value falls out of range */ + if(postdiv > MAX_DIV_VALUE) + { + return TNETD73XX_ERR_ERROR; + } + + + /*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) ); + + /*wait for divider output to stabilise*/ + for(temp =0; temp < DIVIDER_LOCK_TIME; temp++); + + /*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); + + /*compute the word to be written to PLLCR + *corresponding to multiplier value + */ + multiplier = (((multiplier - 1) & 0xf) << 12)| ((255 <<3) | 0x0e); + + /* wait till PLL enters div mode */ + while(REG32_DATA(CLKC_CLKPLLCR(clk_id)) & CLKC_PLL_STATUS) + /*nothing*/; + + REG32_WRITE(CLKC_CLKPLLCR(clk_id), multiplier); + + while(!REG32_DATA(CLKC_CLKPLLCR(clk_id)) & CLKC_PLL_STATUS) + /*nothing*/; + + + /*wait for External pll to lock*/ + for(temp =0; temp < PLL_LOCK_TIME; temp++); + + if(clk_id == CLKC_SYS) + { + /* Bring DRAM out of hold */ + REG32_DATA(TNETD73XX_EMIF_SDRAM_CFG) &= ~0x80000000; + } + + return TNETD73XX_ERR_OK ; +} + +/**************************************************************************** + * 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 + ) +{ + + u32 clk_ctrl_register; + u32 clk_pll_setting; + u32 clk_predivider; + u32 clk_postdivider; + u16 pll_factor; + u32 base_freq; + u32 divider; + + 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; + + divider = clk_predivider * clk_postdivider; + + + if( (REG32_DATA(TNETD73XX_DCL_BOOTCR) & BOOTCR_PLL_BYPASS)) + { + return (CEIL(base_freq, divider)); /* PLLs bypassed.*/ + } + + + else + { + /* return the current clock speed based upon the PLL setting */ + clk_pll_setting = REG32_DATA(CLKC_CLKPLLCR(clk_id)); + + /* Get the PLL multiplication factor */ + pll_factor = ((clk_pll_setting & CLKC_PLL_FACTOR) >> 12) + 1; + + /* 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)); + } + + 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 + { + /* clk = base_freq */ + return(CEIL(base_freq, divider)); + } + } + } + return(0); /* Should never reach here */ + + } + +} + + +/* local helper functions */ + +/**************************************************************************** + * 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) + { + *clk_src[clk_id] = tnetd73xx_clkc_get_freq(CLKC_MIPS); + } + + + /* 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]); + +} + + + +/**************************************************************************** + * 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) + { + return min; + } + else + { + return find_gcd(max % min, min); + } +} + +/**************************************************************************** + * FUNCTION: compute_prediv + **************************************************************************** + * Description: The above routine is called to compute predivider value + ***************************************************************************/ +static u32 compute_prediv(u32 divider, u32 min, u32 max) +{ + u16 prediv; + + /* return the divider itself it it falls within the range of predivider*/ + if (min <= divider && divider <= max) + { + return divider; + } + + /* find a value for prediv such that it is a factor of divider */ + for (prediv = max; prediv >= min ; prediv--) + { + if ( (divider % prediv) == 0 ) + { + return prediv; + } + } + + /* No such factor exists, return min as prediv */ + return min; +} + +/**************************************************************************** + * FUNCTION: get_val + **************************************************************************** + * Description: This routine is called to get values of divider and multiplier. + ***************************************************************************/ + +static void get_val(u32 output_freq, u32 base_freq,u32 *multiplier, u32 *divider) +{ + u32 temp_mul; + u32 temp_div; + u32 gcd; + u32 min_freq; + u32 max_freq; + + /* 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); + + if(gcd == 0) + return; /* ERROR */ + + /* compute values of multiplier and divider */ + temp_mul = output_freq / gcd; + temp_div = base_freq / gcd; + + + /* set multiplier such that 1 <= multiplier <= PLL_MUL_MAXFACTOR */ + if( temp_mul > PLL_MUL_MAXFACTOR ) + { + if((temp_mul / temp_div) > PLL_MUL_MAXFACTOR) + return; + + find_approx(&temp_mul,&temp_div,base_freq); + } + + *multiplier = temp_mul; + *divider = temp_div; +} + +/**************************************************************************** + * 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; + 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--) + { + + temp_denom = CEIL(temp_num * denom1, num1); + output_freq = (temp_num * base_freq) / temp_denom; + + 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 +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); @@ -103,3 +109,10 @@ #endif EXPORT_SYMBOL(get_wchan); + +#ifdef CONFIG_AR7 +EXPORT_SYMBOL_NOVERS(avalanche_request_pacing); +EXPORT_SYMBOL_NOVERS(prom_getenv); +EXPORT_SYMBOL_NOVERS(prom_iterenv); +#endif + 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-10-21 16:45:42.130064250 +0200 @@ -235,7 +235,11 @@ #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) +#ifdef CONFIG_AR7 +#define MAXMEM HIGHMEM_START + CONFIG_AR7_MEMORY +#else #define MAXMEM HIGHMEM_START +#endif #define MAXMEM_PFN PFN_DOWN(MAXMEM) static inline void bootmem_init(void) @@ -320,7 +324,12 @@ #endif /* Initialize the boot-time allocator with low memory only. */ +#ifdef CONFIG_AR7 + bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, + CONFIG_AR7_MEMORY >> PAGE_SHIFT, max_low_pfn); +#else bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn); +#endif /* * Register fully available low RAM pages with the bootmem allocator. @@ -494,6 +503,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 +701,11 @@ pmc_yosemite_setup(); break; #endif +#ifdef CONFIG_AR7 + case MACH_GROUP_UNKNOWN: + ar7_setup(); + break; +#endif default: panic("Unsupported architecture"); } diff -urN linux.old/arch/mips/kernel/traps.c linux.dev/arch/mips/kernel/traps.c --- linux.old/arch/mips/kernel/traps.c 2005-10-21 16:43:16.400956750 +0200 +++ linux.dev/arch/mips/kernel/traps.c 2005-10-21 16:45:42.130064250 +0200 @@ -869,9 +869,15 @@ exception_handlers[n] = handler; if (n == 0 && cpu_has_divec) { +#ifdef CONFIG_AR7 + *(volatile u32 *)(KSEG0+0x200+CONFIG_AR7_MEMORY) = 0x08000000 | + (0x03ffffff & (handler >> 2)); + flush_icache_range(KSEG0+0x200+CONFIG_AR7_MEMORY, KSEG0 + 0x204 + CONFIG_AR7_MEMORY); +#else *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | (0x03ffffff & (handler >> 2)); flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); +#endif } return (void *)old_handler; } @@ -1022,6 +1028,12 @@ if (board_nmi_handler_setup) board_nmi_handler_setup(); +#ifdef CONFIG_AR7 + memcpy((void *)(KSEG0 + CONFIG_AR7_MEMORY + 0x80), &except_vec1_generic, 0x80); + memcpy((void *)(KSEG0 + CONFIG_AR7_MEMORY + 0x180), &except_vec3_generic, 0x80); + memcpy((void *)(KSEG0 + CONFIG_AR7_MEMORY + 0x200), &except_vec4, 8); + flush_icache_range(KSEG0 + CONFIG_AR7_MEMORY, KSEG0 + CONFIG_AR7_MEMORY + 0x208); +#endif flush_icache_range(KSEG0, KSEG0 + 0x400); diff -urN linux.old/arch/mips/lib/promlib.c linux.dev/arch/mips/lib/promlib.c --- linux.old/arch/mips/lib/promlib.c 2003-08-25 13:44:40.000000000 +0200 +++ linux.dev/arch/mips/lib/promlib.c 2005-10-21 16:45:42.130064250 +0200 @@ -1,6 +1,8 @@ #include #include +#include +#ifndef CONFIG_AR7 extern void prom_putchar(char); void prom_printf(char *fmt, ...) @@ -22,3 +24,4 @@ } va_end(args); } +#endif 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-10-21 16:45:42.134064500 +0200 @@ -248,6 +248,9 @@ max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; +#ifdef CONFIG_AR7 + low = NODE_DATA(0)->bdata->node_low_pfn - (CONFIG_AR7_MEMORY >> PAGE_SHIFT); +#endif high = highend_pfn; #ifdef CONFIG_ISA @@ -270,7 +273,11 @@ zones_size[ZONE_HIGHMEM] = high - low; #endif +#ifdef CONFIG_AR7 + free_area_init_node(0, NODE_DATA(0), 0, zones_size, CONFIG_AR7_MEMORY, 0); +#else free_area_init(zones_size); +#endif } #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) @@ -298,6 +305,10 @@ return 0; } +#ifdef CONFIG_AR7 +#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT) +#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) +#endif void __init mem_init(void) { unsigned long codesize, reservedpages, datasize, initsize; @@ -315,9 +326,21 @@ #else max_mapnr = num_mappedpages = num_physpages = max_low_pfn; #endif + +#ifdef CONFIG_AR7 + max_mapnr = num_mappedpages = num_physpages = MAX_LOW_PFN - START_PFN; + high_memory = (void *) __va(MAX_LOW_PFN * PAGE_SIZE); + +#if 0 + /* WTF? */ + free_bootmem_node(NODE_DATA(0), (CONFIG_AR7_MEMORY+PAGE_SIZE), (__pa(&_ftext))-(CONFIG_AR7_MEMORY+PAGE_SIZE)); +#endif + totalram_pages += free_all_bootmem_node(NODE_DATA(0)); +#else high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); - totalram_pages += free_all_bootmem(); +#endif + totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ reservedpages = ram = 0; 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-10-21 17:02:20.199991500 +0200 @@ -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-10-21 16:45:47.854422000 +0200 @@ -0,0 +1,414 @@ +# +# Character device configuration +# +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 + +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 + +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 + +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 + +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 + +if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ] ; then + bool 'SGI SN2 fetchop support' CONFIG_FETCHOP +fi + +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 + +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 + +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 + +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 + +if [ "$CONFIG_X86" = "y" ]; then + tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE +fi + +endmenu + +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 + +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 + +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-10-21 17:02:20.199991500 +0200 @@ -240,6 +240,13 @@ obj-y += joystick/js.o endif +# +# 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 @@ -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 + 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-10-21 16:54:20.566016250 +0200 @@ -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.. +# + +# +# This file contains the font map for the default (hardware) font +# +FONTMAPFILE = cp437.uni + +O_TARGET := char.o + +obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o + +# All of the (potential) objects that export symbols. +# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. + +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 + +mod-subdirs := joystick ftape drm drm-4.0 pcmcia + +list-multi := + +KEYMAP =defkeymap.o +KEYBD =pc_keyb.o +CONSOLE =console.o +SERIAL =serial.o + +ifeq ($(ARCH),s390) + KEYMAP = + KEYBD = + CONSOLE = + SERIAL = +endif + +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 + +ifeq ($(ARCH),s390x) + KEYMAP = + KEYBD = + CONSOLE = + SERIAL = +endif + +ifeq ($(ARCH),m68k) + ifdef CONFIG_AMIGA + KEYBD = amikeyb.o + else + ifndef CONFIG_MAC + KEYBD = + endif + endif + SERIAL = +endif + +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 + +ifdef CONFIG_Q40 + KEYBD += q40_keyb.o + SERIAL = serial.o +endif + +ifdef CONFIG_APOLLO + KEYBD += dn_keyb.o +endif + +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 + +ifeq ($(ARCH),arm) + ifneq ($(CONFIG_PC_KEYMAP),y) + KEYMAP = + endif + ifneq ($(CONFIG_PC_KEYB),y) + KEYBD = + endif +endif + +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 + +ifeq ($(CONFIG_DECSTATION),y) + KEYMAP = + KEYBD = +endif + +ifeq ($(CONFIG_BAGET_MIPS),y) + KEYBD = + SERIAL = vac-serial.o +endif + +ifeq ($(CONFIG_NINO),y) + SERIAL = +endif + +ifneq ($(CONFIG_SUN_SERIAL),) + SERIAL = +endif + +ifeq ($(CONFIG_QTRONIX_KEYBOARD),y) + KEYBD = qtronix.o + KEYMAP = qtronixmap.o +endif + +ifeq ($(CONFIG_DUMMY_KEYB),y) + KEYBD = dummy_keyb.o +endif + +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 + +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 + +# +# 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 + +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 + +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-10-21 17:02:20.195991250 +0200 @@ -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-10-21 17:02:20.195991250 +0200 @@ -0,0 +1,184 @@ +/* + * 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 + * 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. + * + * 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*/ + +/* These defines are board specific */ + + +#define VLYNQ0_REMOTE_WINDOW1_OFFSET (0x0C000000) +#define VLYNQ0_REMOTE_WINDOW1_SIZE (0x500) + + +#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"); + + } +} + +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( ); + +} + +/* 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) +{ + 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 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-10-21 17:02:20.199991500 +0200 @@ -0,0 +1,243 @@ +/****************************************************************************** + * FILE PURPOSE: Vlynq Linux Device Driver Source + ****************************************************************************** + * FILE NAME: vlynq_drv.c + * + * DESCRIPTION: Vlynq Linux Device Driver Source + * + * REVISION HISTORY: + * + * 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 + + +#define TI_VLYNQ_VERSION "0.2" + +/* debug on ? */ +#define VLYNQ_DEBUG + +/* Macro for debug and error printf's */ +#ifdef VLYNQ_DEBUG +#define DBGPRINT printk +#else +#define DBGPRINT(x) +#endif + +#define ERRPRINT printk + +/* Define the max vlynq ports this driver will support. + Device name strings are statically added here */ +#define MAX_VLYNQ_PORTS 2 + + +/* Type define for VLYNQ private structure */ +typedef struct vlynqPriv{ + int irq; + VLYNQ_DEV *vlynqDevice; +}VLYNQ_PRIV; + +extern int vlynq_init_status[2]; + +/* 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 + */ + +VLYNQ_DEV vlynqDevice0; +VLYNQ_DEV vlynqDevice1; + +/* Defining dummy macro AVALANCHE_HIGH_VLYNQ_INT to take + * care of compilation in case of single vlynq device + */ + +#ifndef AVALANCHE_HIGH_VLYNQ_INT +#define AVALANCHE_HIGH_VLYNQ_INT 0 +#endif + + + +/* vlynq private object */ +VLYNQ_PRIV vlynq_priv[CONFIG_AR7_VLYNQ_PORTS] = { + { LNXINTNUM(AVALANCHE_LOW_VLYNQ_INT),&vlynqDevice0}, + { LNXINTNUM(AVALANCHE_HIGH_VLYNQ_INT),&vlynqDevice1}, +}; + +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; +} + +static struct file_operations vlynq_fops = { + owner: THIS_MODULE, + ioctl: vlynq_ioctl, +}; + +/* Vlynq device object */ +static struct miscdevice vlynq_dev [MAX_VLYNQ_PORTS] = { + { MISC_DYNAMIC_MINOR , "vlynq0", &vlynq_fops }, + { MISC_DYNAMIC_MINOR , "vlynq1", &vlynq_fops }, +}; + + +/* 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; + + len += sprintf(buf + len, "VLYNQ %d: Link state: %s\n",instance,link_msg[link_state]); + + } + /* 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; +} + + + + +/* Wrapper for vlynq ISR */ +static void lnx_vlynq_root_isr(int irq, void * arg, struct pt_regs *regs) +{ + vlynq_root_isr(arg); +} + +/* =================================== init and cleanup */ + +int vlynq_init_module(void) +{ + int ret; + int unit = 0; + int instance_count = CONFIG_AR7_VLYNQ_PORTS; + volatile int *ptr; + + vlynq_dev_init(); + + 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); + } + + /* register the misc device */ + for (unit = 0; unit < CONFIG_AR7_VLYNQ_PORTS; unit++) + { + ret = misc_register(&vlynq_dev[unit]); + + 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 + + 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); + } + } + + 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; +} + +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]); + } + + remove_proc_entry("avalanche/vlynq_link", NULL); + remove_proc_entry("avalanche/vlynq_ver", NULL); +} + + +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-10-21 16:45:47.838421000 +0200 @@ -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 void vlynq_configClock(VLYNQ_DEV * pdev) +{ + 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; + } +} + + /* ---------------------------------------------------------------------------- + * 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) +{ + /*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; + } + + + /** 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*/ + + 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; + +} + + +/* ---------------------------------------------------------------------------- + * 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) +{ + 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; + } + + /** Reset mapping for IV 0-7 **/ + VLYNQ_IVR_03TO00_REG = 0; + VLYNQ_IVR_07TO04_REG = 0; + + return VLYNQ_SUCCESS; +} + +/** 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*/ + + + /* ---------------------------------------------------------------------------- + * 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; + + 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 */ + + debugPrint("vlynq_root_isr: dev %u. INTCR = 0x%08lx\n", pdev->dev_idx, clrInterrupts,0,0,0,0); + + /* 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 */ +} + + + /* ---------------------------------------------------------------------------- + * 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) +{ + 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); + +} + + /* ---------------------------------------------------------------------------- + * 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) +{ + 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; + + 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-10-21 16:45:42.166066500 +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) +{ + 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 + outb(value, info->port + (offset * 4)); +#else + outb_p(value, info->port + (offset * 4)); +#endif +} + +#elif defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_SEAD) #include @@ -478,8 +511,10 @@ * needed for certain old 386 machines, I've left these #define's * in.... */ +#ifndef CONFIG_AR7 #define serial_inp(info, offset) serial_in(info, offset) #define serial_outp(info, offset, value) serial_out(info, offset, value) +#endif /* @@ -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*500000) / baud; + + if ((quot%16)>7) + quot += 8; + quot /=16; +#else quot = baud_base / baud; +#endif } /* If the quotient is zero refuse the change */ if (!quot && old_termios) { @@ -5540,8 +5583,10 @@ state->irq = irq_cannonicalize(state->irq); if (state->hub6) state->io_type = SERIAL_IO_HUB6; +#ifndef CONFIG_AR7 if (state->port && check_region(state->port,8)) continue; +#endif #ifdef CONFIG_MCA if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus) continue; @@ -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 = (CONFIG_AR7_SYS*500000) / baud; + + if ((quot%16)>7) + quot += 8; + quot /=16; +#else quot = state->baud_base / baud; +#endif cval = cflag & (CSIZE | CSTOPB); #if defined(__powerpc__) || defined(__alpha__) cval >>= 8; 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-10-21 16:43:20.709226000 +0200 @@ -0,0 +1,6054 @@ +/* + * 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 + * + * 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 + * + * 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 + * + * 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. + */ + +static char *serial_version = "5.05c"; +static char *serial_revdate = "2001-07-08"; + +/* + * Serial driver configuration section. Here are the various options: + * + * CONFIG_HUB6 + * Enables support for the venerable Bell Technologies + * HUB6 card. + * + * CONFIG_SERIAL_MANY_PORTS + * Enables support for ports beyond the standard, stupid + * COM 1/2/3/4. + * + * CONFIG_SERIAL_MULTIPORT + * Enables support for special multiport board support. + * + * 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 + * + * 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. + */ + +#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 + +#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 + +#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 */ + +#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 + +/* 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 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 + +/* + * End of serial driver configuration section. + */ + +#include + +#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 + +/* + * 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 + +#ifdef SERIAL_INLINE +#define _INLINE_ inline +#else +#define _INLINE_ +#endif + +static char *serial_name = "Serial driver"; + +static DECLARE_TASK_QUEUE(tq_serial); + +static struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +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} +}; + +#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 */ +}; + +#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) +{ +#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; +} + +#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_SEAD) + +#include + +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); +} + +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; +} + +#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); + } +} + +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 + + +/* + * 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) + + +/* + * 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); +} + +unsigned int serial_icr_read(struct async_struct *info, int offset) +{ + int value; + + 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; +} + +/* + * ------------------------------------------------------------ + * 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; + + 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); +} + +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); +} + +/* + * ---------------------------------------------------------------------- + * + * 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 + * ----------------------------------------------------------------------- + */ + +/* + * 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); +} + +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; + + 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 +} + +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; + + if (info->xmit.head == info->xmit.tail) { + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } +} + +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); + } + + 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); + } + } + } +} + +#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 + +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt(%d)...", irq); +#endif + + info = IRQ_ports[irq]; + if (!info) + return; + +#ifdef CONFIG_SERIAL_MULTIPORT + multi = &rs_multiport[irq]; + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); +#endif + + 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; + + info->last_active = jiffies; + + 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 + + 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 */ + + +/* + * 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 + + 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 + + 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; + + info->last_active = jiffies; + + 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; + + 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 + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * 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); +} + +static void do_softint(void *private_) +{ + struct async_struct *info = (struct async_struct *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + tty_wakeup(tty); + +#ifdef SERIAL_HAVE_POLL_WAIT + wake_up_interruptible(&tty->poll_wait); +#endif + } +} + +/* + * 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; + + 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); + + mod_timer(&serial_timer, jiffies + IRQ_timeout[0]); + } +} + +/* + * --------------------------------------------------------------- + * 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. + * --------------------------------------------------------------- + */ + +/* + * 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 :-) */ + + 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; +} + +#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; + + save_flags(flags); cli(); + mode = serial_inp(info, UART_RSA_MSR); + result = mode & UART_RSA_MSR_FIFO; + + 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; + } + + restore_flags(flags); + return result; +} + +/* 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; + + save_flags(flags); cli(); + mode = serial_inp(info, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); + + 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); + } + + restore_flags(flags); + return result; +} +#endif /* CONFIG_SERIAL_RSA */ + +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 + + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + save_flags(flags); cli(); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } + + if (!CONFIGURED_SERIAL_PORT(state) || !state->type) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + free_page(page); + goto errout; + } + if (info->xmit.buf) + free_page(page); + else + info->xmit.buf = (unsigned char *) page; + +#ifdef SERIAL_DEBUG_OPEN + printk("starting up ttys%d (irq %d)...", info->line, state->irq); +#endif + + 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); + } + + if (state->type == PORT_16750) { + /* Wake up UART */ + serial_outp(info, UART_IER, 0); + } + + 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-10-21 17:02:20.199991500 +0200 @@ -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-10-21 17:02:20.199991500 +0200 @@ -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/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-10-21 17:02:25.564326750 +0200 @@ -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-10-21 16:45:42.178067250 +0200 @@ -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-10-21 17:02:25.568327000 +0200 @@ -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-10-21 16:45:42.178067250 +0200 @@ -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-10-21 16:45:42.182067500 +0200 @@ -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-10-21 17:02:25.568327000 +0200 @@ -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-10-21 16:45:42.182067500 +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 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-10-21 16:45:42.222070000 +0200 @@ -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-10-21 16:45:42.182067500 +0200 @@ -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-10-21 16:45:42.222070000 +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. + */ + +#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-10-21 16:45:42.222070000 +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 + *******************************************************************************/ + + +#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-10-21 16:45:42.222070000 +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 + *******************************************************************************/ + +#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; + +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); + +/***************************************************************************** + * GPIO Control + *****************************************************************************/ + +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; + +typedef enum TNETD73XX_GPIO_PIN_DIRECTION_tag +{ + 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); + +/* TNETD73XX Revision */ +__u32 tnetd73xx_get_revision(void); + +#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-10-21 16:45:47.858422250 +0200 @@ -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 + + /* 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 + +#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) + +/* Vlynq Defines and Macros */ + +#define VLYNQ_NUM_INT_BITS 32 /* 32 bit interrupt staus register */ + +/* Base address of module */ +#define VLYNQ_BASE (pdev->module_base) + +#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 + +#define VLYNQ_RX0MAP_SIZE_REG_OFFSET 0x0020 +#define VLYNQ_RX0MAP_OFFSET_REG_OFFSET 0x0024 + +#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 + +#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)) + +/** 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))) + +#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) ) + +#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)) + + + +/********************************* + * 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 + +#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 + +#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))) + +#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)) + + +/*** 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)) ) + + +/****End of remote register set definition******/ + + +/*** Masks for individual register fields ***/ + +#define VLYNQ_MODULE_ID_MASK 0xffff0000 +#define VLYNQ_MAJOR_REV_MASK 0x0000ff00 +#define VLYNQ_MINOR_REV_MASK 0x000000ff + + +#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; + + +/* 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; + + +/* 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; + + +/* VLYNQ_INTR_POLARITY - vlynq interrupt polarity setting */ +typedef enum +{ + VLYNQ_INTR_ACTIVE_HIGH = 0, + VLYNQ_INTR_ACTIVE_LOW = 1 +}VLYNQ_INTR_POLARITY; + + +/* VLYNQ_INTR_TYPE - vlynq interrupt type */ +typedef enum +{ + VLYNQ_INTR_LEVEL = 0, + VLYNQ_INTR_PULSED = 1 +}VLYNQ_INTR_TYPE; + + +/* 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; + + + +/************************************* + * Typedefs * + *************************************/ + +struct VLYNQ_DEV_t; /*forward declaration*/ + +/*--------Function Pointers defintions -----------*/ + +/* prototype for interrupt handler definition */ +typedef void (*VLYNQ_INTR_CNTRL_ISR)(void *arg1,void *arg2,void *arg3); + +typedef void +(*VLYNQ_RESET_REMOTE)(struct VLYNQ_DEV_t *pDev, VLYNQ_RESET_MODE mode); + +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 */ + + +/*-------Structure Definitions------------*/ + +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; + + +/**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; + + +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; + + /*** 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; + + unsigned int intCount; /* number of interrupts generated so far */ + unsigned int isrCount; /* number of ISR invocations so far */ +}VLYNQ_DEV; + + +typedef struct VLYNQ_ISR_ARGS_t +{ + int irq; + void * arg; + void * regset; +}VLYNQ_ISR_ARGS; + + +/**************************************** + * Function Prototypes * + * API exported by generic vlynq driver * + ****************************************/ +/* Initialization function */ +int vlynq_init( VLYNQ_DEV *pdev, VLYNQ_INIT_OPTIONS options); + +/* Check vlynq link */ +unsigned int vlynq_link_check( VLYNQ_DEV * pdev); + +/* 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); + + +int vlynq_interrupt_vector_cntl( VLYNQ_DEV *pdev, + unsigned int int_vector, + VLYNQ_DEV_TYPE dev, + unsigned int enable); + +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); + + + + + +#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-10-21 17:02:25.568327000 +0200 @@ -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 GLOBAL +#define GLOBAL +#endif + +/* 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 + +/* Error defines */ +#define VLYNQ_SUCCESS 0 + +#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) + +/* Vlynq Defines and Macros */ + +#define VLYNQ_NUM_INT_BITS 32 /* 32 bit interrupt staus register */ + +/* Base address of module */ +#define VLYNQ_BASE (pdev->module_base) + +#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 + +#define VLYNQ_RX0MAP_SIZE_REG_OFFSET 0x0020 +#define VLYNQ_RX0MAP_OFFSET_REG_OFFSET 0x0024 + +#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 + +#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)) + +/* 0 =< ivr <= 31; currently ivr < VLYNQ_IVR_MAXIVR=8) */ +#define VLYNQ_IVR_OFFSET(ivr) \ + (VLYNQ_BASE + VLYNQ_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3) ) + +#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**/ + +#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)) + + + +/********************************* + * 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 + +#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 + +#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)) + +/** 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))) + +#define VLYNQ_R_CHIP_VER_REG *((volatile UINT32 *)(VLYNQ_BASE + VLYNQ_R_CHIP_VER_OFFSET) + +#define VLYNQ_R_IVR_OFFSET(ivr) \ + (VLYNQ_BASE + VLYNQ_R_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3)) + + +/*** 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)) ) + + +/****End of remote register set definition******/ + + +/*** Masks for individual register fields ***/ + +#define VLYNQ_MODULE_ID_MASK 0xffff0000 +#define VLYNQ_MAJOR_REV_MASK 0x0000ff00 +#define VLYNQ_MINOR_REV_MASK 0x000000ff + + +#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; + + +/* 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; + + +/* 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; + + +/* VLYNQ_INTR_POLARITY - vlynq interrupt polarity setting */ +typedef enum +{ + VLYNQ_INTR_ACTIVE_HIGH = 0, + VLYNQ_INTR_ACTIVE_LOW = 1 +}VLYNQ_INTR_POLARITY; + + +/* VLYNQ_INTR_TYPE - vlynq interrupt type */ +typedef enum +{ + VLYNQ_INTR_LEVEL = 0, + VLYNQ_INTR_PULSED = 1 +}VLYNQ_INTR_TYPE; + + +/* 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; + + + +/************************************* + * Typedefs * + *************************************/ + +struct VLYNQ_DEV_t; /*forward declaration*/ + +/*--------Function Pointers defintions -----------*/ + +/* prototype for interrupt handler definition */ +typedef void (*VLYNQ_INTR_CNTRL_ISR)(void *arg1,void *arg2,void *arg3); + +typedef void +(*VLYNQ_RESET_REMOTE)(struct VLYNQ_DEV_t *pDev, VLYNQ_RESET_MODE mode); + +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 */ + + +/*-------Structure Definitions------------*/ + +typedef struct VLYNQ_MEMORY_MAP_t +{ + UINT32 Txmap; + UINT32 RxOffset[VLYNQ_MAX_MEMORY_REGIONS]; + UINT32 RxSize[VLYNQ_MAX_MEMORY_REGIONS]; +}VLYNQ_MEMORY_MAP; + + +/**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*/ + UINT32 map_vector; + + /* used only if remote interrupts are to be handled by system ISR*/ + UINT32 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 */ + 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 struct VLYNQ_DEV_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; + + /*** 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 +{ + int irq; + void * arg; + void * regset; +}VLYNQ_ISR_ARGS; + + +/**************************************** + * 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-10-21 17:02:25.568327000 +0200 @@ -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-10-21 16:45:42.250071750 +0200 @@ -63,8 +63,12 @@ #ifdef CONFIG_64BIT_PHYS_ADDR #define page_to_phys(page) ((u64)(page - mem_map) << PAGE_SHIFT) #else +#ifdef CONFIG_AR7 +#define page_to_phys(page) (((page - mem_map) << PAGE_SHIFT) + CONFIG_AR7_MEMORY) +#else #define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT) #endif +#endif #define IO_SPACE_LIMIT 0xffff 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-10-21 16:45:42.278073500 +0200 @@ -14,7 +14,12 @@ #include #include +#ifdef CONFIG_AR7 +#include +#define NR_IRQS AVALANCHE_INT_END + 1 +#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 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-10-21 16:45:42.282073750 +0200 @@ -129,7 +129,11 @@ #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) +#ifdef CONFIG_AR7 +#define virt_to_page(kaddr) phys_to_page(__pa(kaddr)) +#else #define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT)) +#endif #define VALID_PAGE(page) ((page - mem_map) < max_mapnr) #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ 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-10-21 16:45:42.286074000 +0200 @@ -108,7 +108,18 @@ * and a page entry and page directory to the page they refer to. */ -#ifdef CONFIG_CPU_VR41XX +#if defined(CONFIG_AR7) +#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) #define mk_pte(page, pgprot) \ ({ \ pte_t __pte; \ @@ -130,6 +141,7 @@ }) #endif + static inline pte_t mk_pte_phys(phys_t physpage, pgprot_t pgprot) { #ifdef CONFIG_CPU_VR41XX @@ -175,7 +187,10 @@ set_pte(ptep, __pte(0)); } -#ifdef CONFIG_CPU_VR41XX +#if defined(CONFIG_AR7) +#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) #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 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-10-21 16:45:42.294074500 +0200 @@ -65,6 +65,15 @@ #define C_P(card,port) (((card)<<6|(port)<<3) + 1) +#ifdef CONFIG_AR7 +#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 }, +#else +#define AR7_SERIAL_PORT_DEFNS +#endif + #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 @@ #endif #define SERIAL_PORT_DFNS \ + AR7_SERIAL_PORT_DEFNS \ ATLAS_SERIAL_PORT_DEFNS \ AU1000_SERIAL_PORT_DEFNS \ COBALT_SERIAL_PORT_DEFNS \