diff options
author | Andi Kleen <andi@basil.nowhere.org> | 2006-11-21 10:22:09 +0100 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-11-21 10:22:09 +0100 |
commit | 1b7f6a626f0ff511c3840678466cbfe1d62c0b29 (patch) | |
tree | 415e8c838c0067bff384afb8a2c91e5f7c6d11d3 /arch/mips | |
parent | b3edc9cec07ade41aaf1804f7c9e876afa90c862 (diff) | |
parent | 3f5a6ca31c334011fd929501a078424c0d3f71be (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/mips')
68 files changed, 1251 insertions, 844 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 14af6cce2fa..1443024b1c7 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -425,9 +425,8 @@ config MOMENCO_OCELOT_G select SWAP_IO_SPACE select SYS_HAS_CPU_RM7000 select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL if BROKEN select SYS_SUPPORTS_BIG_ENDIAN - select ARCH_SPARSEMEM_ENABLE help The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer <http://www.momenco.com/>. @@ -560,6 +559,7 @@ config SGI_IP27 select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_NUMA + select SYS_SUPPORTS_SMP help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y @@ -1633,9 +1633,6 @@ config ARCH_DISCONTIGMEM_ENABLE config ARCH_SPARSEMEM_ENABLE bool - -config ARCH_SPARSEMEM_ENABLE - bool select SPARSEMEM_STATIC config NUMA @@ -1690,6 +1687,7 @@ config NR_CPUS depends on SMP default "64" if SGI_IP27 default "2" + default "8" if MIPS_MT_SMTC help This allows you to specify the maximum number of CPUs which this kernel will support. The maximum supported value is 32 for 32-bit diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 641aa30b363..d580d46f967 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -63,7 +63,9 @@ cflags-y += -mabi=64 ifdef CONFIG_BUILD_ELF64 cflags-y += $(call cc-option,-mno-explicit-relocs) else -cflags-y += $(call cc-option,-msym32) +# -msym32 can not be used for modules since they are loaded into XKSEG +CFLAGS_MODULE += $(call cc-option,-mno-explicit-relocs) +CFLAGS_KERNEL += $(call cc-option,-msym32) endif endif diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c index b4b010a2fe3..6fce60af005 100644 --- a/arch/mips/au1000/common/prom.c +++ b/arch/mips/au1000/common/prom.c @@ -47,7 +47,7 @@ extern int prom_argc; extern char **prom_argv, **prom_envp; -char * prom_getcmdline(void) +char * __init_or_module prom_getcmdline(void) { return &(arcs_cmdline[0]); } diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index 377ae0d8ff0..919172db560 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c @@ -43,7 +43,7 @@ #include <asm/mach-au1x00/au1000.h> #include <asm/time.h> -extern char * __init prom_getcmdline(void); +extern char * prom_getcmdline(void); extern void __init board_setup(void); extern void au1000_restart(char *); extern void au1000_halt(void); diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 94f09194d63..fa1c62f0551 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -53,9 +53,6 @@ static unsigned long r4k_cur; /* What counter should be at next timer irq */ int no_au1xxx_32khz; extern int allow_au1k_wait; /* default off for CP0 Counter */ -/* Cycle counter value at the previous timer interrupt.. */ -static unsigned int timerhi = 0, timerlo = 0; - #ifdef CONFIG_PM #if HZ < 100 || HZ > 1000 #error "unsupported HZ value! Must be in [100,1000]" @@ -82,7 +79,6 @@ unsigned long wtimer; void mips_timer_interrupt(void) { int irq = 63; - unsigned long count; irq_enter(); kstat_this_cpu.irqs[irq]++; @@ -91,10 +87,6 @@ void mips_timer_interrupt(void) goto null; do { - count = read_c0_count(); - timerhi += (count < timerlo); /* Wrap around */ - timerlo = count; - kstat_this_cpu.irqs[irq]++; do_timer(1); #ifndef CONFIG_SMP @@ -231,7 +223,6 @@ wakeup_counter0_set(int ticks) */ unsigned long cal_r4koff(void) { - unsigned long count; unsigned long cpu_speed; unsigned long flags; unsigned long counter; @@ -258,7 +249,7 @@ unsigned long cal_r4koff(void) #if defined(CONFIG_AU1000_USE32K) { - unsigned long start, end; + unsigned long start, end, count; start = au_readl(SYS_RTCREAD); start += 2; @@ -282,7 +273,6 @@ unsigned long cal_r4koff(void) #else cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; - count = cpu_speed / 2; #endif } else { @@ -291,98 +281,15 @@ unsigned long cal_r4koff(void) * NOTE: some old silicon doesn't allow reading the PLL. */ cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; - count = cpu_speed / 2; no_au1xxx_32khz = 1; } - mips_hpt_frequency = count; + mips_hpt_frequency = cpu_speed; // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); spin_unlock_irqrestore(&time_lock, flags); return (cpu_speed / HZ); } -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC (0x100000000LL*1000000/HZ&0xffffffff) - -static unsigned long -div64_32(unsigned long v1, unsigned long v2, unsigned long v3) -{ - unsigned long r0; - do_div64_32(r0, v1, v2, v3); - return r0; -} - -static unsigned long do_fast_cp0_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - unsigned long r0; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies=0; - unsigned long quotient; - - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient=0; - - tmp = jiffies; - - quotient = cached_quotient; - - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies != 0) { - r0 = div64_32(timerhi, timerlo, tmp); - quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0); - cached_quotient = quotient; - } - } - - /* Get last timer tick in absolute kernel time */ - count = read_c0_count(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - : "=r" (res) - : "r" (count), "r" (quotient) - : "hi", "lo", GCC_REG_ACCUM); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; - - return res; -} - -#ifdef CONFIG_PM -static unsigned long do_fast_pm_gettimeoffset(void) -{ - unsigned long pc0; - unsigned long offset; - - pc0 = au_readl(SYS_TOYREAD); - au_sync(); - offset = pc0 - last_pc0; - if (offset > 2*MATCH20_INC) { - printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", - (unsigned)offset, (unsigned)last_pc0, - (unsigned)last_match20, (unsigned)pc0); - } - offset = (unsigned long)((offset * 305) / 10); - return offset; -} -#endif - void __init plat_timer_setup(struct irqaction *irq) { unsigned int est_freq; @@ -420,7 +327,6 @@ void __init plat_timer_setup(struct irqaction *irq) unsigned int c0_status; printk("WARNING: no 32KHz clock found.\n"); - do_gettimeoffset = do_fast_cp0_gettimeoffset; /* Ensure we get CPO_COUNTER interrupts. */ @@ -445,19 +351,11 @@ void __init plat_timer_setup(struct irqaction *irq) while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); startup_match20_interrupt(counter0_irq); - do_gettimeoffset = do_fast_pm_gettimeoffset; - /* We can use the real 'wait' instruction. */ allow_au1k_wait = 1; } -#else - /* We have to do this here instead of in timer_init because - * the generic code in arch/mips/kernel/time.c will write - * over our function pointer. - */ - do_gettimeoffset = do_fast_cp0_gettimeoffset; #endif } diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index 4cf0c06e241..69e424e9ab6 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -160,11 +160,6 @@ static unsigned int dec_ioasic_hpt_read(void) return ioasic_read(IO_REG_FCTR); } -static void dec_ioasic_hpt_init(unsigned int count) -{ - ioasic_write(IO_REG_FCTR, ioasic_read(IO_REG_FCTR) - count); -} - void __init dec_time_init(void) { @@ -174,11 +169,9 @@ void __init dec_time_init(void) mips_timer_state = dec_timer_state; mips_timer_ack = dec_timer_ack; - if (!cpu_has_counter && IOASIC) { + if (!cpu_has_counter && IOASIC) /* For pre-R4k systems we use the I/O ASIC's counter. */ mips_hpt_read = dec_ioasic_hpt_read; - mips_hpt_init = dec_ioasic_hpt_init; - } /* Set up the rate of periodic DS1287 interrupts. */ CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A); diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c index 7c930860c92..197ed4c2ba0 100644 --- a/arch/mips/emma2rh/common/irq_emma2rh.c +++ b/arch/mips/emma2rh/common/irq_emma2rh.c @@ -97,7 +97,7 @@ void emma2rh_irq_init(u32 irq_base) irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; - irq_desc[i].handler = &emma2rh_irq_controller; + irq_desc[i].chip = &emma2rh_irq_controller; } emma2rh_irq_base = irq_base; diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c index f23ae9fcffa..0b36eb001e6 100644 --- a/arch/mips/emma2rh/markeins/irq_markeins.c +++ b/arch/mips/emma2rh/markeins/irq_markeins.c @@ -86,7 +86,7 @@ void emma2rh_sw_irq_init(u32 irq_base) irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 2; - irq_desc[i].handler = &emma2rh_sw_irq_controller; + irq_desc[i].chip = &emma2rh_sw_irq_controller; } emma2rh_sw_irq_base = irq_base; @@ -166,7 +166,7 @@ void emma2rh_gpio_irq_init(u32 irq_base) irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 2; - irq_desc[i].handler = &emma2rh_gpio_irq_controller; + irq_desc[i].chip = &emma2rh_gpio_irq_controller; } emma2rh_gpio_irq_base = irq_base; diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c index 15cc61df362..11567702b15 100644 --- a/arch/mips/emma2rh/markeins/platform.c +++ b/arch/mips/emma2rh/markeins/platform.c @@ -44,18 +44,45 @@ #define I2C_EMMA2RH "emma2rh-iic" /* must be in sync with IIC driver */ static struct resource i2c_emma_resources_0[] = { - { NULL, EMMA2RH_IRQ_PIIC0, EMMA2RH_IRQ_PIIC0, IORESOURCE_IRQ }, - { NULL, KSEG1ADDR(EMMA2RH_PIIC0_BASE), KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), 0 }, + { + .name = NULL, + .start = EMMA2RH_IRQ_PIIC0, + .end = EMMA2RH_IRQ_PIIC0, + .flags = IORESOURCE_IRQ + }, { + .name = NULL, + .start = EMMA2RH_PIIC0_BASE, + .end = EMMA2RH_PIIC0_BASE + 0x1000, + .flags = 0 + }, }; struct resource i2c_emma_resources_1[] = { - { NULL, EMMA2RH_IRQ_PIIC1, EMMA2RH_IRQ_PIIC1, IORESOURCE_IRQ }, - { NULL, KSEG1ADDR(EMMA2RH_PIIC1_BASE), KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), 0 }, + { + .name = NULL, + .start = EMMA2RH_IRQ_PIIC1, + .end = EMMA2RH_IRQ_PIIC1, + .flags = IORESOURCE_IRQ + }, { + .name = NULL, + .start = EMMA2RH_PIIC1_BASE, + .end = EMMA2RH_PIIC1_BASE + 0x1000, + .flags = 0 + }, }; struct resource i2c_emma_resources_2[] = { - { NULL, EMMA2RH_IRQ_PIIC2, EMMA2RH_IRQ_PIIC2, IORESOURCE_IRQ }, - { NULL, KSEG1ADDR(EMMA2RH_PIIC2_BASE), KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), 0 }, + { + .name = NULL, + .start = EMMA2RH_IRQ_PIIC2, + .end = EMMA2RH_IRQ_PIIC2, + .flags = IORESOURCE_IRQ + }, { + .name = NULL, + .start = EMMA2RH_PIIC2_BASE, + .end = EMMA2RH_PIIC2_BASE + 0x1000, + .flags = 0 + }, }; struct platform_device i2c_emma_devices[] = { @@ -83,32 +110,29 @@ struct platform_device i2c_emma_devices[] = { #define EMMA2RH_SERIAL_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST static struct plat_serial8250_port platform_serial_ports[] = { - [0] = { - .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3), - .irq = EMMA2RH_IRQ_PFUR0, - .uartclk = EMMA2RH_SERIAL_CLOCK, - .regshift = 4, - .iotype = UPIO_MEM, - .flags = EMMA2RH_SERIAL_FLAGS, - }, - [1] = { - .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3), - .irq = EMMA2RH_IRQ_PFUR1, - .uartclk = EMMA2RH_SERIAL_CLOCK, - .regshift = 4, - .iotype = UPIO_MEM, - .flags = EMMA2RH_SERIAL_FLAGS, - }, - [2] = { - .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3), - .irq = EMMA2RH_IRQ_PFUR2, - .uartclk = EMMA2RH_SERIAL_CLOCK, - .regshift = 4, - .iotype = UPIO_MEM, - .flags = EMMA2RH_SERIAL_FLAGS, - }, - [3] = { - .flags = 0, + [0] = { + .membase= (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR0, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, [1] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR1, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, [2] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR2, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, [3] = { + .flags = 0, }, }; diff --git a/arch/mips/gt64120/common/time.c b/arch/mips/gt64120/common/time.c index c83ae6acd60..c47eeb76819 100644 --- a/arch/mips/gt64120/common/time.c +++ b/arch/mips/gt64120/common/time.c @@ -64,14 +64,14 @@ static irqreturn_t gt64120_irq(int irq, void *dev_id) * as *irq (=irq0 in ../kernel/time.c). We will do our own timer interrupt * handling. */ -void gt64120_time_init(void) +void __init plat_timer_setup(struct irqaction *irq) { static struct irqaction timer; /* Disable timer first */ GT_WRITE(GT_TC_CONTROL_OFS, 0); /* Load timer value for 100 Hz */ - GT_WRITE(GT_TC3_OFS, Sys_clock / 100); + GT_WRITE(GT_TC3_OFS, Sys_clock / HZ); /* * Create the IRQ structure entry for the timer. Since we're too early diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c index 91c2d3f4161..99c8d42212e 100644 --- a/arch/mips/gt64120/ev64120/setup.c +++ b/arch/mips/gt64120/ev64120/setup.c @@ -68,7 +68,6 @@ unsigned long __init prom_free_prom_memory(void) * Initializes basic routines and structures pointers, memory size (as * given by the bios and saves the command line. */ -extern void gt64120_time_init(void); void __init plat_mem_setup(void) { @@ -76,7 +75,6 @@ void __init plat_mem_setup(void) _machine_halt = galileo_machine_halt; pm_power_off = galileo_machine_power_off; - board_time_init = gt64120_time_init; set_io_port_base(KSEG1); } diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c index 0e5bbee2d5b..94f94ebbda6 100644 --- a/arch/mips/gt64120/momenco_ocelot/setup.c +++ b/arch/mips/gt64120/momenco_ocelot/setup.c @@ -70,7 +70,6 @@ extern void momenco_ocelot_restart(char *command); extern void momenco_ocelot_halt(void); extern void momenco_ocelot_power_off(void); -extern void gt64120_time_init(void); extern void momenco_ocelot_irq_setup(void); static char reset_reason; @@ -156,8 +155,6 @@ void __init plat_mem_setup(void) void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); unsigned int tmpword; - board_time_init = gt64120_time_init; - _machine_restart = momenco_ocelot_restart; _machine_halt = momenco_ocelot_halt; pm_power_off = momenco_ocelot_power_off; diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c index 39a0243bed9..de4a238c28b 100644 --- a/arch/mips/jmr3927/rbhma3100/irq.c +++ b/arch/mips/jmr3927/rbhma3100/irq.c @@ -288,6 +288,8 @@ static void tx_branch_likely_bug_fixup(void) static void jmr3927_spurious(void) { + struct pt_regs * regs = get_irq_regs(); + #ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND tx_branch_likely_bug_fixup(); #endif @@ -297,6 +299,7 @@ static void jmr3927_spurious(void) asmlinkage void plat_irq_dispatch(void) { + struct pt_regs * regs = get_irq_regs(); int irq; #ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index 025434054ed..16e5dfe7aa8 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -170,12 +170,20 @@ static void jmr3927_machine_power_off(void) while (1); } +static unsigned int jmr3927_hpt_read(void) +{ + /* We assume this function is called xtime_lock held. */ + return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr; +} + #define USE_RTC_DS1742 #ifdef USE_RTC_DS1742 extern void rtc_ds1742_init(unsigned long base); #endif static void __init jmr3927_time_init(void) { + mips_hpt_read = jmr3927_hpt_read; + mips_hpt_frequency = JMR3927_TIMER_CLK; #ifdef USE_RTC_DS1742 if (jmr3927_have_nvram()) { rtc_ds1742_init(JMR3927_IOC_NVRAMB_ADDR); @@ -183,12 +191,8 @@ static void __init jmr3927_time_init(void) #endif } -unsigned long jmr3927_do_gettimeoffset(void); - void __init plat_timer_setup(struct irqaction *irq) { - do_gettimeoffset = jmr3927_do_gettimeoffset; - jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ; jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE; jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD; @@ -200,34 +204,6 @@ void __init plat_timer_setup(struct irqaction *irq) #define USECS_PER_JIFFY (1000000/HZ) -unsigned long jmr3927_do_gettimeoffset(void) -{ - unsigned long count; - unsigned long res = 0; - - /* MUST read TRR before TISR. */ - count = jmr3927_tmrptr->trr; - - if (jmr3927_tmrptr->tisr & TXx927_TMTISR_TIIS) { - /* timer interrupt is pending. use Max value. */ - res = USECS_PER_JIFFY - 1; - } else { - /* convert to usec */ - /* res = count / (JMR3927_TIMER_CLK / 1000000); */ - res = (count << 7) / ((JMR3927_TIMER_CLK << 7) / 1000000); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; - } - - return res; -} - - //#undef DO_WRITE_THROUGH #define DO_WRITE_THROUGH #define DO_ENABLE_CACHE diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index e9ce5b3721a..ff88b06f89d 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -22,7 +22,7 @@ #define offset(string, ptr, member) \ __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) #define constant(string, member) \ - __asm__("\n@@@" string "%x0" : : "ri" (member)) + __asm__("\n@@@" string "%X0" : : "ri" (member)) #define size(string, size) \ __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) #define linefeed text("") diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index 417c08ac76e..f10b6a19f8b 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -83,7 +83,10 @@ FEXPORT(syscall_exit) FEXPORT(restore_all) # restore full frame #ifdef CONFIG_MIPS_MT_SMTC /* Detect and execute deferred IPI "interrupts" */ + LONG_L s0, TI_REGS($28) + LONG_S sp, TI_REGS($28) jal deferred_smtc_ipi + LONG_S s0, TI_REGS($28) /* Re-arm any temporarily masked interrupts not explicitly "acked" */ mfc0 v0, CP0_TCSTATUS ori v1, v0, TCSTATUS_IXMT diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 8c6db0fc72f..ddc1b71c937 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -189,7 +189,8 @@ NESTED(kernel_entry, 16, sp) # kernel entry point MTC0 zero, CP0_CONTEXT # clear context register PTR_LA $28, init_thread_union - PTR_ADDIU sp, $28, _THREAD_SIZE - 32 + PTR_LI sp, _THREAD_SIZE - 32 + PTR_ADDU sp, $28 set_saved_sp sp, t0, t1 PTR_SUBU sp, 4 * SZREG # init stack pointer diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index dd24434392b..9b0e49d63d7 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -26,6 +26,48 @@ #include <asm/system.h> #include <asm/uaccess.h> +static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; + +int __devinit allocate_irqno(void) +{ + int irq; + +again: + irq = find_first_zero_bit(irq_map, NR_IRQS); + + if (irq >= NR_IRQS) + return -ENOSPC; + + if (test_and_set_bit(irq, irq_map)) + goto again; + + return irq; +} + +EXPORT_SYMBOL_GPL(allocate_irqno); + +/* + * Allocate the 16 legacy interrupts for i8259 devices. This happens early + * in the kernel initialization so treating allocation failure as BUG() is + * ok. + */ +void __init alloc_legacy_irqno(void) +{ + int i; + + for (i = 0; i <= 16; i++) + BUG_ON(test_and_set_bit(i, irq_map)); +} + +void __devinit free_irqno(unsigned int irq) +{ + smp_mb__before_clear_bit(); + clear_bit(irq, irq_map); + smp_mb__after_clear_bit(); +} + +EXPORT_SYMBOL_GPL(free_irqno); + /* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves. diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index d5c8b82fed7..cc566cf1224 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -85,7 +85,12 @@ move $28, a2 cpu_restore_nonscratch a1 +#if (_THREAD_SIZE - 32) < 0x10000 PTR_ADDIU t0, $28, _THREAD_SIZE - 32 +#else + PTR_LI t0, _THREAD_SIZE - 32 + PTR_ADDU t0, $28 +#endif set_saved_sp t0, t1, t2 #ifdef CONFIG_MIPS_MT_SMTC /* Read-modify-writes of Status must be atomic on a VPE */ diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 720fac3435d..a95f37de080 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -654,6 +654,8 @@ einval: li v0, -EINVAL sys sys_set_robust_list 2 sys sys_get_robust_list 3 /* 4310 */ sys sys_ni_syscall 0 + sys sys_getcpu 3 + sys sys_epoll_pwait 6 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 3a34f62c8b1..8fb0f60f657 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -469,3 +469,5 @@ sys_call_table: PTR sys_set_robust_list PTR sys_get_robust_list PTR sys_ni_syscall /* 5270 */ + PTR sys_getcpu + PTR sys_epoll_pwait diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 67b92a1d6c7..0da5ca2040f 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -395,3 +395,5 @@ EXPORT(sysn32_call_table) PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list PTR sys_ni_syscall + PTR sys_getcpu + PTR sys_epoll_pwait diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 2875c4a3fa5..b9d00cae8b5 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -517,4 +517,6 @@ sys_call_table: PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list /* 4310 */ PTR sys_ni_syscall + PTR sys_getcpu + PTR sys_epoll_pwait .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index fdbb508661c..8f6e89697cc 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -223,7 +223,11 @@ disable: #else /* !CONFIG_BLK_DEV_INITRD */ -#define init_initrd() 0 +static unsigned long __init init_initrd(void) +{ + return 0; +} + #define finalize_initrd() do {} while (0) #endif diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 3b5f3b63262..2ac19a6cbf6 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -140,15 +140,90 @@ static struct irqaction irq_call = { .name = "IPI_call" }; +static void __init smp_copy_vpe_config(void) +{ + write_vpe_c0_status( + (read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0); + + /* set config to be the same as vpe0, particularly kseg0 coherency alg */ + write_vpe_c0_config( read_c0_config()); + + /* make sure there are no software interrupts pending */ + write_vpe_c0_cause(0); + + /* Propagate Config7 */ + write_vpe_c0_config7(read_c0_config7()); + + write_vpe_c0_count(read_c0_count()); +} + +static unsigned int __init smp_vpe_init(unsigned int tc, unsigned int mvpconf0, + unsigned int ncpu) +{ + if (tc > ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)) + return ncpu; + + /* Deactivate all but VPE 0 */ + if (tc != 0) { + unsigned long tmp = read_vpe_c0_vpeconf0(); + + tmp &= ~VPECONF0_VPA; + + /* master VPE */ + tmp |= VPECONF0_MVP; + write_vpe_c0_vpeconf0(tmp); + + /* Record this as available CPU */ + cpu_set(tc, phys_cpu_present_map); + __cpu_number_map[tc] = ++ncpu; + __cpu_logical_map[ncpu] = tc; + } + + /* Disable multi-threading with TC's */ + write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE); + + if (tc != 0) + smp_copy_vpe_config(); + + return ncpu; +} + +static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0) +{ + unsigned long tmp; + + if (!tc) + return; + + /* bind a TC to each VPE, May as well put all excess TC's + on the last VPE */ + if (tc >= (((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)+1)) + write_tc_c0_tcbind(read_tc_c0_tcbind() | ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)); + else { + write_tc_c0_tcbind(read_tc_c0_tcbind() | tc); + + /* and set XTC */ + write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | (tc << VPECONF0_XTC_SHIFT)); + } + + tmp = read_tc_c0_tcstatus(); + + /* mark not allocated and not dynamically allocatable */ + tmp &= ~(TCSTATUS_A | TCSTATUS_DA); + tmp |= TCSTATUS_IXMT; /* interrupt exempt */ + write_tc_c0_tcstatus(tmp); + + write_tc_c0_tchalt(TCHALT_H); +} + /* * Common setup before any secondaries are started * Make sure all CPU's are in a sensible state before we boot any of the * secondarys */ -void plat_smp_setup(void) +void __init plat_smp_setup(void) { - unsigned long val; - int i, num; + unsigned int mvpconf0, ntc, tc, ncpu = 0; #ifdef CONFIG_MIPS_MT_FPAFF /* If we have an FPU, enroll ourselves in the FPU-full mask */ @@ -167,75 +242,16 @@ void plat_smp_setup(void) /* Put MVPE's into 'configuration state' */ set_c0_mvpcontrol(MVPCONTROL_VPC); - val = read_c0_mvpconf0(); + mvpconf0 = read_c0_mvpconf0(); + ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT; /* we'll always have more TC's than VPE's, so loop setting everything to a sensible state */ - for (i = 0, num = 0; i <= ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT); i++) { - settc(i); - - /* VPE's */ - if (i <= ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)) { - - /* deactivate all but vpe0 */ - if (i != 0) { - unsigned long tmp = read_vpe_c0_vpeconf0(); - - tmp &= ~VPECONF0_VPA; - - /* master VPE */ - tmp |= VPECONF0_MVP; - write_vpe_c0_vpeconf0(tmp); - - /* Record this as available CPU */ - cpu_set(i, phys_cpu_present_map); - __cpu_number_map[i] = ++num; - __cpu_logical_map[num] = i; - } - - /* disable multi-threading with TC's */ - write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE); - - if (i != 0) { - write_vpe_c0_status((read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0); + for (tc = 0; tc <= ntc; tc++) { + settc(tc); - /* set config to be the same as vpe0, particularly kseg0 coherency alg */ - write_vpe_c0_config( read_c0_config()); - - /* make sure there are no software interrupts pending */ - write_vpe_c0_cause(0); - - /* Propagate Config7 */ - write_vpe_c0_config7(read_c0_config7()); - } - - } - - /* TC's */ - - if (i != 0) { - unsigned long tmp; - - /* bind a TC to each VPE, May as well put all excess TC's - on the last VPE */ - if ( i >= (((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT)+1) ) - write_tc_c0_tcbind(read_tc_c0_tcbind() | ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) ); - else { - write_tc_c0_tcbind( read_tc_c0_tcbind() | i); - - /* and set XTC */ - write_vpe_c0_vpeconf0( read_vpe_c0_vpeconf0() | (i << VPECONF0_XTC_SHIFT)); - } - - tmp = read_tc_c0_tcstatus(); - - /* mark not allocated and not dynamically allocatable */ - tmp &= ~(TCSTATUS_A | TCSTATUS_DA); - tmp |= TCSTATUS_IXMT; /* interrupt exempt */ - write_tc_c0_tcstatus(tmp); - - write_tc_c0_tchalt(TCHALT_H); - } + smp_tc_init(tc, mvpconf0); + ncpu = smp_vpe_init(tc, mvpconf0, ncpu); } /* Release config state */ @@ -243,7 +259,7 @@ void plat_smp_setup(void) /* We'll wait until starting the secondaries before starting MVPE */ - printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); + printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu); } void __init plat_prepare_cpus(unsigned int max_cpus) diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S index 1cb9441f147..921207c4a83 100644 --- a/arch/mips/kernel/smtc-asm.S +++ b/arch/mips/kernel/smtc-asm.S @@ -101,7 +101,9 @@ FEXPORT(__smtc_ipi_vector) lw t0,PT_PADSLOT5(sp) /* Argument from sender passed in stack pad slot 4 */ lw a0,PT_PADSLOT4(sp) - PTR_LA ra, _ret_from_irq + LONG_L s0, TI_REGS($28) + LONG_S sp, TI_REGS($28) + PTR_LA ra, ret_from_irq jr t0 /* @@ -119,7 +121,10 @@ LEAF(self_ipi) subu t1,sp,PT_SIZE sw ra,PT_EPC(t1) sw a0,PT_PADSLOT4(t1) + LONG_L s0, TI_REGS($28) + LONG_S sp, TI_REGS($28) la t2,ipi_decode + LONG_S s0, TI_REGS($28) sw t2,PT_PADSLOT5(t1) /* Save pre-disable value of TCStatus */ sw t0,PT_TCSTATUS(t1) diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index cc1f7474f7d..3b78caf112f 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -476,6 +476,7 @@ void mipsmt_prepare_cpus(void) write_vpe_c0_compare(0); /* Propagate Config7 */ write_vpe_c0_config7(read_c0_config7()); + write_vpe_c0_count(read_c0_count()); } /* enable multi-threading within VPE */ write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE); diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index debe86c2f69..e535f86efa2 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -11,6 +11,7 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ +#include <linux/clocksource.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> @@ -67,15 +68,9 @@ int (*rtc_mips_set_time)(unsigned long) = null_rtc_set_time; int (*rtc_mips_set_mmss)(unsigned long); -/* usecs per counter cycle, shifted to left by 32 bits */ -static unsigned int sll32_usecs_per_cycle; - /* how many counter cycles in a jiffy */ static unsigned long cycles_per_jiffy __read_mostly; -/* Cycle counter value at the previous timer interrupt.. */ -static unsigned int timerhi, timerlo; - /* expirelo is the count value for next CPU timer interrupt */ static unsigned int expirelo; @@ -93,7 +88,7 @@ static unsigned int null_hpt_read(void) return 0; } -static void null_hpt_init(unsigned int count) +static void __init null_hpt_init(void) { /* nothing */ } @@ -128,186 +123,18 @@ static unsigned int c0_hpt_read(void) return read_c0_count(); } -/* For use solely as a high precision timer. */ -static void c0_hpt_init(unsigned int count) -{ - write_c0_count(read_c0_count() - count); -} - /* For use both as a high precision timer and an interrupt source. */ -static void c0_hpt_timer_init(unsigned int count) +static void __init c0_hpt_timer_init(void) { - count = read_c0_count() - count; - expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy; - write_c0_count(expirelo - cycles_per_jiffy); + expirelo = read_c0_count() + cycles_per_jiffy; write_c0_compare(expirelo); - write_c0_count(count); } int (*mips_timer_state)(void); void (*mips_timer_ack)(void); unsigned int (*mips_hpt_read)(void); -void (*mips_hpt_init)(unsigned int); - -/* - * Gettimeoffset routines. These routines returns the time duration - * since last timer interrupt in usecs. - * - * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset. - * Otherwise use calibrate_gettimeoffset() - * - * If the CPU does not have the counter register, you can either supply - * your own gettimeoffset() routine, or use null_gettimeoffset(), which - * gives the same resolution as HZ. - */ - -static unsigned long null_gettimeoffset(void) -{ - return 0; -} - - -/* The function pointer to one of the gettimeoffset funcs. */ -unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset; - - -static unsigned long fixed_rate_gettimeoffset(void) -{ - u32 count; - unsigned long res; - - /* Get last timer tick in absolute kernel time */ - count = mips_hpt_read(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu %1,%2" - : "=h" (res) - : "r" (count), "r" (sll32_usecs_per_cycle) - : "lo", GCC_REG_ACCUM); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; - - return res; -} - - -/* - * Cached "1/(clocks per usec) * 2^32" value. - * It has to be recalculated once each jiffy. - */ -static unsigned long cached_quotient; - -/* Last jiffy when calibrate_divXX_gettimeoffset() was called. */ -static unsigned long last_jiffies; - -/* - * This is moved from dec/time.c:do_ioasic_gettimeoffset() by Maciej. - */ -static unsigned long calibrate_div32_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - unsigned long quotient; - - tmp = jiffies; - - quotient = cached_quotient; - - if (last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies != 0) { - unsigned long r0; - do_div64_32(r0, timerhi, timerlo, tmp); - do_div64_32(quotient, USECS_PER_JIFFY, - USECS_PER_JIFFY_FRAC, r0); - cached_quotient = quotient; - } - } - - /* Get last timer tick in absolute kernel time */ - count = mips_hpt_read(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu %1,%2" - : "=h" (res) - : "r" (count), "r" (quotient) - : "lo", GCC_REG_ACCUM); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; - - return res; -} - -static unsigned long calibrate_div64_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - unsigned long quotient; - - tmp = jiffies; - - quotient = cached_quotient; - - if (last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies) { - unsigned long r0; - __asm__(".set push\n\t" - ".set mips3\n\t" - "lwu %0,%3\n\t" - "dsll32 %1,%2,0\n\t" - "or %1,%1,%0\n\t" - "ddivu $0,%1,%4\n\t" - "mflo %1\n\t" - "dsll32 %0,%5,0\n\t" - "or %0,%0,%6\n\t" - "ddivu $0,%0,%1\n\t" - "mflo %0\n\t" - ".set pop" - : "=&r" (quotient), "=&r" (r0) - : "r" (timerhi), "m" (timerlo), - "r" (tmp), "r" (USECS_PER_JIFFY), - "r" (USECS_PER_JIFFY_FRAC) - : "hi", "lo", GCC_REG_ACCUM); - cached_quotient = quotient; - } - } - - /* Get last timer tick in absolute kernel time */ - count = mips_hpt_read(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu %1,%2" - : "=h" (res) - : "r" (count), "r" (quotient) - : "lo", GCC_REG_ACCUM); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; - - return res; -} - +void (*mips_hpt_init)(void) __initdata = null_hpt_init; +unsigned int mips_hpt_mask = 0xffffffff; /* last time when xtime and rtc are sync'ed up */ static long last_rtc_update; @@ -334,18 +161,10 @@ void local_timer_interrupt(int irq, void *dev_id) */ irqreturn_t timer_interrupt(int irq, void *dev_id) { - unsigned long j; - unsigned int count; - write_seqlock(&xtime_lock); - count = mips_hpt_read(); mips_timer_ack(); - /* Update timerhi/timerlo for intra-jiffy calibration. */ - timerhi += count < timerlo; /* Wrap around */ - timerlo = count; - /* * call the generic timer interrupt handling */ @@ -368,47 +187,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) } } - /* - * If jiffies has overflown in this timer_interrupt, we must - * update the timer[hi]/[lo] to make fast gettimeoffset funcs - * quotient calc still valid. -arca - * - * The first timer interrupt comes late as interrupts are - * enabled long after timers are initialized. Therefore the - * high precision timer is fast, leading to wrong gettimeoffset() - * calculations. We deal with it by setting it based on the - * number of its ticks between the second and the third interrupt. - * That is still somewhat imprecise, but it's a good estimate. - * --macro - */ - j = jiffies; - if (j < 4) { - static unsigned int prev_count; - static int hpt_initialized; - - switch (j) { - case 0: - timerhi = timerlo = 0; - mips_hpt_init(count); - break; - case 2: - prev_count = count; - break; - case 3: - if (!hpt_initialized) { - unsigned int c3 = 3 * (count - prev_count); - - timerhi = 0; - timerlo = c3; - mips_hpt_init(count - c3); - hpt_initialized = 1; - } - break; - default: - break; - } - } - write_sequnlock(&xtime_lock); /* @@ -476,12 +254,11 @@ asmlinkage void ll_local_timer_interrupt(int irq) * 1) board_time_init() - * a) (optional) set up RTC routines, * b) (optional) calibrate and set the mips_hpt_frequency - * (only needed if you intended to use fixed_rate_gettimeoffset - * or use cpu counter as timer interrupt source) + * (only needed if you intended to use cpu counter as timer interrupt + * source) * 2) setup xtime based on rtc_mips_get_time(). - * 3) choose a appropriate gettimeoffset routine. - * 4) calculate a couple of cached variables for later usage - * 5) plat_timer_setup() - + * 3) calculate a couple of cached variables for later usage + * 4) plat_timer_setup() - * a) (optional) over-write any choices made above by time_init(). * b) machine specific code should setup the timer irqaction. * c) enable the timer interrupt @@ -533,13 +310,48 @@ static unsigned int __init calibrate_hpt(void) } while (--i); hpt_end = mips_hpt_read(); - hpt_count = hpt_end - hpt_start; + hpt_count = (hpt_end - hpt_start) & mips_hpt_mask; hz = HZ; frequency = (u64)hpt_count * (u64)hz; return frequency >> log_2_loops; } +static cycle_t read_mips_hpt(void) +{ + return (cycle_t)mips_hpt_read(); +} + +static struct clocksource clocksource_mips = { + .name = "MIPS", + .read = read_mips_hpt, + .is_continuous = 1, +}; + +static void __init init_mips_clocksource(void) +{ + u64 temp; + u32 shift; + + if (!mips_hpt_frequency || mips_hpt_read == null_hpt_read) + return; + + /* Calclate a somewhat reasonable rating value */ + clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; + /* Find a shift value */ + for (shift = 32; shift > 0; shift--) { + temp = (u64) NSEC_PER_SEC << shift; + do_div(temp, mips_hpt_frequency); + if ((temp >> 32) == 0) + break; + } + clocksource_mips.shift = shift; + clocksource_mips.mult = (u32)temp; + clocksource_mips.mask = mips_hpt_mask; + + clocksource_register(&clocksource_mips); +} + void __init time_init(void) { if (board_time_init) @@ -555,41 +367,21 @@ void __init time_init(void) -xtime.tv_sec, -xtime.tv_nsec); /* Choose appropriate high precision timer routines. */ - if (!cpu_has_counter && !mips_hpt_read) { + if (!cpu_has_counter && !mips_hpt_read) /* No high precision timer -- sorry. */ mips_hpt_read = null_hpt_read; - mips_hpt_init = null_hpt_init; - } else if (!mips_hpt_frequency && !mips_timer_state) { + else if (!mips_hpt_frequency && !mips_timer_state) { /* A high precision timer of unknown frequency. */ - if (!mips_hpt_read) { + if (!mips_hpt_read) /* No external high precision timer -- use R4k. */ mips_hpt_read = c0_hpt_read; - mips_hpt_init = c0_hpt_init; - } - - if (cpu_has_mips32r1 || cpu_has_mips32r2 || - (current_cpu_data.isa_level == MIPS_CPU_ISA_I) || - (current_cpu_data.isa_level == MIPS_CPU_ISA_II)) - /* - * We need to calibrate the counter but we don't have - * 64-bit division. - */ - do_gettimeoffset = calibrate_div32_gettimeoffset; - else - /* - * We need to calibrate the counter but we *do* have - * 64-bit division. - */ - do_gettimeoffset = calibrate_div64_gettimeoffset; } else { /* We know counter frequency. Or we can get it. */ if (!mips_hpt_read) { /* No external high precision timer -- use R4k. */ mips_hpt_read = c0_hpt_read; - if (mips_timer_state) - mips_hpt_init = c0_hpt_init; - else { + if (!mips_timer_state) { /* No external timer interrupt -- use R4k. */ mips_hpt_init = c0_hpt_timer_init; mips_timer_ack = c0_timer_ack; @@ -598,16 +390,9 @@ void __init time_init(void) if (!mips_hpt_frequency) mips_hpt_frequency = calibrate_hpt(); - do_gettimeoffset = fixed_rate_gettimeoffset; - /* Calculate cache parameters. */ cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ; - /* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */ - do_div64_32(sll32_usecs_per_cycle, - 1000000, mips_hpt_frequency / 2, - mips_hpt_frequency); - /* Report the high precision timer rate for a reference. */ printk("Using %u.%03u MHz high precision timer.\n", ((mips_hpt_frequency + 500) / 1000) / 1000, @@ -619,7 +404,7 @@ void __init time_init(void) mips_timer_ack = null_timer_ack; /* This sets up the high precision timer for the first interrupt. */ - mips_hpt_init(mips_hpt_read()); + mips_hpt_init(); /* * Call board specific timer interrupt setup. @@ -633,6 +418,8 @@ void __init time_init(void) * is not invoked accidentally. */ plat_timer_setup(&timer_irqaction); + + init_mips_clocksource(); } #define FEBRUARY 2 diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index cce8313ec27..9fda1b8be3a 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1111,7 +1111,7 @@ static struct shadow_registers { static void mips_srs_init(void) { shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1; - printk(KERN_INFO "%d MIPSR2 register sets available\n", + printk(KERN_INFO "%ld MIPSR2 register sets available\n", shadow_registers.sr_supported); shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */ } diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 0bb9cd88945..79f0317d84a 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -50,6 +50,16 @@ SECTIONS /* writeable */ .data : { /* Data */ . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ + /* + * This ALIGN is needed as a workaround for a bug a gcc bug upto 4.1 which + * limits the maximum alignment to at most 32kB and results in the following + * warning: + * + * CC arch/mips/kernel/init_task.o + * arch/mips/kernel/init_task.c:30: warning: alignment of ‘init_thread_union’ + * is greater than maximum object file alignment. Using 32768 + */ + . = ALIGN(_PAGE_SIZE); *(.data.init_task) *(.data) @@ -91,13 +101,7 @@ SECTIONS __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c index be8261be679..594df1a05ec 100644 --- a/arch/mips/lib-64/dump_tlb.c +++ b/arch/mips/lib-64/dump_tlb.c @@ -149,7 +149,7 @@ void dump_list_process(struct task_struct *t, void *address) printk("Addr == %08lx\n", addr); printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd); - page_dir = pgd_offset(t->mm, 0); + page_dir = pgd_offset(t->mm, 0UL); printk("page_dir == %016lx\n", (unsigned long) page_dir); pgd = pgd_offset(t->mm, addr); @@ -184,13 +184,13 @@ void dump_list_current(void *address) dump_list_process(current, address); } -unsigned int vtop(void *address) +unsigned long vtop(void *address) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; - unsigned int addr, paddr; + unsigned long addr, paddr; addr = (unsigned long) address; pgd = pgd_offset(current->mm, addr); diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c index be80c5dd4a0..eeed944e0f8 100644 --- a/arch/mips/mips-boards/generic/memory.c +++ b/arch/mips/mips-boards/generic/memory.c @@ -176,7 +176,7 @@ unsigned long __init prom_free_prom_memory(void) if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) continue; - addr = boot_mem_map.map[i].addr; + addr = PAGE_ALIGN(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))); diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c index 9337f6c8873..3192a14698c 100644 --- a/arch/mips/mips-boards/generic/pci.c +++ b/arch/mips/mips-boards/generic/pci.c @@ -90,7 +90,7 @@ static struct pci_controller msc_controller = { void __init mips_pcibios_init(void) { struct pci_controller *controller; - unsigned long start, end, map, start1, end1, map1, map2, map3, mask; + resource_size_t start, end, map, start1, end1, map1, map2, map3, mask; switch (mips_revision_corid) { case MIPS_REVISION_CORID_QED_RM5261: diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 6f8a9fe7c1e..d817c60c5ca 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c @@ -187,7 +187,7 @@ out: } /* - * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect */ static unsigned int __init estimate_cpu_frequency(void) { @@ -208,7 +208,8 @@ static unsigned int __init estimate_cpu_frequency(void) count = 6000000; #endif #if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA) - unsigned int flags; + unsigned long flags; + unsigned int start; local_irq_save(flags); @@ -217,13 +218,13 @@ static unsigned int __init estimate_cpu_frequency(void) while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); /* Start r4k counter. */ - write_c0_count(0); + start = read_c0_count(); /* Read counter exactly on falling edge of update flag */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - count = read_c0_count(); + count = read_c0_count() - start; /* restore interrupts */ local_irq_restore(flags); diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c index c566b9bd042..24a4ed00cc0 100644 --- a/arch/mips/mips-boards/sim/sim_time.c +++ b/arch/mips/mips-boards/sim/sim_time.c @@ -102,7 +102,7 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id) /* - * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect */ static unsigned int __init estimate_cpu_frequency(void) { diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c index 5537558f19f..d0ddb4a768a 100644 --- a/arch/mips/mm/c-sb1.c +++ b/arch/mips/mm/c-sb1.c @@ -49,6 +49,15 @@ static unsigned short dcache_sets; static unsigned int icache_range_cutoff; static unsigned int dcache_range_cutoff; +static inline void sb1_on_each_cpu(void (*func) (void *info), void *info, + int retry, int wait) +{ + preempt_disable(); + smp_call_function(func, info, retry, wait); + func(info); + preempt_enable(); +} + /* * The dcache is fully coherent to the system, with one * big caveat: the instruction stream. In other words, @@ -226,7 +235,7 @@ static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, args.vma = vma; args.addr = addr; args.pfn = pfn; - on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); + sb1_on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); } #else void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) @@ -249,7 +258,7 @@ void sb1___flush_cache_all_ipi(void *ignored) static void sb1___flush_cache_all(void) { - on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); + sb1_on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); } #else void sb1___flush_cache_all(void) @@ -299,7 +308,7 @@ void sb1_flush_icache_range(unsigned long start, unsigned long end) args.start = start; args.end = end; - on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); + sb1_on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); } #else void sb1_flush_icache_range(unsigned long start, unsigned long end) @@ -326,7 +335,7 @@ static void sb1_flush_cache_sigtramp_ipi(void *info) static void sb1_flush_cache_sigtramp(unsigned long addr) { - on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); + sb1_on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); } #else void sb1_flush_cache_sigtramp(unsigned long addr) @@ -444,7 +453,6 @@ static __init void probe_cache_sizes(void) void sb1_cache_init(void) { extern char except_vec2_sb1; - extern char handle_vec2_sb1; /* Special cache error handler for SB1 */ set_uncached_handler (0x100, &except_vec2_sb1, 0x80); @@ -497,5 +505,5 @@ void sb1_cache_init(void) : : "memory"); - flush_cache_all(); + local_sb1___flush_cache_all(); } diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 88b72c9a849..2de4d3c367a 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -30,11 +30,34 @@ #include <asm/cachectl.h> #include <asm/cpu.h> #include <asm/dma.h> +#include <asm/kmap_types.h> #include <asm/mmu_context.h> #include <asm/sections.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/tlb.h> +#include <asm/fixmap.h> + +/* Atomicity and interruptability */ +#ifdef CONFIG_MIPS_MT_SMTC + +#include <asm/mipsmtregs.h> + +#define ENTER_CRITICAL(flags) \ + { \ + unsigned int mvpflags; \ + local_irq_save(flags);\ + mvpflags = dvpe() +#define EXIT_CRITICAL(flags) \ + evpe(mvpflags); \ + local_irq_restore(flags); \ + } +#else + +#define ENTER_CRITICAL(flags) local_irq_save(flags) +#define EXIT_CRITICAL(flags) local_irq_restore(flags) + +#endif /* CONFIG_MIPS_MT_SMTC */ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -80,13 +103,142 @@ unsigned long setup_zero_pages(void) return 1UL << order; } -#ifdef CONFIG_HIGHMEM -pte_t *kmap_pte; -pgprot_t kmap_prot; +/* + * These are almost like kmap_atomic / kunmap_atmic except they take an + * additional address argument as the hint. + */ #define kmap_get_fixmap_pte(vaddr) \ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr)) +#ifdef CONFIG_MIPS_MT_SMTC +static pte_t *kmap_coherent_pte; +static void __init kmap_coherent_init(void) +{ + unsigned long vaddr; + + /* cache the first coherent kmap pte */ + vaddr = __fix_to_virt(FIX_CMAP_BEGIN); + kmap_coherent_pte = kmap_get_fixmap_pte(vaddr); +} +#else +static inline void kmap_coherent_init(void) {} +#endif + +static inline void *kmap_coherent(struct page *page, unsigned long addr) +{ + enum fixed_addresses idx; + unsigned long vaddr, flags, entrylo; + unsigned long old_ctx; + pte_t pte; + int tlbidx; + + inc_preempt_count(); + idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1); +#ifdef CONFIG_MIPS_MT_SMTC + idx += FIX_N_COLOURS * smp_processor_id(); +#endif + vaddr = __fix_to_virt(FIX_CMAP_END - idx); + pte = mk_pte(page, PAGE_KERNEL); +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1) + entrylo = pte.pte_high; +#else + entrylo = pte_val(pte) >> 6; +#endif + + ENTER_CRITICAL(flags); + old_ctx = read_c0_entryhi(); + write_c0_entryhi(vaddr & (PAGE_MASK << 1)); + write_c0_entrylo0(entrylo); + write_c0_entrylo1(entrylo); +#ifdef CONFIG_MIPS_MT_SMTC + set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte); + /* preload TLB instead of local_flush_tlb_one() */ + mtc0_tlbw_hazard(); + tlb_probe(); + tlb_probe_hazard(); + tlbidx = read_c0_index(); + mtc0_tlbw_hazard(); + if (tlbidx < 0) + tlb_write_random(); + else + tlb_write_indexed(); +#else + tlbidx = read_c0_wired(); + write_c0_wired(tlbidx + 1); + write_c0_index(tlbidx); + mtc0_tlbw_hazard(); + tlb_write_indexed(); +#endif + tlbw_use_hazard(); + write_c0_entryhi(old_ctx); + EXIT_CRITICAL(flags); + + return (void*) vaddr; +} + +#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) + +static inline void kunmap_coherent(struct page *page) +{ +#ifndef CONFIG_MIPS_MT_SMTC + unsigned int wired; + unsigned long flags, old_ctx; + + ENTER_CRITICAL(flags); + old_ctx = read_c0_entryhi(); + wired = read_c0_wired() - 1; + write_c0_wired(wired); + write_c0_index(wired); + write_c0_entryhi(UNIQUE_ENTRYHI(wired)); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + mtc0_tlbw_hazard(); + tlb_write_indexed(); + tlbw_use_hazard(); + write_c0_entryhi(old_ctx); + EXIT_CRITICAL(flags); +#endif + dec_preempt_count(); + preempt_check_resched(); +} + +void copy_to_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + if (cpu_has_dc_aliases) { + void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(vto, src, len); + kunmap_coherent(page); + } else + memcpy(dst, src, len); + if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) + flush_cache_page(vma, vaddr, page_to_pfn(page)); +} + +EXPORT_SYMBOL(copy_to_user_page); + +void copy_from_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + if (cpu_has_dc_aliases) { + void *vfrom = + kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(dst, vfrom, len); + kunmap_coherent(page); + } else + memcpy(dst, src, len); +} + +EXPORT_SYMBOL(copy_from_user_page); + + +#ifdef CONFIG_HIGHMEM +pte_t *kmap_pte; +pgprot_t kmap_prot; + static void __init kmap_init(void) { unsigned long kmap_vstart; @@ -97,11 +249,12 @@ static void __init kmap_init(void) kmap_prot = PAGE_KERNEL; } +#endif /* CONFIG_HIGHMEM */ -#ifdef CONFIG_32BIT void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) { +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_MIPS_MT_SMTC) pgd_t *pgd; pud_t *pud; pmd_t *pmd; @@ -122,7 +275,7 @@ void __init fixrange_init(unsigned long start, unsigned long end, for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) { if (pmd_none(*pmd)) { pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - set_pmd(pmd, __pmd(pte)); + set_pmd(pmd, __pmd((unsigned long)pte)); if (pte != pte_offset_kernel(pmd, 0)) BUG(); } @@ -132,9 +285,8 @@ void __init fixrange_init(unsigned long start, unsigned long end, } j = 0; } +#endif } -#endif /* CONFIG_32BIT */ -#endif /* CONFIG_HIGHMEM */ #ifndef CONFIG_NEED_MULTIPLE_NODES extern void pagetable_init(void); @@ -175,6 +327,7 @@ void __init paging_init(void) #ifdef CONFIG_HIGHMEM kmap_init(); #endif + kmap_coherent_init(); max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c index b7c749232ff..d41fc5885e8 100644 --- a/arch/mips/mm/pg-r4k.c +++ b/arch/mips/mm/pg-r4k.c @@ -270,6 +270,20 @@ static inline void build_addiu_a2_a0(unsigned long offset) emit_instruction(mi); } +static inline void build_addiu_a2(unsigned long offset) +{ + union mips_instruction mi; + + BUG_ON(offset > 0x7fff); + + mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; + mi.i_format.rs = 6; /* $a2 */ + mi.i_format.rt = 6; /* $a2 */ + mi.i_format.simmediate = offset; + + emit_instruction(mi); +} + static inline void build_addiu_a1(unsigned long offset) { union mips_instruction mi; @@ -333,6 +347,7 @@ static inline void build_jr_ra(void) void __init build_clear_page(void) { unsigned int loop_start; + unsigned long off; epc = (unsigned int *) &clear_page_array; instruction_pending = 0; @@ -369,7 +384,12 @@ void __init build_clear_page(void) } } - build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0)); + off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0); + if (off > 0x7fff) { + build_addiu_a2_a0(off >> 1); + build_addiu_a2(off >> 1); + } else + build_addiu_a2_a0(off); if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ @@ -420,12 +440,18 @@ dest = label(); void __init build_copy_page(void) { unsigned int loop_start; + unsigned long off; epc = (unsigned int *) ©_page_array; store_offset = load_offset = 0; instruction_pending = 0; - build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0)); + off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0); + if (off > 0x7fff) { + build_addiu_a2_a0(off >> 1); + build_addiu_a2(off >> 1); + } else + build_addiu_a2_a0(off); if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c index 4bdaa05f485..4a61e624b0e 100644 --- a/arch/mips/mm/pgtable-32.c +++ b/arch/mips/mm/pgtable-32.c @@ -31,9 +31,10 @@ void pgd_init(unsigned long page) void __init pagetable_init(void) { -#ifdef CONFIG_HIGHMEM unsigned long vaddr; - pgd_t *pgd, *pgd_base; + pgd_t *pgd_base; +#ifdef CONFIG_HIGHMEM + pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -44,7 +45,6 @@ void __init pagetable_init(void) pgd_init((unsigned long)swapper_pg_dir + sizeof(pgd_t) * USER_PTRS_PER_PGD); -#ifdef CONFIG_HIGHMEM pgd_base = swapper_pg_dir; /* @@ -53,6 +53,7 @@ void __init pagetable_init(void) vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; fixrange_init(vaddr, 0, pgd_base); +#ifdef CONFIG_HIGHMEM /* * Permanent kmaps: */ diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c index 44b5e97fff6..8d600d307d5 100644 --- a/arch/mips/mm/pgtable-64.c +++ b/arch/mips/mm/pgtable-64.c @@ -8,6 +8,7 @@ */ #include <linux/init.h> #include <linux/mm.h> +#include <asm/fixmap.h> #include <asm/pgtable.h> void pgd_init(unsigned long page) @@ -52,7 +53,17 @@ void pmd_init(unsigned long addr, unsigned long pagetable) void __init pagetable_init(void) { + unsigned long vaddr; + pgd_t *pgd_base; + /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); + + pgd_base = swapper_pg_dir; + /* + * Fixed mappings: + */ + vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; + fixrange_init(vaddr, 0, pgd_base); } diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 6f8b25cfa6f..fec318a1c8c 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -102,7 +102,7 @@ enum opcode { insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, - insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, + insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, @@ -145,6 +145,7 @@ static __initdata struct insn insn_table[] = { { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE }, + { insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE }, { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD }, { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 }, { insn_j, M(j_op,0,0,0,0,0), JIMM }, @@ -385,6 +386,7 @@ I_u2u1u3(_dsll); I_u2u1u3(_dsll32); I_u2u1u3(_dsra); I_u2u1u3(_dsrl); +I_u2u1u3(_dsrl32); I_u3u1u2(_dsubu); I_0(_eret); I_u1(_j); @@ -996,7 +998,12 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r, #endif l_vmalloc_done(l, *p); - i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */ + + if (PGDIR_SHIFT - 3 < 32) /* get pgd offset in bytes */ + i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); + else + i_dsrl32(p, tmp, tmp, PGDIR_SHIFT - 3 - 32); + i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3); i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */ i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */ @@ -1073,7 +1080,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) static __init void build_adjust_context(u32 **p, unsigned int ctx) { - unsigned int shift = 4 - (PTE_T_LOG2 + 1); + unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); switch (current_cpu_data.cputype) { diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile index 8bcea64dd27..d5a090a85a1 100644 --- a/arch/mips/momentum/ocelot_3/Makefile +++ b/arch/mips/momentum/ocelot_3/Makefile @@ -5,4 +5,4 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # -obj-y += irq.o prom.o reset.o setup.o +obj-y += irq.o platform.o prom.o reset.o setup.o diff --git a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h b/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h index 227e429fe72..5710a9029f1 100644 --- a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h +++ b/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h @@ -51,7 +51,9 @@ extern unsigned long ocelot_fpga_base; -#define OCELOT_FPGA_WRITE(x, y) writeb(x, ocelot_fpga_base + OCELOT_3_REG_##y) -#define OCELOT_FPGA_READ(x) readb(ocelot_fpga_base + OCELOT_3_REG_##x) +#define __FPGA_REG_TO_ADDR(reg) \ + ((void *) ocelot_fpga_base + OCELOT_3_REG_##reg) +#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg)) +#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg)) #endif diff --git a/arch/mips/momentum/ocelot_3/platform.c b/arch/mips/momentum/ocelot_3/platform.c new file mode 100644 index 00000000000..eefe5841fbb --- /dev/null +++ b/arch/mips/momentum/ocelot_3/platform.c @@ -0,0 +1,235 @@ +#include <linux/delay.h> +#include <linux/if_ether.h> +#include <linux/ioport.h> +#include <linux/mv643xx.h> +#include <linux/platform_device.h> + +#include "ocelot_3_fpga.h" + +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) + +static struct resource mv643xx_eth_shared_resources[] = { + [0] = { + .name = "ethernet shared base", + .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, + .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + + MV643XX_ETH_SHARED_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mv643xx_eth_shared_device = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), + .resource = mv643xx_eth_shared_resources, +}; + +#define MV_SRAM_BASE 0xfe000000UL +#define MV_SRAM_SIZE (256 * 1024) + +#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) +#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) + +#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE +#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) + +#define MV64x60_IRQ_ETH_0 48 +#define MV64x60_IRQ_ETH_1 49 +#define MV64x60_IRQ_ETH_2 50 + +#ifdef CONFIG_MV643XX_ETH_0 + +static struct resource mv64x60_eth0_resources[] = { + [0] = { + .name = "eth0 irq", + .start = MV64x60_IRQ_ETH_0, + .end = MV64x60_IRQ_ETH_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth0_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth0_pd = { + .mac_addr = eth0_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH0, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth0_device = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), + .resource = mv64x60_eth0_resources, + .dev = { + .platform_data = ð0_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_0 */ + +#ifdef CONFIG_MV643XX_ETH_1 + +static struct resource mv64x60_eth1_resources[] = { + [0] = { + .name = "eth1 irq", + .start = MV64x60_IRQ_ETH_1, + .end = MV64x60_IRQ_ETH_1, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth1_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth1_pd = { + .mac_addr = eth1_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH1, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth1_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), + .resource = mv64x60_eth1_resources, + .dev = { + .platform_data = ð1_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_1 */ + +#ifdef CONFIG_MV643XX_ETH_2 + +static struct resource mv64x60_eth2_resources[] = { + [0] = { + .name = "eth2 irq", + .start = MV64x60_IRQ_ETH_2, + .end = MV64x60_IRQ_ETH_2, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth2_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth2_pd = { + .mac_addr = eth2_mac_addr, +}; + +static struct platform_device eth2_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth2_resources), + .resource = mv64x60_eth2_resources, + .dev = { + .platform_data = ð2_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_2 */ + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, +#ifdef CONFIG_MV643XX_ETH_0 + ð0_device, +#endif +#ifdef CONFIG_MV643XX_ETH_1 + ð1_device, +#endif +#ifdef CONFIG_MV643XX_ETH_2 + ð2_device, +#endif +}; + +static u8 __init exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + udelay(1); + + /* turn the clock on */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + udelay(1); + + /* turn the clock off and read-strobe */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1; +} + +static void __init get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} + +/* + * Copy and increment ethernet MAC address by a small value. + * + * This is useful for systems where the only one MAC address is stored in + * non-volatile memory for multiple ports. + */ +static inline void eth_mac_add(unsigned char *dst, unsigned char *src, + unsigned int add) +{ + int i; + + BUG_ON(add >= 256); + + for (i = ETH_ALEN; i >= 0; i--) { + dst[i] = src[i] + add; + add = dst[i] < src[i]; /* compute carry */ + } + + WARN_ON(add); +} + +static int __init mv643xx_eth_add_pds(void) +{ + unsigned char mac[ETH_ALEN]; + int ret; + + get_mac(mac); +#ifdef CONFIG_MV643XX_ETH_0 + eth_mac_add(eth1_mac_addr, mac, 0); +#endif +#ifdef CONFIG_MV643XX_ETH_1 + eth_mac_add(eth1_mac_addr, mac, 1); +#endif +#ifdef CONFIG_MV643XX_ETH_2 + eth_mac_add(eth2_mac_addr, mac, 2); +#endif + ret = platform_add_devices(mv643xx_eth_pd_devs, + ARRAY_SIZE(mv643xx_eth_pd_devs)); + + return ret; +} + +device_initcall(mv643xx_eth_add_pds); + +#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c index 296d945bc24..6ce9b7fdb82 100644 --- a/arch/mips/momentum/ocelot_3/prom.c +++ b/arch/mips/momentum/ocelot_3/prom.c @@ -34,64 +34,11 @@ struct callvectors* debug_vectors; extern unsigned long marvell_base; extern unsigned long cpu_clock; -#ifdef CONFIG_MV643XX_ETH -extern unsigned char prom_mac_addr_base[6]; -#endif - const char *get_system_type(void) { return "Momentum Ocelot-3"; } -#ifdef CONFIG_MV643XX_ETH -void burn_clocks(void) -{ - int i; - - /* this loop should burn at least 1us -- this should be plenty */ - for (i = 0; i < 0x10000; i++) - ; -} - -u8 exchange_bit(u8 val, u8 cs) -{ - /* place the data */ - OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); - burn_clocks(); - - /* turn the clock on */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); - burn_clocks(); - - /* turn the clock off and read-strobe */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); - - /* return the data */ - return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); -} - -void get_mac(char dest[6]) -{ - u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i,j; - - for (i = 0; i < 12; i++) - exchange_bit(read_opcode[i], 1); - - for (j = 0; j < 6; j++) { - dest[j] = 0; - for (i = 0; i < 8; i++) { - dest[j] <<= 1; - dest[j] |= exchange_bit(0, 1); - } - } - - /* turn off CS */ - exchange_bit(0,0); -} -#endif - - #ifdef CONFIG_64BIT unsigned long signext(unsigned long addr) @@ -228,11 +175,6 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_OCELOT_3; -#ifdef CONFIG_MV643XX_ETH - /* get the base MAC address for on-board ethernet ports */ - get_mac(prom_mac_addr_base); -#endif - #ifndef CONFIG_64BIT debug_vectors->printf("Booting Linux kernel...\n"); #endif diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c index 7d74f8c5412..ff0829f8111 100644 --- a/arch/mips/momentum/ocelot_3/setup.c +++ b/arch/mips/momentum/ocelot_3/setup.c @@ -4,7 +4,7 @@ * BRIEF MODULE DESCRIPTION * Momentum Computer Ocelot-3 board dependent boot routines * - * Copyright (C) 1996, 1997, 01, 05 Ralf Baechle + * Copyright (C) 1996, 1997, 01, 05 - 06 Ralf Baechle * Copyright (C) 2000 RidgeRun, Inc. * Copyright (C) 2001 Red Hat, Inc. * Copyright (C) 2002 Momentum Computer diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile index 94802b4db47..d69161aa167 100644 --- a/arch/mips/momentum/ocelot_c/Makefile +++ b/arch/mips/momentum/ocelot_c/Makefile @@ -2,7 +2,7 @@ # Makefile for Momentum Computer's Ocelot-C and -CS boards. # -obj-y += cpci-irq.o irq.o prom.o reset.o \ +obj-y += cpci-irq.o irq.o platform.o prom.o reset.o \ setup.o uart-irq.o obj-$(CONFIG_KGDB) += dbg_io.o diff --git a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h index 7228cd19e5e..f0f5581dcb5 100644 --- a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h +++ b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h @@ -53,7 +53,9 @@ #define OCELOT_C_REG_INTSET 0xe #define OCELOT_C_REG_INTCLR 0xf -#define OCELOT_FPGA_WRITE(x, y) writeb(x, OCELOT_C_CS0_ADDR + OCELOT_C_REG_##y) -#define OCELOT_FPGA_READ(x) readb(OCELOT_C_CS0_ADDR + OCELOT_C_REG_##x) +#define __FPGA_REG_TO_ADDR(reg) \ + ((void *) OCELOT_C_CS0_ADDR + OCELOT_C_REG_##reg) +#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg)) +#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg)) #endif diff --git a/arch/mips/momentum/ocelot_c/platform.c b/arch/mips/momentum/ocelot_c/platform.c new file mode 100644 index 00000000000..6c495b2f156 --- /dev/null +++ b/arch/mips/momentum/ocelot_c/platform.c @@ -0,0 +1,201 @@ +#include <linux/delay.h> +#include <linux/if_ether.h> +#include <linux/ioport.h> +#include <linux/mv643xx.h> +#include <linux/platform_device.h> + +#include "ocelot_c_fpga.h" + +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) + +static struct resource mv643xx_eth_shared_resources[] = { + [0] = { + .name = "ethernet shared base", + .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, + .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + + MV643XX_ETH_SHARED_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mv643xx_eth_shared_device = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), + .resource = mv643xx_eth_shared_resources, +}; + +#define MV_SRAM_BASE 0xfe000000UL +#define MV_SRAM_SIZE (256 * 1024) + +#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) +#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) + +#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE +#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) + +#define MV64x60_IRQ_ETH_0 48 +#define MV64x60_IRQ_ETH_1 49 + +#ifdef CONFIG_MV643XX_ETH_0 + +static struct resource mv64x60_eth0_resources[] = { + [0] = { + .name = "eth0 irq", + .start = MV64x60_IRQ_ETH_0, + .end = MV64x60_IRQ_ETH_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth0_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth0_pd = { + .mac_addr = eth0_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH0, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth0_device = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), + .resource = mv64x60_eth0_resources, + .dev = { + .platform_data = ð0_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_0 */ + +#ifdef CONFIG_MV643XX_ETH_1 + +static struct resource mv64x60_eth1_resources[] = { + [0] = { + .name = "eth1 irq", + .start = MV64x60_IRQ_ETH_1, + .end = MV64x60_IRQ_ETH_1, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth1_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth1_pd = { + .mac_addr = eth1_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH1, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth1_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), + .resource = mv64x60_eth1_resources, + .dev = { + .platform_data = ð1_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_1 */ + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, +#ifdef CONFIG_MV643XX_ETH_0 + ð0_device, +#endif +#ifdef CONFIG_MV643XX_ETH_1 + ð1_device, +#endif + /* The third port is not wired up on the Ocelot C */ +}; + +static u8 __init exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + udelay(1); + + /* turn the clock on */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + udelay(1); + + /* turn the clock off and read-strobe */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1; +} + +static void __init get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} + +/* + * Copy and increment ethernet MAC address by a small value. + * + * This is useful for systems where the only one MAC address is stored in + * non-volatile memory for multiple ports. + */ +static inline void eth_mac_add(unsigned char *dst, unsigned char *src, + unsigned int add) +{ + int i; + + BUG_ON(add >= 256); + + for (i = ETH_ALEN; i >= 0; i--) { + dst[i] = src[i] + add; + add = dst[i] < src[i]; /* compute carry */ + } + + WARN_ON(add); +} + +static int __init mv643xx_eth_add_pds(void) +{ + unsigned char mac[ETH_ALEN]; + int ret; + + get_mac(mac); +#ifdef CONFIG_MV643XX_ETH_0 + eth_mac_add(eth1_mac_addr, mac, 0); +#endif +#ifdef CONFIG_MV643XX_ETH_1 + eth_mac_add(eth1_mac_addr, mac, 1); +#endif + ret = platform_add_devices(mv643xx_eth_pd_devs, + ARRAY_SIZE(mv643xx_eth_pd_devs)); + + return ret; +} + +device_initcall(mv643xx_eth_add_pds); + +#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c index 4c50a147f42..d0b77e101d7 100644 --- a/arch/mips/momentum/ocelot_c/prom.c +++ b/arch/mips/momentum/ocelot_c/prom.c @@ -29,11 +29,7 @@ struct callvectors* debug_vectors; extern unsigned long marvell_base; -extern unsigned long cpu_clock; - -#ifdef CONFIG_MV643XX_ETH -extern unsigned char prom_mac_addr_base[6]; -#endif +extern unsigned int cpu_clock; const char *get_system_type(void) { @@ -44,55 +40,6 @@ const char *get_system_type(void) #endif } -#ifdef CONFIG_MV643XX_ETH -static void burn_clocks(void) -{ - int i; - - /* this loop should burn at least 1us -- this should be plenty */ - for (i = 0; i < 0x10000; i++) - ; -} - -static u8 exchange_bit(u8 val, u8 cs) -{ - /* place the data */ - OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); - burn_clocks(); - - /* turn the clock on */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); - burn_clocks(); - - /* turn the clock off and read-strobe */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); - - /* return the data */ - return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); -} - -void get_mac(char dest[6]) -{ - u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i,j; - - for (i = 0; i < 12; i++) - exchange_bit(read_opcode[i], 1); - - for (j = 0; j < 6; j++) { - dest[j] = 0; - for (i = 0; i < 8; i++) { - dest[j] <<= 1; - dest[j] |= exchange_bit(0, 1); - } - } - - /* turn off CS */ - exchange_bit(0,0); -} -#endif - - #ifdef CONFIG_64BIT unsigned long signext(unsigned long addr) @@ -226,11 +173,6 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_OCELOT_C; -#ifdef CONFIG_MV643XX_ETH - /* get the base MAC address for on-board ethernet ports */ - get_mac(prom_mac_addr_base); -#endif - #ifndef CONFIG_64BIT debug_vectors->printf("Booting Linux kernel...\n"); #endif diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index 9c0c462af65..0b6b2338cfb 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -69,8 +69,7 @@ #include "ocelot_c_fpga.h" unsigned long marvell_base; -extern unsigned long mv64340_sram_base; -unsigned long cpu_clock; +unsigned int cpu_clock; /* These functions are used for rebooting or halting the machine*/ extern void momenco_ocelot_restart(char *command); @@ -119,7 +118,6 @@ void PMON_v2_setup(void) add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M); marvell_base = 0xfffffffff4000000; - mv64340_sram_base = 0xfffffffffe000000; #else /* marvell and extra space */ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K); @@ -129,7 +127,6 @@ void PMON_v2_setup(void) add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M); marvell_base = 0xf4000000; - mv64340_sram_base = 0xfe000000; #endif } @@ -346,22 +343,20 @@ void __init plat_mem_setup(void) } } -#ifndef CONFIG_64BIT -/* This needs to be one of the first initcalls, because no I/O port access - can work before this */ +/* + * This needs to be one of the first initcalls, because no I/O port access + * can work before this + */ static int io_base_ioremap(void) { - /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */ - void *io_remap_range = ioremap(0xc0000000, 0x30000000); + void __iomem * io_remap_range = ioremap(0xc0000000UL, 0x10000); - if (!io_remap_range) { + if (!io_remap_range) panic("Could not ioremap I/O port range"); - } - printk("io_remap_range set at 0x%08x\n", (uint32_t)io_remap_range); - set_io_port_base(io_remap_range - 0xc0000000); + + set_io_port_base((unsigned long) io_remap_range); return 0; } module_init(io_base_ioremap); -#endif diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c index 7b5cc6648f7..e5576bd50fa 100644 --- a/arch/mips/momentum/ocelot_g/gt-irq.c +++ b/arch/mips/momentum/ocelot_g/gt-irq.c @@ -27,7 +27,7 @@ unsigned long bus_clock; * be handled and ack'ed differently than other MIPS interrupts. */ -#if CURRENTLY_UNUSED +#if 0 struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); @@ -95,7 +95,7 @@ int disable_galileo_irq(int int_cause, int bit_num) return 0; return 1; } -#endif /* UNUSED */ +#endif /* 0 */ /* * Interrupt handler for interrupts coming from the Galileo chip via P0_INT#. @@ -196,7 +196,7 @@ void gt64240_time_init(void) void gt64240_irq_init(void) { -#if CURRENTLY_UNUSED +#if 0 int i, j; /* Reset irq handlers pointers to NULL */ @@ -208,5 +208,5 @@ void gt64240_irq_init(void) irq_handlers[i][j].data = NULL; } } -#endif +#endif /* 0 */ } diff --git a/arch/mips/momentum/ocelot_g/ocelot_pld.h b/arch/mips/momentum/ocelot_g/ocelot_pld.h index fcb8275e219..95e0534026d 100644 --- a/arch/mips/momentum/ocelot_g/ocelot_pld.h +++ b/arch/mips/momentum/ocelot_g/ocelot_pld.h @@ -23,8 +23,8 @@ #define OCELOT_REG_INTSET (12) #define OCELOT_REG_INTCLR (13) -#define OCELOT_PLD_WRITE(x, y) writeb(x, OCELOT_CS0_ADDR + OCELOT_REG_##y) -#define OCELOT_PLD_READ(x) readb(OCELOT_CS0_ADDR + OCELOT_REG_##x) - +#define __PLD_REG_TO_ADDR(reg) ((void *) OCELOT_CS0_ADDR + OCELOT_REG_##reg) +#define OCELOT_PLD_WRITE(x, reg) writeb(x, __PLD_REG_TO_ADDR(reg)) +#define OCELOT_PLD_READ(reg) readb(__PLD_REG_TO_ADDR(reg)) #endif /* __MOMENCO_OCELOT_PLD_H__ */ diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c index 56ec47039c1..d288f7b0184 100644 --- a/arch/mips/momentum/ocelot_g/setup.c +++ b/arch/mips/momentum/ocelot_g/setup.c @@ -57,6 +57,7 @@ #include <asm/gt64240.h> #include <asm/irq.h> #include <asm/pci.h> +#include <asm/pgtable.h> #include <asm/processor.h> #include <asm/reboot.h> #include <linux/bootmem.h> @@ -160,6 +161,10 @@ static void __init setup_l3cache(unsigned long size) printk("Done\n"); } +void __init plat_timer_setup(struct irqaction *irq) +{ +} + void __init plat_mem_setup(void) { void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache); diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index dd0aec9c3ce..1fb240c57ba 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -31,16 +31,18 @@ #define M_COUNTER_OVERFLOW (1UL << 31) #ifdef CONFIG_MIPS_MT_SMP -#define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) +#define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) +#define vpe_id() smp_processor_id() #else -#define WHAT 0 +#define WHAT 0 +#define vpe_id() smp_processor_id() #endif #define __define_perf_accessors(r, n, np) \ \ static inline unsigned int r_c0_ ## r ## n(void) \ { \ - unsigned int cpu = smp_processor_id(); \ + unsigned int cpu = vpe_id(); \ \ switch (cpu) { \ case 0: \ @@ -55,7 +57,7 @@ static inline unsigned int r_c0_ ## r ## n(void) \ \ static inline void w_c0_ ## r ## n(unsigned int value) \ { \ - unsigned int cpu = smp_processor_id(); \ + unsigned int cpu = vpe_id(); \ \ switch (cpu) { \ case 0: \ @@ -218,7 +220,7 @@ static inline int n_counters(void) { int counters = __n_counters(); -#ifndef CONFIG_SMP +#ifdef CONFIG_MIPS_MT_SMP if (current_cpu_data.cputype == CPU_34K) return counters >> 1; #endif diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 3cf0dd4ba54..70cb55b89df 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o obj-$(CONFIG_LASAT) += pci-lasat.o obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o -obj-$(CONFIG_MIPS_EV64120) += fixup-ev64120.o +obj-$(CONFIG_MIPS_EV64120) += pci-ev64120.o obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o diff --git a/arch/mips/pci/fixup-ev64120.c b/arch/mips/pci/fixup-ev64120.c deleted file mode 100644 index 8dbb90d63f0..00000000000 --- a/arch/mips/pci/fixup-ev64120.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <linux/pci.h> -#include <linux/init.h> - -int pci_range_ck(unsigned char bus, unsigned char dev) -{ - if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8)) - return 0; - - return -1; -} - -/* - * After detecting all agents over the PCI , this function is called - * in order to give an interrupt number for each PCI device starting - * from IRQ 20. It does also enables master for each device. - */ -void __devinit pcibios_fixup_bus(struct pci_bus *bus) -{ - unsigned int irq = 20; - struct pci_bus *current_bus = bus; - struct pci_dev *dev; - struct list_head *devices_link; - - list_for_each(devices_link, &(current_bus->devices)) { - dev = pci_dev_b(devices_link); - if (dev != NULL) { - dev->irq = irq++; - - /* Assign an interrupt number for the device */ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); - pcibios_set_master(dev); - } - } -} diff --git a/arch/mips/pci/pci-ev64120.c b/arch/mips/pci/pci-ev64120.c new file mode 100644 index 00000000000..9cd859ef184 --- /dev/null +++ b/arch/mips/pci/pci-ev64120.c @@ -0,0 +1,21 @@ +#include <linux/pci.h> + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq; + + if (!pin) + return 0; + + irq = allocate_irqno(); + if (irq < 0) + return 0; + + return irq; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c index 0af655b1f33..65c440e8480 100644 --- a/arch/mips/philips/pnx8550/common/time.c +++ b/arch/mips/philips/pnx8550/common/time.c @@ -41,8 +41,8 @@ extern unsigned int mips_hpt_frequency; * 1) board_time_init() - * a) (optional) set up RTC routines, * b) (optional) calibrate and set the mips_hpt_frequency - * (only needed if you intended to use fixed_rate_gettimeoffset - * or use cpu counter as timer interrupt source) + * (only needed if you intended to use cpu counter as timer interrupt + * source) */ void pnx8550_time_init(void) diff --git a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c index 416da22b3bf..85b14c73c22 100644 --- a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c +++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c @@ -74,7 +74,7 @@ static int titan_i2c_poll(void) int titan_i2c_xfer(unsigned int slave_addr, titan_i2c_command * cmd, int size, unsigned int *addr) { - int loop = 0, bytes, i; + int loop, bytes = 0, i; unsigned int *write_data, data, *read_data; unsigned long reg_val, val; diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index 65fa3a23ea5..3cc0436db6c 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -3,9 +3,7 @@ #include <asm/pmon.h> #include <asm/titan_dep.h> - -extern unsigned int (*mips_hpt_read)(void); -extern void (*mips_hpt_init)(unsigned int); +#include <asm/time.h> #define LAUNCHSTACK_SIZE 256 @@ -101,7 +99,7 @@ void prom_cpus_done(void) */ void prom_init_secondary(void) { - mips_hpt_init(mips_hpt_read()); + mips_hpt_init(); set_c0_status(ST0_CO | ST0_IE | ST0_IM); } diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index f01ba1f9077..270ecd3e6b4 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -354,29 +354,6 @@ static struct irq_chip bridge_irq_type = { .end = end_bridge_irq, }; -static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; - -int allocate_irqno(void) -{ - int irq; - -again: - irq = find_first_zero_bit(irq_map, NR_IRQS); - - if (irq >= NR_IRQS) - return -ENOSPC; - - if (test_and_set_bit(irq, irq_map)) - goto again; - - return irq; -} - -void free_irqno(unsigned int irq) -{ - clear_bit(irq, irq_map); -} - void __devinit register_bridge_irq(unsigned int irq) { irq_desc[irq].status = IRQ_DISABLED; diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 4e870fc4469..5e82a268e3c 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -134,13 +134,6 @@ again: irq_exit(); } -unsigned long ip27_do_gettimeoffset(void) -{ - unsigned long ct_cur1; - ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY; - return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000; -} - /* Includes for ioc3_init(). */ #include <asm/sn/types.h> #include <asm/sn/sn0/addrs.h> @@ -221,8 +214,6 @@ static struct irqaction rt_irqaction = { .name = "timer" }; -extern int allocate_irqno(void); - void __init plat_timer_setup(struct irqaction *irq) { int irqno = allocate_irqno(); @@ -248,12 +239,17 @@ void __init plat_timer_setup(struct irqaction *irq) setup_irq(irqno, &rt_irqaction); } +static unsigned int ip27_hpt_read(void) +{ + return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); +} + void __init ip27_time_init(void) { + mips_hpt_read = ip27_hpt_read; + mips_hpt_frequency = CYCLES_PER_SEC; xtime.tv_sec = get_m48t35_time(); xtime.tv_nsec = 0; - - do_gettimeoffset = ip27_do_gettimeoffset; } void __init cpu_time_init(void) diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c index bf12af46132..e136bde5248 100644 --- a/arch/mips/sibyte/bcm1480/time.c +++ b/arch/mips/sibyte/bcm1480/time.c @@ -47,6 +47,12 @@ #define IMR_IP3_VAL K_BCM1480_INT_MAP_I1 #define IMR_IP4_VAL K_BCM1480_INT_MAP_I2 +#ifdef CONFIG_SIMULATION +#define BCM1480_HPT_VALUE 50000 +#else +#define BCM1480_HPT_VALUE 1000000 +#endif + extern int bcm1480_steal_irq(int irq); void bcm1480_time_init(void) @@ -59,11 +65,6 @@ void bcm1480_time_init(void) BUG(); } - if (!cpu) { - /* Use our own gettimeoffset() routine */ - do_gettimeoffset = bcm1480_gettimeoffset; - } - bcm1480_mask_irq(cpu, irq); /* Map the timer interrupt to ip[4] of this cpu */ @@ -74,11 +75,7 @@ void bcm1480_time_init(void) /* Disable the timer and set up the count */ __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); __raw_writeq( -#ifndef CONFIG_SIMULATION - 1000000/HZ -#else - 50000/HZ -#endif + BCM1480_HPT_VALUE/HZ , IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT))); /* Set the timer running */ @@ -122,16 +119,16 @@ void bcm1480_timer_interrupt(void) } } -/* - * We use our own do_gettimeoffset() instead of the generic one, - * because the generic one does not work for SMP case. - * In addition, since we use general timer 0 for system time, - * we can get accurate intra-jiffy offset without calibration. - */ -unsigned long bcm1480_gettimeoffset(void) +static unsigned int bcm1480_hpt_read(void) { + /* We assume this function is called xtime_lock held. */ unsigned long count = __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT))); + return (jiffies + 1) * (BCM1480_HPT_VALUE / HZ) - count; +} - return 1000000/HZ - count; +void __init bcm1480_hpt_setup(void) +{ + mips_hpt_read = bcm1480_hpt_read; + mips_hpt_frequency = BCM1480_HPT_VALUE; } diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c index 0ccf1796dd7..bcb74f2c194 100644 --- a/arch/mips/sibyte/sb1250/time.c +++ b/arch/mips/sibyte/sb1250/time.c @@ -47,15 +47,11 @@ #define SB1250_HPT_NUM 3 #define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */ -#define SB1250_HPT_SHIFT ((sizeof(unsigned int)*8)-V_SCD_TIMER_WIDTH) extern int sb1250_steal_irq(int irq); static unsigned int sb1250_hpt_read(void); -static void sb1250_hpt_init(unsigned int); - -static unsigned int hpt_offset; void __init sb1250_hpt_setup(void) { @@ -69,13 +65,9 @@ void __init sb1250_hpt_setup(void) __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG))); - /* - * we need to fill 32 bits, so just use the upper 23 bits and pretend - * the timer is going 512Mhz instead of 1Mhz - */ - mips_hpt_frequency = V_SCD_TIMER_FREQ << SB1250_HPT_SHIFT; - mips_hpt_init = sb1250_hpt_init; + mips_hpt_frequency = V_SCD_TIMER_FREQ; mips_hpt_read = sb1250_hpt_read; + mips_hpt_mask = M_SCD_TIMER_INIT; } } @@ -149,11 +141,7 @@ void sb1250_timer_interrupt(void) /* * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over - * again. There's no easy way to set to a specific value so store init value - * in hpt_offset and subtract each time. - * - * Note: Timer isn't full 32bits so shift it into the upper part making - * it appear to run at a higher frequency. + * again. */ static unsigned int sb1250_hpt_read(void) { @@ -161,13 +149,5 @@ static unsigned int sb1250_hpt_read(void) count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT)))); - count = (SB1250_HPT_VALUE - count) << SB1250_HPT_SHIFT; - - return count - hpt_offset; -} - -static void sb1250_hpt_init(unsigned int count) -{ - hpt_offset = count; - return; + return SB1250_HPT_VALUE - count; } diff --git a/arch/mips/tx4927/common/smsc_fdc37m81x.c b/arch/mips/tx4927/common/smsc_fdc37m81x.c new file mode 100644 index 00000000000..33f517bc9a0 --- /dev/null +++ b/arch/mips/tx4927/common/smsc_fdc37m81x.c @@ -0,0 +1,172 @@ +/* + * Interface for smsc fdc48m81x Super IO chip + * + * Author: MontaVista Software, Inc. source@mvista.com + * + * 2001-2003 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Copyright 2004 (c) MontaVista Software, Inc. + */ +#include <linux/init.h> +#include <linux/types.h> +#include <asm/io.h> +#include <asm/tx4927/smsc_fdc37m81x.h> + +#define DEBUG + +/* Common Registers */ +#define SMSC_FDC37M81X_CONFIG_INDEX 0x00 +#define SMSC_FDC37M81X_CONFIG_DATA 0x01 +#define SMSC_FDC37M81X_CONF 0x02 +#define SMSC_FDC37M81X_INDEX 0x03 +#define SMSC_FDC37M81X_DNUM 0x07 +#define SMSC_FDC37M81X_DID 0x20 +#define SMSC_FDC37M81X_DREV 0x21 +#define SMSC_FDC37M81X_PCNT 0x22 +#define SMSC_FDC37M81X_PMGT 0x23 +#define SMSC_FDC37M81X_OSC 0x24 +#define SMSC_FDC37M81X_CONFPA0 0x26 +#define SMSC_FDC37M81X_CONFPA1 0x27 +#define SMSC_FDC37M81X_TEST4 0x2B +#define SMSC_FDC37M81X_TEST5 0x2C +#define SMSC_FDC37M81X_TEST1 0x2D +#define SMSC_FDC37M81X_TEST2 0x2E +#define SMSC_FDC37M81X_TEST3 0x2F + +/* Logical device numbers */ +#define SMSC_FDC37M81X_FDD 0x00 +#define SMSC_FDC37M81X_SERIAL1 0x04 +#define SMSC_FDC37M81X_SERIAL2 0x05 +#define SMSC_FDC37M81X_KBD 0x07 + +/* Logical device Config Registers */ +#define SMSC_FDC37M81X_ACTIVE 0x30 +#define SMSC_FDC37M81X_BASEADDR0 0x60 +#define SMSC_FDC37M81X_BASEADDR1 0x61 +#define SMSC_FDC37M81X_INT 0x70 +#define SMSC_FDC37M81X_INT2 0x72 +#define SMSC_FDC37M81X_MODE 0xF0 + +/* Chip Config Values */ +#define SMSC_FDC37M81X_CONFIG_ENTER 0x55 +#define SMSC_FDC37M81X_CONFIG_EXIT 0xaa +#define SMSC_FDC37M81X_CHIP_ID 0x4d + +static unsigned long g_smsc_fdc37m81x_base = 0; + +static inline unsigned char smsc_fdc37m81x_rd(unsigned char index) +{ + outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); + + return inb(g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA); +} + +static inline void smsc_dc37m81x_wr(unsigned char index, unsigned char data) +{ + outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); + outb(data, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA); +} + +void smsc_fdc37m81x_config_beg(void) +{ + if (g_smsc_fdc37m81x_base) { + outb(SMSC_FDC37M81X_CONFIG_ENTER, + g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); + } +} + +void smsc_fdc37m81x_config_end(void) +{ + if (g_smsc_fdc37m81x_base) + outb(SMSC_FDC37M81X_CONFIG_EXIT, + g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); +} + +u8 smsc_fdc37m81x_config_get(u8 reg) +{ + u8 val = 0; + + if (g_smsc_fdc37m81x_base) + val = smsc_fdc37m81x_rd(reg); + + return val; +} + +void smsc_fdc37m81x_config_set(u8 reg, u8 val) +{ + if (g_smsc_fdc37m81x_base) + smsc_dc37m81x_wr(reg, val); +} + +unsigned long __init smsc_fdc37m81x_init(unsigned long port) +{ + const int field = sizeof(unsigned long) * 2; + u8 chip_id; + + if (g_smsc_fdc37m81x_base) + printk("smsc_fdc37m81x_init() stepping on old base=0x%0*lx\n", + field, g_smsc_fdc37m81x_base); + + g_smsc_fdc37m81x_base = port; + + smsc_fdc37m81x_config_beg(); + + chip_id = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DID); + if (chip_id == SMSC_FDC37M81X_CHIP_ID) + smsc_fdc37m81x_config_end(); + else { + printk("smsc_fdc37m81x_init() unknow chip id 0x%02x\n", + chip_id); + g_smsc_fdc37m81x_base = 0; + } + + return g_smsc_fdc37m81x_base; +} + +#ifdef DEBUG +void smsc_fdc37m81x_config_dump_one(char *key, u8 dev, u8 reg) +{ + printk("%s: dev=0x%02x reg=0x%02x val=0x%02x\n", key, dev, reg, + smsc_fdc37m81x_rd(reg)); +} + +void smsc_fdc37m81x_config_dump(void) +{ + u8 orig; + char *fname = "smsc_fdc37m81x_config_dump()"; + + smsc_fdc37m81x_config_beg(); + + orig = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DNUM); + + printk("%s: common\n", fname); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_DNUM); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_DID); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_DREV); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_PCNT); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, + SMSC_FDC37M81X_PMGT); + + printk("%s: keyboard\n", fname); + smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, SMSC_FDC37M81X_KBD); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, + SMSC_FDC37M81X_ACTIVE); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, + SMSC_FDC37M81X_INT); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, + SMSC_FDC37M81X_INT2); + smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, + SMSC_FDC37M81X_LDCR_F0); + + smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, orig); + + smsc_fdc37m81x_config_end(); +} +#endif diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c index 4658b2ae483..941c441729b 100644 --- a/arch/mips/tx4927/common/tx4927_setup.c +++ b/arch/mips/tx4927/common/tx4927_setup.c @@ -112,8 +112,6 @@ void print_cp0(char *key, int num, char *name, u32 val) return; } -indent: Standard input:25: Error:Unexpected end of file - void dump_cp0(char *key) { diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c index b926e6a75c2..08b20cdfd7b 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c @@ -36,14 +36,18 @@ void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on) static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait); -static void txx9_spi_interrupt(int irq, void *dev_id) +static irqreturn_t txx9_spi_interrupt(int irq, void *dev_id) { /* disable rx intr */ tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE; wake_up(&txx9_spi_wait); + + return IRQ_HANDLED; } + static struct irqaction txx9_spi_action = { - txx9_spi_interrupt, 0, 0, "spi", NULL, NULL, + .handler = txx9_spi_interrupt, + .name = "spi", }; void __init txx9_spi_irqinit(int irc_irq) |