📄 update-2.4.22-mipsorg-0.030928.1.patch
字号:
diff -Naur --exclude='*.orig' --exclude=CVS --exclude=.cvsignore --exclude='.#*' --exclude=README.Debian linux-2.4.22.clean/arch/mips/au1000/common/pci_ops.c linux-2.4.22/arch/mips/au1000/common/pci_ops.c--- linux-2.4.22.clean/arch/mips/au1000/common/pci_ops.c 2003-08-25 13:44:39.000000000 +0200+++ linux-2.4.22/arch/mips/au1000/common/pci_ops.c 2003-09-27 14:07:03.000000000 +0200@@ -6,7 +6,8 @@ * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com *- * Support for all devices (greater than 16) added by David Gathright.+ * - Support for all devices (greater than 16) added by David Gathright.+ * - Wired tlb fix for ioremap calls in interrupt routines by Embedded Edge. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the@@ -36,6 +37,7 @@ #include <linux/pci.h> #include <linux/kernel.h> #include <linux/init.h>+#include <linux/vmalloc.h> #include <asm/au1000.h> #ifdef CONFIG_MIPS_PB1000@@ -53,6 +55,8 @@ #define DBG(x...) #endif +int (*board_pci_idsel)(unsigned int devsel, int assert);+ /* TBD */ static struct resource pci_io_resource = { "pci IO space", @@ -120,6 +124,41 @@ #else ++/* CP0 hazard avoidance. */+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \+ "nop; nop; nop; nop;\t" \+ ".set reorder\n\t")++void mod_wired_entry(int entry, unsigned long entrylo0, + unsigned long entrylo1, unsigned long entryhi, + unsigned long pagemask)+{+ unsigned long old_pagemask;+ unsigned long old_ctx;++ /* Save old context and create impossible VPN2 value */+ old_ctx = read_c0_entryhi() & 0xff;+ old_pagemask = read_c0_pagemask();+ write_c0_index(entry);+ BARRIER;+ write_c0_pagemask(pagemask);+ write_c0_entryhi(entryhi);+ write_c0_entrylo0(entrylo0);+ write_c0_entrylo1(entrylo1);+ BARRIER;+ tlb_write_indexed();+ BARRIER;+ write_c0_entryhi(old_ctx);+ BARRIER;+ write_c0_pagemask(old_pagemask);+}++struct vm_struct *pci_cfg_vm;+static int pci_cfg_wired_entry;+static int first_cfg = 1;+unsigned long last_entryLo0, last_entryLo1;+ static int config_access(unsigned char access_type, struct pci_dev *dev, unsigned char where, u32 * data) {@@ -128,68 +167,107 @@ unsigned int dev_fn = dev->devfn; unsigned int device = PCI_SLOT(dev_fn); unsigned int function = PCI_FUNC(dev_fn);- unsigned long config, status;- unsigned long cfg_addr;+ unsigned long offset, status;+ unsigned long cfg_base;+ unsigned long flags;+ int error = PCIBIOS_SUCCESSFUL;+ unsigned long entryLo0, entryLo1; if (device > 19) { *data = 0xffffffff; return -1; } + local_irq_save(flags); au_writel(((0x2000 << 16) | (au_readl(Au1500_PCI_STATCMD) & 0xffff)), Au1500_PCI_STATCMD);- //au_writel(au_readl(Au1500_PCI_CFG) & ~PCI_ERROR, Au1500_PCI_CFG); au_sync_udelay(1); + /*+ * We can't ioremap the entire pci config space because it's + * too large. Nor can we call ioremap dynamically because some + * device drivers use the pci config routines from within + * interrupt handlers and that becomes a problem in get_vm_area().+ * We use one wired tlb to handle all config accesses for all + * busses. To improve performance, if the current device+ * is the same as the last device accessed, we don't touch the+ * tlb.+ */+ if (first_cfg) {+ /* reserve a wired entry for pci config accesses */+ first_cfg = 0;+ pci_cfg_vm = get_vm_area(0x1000, 0);+ if (!pci_cfg_vm) + panic (KERN_ERR "PCI unable to get vm area\n");+ pci_cfg_wired_entry = read_c0_wired();+ add_wired_entry(0, 0, (unsigned long)pci_cfg_vm->addr, + PM_4K);+ last_entryLo0 = last_entryLo1 = 0xffffffff;+ }++ /* Since the Au1xxx doesn't do the idsel timing exactly to spec,+ * many board vendors implement their own off-chip idsel, so call+ * it now. If it doesn't succeed, may as well bail out at this point.+ */+ if (board_pci_idsel) {+ if (board_pci_idsel(device, 1) == 0) {+ *data = 0xffffffff;+ local_irq_restore(flags);+ return -1;+ }+ }+ /* setup the config window */ if (bus == 0) {- cfg_addr = ioremap( Au1500_EXT_CFG | ((1<<device)<<11) , - 0x00100000);+ cfg_base = ((1<<device)<<11); } else {- cfg_addr = ioremap( Au1500_EXT_CFG_TYPE1 | (bus<<16) | - (device<<11), 0x00100000);+ cfg_base = 0x80000000 | (bus<<16) | (device<<11); }-- if (!cfg_addr)- panic (KERN_ERR "PCI unable to ioremap cfg space\n");+ cfg_base &= ~0xfff; /* setup the lower bits of the 36 bit address */- config = cfg_addr | (function << 8) | (where & ~0x3);+ offset = (function << 8) | (where & ~0x3); -#if 0- printk("cfg access: config %x, dev_fn %x, device %x function %x\n",- config, dev_fn, device, function);-#endif+ entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7;+ entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7;++ if ((entryLo0 != last_entryLo0) || (entryLo1 != last_entryLo1)) {+ mod_wired_entry(pci_cfg_wired_entry, entryLo0, entryLo1, + (unsigned long)pci_cfg_vm->addr, PM_4K);+ last_entryLo0 = entryLo0;+ last_entryLo1 = entryLo1;+ } if (access_type == PCI_ACCESS_WRITE) {- au_writel(*data, config);+ au_writel(*data, (int)(pci_cfg_vm->addr + offset)); } else {- *data = au_readl(config);+ *data = au_readl((int)(pci_cfg_vm->addr + offset)); } au_sync_udelay(2); - DBG("config_access: %d bus %d device %d at %x *data %x, conf %x\n", - access_type, bus, device, where, *data, config);-- /* unmap io space */- iounmap( cfg_addr );+ access_type, bus, device, where, *data, offset); /* check master abort */ status = au_readl(Au1500_PCI_STATCMD);-#if 0-printk("cfg access: status %x, data %x\n", status, *data );-#endif+ if (status & (1<<29)) { *data = 0xffffffff;- return -1;+ error = -1; } else if ((status >> 28) & 0xf) { DBG("PCI ERR detected: status %x\n", status); *data = 0xffffffff;- return -1;- } else {- return PCIBIOS_SUCCESSFUL;+ error = -1;+ } + + /* Take away the idsel.+ */+ if (board_pci_idsel) {+ (void)board_pci_idsel(device, 0); }++ local_irq_restore(flags);+ return error; #endif } #endifdiff -Naur --exclude='*.orig' --exclude=CVS --exclude=.cvsignore --exclude='.#*' --exclude=README.Debian linux-2.4.22.clean/arch/mips/au1000/common/power.c linux-2.4.22/arch/mips/au1000/common/power.c--- linux-2.4.22.clean/arch/mips/au1000/common/power.c 2003-08-25 13:44:39.000000000 +0200+++ linux-2.4.22/arch/mips/au1000/common/power.c 2003-09-27 14:07:03.000000000 +0200@@ -34,7 +34,6 @@ #include <linux/pm.h> #include <linux/slab.h> #include <linux/sysctl.h>-#include <linux/acpi.h> #include <asm/string.h> #include <asm/uaccess.h>@@ -52,10 +51,10 @@ extern void au1k_wait(void); static void calibrate_delay(void); -extern void set_au1000_speed(unsigned int new_freq);-extern unsigned int get_au1000_speed(void);-extern unsigned long get_au1000_uart_baud_base(void);-extern void set_au1000_uart_baud_base(unsigned long new_baud_base);+extern void set_au1x00_speed(unsigned int new_freq);+extern unsigned int get_au1x00_speed(void);+extern unsigned long get_au1x00_uart_baud_base(void);+extern void set_au1x00_uart_baud_base(unsigned long new_baud_base); extern unsigned long save_local_and_disable(int controller); extern void restore_local_and_enable(int controller, unsigned long mask); extern void local_enable_irq(unsigned int irq_nr);@@ -188,13 +187,13 @@ return -EFAULT; } - old_baud_base = get_au1000_uart_baud_base();- old_cpu_freq = get_au1000_speed();+ old_baud_base = get_au1x00_uart_baud_base();+ old_cpu_freq = get_au1x00_speed(); new_cpu_freq = pll * 12 * 1000000; new_baud_base = (new_cpu_freq / 4) / 16;- set_au1000_speed(new_cpu_freq);- set_au1000_uart_baud_base(new_baud_base);+ set_au1x00_speed(new_cpu_freq);+ set_au1x00_uart_baud_base(new_baud_base); old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff; new_refresh =diff -Naur --exclude='*.orig' --exclude=CVS --exclude=.cvsignore --exclude='.#*' --exclude=README.Debian linux-2.4.22.clean/arch/mips/au1000/common/setup.c linux-2.4.22/arch/mips/au1000/common/setup.c--- linux-2.4.22.clean/arch/mips/au1000/common/setup.c 2003-08-25 13:44:39.000000000 +0200+++ linux-2.4.22/arch/mips/au1000/common/setup.c 2003-09-27 14:07:03.000000000 +0200@@ -44,6 +44,7 @@ #include <asm/reboot.h> #include <asm/pgtable.h> #include <asm/au1000.h>+#include <asm/time.h> #if defined(CONFIG_AU1X00_SERIAL_CONSOLE) extern void console_setup(char *, int *);@@ -72,6 +73,8 @@ extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size); static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size); #endif+extern void au1xxx_time_init(void);+extern void au1xxx_timer_setup(void); void __init au1x00_setup(void) {@@ -126,6 +129,9 @@ fixup_bigphys_addr = au1500_fixup_bigphys_addr; #endif + board_time_init = au1xxx_time_init;+ board_timer_setup = au1xxx_timer_setup;+ // IO/MEM resources. set_io_port_base(0); ioport_resource.start = IOPORT_RESOURCE_START;diff -Naur --exclude='*.orig' --exclude=CVS --exclude=.cvsignore --exclude='.#*' --exclude=README.Debian linux-2.4.22.clean/arch/mips/au1000/common/time.c linux-2.4.22/arch/mips/au1000/common/time.c--- linux-2.4.22.clean/arch/mips/au1000/common/time.c 2003-08-25 13:44:39.000000000 +0200+++ linux-2.4.22/arch/mips/au1000/common/time.c 2003-09-27 14:07:03.000000000 +0200@@ -25,6 +25,11 @@ * * Setting up the clock on the MIPS boards. *+ * Update. Always configure the kernel with CONFIG_NEW_TIME_C. This+ * will use the user interface gettimeofday() functions from the+ * arch/mips/kernel/time.c, and we provide the clock interrupt processing+ * and the timer offset compute functions. If CONFIG_PM is selected,+ * we also ensure the 32KHz timer is available. -- Dan */ #include <linux/types.h>@@ -44,6 +49,10 @@ #include <linux/mc146818rtc.h> #include <linux/timex.h> +#if !defined(CONFIG_NEW_TIME_C)+#error "Alchemy processors need CONFIG_NEW_TIME_C defined"+#endif+ extern void startup_match20_interrupt(void); extern void do_softirq(void); extern volatile unsigned long wall_jiffies;@@ -52,7 +61,8 @@ static unsigned long r4k_offset; /* Amount to increment compare reg each time */ static unsigned long r4k_cur; /* What counter should be at next timer irq */ extern rwlock_t xtime_lock;-unsigned int mips_counter_frequency = 0;+int no_au1xxx_32khz;+void (*au1k_wait_ptr)(void); /* Cycle counter value at the previous timer interrupt.. */ static unsigned int timerhi = 0, timerlo = 0;@@ -160,6 +170,57 @@ do_timer(regs); /* increment jiffies by one */ } }++/* When we wakeup from sleep, we have to "catch up" on all of the+ * timer ticks we have missed.+ */+void+wakeup_counter0_adjust(void)+{+ unsigned long pc0;+ int time_elapsed;++ pc0 = au_readl(SYS_TOYREAD);+ if (pc0 < last_match20) {+ /* counter overflowed */+ time_elapsed = (0xffffffff - last_match20) + pc0;+ }+ else {+ time_elapsed = pc0 - last_match20;+ }++ while (time_elapsed > 0) {+ time_elapsed -= MATCH20_INC;+ last_match20 += MATCH20_INC;+ }++ last_pc0 = pc0;+ au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);+ au_sync();++}++/* This is just for debugging to set the timer for a sleep delay.+*/+void+wakeup_counter0_set(int ticks)+{+ unsigned long pc0;++ pc0 = au_readl(SYS_TOYREAD);+ last_pc0 = pc0;+ au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2);+ au_sync();+}+#endif++/* I haven't found anyone that doesn't use a 12 MHz source clock,+ * but just in case.....+ */+#ifdef CONFIG_AU1000_SRC_CLK+#define AU1000_SRC_CLK CONFIG_AU1000_SRC_CLK+#else+#define AU1000_SRC_CLK 12 #endif /*@@ -171,104 +232,72 @@ { unsigned long count; unsigned long cpu_speed;- unsigned long start, end;- unsigned long counter;- int trim_divide = 16; unsigned long flags; spin_lock_irqsave(&time_lock, flags);-+#ifdef CONFIG_AU1000_USE32K counter = au_readl(SYS_COUNTER_CNTRL);- au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL);-- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);- au_writel(trim_divide-1, SYS_RTCTRIM); /* RTC now ticks at 32.768/16 kHz */- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);-- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);- au_writel (0, SYS_TOYWRITE);- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);-- start = au_readl(SYS_RTCREAD);- start += 2;- /* wait for the beginning of a new tick */- while (au_readl(SYS_RTCREAD) < start);-- /* Start r4k counter. */- write_c0_count(0);- end = start + (32768 / trim_divide)/2; /* wait 0.5 seconds */-- while (end > au_readl(SYS_RTCREAD));-- count = read_c0_count();- cpu_speed = count * 2;- mips_counter_frequency = count;- set_au1x00_uart_baud_base(((cpu_speed) / 4) / 16);- spin_unlock_irqrestore(&time_lock, flags);- return (cpu_speed / HZ);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -