diff --git a/[refs] b/[refs] index 60f2f27362f1..b30b15b66cb9 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 2a4a7e02e27b4f542473772d588f81759c209fb3 +refs/heads/master: 05ab3014636ff60a319d37cdf37dca594b015eec diff --git a/trunk/arch/arm/mach-s3c2410/clock.c b/trunk/arch/arm/mach-s3c2410/clock.c index 8d986b8401c2..e23f534d4e1d 100644 --- a/trunk/arch/arm/mach-s3c2410/clock.c +++ b/trunk/arch/arm/mach-s3c2410/clock.c @@ -478,7 +478,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev) { unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); - s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate); + s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate) * 2; printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n", print_mhz(s3c2440_clk_upll.rate)); diff --git a/trunk/arch/arm/mach-s3c2410/s3c2440.c b/trunk/arch/arm/mach-s3c2410/s3c2440.c index d4c8281b55f6..9a8cc5ae2255 100644 --- a/trunk/arch/arm/mach-s3c2410/s3c2440.c +++ b/trunk/arch/arm/mach-s3c2410/s3c2440.c @@ -192,11 +192,9 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size) iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc)); iotable_init(mach_desc, size); - /* rename any peripherals used differing from the s3c2410 */ - s3c_device_i2c.name = "s3c2440-i2c"; - s3c_device_nand.name = "s3c2440-nand"; + s3c_device_i2c.name = "s3c2440-i2c"; /* change irq for watchdog */ @@ -227,7 +225,7 @@ void __init s3c2440_init_clocks(int xtal) break; case S3C2440_CLKDIVN_HDIVN_2: - hdiv = 2; + hdiv = 1; break; case S3C2440_CLKDIVN_HDIVN_4_8: diff --git a/trunk/arch/arm/mm/Kconfig b/trunk/arch/arm/mm/Kconfig index 48bac7da8c70..c4fc6be629de 100644 --- a/trunk/arch/arm/mm/Kconfig +++ b/trunk/arch/arm/mm/Kconfig @@ -412,20 +412,21 @@ config CPU_BPREDICT_DISABLE config TLS_REG_EMUL bool - default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3) + default y if (SMP || CPU_32v6) && (CPU_32v5 || CPU_32v4 || CPU_32v3) help - An SMP system using a pre-ARMv6 processor (there are apparently - a few prototypes like that in existence) and therefore access to - that required register must be emulated. + We might be running on an ARMv6+ processor which should have the TLS + register but for some reason we can't use it, or maybe an SMP system + using a pre-ARMv6 processor (there are apparently a few prototypes + like that in existence) and therefore access to that register must + be emulated. config HAS_TLS_REG bool - depends on !TLS_REG_EMUL - default y if SMP || CPU_32v7 + depends on CPU_32v6 + default y if !TLS_REG_EMUL help This selects support for the CP15 thread register. - It is defined to be available on some ARMv6 processors (including - all SMP capable ARMv6's) or later processors. User space may - assume directly accessing that register and always obtain the - expected value only on ARMv7 and above. + It is defined to be available on ARMv6 or later. If a particular + ARMv6 or later CPU doesn't support it then it must omc;ide "select + TLS_REG_EMUL" along with its other caracteristics. diff --git a/trunk/arch/arm/mm/copypage-v4mc.S b/trunk/arch/arm/mm/copypage-v4mc.S new file mode 100644 index 000000000000..305af3dab3d8 --- /dev/null +++ b/trunk/arch/arm/mm/copypage-v4mc.S @@ -0,0 +1,80 @@ +/* + * linux/arch/arm/lib/copy_page-armv4mc.S + * + * Copyright (C) 1995-2001 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ASM optimised string functions + */ +#include +#include +#include + + .text + .align 5 +/* + * ARMv4 mini-dcache optimised copy_user_page + * + * We flush the destination cache lines just before we write the data into the + * corresponding address. Since the Dcache is read-allocate, this removes the + * Dcache aliasing issue. The writes will be forwarded to the write buffer, + * and merged as appropriate. + * + * Note: We rely on all ARMv4 processors implementing the "invalidate D line" + * instruction. If your processor does not supply this, you have to write your + * own copy_user_page that does the right thing. + */ +ENTRY(v4_mc_copy_user_page) + stmfd sp!, {r4, lr} @ 2 + mov r4, r0 + mov r0, r1 + bl map_page_minicache + mov r1, #PAGE_SZ/64 @ 1 + ldmia r0!, {r2, r3, ip, lr} @ 4 +1: mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line + stmia r4!, {r2, r3, ip, lr} @ 4 + ldmia r0!, {r2, r3, ip, lr} @ 4+1 + stmia r4!, {r2, r3, ip, lr} @ 4 + ldmia r0!, {r2, r3, ip, lr} @ 4 + mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line + stmia r4!, {r2, r3, ip, lr} @ 4 + ldmia r0!, {r2, r3, ip, lr} @ 4 + subs r1, r1, #1 @ 1 + stmia r4!, {r2, r3, ip, lr} @ 4 + ldmneia r0!, {r2, r3, ip, lr} @ 4 + bne 1b @ 1 + ldmfd sp!, {r4, pc} @ 3 + + .align 5 +/* + * ARMv4 optimised clear_user_page + * + * Same story as above. + */ +ENTRY(v4_mc_clear_user_page) + str lr, [sp, #-4]! + mov r1, #PAGE_SZ/64 @ 1 + mov r2, #0 @ 1 + mov r3, #0 @ 1 + mov ip, #0 @ 1 + mov lr, #0 @ 1 +1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line + stmia r0!, {r2, r3, ip, lr} @ 4 + stmia r0!, {r2, r3, ip, lr} @ 4 + mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line + stmia r0!, {r2, r3, ip, lr} @ 4 + stmia r0!, {r2, r3, ip, lr} @ 4 + subs r1, r1, #1 @ 1 + bne 1b @ 1 + ldr pc, [sp], #4 + + __INITDATA + + .type v4_mc_user_fns, #object +ENTRY(v4_mc_user_fns) + .long v4_mc_clear_user_page + .long v4_mc_copy_user_page + .size v4_mc_user_fns, . - v4_mc_user_fns diff --git a/trunk/arch/arm/mm/copypage-v4mc.c b/trunk/arch/arm/mm/copypage-v4mc.c deleted file mode 100644 index 16384a7600a1..000000000000 --- a/trunk/arch/arm/mm/copypage-v4mc.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * linux/arch/arm/lib/copypage-armv4mc.S - * - * Copyright (C) 1995-2005 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This handles the mini data cache, as found on SA11x0 and XScale - * processors. When we copy a user page page, we map it in such a way - * that accesses to this page will not touch the main data cache, but - * will be cached in the mini data cache. This prevents us thrashing - * the main data cache on page faults. - */ -#include -#include - -#include -#include -#include - -/* - * 0xffff8000 to 0xffffffff is reserved for any ARM architecture - * specific hacks for copying pages efficiently. - */ -#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \ - L_PTE_CACHEABLE) - -#define TOP_PTE(x) pte_offset_kernel(top_pmd, x) - -static DEFINE_SPINLOCK(minicache_lock); - -/* - * ARMv4 mini-dcache optimised copy_user_page - * - * We flush the destination cache lines just before we write the data into the - * corresponding address. Since the Dcache is read-allocate, this removes the - * Dcache aliasing issue. The writes will be forwarded to the write buffer, - * and merged as appropriate. - * - * Note: We rely on all ARMv4 processors implementing the "invalidate D line" - * instruction. If your processor does not supply this, you have to write your - * own copy_user_page that does the right thing. - */ -static void __attribute__((naked)) -mc_copy_user_page(void *from, void *to) -{ - asm volatile( - "stmfd sp!, {r4, lr} @ 2\n\ - mov r4, %2 @ 1\n\ - ldmia %0!, {r2, r3, ip, lr} @ 4\n\ -1: mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\ - stmia %1!, {r2, r3, ip, lr} @ 4\n\ - ldmia %0!, {r2, r3, ip, lr} @ 4+1\n\ - stmia %1!, {r2, r3, ip, lr} @ 4\n\ - ldmia %0!, {r2, r3, ip, lr} @ 4\n\ - mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\ - stmia %1!, {r2, r3, ip, lr} @ 4\n\ - ldmia %0!, {r2, r3, ip, lr} @ 4\n\ - subs r4, r4, #1 @ 1\n\ - stmia %1!, {r2, r3, ip, lr} @ 4\n\ - ldmneia %0!, {r2, r3, ip, lr} @ 4\n\ - bne 1b @ 1\n\ - ldmfd sp!, {r4, pc} @ 3" - : - : "r" (from), "r" (to), "I" (PAGE_SIZE / 64)); -} - -void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) -{ - spin_lock(&minicache_lock); - - set_pte(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot)); - flush_tlb_kernel_page(COPYPAGE_MINICACHE); - - mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto); - - spin_unlock(&minicache_lock); -} - -/* - * ARMv4 optimised clear_user_page - */ -void __attribute__((naked)) -v4_mc_clear_user_page(void *kaddr, unsigned long vaddr) -{ - asm volatile( - "str lr, [sp, #-4]!\n\ - mov r1, %0 @ 1\n\ - mov r2, #0 @ 1\n\ - mov r3, #0 @ 1\n\ - mov ip, #0 @ 1\n\ - mov lr, #0 @ 1\n\ -1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - subs r1, r1, #1 @ 1\n\ - bne 1b @ 1\n\ - ldr pc, [sp], #4" - : - : "I" (PAGE_SIZE / 64)); -} - -struct cpu_user_fns v4_mc_user_fns __initdata = { - .cpu_clear_user_page = v4_mc_clear_user_page, - .cpu_copy_user_page = v4_mc_copy_user_page, -}; diff --git a/trunk/arch/arm/mm/copypage-v6.c b/trunk/arch/arm/mm/copypage-v6.c index a8c00236bd3d..694ac8208858 100644 --- a/trunk/arch/arm/mm/copypage-v6.c +++ b/trunk/arch/arm/mm/copypage-v6.c @@ -26,8 +26,8 @@ #define to_address (0xffffc000) #define to_pgprot PAGE_KERNEL -#define TOP_PTE(x) pte_offset_kernel(top_pmd, x) - +static pte_t *from_pte; +static pte_t *to_pte; static DEFINE_SPINLOCK(v6_lock); #define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT) @@ -74,8 +74,8 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd */ spin_lock(&v6_lock); - set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot)); - set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot)); + set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot)); + set_pte(to_pte + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot)); from = from_address + (offset << PAGE_SHIFT); to = to_address + (offset << PAGE_SHIFT); @@ -114,7 +114,7 @@ void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr) */ spin_lock(&v6_lock); - set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot)); + set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot)); flush_tlb_kernel_page(to); clear_page((void *)to); @@ -129,6 +129,21 @@ struct cpu_user_fns v6_user_fns __initdata = { static int __init v6_userpage_init(void) { if (cache_is_vipt_aliasing()) { + pgd_t *pgd; + pmd_t *pmd; + + pgd = pgd_offset_k(from_address); + pmd = pmd_alloc(&init_mm, pgd, from_address); + if (!pmd) + BUG(); + from_pte = pte_alloc_kernel(&init_mm, pmd, from_address); + if (!from_pte) + BUG(); + + to_pte = pte_alloc_kernel(&init_mm, pmd, to_address); + if (!to_pte) + BUG(); + cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing; cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing; } @@ -136,4 +151,5 @@ static int __init v6_userpage_init(void) return 0; } -core_initcall(v6_userpage_init); +__initcall(v6_userpage_init); + diff --git a/trunk/arch/arm/mm/flush.c b/trunk/arch/arm/mm/flush.c index 4085ed983e46..c6de48d89503 100644 --- a/trunk/arch/arm/mm/flush.c +++ b/trunk/arch/arm/mm/flush.c @@ -13,29 +13,6 @@ #include #include -#include - -#ifdef CONFIG_CPU_CACHE_VIPT -#define ALIAS_FLUSH_START 0xffff4000 - -#define TOP_PTE(x) pte_offset_kernel(top_pmd, x) - -static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) -{ - unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT); - - set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL)); - flush_tlb_kernel_page(to); - - asm( "mcrr p15, 0, %1, %0, c14\n" - " mcrr p15, 0, %1, %0, c5\n" - : - : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES) - : "cc"); -} -#else -#define flush_pfn_alias(pfn,vaddr) do { } while (0) -#endif static void __flush_dcache_page(struct address_space *mapping, struct page *page) { @@ -59,18 +36,6 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page if (!mapping) return; - /* - * This is a page cache page. If we have a VIPT cache, we - * only need to do one flush - which would be at the relevant - * userspace colour, which is congruent with page->index. - */ - if (cache_is_vipt()) { - if (cache_is_vipt_aliasing()) - flush_pfn_alias(page_to_pfn(page), - page->index << PAGE_CACHE_SHIFT); - return; - } - /* * There are possible user space mappings of this page: * - VIVT cache: we need to also write back and invalidate all user @@ -92,6 +57,8 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page continue; offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; flush_cache_page(mpnt, mpnt->vm_start + offset, page_to_pfn(page)); + if (cache_is_vipt()) + break; } flush_dcache_mmap_unlock(mapping); } diff --git a/trunk/arch/arm/mm/mm-armv.c b/trunk/arch/arm/mm/mm-armv.c index fa60fd65fcf8..585dfb8e20b9 100644 --- a/trunk/arch/arm/mm/mm-armv.c +++ b/trunk/arch/arm/mm/mm-armv.c @@ -37,8 +37,6 @@ pgprot_t pgprot_kernel; EXPORT_SYMBOL(pgprot_kernel); -pmd_t *top_pmd; - struct cachepolicy { const char policy[16]; unsigned int cr_mask; @@ -144,16 +142,6 @@ __setup("noalign", noalign_setup); #define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD) -static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt) -{ - return pmd_offset(pgd, virt); -} - -static inline pmd_t *pmd_off_k(unsigned long virt) -{ - return pmd_off(pgd_offset_k(virt), virt); -} - /* * need to get a 16k page for level 1 */ @@ -232,7 +220,7 @@ void free_pgd_slow(pgd_t *pgd) return; /* pgd is always present and good */ - pmd = pmd_off(pgd, 0); + pmd = (pmd_t *)pgd; if (pmd_none(*pmd)) goto free; if (pmd_bad(*pmd)) { @@ -258,8 +246,9 @@ void free_pgd_slow(pgd_t *pgd) static inline void alloc_init_section(unsigned long virt, unsigned long phys, int prot) { - pmd_t *pmdp = pmd_off_k(virt); + pmd_t *pmdp; + pmdp = pmd_offset(pgd_offset_k(virt), virt); if (virt & (1 << 20)) pmdp++; @@ -294,9 +283,11 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot) static inline void alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot) { - pmd_t *pmdp = pmd_off_k(virt); + pmd_t *pmdp; pte_t *ptep; + pmdp = pmd_offset(pgd_offset_k(virt), virt); + if (pmd_none(*pmdp)) { unsigned long pmdval; ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * @@ -319,7 +310,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg */ static inline void clear_mapping(unsigned long virt) { - pmd_clear(pmd_off_k(virt)); + pmd_clear(pmd_offset(pgd_offset_k(virt), virt)); } struct mem_types { @@ -587,7 +578,7 @@ void setup_mm_for_reboot(char mode) PMD_TYPE_SECT; if (cpu_arch <= CPU_ARCH_ARMv5) pmdval |= PMD_BIT4; - pmd = pmd_off(pgd, i << PGDIR_SHIFT); + pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT); pmd[0] = __pmd(pmdval); pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))); flush_pmd_entry(pmd); @@ -684,8 +675,6 @@ void __init memtable_init(struct meminfo *mi) flush_cache_all(); flush_tlb_all(); - - top_pmd = pmd_off_k(VECTORS_HIGH); } /* diff --git a/trunk/drivers/mmc/Kconfig b/trunk/drivers/mmc/Kconfig index 4991bbd054f3..2e70d74fbdee 100644 --- a/trunk/drivers/mmc/Kconfig +++ b/trunk/drivers/mmc/Kconfig @@ -51,7 +51,7 @@ config MMC_PXA config MMC_WBSD tristate "Winbond W83L51xD SD/MMC Card Interface support" - depends on MMC && ISA_DMA_API + depends on MMC && ISA && ISA_DMA_API help This selects the Winbond(R) W83L51xD Secure digital and Multimedia card Interface. diff --git a/trunk/drivers/mmc/wbsd.c b/trunk/drivers/mmc/wbsd.c index b7fbd30b49a0..39747526c719 100644 --- a/trunk/drivers/mmc/wbsd.c +++ b/trunk/drivers/mmc/wbsd.c @@ -28,9 +28,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -42,7 +40,7 @@ #include "wbsd.h" #define DRIVER_NAME "wbsd" -#define DRIVER_VERSION "1.2" +#define DRIVER_VERSION "1.1" #ifdef CONFIG_MMC_DEBUG #define DBG(x...) \ @@ -54,6 +52,10 @@ #define DBGF(x...) do { } while (0) #endif +static unsigned int io = 0x248; +static unsigned int irq = 6; +static int dma = 2; + #ifdef CONFIG_MMC_DEBUG void DBG_REG(int reg, u8 value) { @@ -76,62 +78,29 @@ void DBG_REG(int reg, u8 value) #define DBG_REG(r, v) do {} while (0) #endif -/* - * Device resources - */ - -#ifdef CONFIG_PNP - -static const struct pnp_device_id pnp_dev_table[] = { - { "WEC0517", 0 }, - { "WEC0518", 0 }, - { "", 0 }, -}; - -MODULE_DEVICE_TABLE(pnp, pnp_dev_table); - -#endif /* CONFIG_PNP */ - -#ifdef CONFIG_PNP -static unsigned int nopnp = 0; -#else -static const unsigned int nopnp = 1; -#endif -static unsigned int io = 0x248; -static unsigned int irq = 6; -static int dma = 2; - /* * Basic functions */ static inline void wbsd_unlock_config(struct wbsd_host* host) { - BUG_ON(host->config == 0); - outb(host->unlock_code, host->config); outb(host->unlock_code, host->config); } static inline void wbsd_lock_config(struct wbsd_host* host) { - BUG_ON(host->config == 0); - outb(LOCK_CODE, host->config); } static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value) { - BUG_ON(host->config == 0); - outb(reg, host->config); outb(value, host->config + 1); } static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg) { - BUG_ON(host->config == 0); - outb(reg, host->config); return inb(host->config + 1); } @@ -163,13 +132,6 @@ static void wbsd_init_device(struct wbsd_host* host) setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET; wbsd_write_index(host, WBSD_IDX_SETUP, setup); - /* - * Set DAT3 to input - */ - setup &= ~WBSD_DAT3_H; - wbsd_write_index(host, WBSD_IDX_SETUP, setup); - host->flags &= ~WBSD_FIGNORE_DETECT; - /* * Read back default clock. */ @@ -185,14 +147,6 @@ static void wbsd_init_device(struct wbsd_host* host) */ wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F); - /* - * Test for card presence - */ - if (inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT) - host->flags |= WBSD_FCARD_PRESENT; - else - host->flags &= ~WBSD_FCARD_PRESENT; - /* * Enable interesting interrupts. */ @@ -453,6 +407,8 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host, } } +static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs); + static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) { int i; @@ -690,13 +646,6 @@ static void wbsd_fill_fifo(struct wbsd_host* host) } wbsd_kunmap_sg(host); - - /* - * The controller stops sending interrupts for - * 'FIFO empty' under certain conditions. So we - * need to be a bit more pro-active. - */ - tasklet_schedule(&host->fifo_tasklet); } static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) @@ -901,11 +850,9 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) wbsd_request_end(host, host->mrq); } -/*****************************************************************************\ - * * - * MMC layer callbacks * - * * -\*****************************************************************************/ +/* + * MMC Callbacks + */ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) { @@ -927,7 +874,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) * If there is no card in the slot then * timeout immediatly. */ - if (!(host->flags & WBSD_FCARD_PRESENT)) + if (!(inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT)) { cmd->error = MMC_ERR_TIMEOUT; goto done; @@ -1006,50 +953,33 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) host->clk = clk; } - /* - * Power up card. - */ if (ios->power_mode != MMC_POWER_OFF) { + /* + * Power up card. + */ pwr = inb(host->base + WBSD_CSR); pwr &= ~WBSD_POWER_N; outb(pwr, host->base + WBSD_CSR); - } - /* - * MMC cards need to have pin 1 high during init. - * Init time corresponds rather nicely with the bus mode. - * It wreaks havoc with the card detection though so - * that needs to be disabed. - */ - setup = wbsd_read_index(host, WBSD_IDX_SETUP); - if ((ios->power_mode == MMC_POWER_ON) && - (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)) - { - setup |= WBSD_DAT3_H; - host->flags |= WBSD_FIGNORE_DETECT; - } - else - { - setup &= ~WBSD_DAT3_H; - host->flags &= ~WBSD_FIGNORE_DETECT; + /* + * This behaviour is stolen from the + * Windows driver. Don't know why, but + * it is needed. + */ + setup = wbsd_read_index(host, WBSD_IDX_SETUP); + if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) + setup |= WBSD_DAT3_H; + else + setup &= ~WBSD_DAT3_H; + wbsd_write_index(host, WBSD_IDX_SETUP, setup); + + mdelay(1); } - wbsd_write_index(host, WBSD_IDX_SETUP, setup); - + spin_unlock_bh(&host->lock); } -static struct mmc_host_ops wbsd_ops = { - .request = wbsd_request, - .set_ios = wbsd_set_ios, -}; - -/*****************************************************************************\ - * * - * Interrupt handling * - * * -\*****************************************************************************/ - /* * Tasklets */ @@ -1075,33 +1005,17 @@ static void wbsd_tasklet_card(unsigned long param) { struct wbsd_host* host = (struct wbsd_host*)param; u8 csr; - int change = 0; spin_lock(&host->lock); - if (host->flags & WBSD_FIGNORE_DETECT) - { - spin_unlock(&host->lock); - return; - } - csr = inb(host->base + WBSD_CSR); WARN_ON(csr == 0xff); if (csr & WBSD_CARDPRESENT) - { - if (!(host->flags & WBSD_FCARD_PRESENT)) - { - DBG("Card inserted\n"); - host->flags |= WBSD_FCARD_PRESENT; - change = 1; - } - } - else if (host->flags & WBSD_FCARD_PRESENT) + DBG("Card inserted\n"); + else { DBG("Card removed\n"); - host->flags &= ~WBSD_FCARD_PRESENT; - change = 1; if (host->mrq) { @@ -1119,8 +1033,7 @@ static void wbsd_tasklet_card(unsigned long param) */ spin_unlock(&host->lock); - if (change) - mmc_detect_change(host->mmc); + mmc_detect_change(host->mmc); } static void wbsd_tasklet_fifo(unsigned long param) @@ -1287,85 +1200,11 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -/*****************************************************************************\ - * * - * Device initialisation and shutdown * - * * -\*****************************************************************************/ - /* - * Allocate/free MMC structure. + * Support functions for probe */ -static int __devinit wbsd_alloc_mmc(struct device* dev) -{ - struct mmc_host* mmc; - struct wbsd_host* host; - - /* - * Allocate MMC structure. - */ - mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev); - if (!mmc) - return -ENOMEM; - - host = mmc_priv(mmc); - host->mmc = mmc; - - host->dma = -1; - - /* - * Set host parameters. - */ - mmc->ops = &wbsd_ops; - mmc->f_min = 375000; - mmc->f_max = 24000000; - mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; - - spin_lock_init(&host->lock); - - /* - * Maximum number of segments. Worst case is one sector per segment - * so this will be 64kB/512. - */ - mmc->max_hw_segs = 128; - mmc->max_phys_segs = 128; - - /* - * Maximum number of sectors in one transfer. Also limited by 64kB - * buffer. - */ - mmc->max_sectors = 128; - - /* - * Maximum segment size. Could be one segment with the maximum number - * of segments. - */ - mmc->max_seg_size = mmc->max_sectors * 512; - - dev_set_drvdata(dev, mmc); - - return 0; -} - -static void __devexit wbsd_free_mmc(struct device* dev) -{ - struct mmc_host* mmc; - - mmc = dev_get_drvdata(dev); - if (!mmc) - return; - - mmc_free_host(mmc); - - dev_set_drvdata(dev, NULL); -} - -/* - * Scan for known chip id:s - */ - -static int __devinit wbsd_scan(struct wbsd_host* host) +static int wbsd_scan(struct wbsd_host* host) { int i, j, k; int id; @@ -1419,16 +1258,12 @@ static int __devinit wbsd_scan(struct wbsd_host* host) return -ENODEV; } -/* - * Allocate/free io port ranges - */ - -static int __devinit wbsd_request_region(struct wbsd_host* host, int base) +static int wbsd_request_regions(struct wbsd_host* host) { if (io & 0x7) return -EINVAL; - if (!request_region(base, 8, DRIVER_NAME)) + if (!request_region(io, 8, DRIVER_NAME)) return -EIO; host->base = io; @@ -1436,25 +1271,19 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base) return 0; } -static void __devexit wbsd_release_regions(struct wbsd_host* host) +static void wbsd_release_regions(struct wbsd_host* host) { if (host->base) release_region(host->base, 8); - - host->base = 0; if (host->config) release_region(host->config, 2); - - host->config = 0; } -/* - * Allocate/free DMA port and buffer - */ - -static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) +static void wbsd_init_dma(struct wbsd_host* host) { + host->dma = -1; + if (dma < 0) return; @@ -1465,7 +1294,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) * We need to allocate a special buffer in * order for ISA to be able to DMA to it. */ - host->dma_buffer = kmalloc(WBSD_DMA_SIZE, + host->dma_buffer = kmalloc(65536, GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN); if (!host->dma_buffer) goto free; @@ -1473,8 +1302,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) /* * Translate the address to a physical address. */ - host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer, - WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); + host->dma_addr = isa_virt_to_bus(host->dma_buffer); /* * ISA DMA must be aligned on a 64k basis. @@ -1497,10 +1325,6 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) */ BUG_ON(1); - dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE, - DMA_BIDIRECTIONAL); - host->dma_addr = (dma_addr_t)NULL; - kfree(host->dma_buffer); host->dma_buffer = NULL; @@ -1512,122 +1336,60 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) "Falling back on FIFO.\n", dma); } -static void __devexit wbsd_release_dma(struct wbsd_host* host) -{ - if (host->dma_addr) - dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE, - DMA_BIDIRECTIONAL); - if (host->dma_buffer) - kfree(host->dma_buffer); - if (host->dma >= 0) - free_dma(host->dma); - - host->dma = -1; - host->dma_buffer = NULL; - host->dma_addr = (dma_addr_t)NULL; -} +static struct mmc_host_ops wbsd_ops = { + .request = wbsd_request, + .set_ios = wbsd_set_ios, +}; /* - * Allocate/free IRQ. + * Device probe */ -static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq) +static int wbsd_probe(struct device* dev) { + struct wbsd_host* host = NULL; + struct mmc_host* mmc = NULL; int ret; /* - * Allocate interrupt. - */ - - ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host); - if (ret) - return ret; - - host->irq = irq; - - /* - * Set up tasklets. + * Allocate MMC structure. */ - tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host); - tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned long)host); - tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host); - tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host); - tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host); - tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host); - - return 0; -} - -static void __devexit wbsd_release_irq(struct wbsd_host* host) -{ - if (!host->irq) - return; - - free_irq(host->irq, host); + mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev); + if (!mmc) + return -ENOMEM; - host->irq = 0; - - tasklet_kill(&host->card_tasklet); - tasklet_kill(&host->fifo_tasklet); - tasklet_kill(&host->crc_tasklet); - tasklet_kill(&host->timeout_tasklet); - tasklet_kill(&host->finish_tasklet); - tasklet_kill(&host->block_tasklet); -} - -/* - * Allocate all resources for the host. - */ - -static int __devinit wbsd_request_resources(struct wbsd_host* host, - int base, int irq, int dma) -{ - int ret; + host = mmc_priv(mmc); + host->mmc = mmc; /* - * Allocate I/O ports. + * Scan for hardware. */ - ret = wbsd_request_region(host, base); + ret = wbsd_scan(host); if (ret) - return ret; + goto freemmc; /* - * Allocate interrupt. + * Reset the chip. + */ + wbsd_write_config(host, WBSD_CONF_SWRST, 1); + wbsd_write_config(host, WBSD_CONF_SWRST, 0); + + /* + * Allocate I/O ports. */ - ret = wbsd_request_irq(host, irq); + ret = wbsd_request_regions(host); if (ret) - return ret; + goto release; /* - * Allocate DMA. + * Set host parameters. */ - wbsd_request_dma(host, dma); + mmc->ops = &wbsd_ops; + mmc->f_min = 375000; + mmc->f_max = 24000000; + mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; - return 0; -} - -/* - * Release all resources for the host. - */ - -static void __devexit wbsd_release_resources(struct wbsd_host* host) -{ - wbsd_release_dma(host); - wbsd_release_irq(host); - wbsd_release_regions(host); -} - -/* - * Configure the resources the chip should use. - */ - -static void __devinit wbsd_chip_config(struct wbsd_host* host) -{ - /* - * Reset the chip. - */ - wbsd_write_config(host, WBSD_CONF_SWRST, 1); - wbsd_write_config(host, WBSD_CONF_SWRST, 0); + spin_lock_init(&host->lock); /* * Select SD/MMC function. @@ -1637,241 +1399,165 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host) /* * Set up card detection. */ - wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11); + wbsd_write_config(host, WBSD_CONF_PINS, 0x02); /* - * Configure chip + * Configure I/O port. */ wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8); wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff); + + /* + * Allocate interrupt. + */ + ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host); + if (ret) + goto release; - wbsd_write_config(host, WBSD_CONF_IRQ, host->irq); - - if (host->dma >= 0) - wbsd_write_config(host, WBSD_CONF_DRQ, host->dma); + host->irq = irq; /* - * Enable and power up chip. + * Set up tasklets. */ - wbsd_write_config(host, WBSD_CONF_ENABLE, 1); - wbsd_write_config(host, WBSD_CONF_POWER, 0x20); -} - -/* - * Check that configured resources are correct. - */ - -static int __devinit wbsd_chip_validate(struct wbsd_host* host) -{ - int base, irq, dma; + tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host); + tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned long)host); + tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host); + tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host); + tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host); + tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host); /* - * Select SD/MMC function. + * Configure interrupt. */ - wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); + wbsd_write_config(host, WBSD_CONF_IRQ, host->irq); /* - * Read configuration. + * Allocate DMA. */ - base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8; - base |= wbsd_read_config(host, WBSD_CONF_PORT_LO); - - irq = wbsd_read_config(host, WBSD_CONF_IRQ); - - dma = wbsd_read_config(host, WBSD_CONF_DRQ); + wbsd_init_dma(host); /* - * Validate against given configuration. + * If all went well, then configure DMA. */ - if (base != host->base) - return 0; - if (irq != host->irq) - return 0; - if ((dma != host->dma) && (host->dma != -1)) - return 0; - - return 1; -} - -/*****************************************************************************\ - * * - * Devices setup and shutdown * - * * -\*****************************************************************************/ - -static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, - int pnp) -{ - struct wbsd_host* host = NULL; - struct mmc_host* mmc = NULL; - int ret; + if (host->dma >= 0) + wbsd_write_config(host, WBSD_CONF_DRQ, host->dma); - ret = wbsd_alloc_mmc(dev); - if (ret) - return ret; + /* + * Maximum number of segments. Worst case is one sector per segment + * so this will be 64kB/512. + */ + mmc->max_hw_segs = 128; + mmc->max_phys_segs = 128; - mmc = dev_get_drvdata(dev); - host = mmc_priv(mmc); + /* + * Maximum number of sectors in one transfer. Also limited by 64kB + * buffer. + */ + mmc->max_sectors = 128; /* - * Scan for hardware. + * Maximum segment size. Could be one segment with the maximum number + * of segments. */ - ret = wbsd_scan(host); - if (ret) - { - if (pnp && (ret == -ENODEV)) - { - printk(KERN_WARNING DRIVER_NAME - ": Unable to confirm device presence. You may " - "experience lock-ups.\n"); - } - else - { - wbsd_free_mmc(dev); - return ret; - } - } + mmc->max_seg_size = mmc->max_sectors * 512; /* - * Request resources. + * Enable chip. */ - ret = wbsd_request_resources(host, io, irq, dma); - if (ret) - { - wbsd_release_resources(host); - wbsd_free_mmc(dev); - return ret; - } + wbsd_write_config(host, WBSD_CONF_ENABLE, 1); /* - * See if chip needs to be configured. + * Power up chip. */ - if (pnp && (host->config != 0)) - { - if (!wbsd_chip_validate(host)) - { - printk(KERN_WARNING DRIVER_NAME - ": PnP active but chip not configured! " - "You probably have a buggy BIOS. " - "Configuring chip manually.\n"); - wbsd_chip_config(host); - } - } - else - wbsd_chip_config(host); + wbsd_write_config(host, WBSD_CONF_POWER, 0x20); /* * Power Management stuff. No idea how this works. * Not tested. */ #ifdef CONFIG_PM - if (host->config) - wbsd_write_config(host, WBSD_CONF_PME, 0xA0); + wbsd_write_config(host, WBSD_CONF_PME, 0xA0); #endif - /* - * Allow device to initialise itself properly. - */ - mdelay(5); /* * Reset the chip into a known state. */ wbsd_init_device(host); + dev_set_drvdata(dev, mmc); + + /* + * Add host to MMC layer. + */ mmc_add_host(mmc); - printk(KERN_INFO "%s: W83L51xD", mmc->host_name); - if (host->chip_id != 0) - printk(" id %x", (int)host->chip_id); - printk(" at 0x%x irq %d", (int)host->base, (int)host->irq); - if (host->dma >= 0) - printk(" dma %d", (int)host->dma); - else - printk(" FIFO"); - if (pnp) - printk(" PnP"); - printk("\n"); + printk(KERN_INFO "%s: W83L51xD id %x at 0x%x irq %d dma %d\n", + mmc->host_name, (int)host->chip_id, (int)host->base, + (int)host->irq, (int)host->dma); return 0; + +release: + wbsd_release_regions(host); + +freemmc: + mmc_free_host(mmc); + + return ret; } -static void __devexit wbsd_shutdown(struct device* dev, int pnp) +/* + * Device remove + */ + +static int wbsd_remove(struct device* dev) { struct mmc_host* mmc = dev_get_drvdata(dev); struct wbsd_host* host; if (!mmc) - return; + return 0; host = mmc_priv(mmc); + /* + * Unregister host with MMC layer. + */ mmc_remove_host(mmc); - if (!pnp) - { - /* - * Power down the SD/MMC function. - */ - wbsd_unlock_config(host); - wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); - wbsd_write_config(host, WBSD_CONF_ENABLE, 0); - wbsd_lock_config(host); - } + /* + * Power down the SD/MMC function. + */ + wbsd_unlock_config(host); + wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); + wbsd_write_config(host, WBSD_CONF_ENABLE, 0); + wbsd_lock_config(host); - wbsd_release_resources(host); + /* + * Free resources. + */ + if (host->dma_buffer) + kfree(host->dma_buffer); - wbsd_free_mmc(dev); -} - -/* - * Non-PnP - */ - -static int __devinit wbsd_probe(struct device* dev) -{ - return wbsd_init(dev, io, irq, dma, 0); -} - -static int __devexit wbsd_remove(struct device* dev) -{ - wbsd_shutdown(dev, 0); - - return 0; -} - -/* - * PnP - */ - -#ifdef CONFIG_PNP + if (host->dma >= 0) + free_dma(host->dma); -static int __devinit -wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id) -{ - int io, irq, dma; + free_irq(host->irq, host); - /* - * Get resources from PnP layer. - */ - io = pnp_port_start(pnpdev, 0); - irq = pnp_irq(pnpdev, 0); - if (pnp_dma_valid(pnpdev, 0)) - dma = pnp_dma(pnpdev, 0); - else - dma = -1; + tasklet_kill(&host->card_tasklet); + tasklet_kill(&host->fifo_tasklet); + tasklet_kill(&host->crc_tasklet); + tasklet_kill(&host->timeout_tasklet); + tasklet_kill(&host->finish_tasklet); + tasklet_kill(&host->block_tasklet); - DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma); + wbsd_release_regions(host); - return wbsd_init(&pnpdev->dev, io, irq, dma, 1); -} + mmc_free_host(mmc); -static void __devexit wbsd_pnp_remove(struct pnp_dev * dev) -{ - wbsd_shutdown(&dev->dev, 1); + return 0; } -#endif /* CONFIG_PNP */ - /* * Power management */ @@ -1895,7 +1581,17 @@ static int wbsd_resume(struct device *dev, u32 level) #define wbsd_resume NULL #endif -static struct platform_device *wbsd_device; +static void wbsd_release(struct device *dev) +{ +} + +static struct platform_device wbsd_device = { + .name = DRIVER_NAME, + .id = -1, + .dev = { + .release = wbsd_release, + }, +}; static struct device_driver wbsd_driver = { .name = DRIVER_NAME, @@ -1907,17 +1603,6 @@ static struct device_driver wbsd_driver = { .resume = wbsd_resume, }; -#ifdef CONFIG_PNP - -static struct pnp_driver wbsd_pnp_driver = { - .name = DRIVER_NAME, - .id_table = pnp_dev_table, - .probe = wbsd_pnp_probe, - .remove = wbsd_pnp_remove, -}; - -#endif /* CONFIG_PNP */ - /* * Module loading/unloading */ @@ -1930,57 +1615,29 @@ static int __init wbsd_drv_init(void) ": Winbond W83L51xD SD/MMC card interface driver, " DRIVER_VERSION "\n"); printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); - -#ifdef CONFIG_PNP - - if (!nopnp) - { - result = pnp_register_driver(&wbsd_pnp_driver); - if (result < 0) - return result; - } - -#endif /* CONFIG_PNP */ - if (nopnp) - { - result = driver_register(&wbsd_driver); - if (result < 0) - return result; - - wbsd_device = platform_device_register_simple(DRIVER_NAME, -1, - NULL, 0); - if (IS_ERR(wbsd_device)) - return PTR_ERR(wbsd_device); - } + result = driver_register(&wbsd_driver); + if (result < 0) + return result; + + result = platform_device_register(&wbsd_device); + if (result < 0) + return result; return 0; } static void __exit wbsd_drv_exit(void) { -#ifdef CONFIG_PNP - - if (!nopnp) - pnp_unregister_driver(&wbsd_pnp_driver); + platform_device_unregister(&wbsd_device); -#endif /* CONFIG_PNP */ - - if (nopnp) - { - platform_device_unregister(wbsd_device); - - driver_unregister(&wbsd_driver); - } + driver_unregister(&wbsd_driver); DBG("unloaded\n"); } module_init(wbsd_drv_init); module_exit(wbsd_drv_exit); -#ifdef CONFIG_PNP -module_param(nopnp, uint, 0444); -#endif module_param(io, uint, 0444); module_param(irq, uint, 0444); module_param(dma, int, 0444); @@ -1989,9 +1646,6 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver"); MODULE_VERSION(DRIVER_VERSION); -#ifdef CONFIG_PNP -MODULE_PARM_DESC(nopnp, "Scan for device instead of relying on PNP. (default 0)"); -#endif MODULE_PARM_DESC(io, "I/O base to allocate. Must be 8 byte aligned. (default 0x248)"); MODULE_PARM_DESC(irq, "IRQ to allocate. (default 6)"); MODULE_PARM_DESC(dma, "DMA channel to allocate. -1 for no DMA. (default 2)"); diff --git a/trunk/drivers/mmc/wbsd.h b/trunk/drivers/mmc/wbsd.h index 864f30828d01..fdc03b56a81f 100644 --- a/trunk/drivers/mmc/wbsd.h +++ b/trunk/drivers/mmc/wbsd.h @@ -35,12 +35,6 @@ const int valid_ids[] = { #define DEVICE_SD 0x03 -#define WBSD_PINS_DAT3_HI 0x20 -#define WBSD_PINS_DAT3_OUT 0x10 -#define WBSD_PINS_GP11_HI 0x04 -#define WBSD_PINS_DETECT_GP11 0x02 -#define WBSD_PINS_DETECT_DAT3 0x01 - #define WBSD_CMDR 0x00 #define WBSD_DFR 0x01 #define WBSD_EIR 0x02 @@ -139,7 +133,6 @@ const int valid_ids[] = { #define WBSD_CRC_OK 0x05 /* S010E (00101) */ #define WBSD_CRC_FAIL 0x0B /* S101E (01011) */ -#define WBSD_DMA_SIZE 65536 struct wbsd_host { @@ -147,11 +140,6 @@ struct wbsd_host spinlock_t lock; /* Mutex */ - int flags; /* Driver states */ - -#define WBSD_FCARD_PRESENT (1<<0) /* Card is present */ -#define WBSD_FIGNORE_DETECT (1<<1) /* Ignore card detection */ - struct mmc_request* mrq; /* Current request */ u8 isr; /* Accumulated ISR */ diff --git a/trunk/drivers/serial/21285.c b/trunk/drivers/serial/21285.c index 33fbda79f350..0b10169961eb 100644 --- a/trunk/drivers/serial/21285.c +++ b/trunk/drivers/serial/21285.c @@ -126,18 +126,8 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r flag = TTY_FRAME; } - if ((rxs & port->ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((rxs & RXSTAT_OVERRUN) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag); + status = *CSR_UARTFLG; } tty_flip_buffer_push(tty); diff --git a/trunk/drivers/serial/8250.c b/trunk/drivers/serial/8250.c index 0d9358608fdf..3bbf0cc6e53f 100644 --- a/trunk/drivers/serial/8250.c +++ b/trunk/drivers/serial/8250.c @@ -1122,18 +1122,9 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) } if (uart_handle_sysrq_char(&up->port, ch, regs)) goto ignore_char; - if ((lsr & up->port.ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((lsr & UART_LSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + + uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); + ignore_char: lsr = serial_inp(up, UART_LSR); } while ((lsr & UART_LSR_DR) && (max_count-- > 0)); diff --git a/trunk/drivers/serial/amba-pl010.c b/trunk/drivers/serial/amba-pl010.c index f2a5e2933c47..2884b310e54d 100644 --- a/trunk/drivers/serial/amba-pl010.c +++ b/trunk/drivers/serial/amba-pl010.c @@ -198,18 +198,8 @@ pl010_rx_chars(struct uart_port *port) if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; - if ((rsr & port->ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((rsr & UART01x_RSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); + ignore_char: status = UART_GET_FR(port); } diff --git a/trunk/drivers/serial/amba-pl011.c b/trunk/drivers/serial/amba-pl011.c index d5cbef3fe8b6..7db88ee18f75 100644 --- a/trunk/drivers/serial/amba-pl011.c +++ b/trunk/drivers/serial/amba-pl011.c @@ -163,18 +163,8 @@ pl011_rx_chars(struct uart_amba_port *uap) if (uart_handle_sysrq_char(&uap->port, ch, regs)) goto ignore_char; - if ((rsr & uap->port.ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((rsr & UART01x_RSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag); + ignore_char: status = readw(uap->port.membase + UART01x_FR); } diff --git a/trunk/drivers/serial/clps711x.c b/trunk/drivers/serial/clps711x.c index 6242f3090a96..e92522b33c48 100644 --- a/trunk/drivers/serial/clps711x.c +++ b/trunk/drivers/serial/clps711x.c @@ -143,10 +143,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re * CHECK: does overrun affect the current character? * ASSUMPTION: it does not. */ - if ((ch & port->ignore_status_mask & ~RXSTAT_OVERRUN) == 0) - tty_insert_flip_char(tty, ch, flg); - if ((ch & ~port->ignore_status_mask & RXSTAT_OVERRUN) == 0) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + uart_insert_char(port, ch, UARTDR_OVERR, ch, flg); ignore_char: status = clps_readl(SYSFLG(port)); diff --git a/trunk/drivers/serial/pxa.c b/trunk/drivers/serial/pxa.c index 51d8a49f4477..9dc151d8fa61 100644 --- a/trunk/drivers/serial/pxa.c +++ b/trunk/drivers/serial/pxa.c @@ -161,20 +161,12 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) else if (*status & UART_LSR_FE) flag = TTY_FRAME; } + if (uart_handle_sysrq_char(&up->port, ch, regs)) goto ignore_char; - if ((*status & up->port.ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((*status & UART_LSR_OE) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + + uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag); + ignore_char: *status = serial_in(up, UART_LSR); } while ((*status & UART_LSR_DR) && (max_count-- > 0)); diff --git a/trunk/drivers/serial/s3c2410.c b/trunk/drivers/serial/s3c2410.c index 435750d40a47..2a9f7ade2c9d 100644 --- a/trunk/drivers/serial/s3c2410.c +++ b/trunk/drivers/serial/s3c2410.c @@ -394,20 +394,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs) if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; - if ((uerstat & port->ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - - if ((uerstat & S3C2410_UERSTAT_OVERRUN) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag); ignore_char: continue; diff --git a/trunk/drivers/serial/sa1100.c b/trunk/drivers/serial/sa1100.c index 157218bc6c6f..22565a67a57c 100644 --- a/trunk/drivers/serial/sa1100.c +++ b/trunk/drivers/serial/sa1100.c @@ -237,10 +237,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) if (uart_handle_sysrq_char(&sport->port, ch, regs)) goto ignore_char; - if ((status & port->ignore_status_mask & ~UTSR1_TO_SM(UTSR1_ROR)) == 0) - tty_insert_flip_char(tty, ch, flg); - if (status & ~port->ignore_status_mask & UTSR1_TO_SM(UTSR1_ROR)) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg); ignore_char: status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | diff --git a/trunk/drivers/serial/serial_lh7a40x.c b/trunk/drivers/serial/serial_lh7a40x.c index 85cfa08d3bad..56f269b6bfb1 100644 --- a/trunk/drivers/serial/serial_lh7a40x.c +++ b/trunk/drivers/serial/serial_lh7a40x.c @@ -190,18 +190,7 @@ lh7a40xuart_rx_chars (struct uart_port* port) if (uart_handle_sysrq_char (port, (unsigned char) data, regs)) continue; - if ((data & port->ignore_status_mask) == 0) { - tty_insert_flip_char(tty, data, flag); - } - if ((data & RxOverrunError) - && tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + uart_insert_char(port, data, RxOverrunError, data, flag); } tty_flip_buffer_push (tty); return; diff --git a/trunk/drivers/serial/serial_txx9.c b/trunk/drivers/serial/serial_txx9.c index 37b2ef297cbe..3f1051a4a13f 100644 --- a/trunk/drivers/serial/serial_txx9.c +++ b/trunk/drivers/serial/serial_txx9.c @@ -350,18 +350,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r } if (uart_handle_sysrq_char(&up->port, ch, regs)) goto ignore_char; - if ((disr & up->port.ignore_status_mask) == 0) { - tty_insert_flip_char(tty, ch, flag); - } - if ((disr & TXX9_SIDISR_UOER) && - tty->flip.count < TTY_FLIPBUF_SIZE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - } + + uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag); + ignore_char: disr = sio_in(up, TXX9_SIDISR); } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0)); diff --git a/trunk/drivers/serial/vr41xx_siu.c b/trunk/drivers/serial/vr41xx_siu.c index 307886199f2f..5d2ceb623e6f 100644 --- a/trunk/drivers/serial/vr41xx_siu.c +++ b/trunk/drivers/serial/vr41xx_siu.c @@ -412,10 +412,8 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status, if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; - if ((lsr & port->ignore_status_mask) == 0) - tty_insert_flip_char(tty, ch, flag); - if ((lsr & UART_LSR_OE) && (tty->flip.count < TTY_FLIPBUF_SIZE)) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); ignore_char: lsr = siu_read(port, UART_LSR); diff --git a/trunk/include/asm-arm/arch-imx/imx-regs.h b/trunk/include/asm-arm/arch-imx/imx-regs.h index 93b840e8fa60..f32c203952cf 100644 --- a/trunk/include/asm-arm/arch-imx/imx-regs.h +++ b/trunk/include/asm-arm/arch-imx/imx-regs.h @@ -227,30 +227,6 @@ #define PD31_PF_TMR2OUT ( GPIO_PORTD | GPIO_PF | 31 ) #define PD31_BIN_SPI2_TXD ( GPIO_PORTD | GPIO_BIN | 31 ) -/* - * PWM controller - */ -#define PWMC __REG(IMX_PWM_BASE + 0x00) /* PWM Control Register */ -#define PWMS __REG(IMX_PWM_BASE + 0x04) /* PWM Sample Register */ -#define PWMP __REG(IMX_PWM_BASE + 0x08) /* PWM Period Register */ -#define PWMCNT __REG(IMX_PWM_BASE + 0x0C) /* PWM Counter Register */ - -#define PWMC_HCTR (0x01<<18) /* Halfword FIFO Data Swapping */ -#define PWMC_BCTR (0x01<<17) /* Byte FIFO Data Swapping */ -#define PWMC_SWR (0x01<<16) /* Software Reset */ -#define PWMC_CLKSRC (0x01<<15) /* Clock Source */ -#define PWMC_PRESCALER(x) (((x-1) & 0x7F) << 8) /* PRESCALER */ -#define PWMC_IRQ (0x01<< 7) /* Interrupt Request */ -#define PWMC_IRQEN (0x01<< 6) /* Interrupt Request Enable */ -#define PWMC_FIFOAV (0x01<< 5) /* FIFO Available */ -#define PWMC_EN (0x01<< 4) /* Enables/Disables the PWM */ -#define PWMC_REPEAT(x) (((x) & 0x03) << 2) /* Sample Repeats */ -#define PWMC_CLKSEL(x) (((x) & 0x03) << 0) /* Clock Selection */ - -#define PWMS_SAMPLE(x) ((x) & 0xFFFF) /* Contains a two-sample word */ -#define PWMP_PERIOD(x) ((x) & 0xFFFF) /* Represents the PWM's period */ -#define PWMC_COUNTER(x) ((x) & 0xFFFF) /* Represents the current count value */ - /* * DMA Controller */ diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-nand.h b/trunk/include/asm-arm/arch-s3c2410/regs-nand.h index 7cff235e667a..c443ac834698 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-nand.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-nand.h @@ -1,17 +1,16 @@ /* linux/include/asm-arm/arch-s3c2410/regs-nand.h * - * Copyright (c) 2004,2005 Simtec Electronics + * Copyright (c) 2004 Simtec Electronics * http://www.simtec.co.uk/products/SWLINUX/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * S3C2410 NAND register definitions + * S3C2410 clock register definitions * * Changelog: * 18-Aug-2004 BJD Copied file from 2.4 and updated - * 01-May-2005 BJD Added definitions for s3c2440 controller */ #ifndef __ASM_ARM_REGS_NAND @@ -27,22 +26,6 @@ #define S3C2410_NFSTAT S3C2410_NFREG(0x10) #define S3C2410_NFECC S3C2410_NFREG(0x14) -#define S3C2440_NFCONT S3C2410_NFREG(0x04) -#define S3C2440_NFCMD S3C2410_NFREG(0x08) -#define S3C2440_NFADDR S3C2410_NFREG(0x0C) -#define S3C2440_NFDATA S3C2410_NFREG(0x10) -#define S3C2440_NFECCD0 S3C2410_NFREG(0x14) -#define S3C2440_NFECCD1 S3C2410_NFREG(0x18) -#define S3C2440_NFECCD S3C2410_NFREG(0x1C) -#define S3C2440_NFSTAT S3C2410_NFREG(0x20) -#define S3C2440_NFESTAT0 S3C2410_NFREG(0x24) -#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28) -#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C) -#define S3C2440_NFMECC1 S3C2410_NFREG(0x30) -#define S3C2440_NFSECC S3C2410_NFREG(0x34) -#define S3C2440_NFSBLK S3C2410_NFREG(0x38) -#define S3C2440_NFEBLK S3C2410_NFREG(0x3C) - #define S3C2410_NFCONF_EN (1<<15) #define S3C2410_NFCONF_512BYTE (1<<14) #define S3C2410_NFCONF_4STEP (1<<13) @@ -54,28 +37,7 @@ #define S3C2410_NFSTAT_BUSY (1<<0) -#define S3C2440_NFCONF_BUSWIDTH_8 (0<<0) -#define S3C2440_NFCONF_BUSWIDTH_16 (1<<0) -#define S3C2440_NFCONF_ADVFLASH (1<<3) -#define S3C2440_NFCONF_TACLS(x) ((x)<<12) -#define S3C2440_NFCONF_TWRPH0(x) ((x)<<8) -#define S3C2440_NFCONF_TWRPH1(x) ((x)<<4) - -#define S3C2440_NFCONT_LOCKTIGHT (1<<13) -#define S3C2440_NFCONT_SOFTLOCK (1<<12) -#define S3C2440_NFCONT_ILLEGALACC_EN (1<<10) -#define S3C2440_NFCONT_RNBINT_EN (1<<9) -#define S3C2440_NFCONT_RN_FALLING (1<<8) -#define S3C2440_NFCONT_SPARE_ECCLOCK (1<<6) -#define S3C2440_NFCONT_MAIN_ECCLOCK (1<<5) -#define S3C2440_NFCONT_INITECC (1<<4) -#define S3C2440_NFCONT_nFCE (1<<1) -#define S3C2440_NFCONT_ENABLE (1<<0) - -#define S3C2440_NFSTAT_READY (1<<0) -#define S3C2440_NFSTAT_nCE (1<<1) -#define S3C2440_NFSTAT_RnB_CHANGE (1<<2) -#define S3C2440_NFSTAT_ILLEGAL_ACCESS (1<<3) +/* think ECC can only be 8bit read? */ #endif /* __ASM_ARM_REGS_NAND */ diff --git a/trunk/include/asm-arm/page.h b/trunk/include/asm-arm/page.h index 019c45d75730..4ca3a8e9348f 100644 --- a/trunk/include/asm-arm/page.h +++ b/trunk/include/asm-arm/page.h @@ -114,8 +114,19 @@ extern void __cpu_copy_user_page(void *to, const void *from, unsigned long user); #endif -#define clear_user_page(addr,vaddr,pg) __cpu_clear_user_page(addr, vaddr) -#define copy_user_page(to,from,vaddr,pg) __cpu_copy_user_page(to, from, vaddr) +#define clear_user_page(addr,vaddr,pg) \ + do { \ + preempt_disable(); \ + __cpu_clear_user_page(addr, vaddr); \ + preempt_enable(); \ + } while (0) + +#define copy_user_page(to,from,vaddr,pg) \ + do { \ + preempt_disable(); \ + __cpu_copy_user_page(to, from, vaddr); \ + preempt_enable(); \ + } while (0) #define clear_page(page) memzero((void *)(page), PAGE_SIZE) extern void copy_page(void *to, const void *from); @@ -160,9 +171,6 @@ typedef unsigned long pgprot_t; #endif /* STRICT_MM_TYPECHECKS */ -/* the upper-most page table pointer */ -extern pmd_t *top_pmd; - /* Pure 2^n version of get_order */ static inline int get_order(unsigned long size) { diff --git a/trunk/include/linux/serial_core.h b/trunk/include/linux/serial_core.h index c3fb5984f250..d6025af7efac 100644 --- a/trunk/include/linux/serial_core.h +++ b/trunk/include/linux/serial_core.h @@ -479,6 +479,25 @@ uart_handle_cts_change(struct uart_port *port, unsigned int status) } } +#include + +static inline void +uart_insert_char(struct uart_port *port, unsigned int status, + unsigned int overrun, unsigned int ch, unsigned int flag) +{ + struct tty_struct *tty = port->info->tty; + + if ((status & port->ignore_status_mask & ~overrun) == 0) + tty_insert_flip_char(tty, ch, flag); + + /* + * Overrun is special. Since it's reported immediately, + * it doesn't affect the current character. + */ + if (status & ~port->ignore_status_mask & overrun) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); +} + /* * UART_ENABLE_MS - determine if port should enable modem status irqs */