提交 bfcf1ae2 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/home/rmk/linux-2.6-arm

* master.kernel.org:/home/rmk/linux-2.6-arm:
  ARM: 6126/1: ARM mpcore_wdt: fix build failure and other fixes
  ARM: 6125/1: ARM TWD: move TWD registers to common header
  ARM: 6110/1: Fix Thumb-2 kernel builds when UACCESS_WITH_MEMCPY is enabled
  ARM: 6112/1: Use the Inner Shareable I-cache and BTB ops on ARMv7 SMP
  ARM: 6111/1: Implement read/write for ownership in the ARMv6 DMA cache ops
  ARM: 6106/1: Implement copy_to_user_page() for noMMU
  ARM: 6105/1: Fix the __arm_ioremap_caller() definition in nommu.c
...@@ -371,6 +371,10 @@ static inline void __flush_icache_all(void) ...@@ -371,6 +371,10 @@ static inline void __flush_icache_all(void)
#ifdef CONFIG_ARM_ERRATA_411920 #ifdef CONFIG_ARM_ERRATA_411920
extern void v6_icache_inval_all(void); extern void v6_icache_inval_all(void);
v6_icache_inval_all(); v6_icache_inval_all();
#elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7
asm("mcr p15, 0, %0, c7, c1, 0 @ invalidate I-cache inner shareable\n"
:
: "r" (0));
#else #else
asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n"
: :
......
#ifndef __ASMARM_SMP_TWD_H #ifndef __ASMARM_SMP_TWD_H
#define __ASMARM_SMP_TWD_H #define __ASMARM_SMP_TWD_H
#define TWD_TIMER_LOAD 0x00
#define TWD_TIMER_COUNTER 0x04
#define TWD_TIMER_CONTROL 0x08
#define TWD_TIMER_INTSTAT 0x0C
#define TWD_WDOG_LOAD 0x20
#define TWD_WDOG_COUNTER 0x24
#define TWD_WDOG_CONTROL 0x28
#define TWD_WDOG_INTSTAT 0x2C
#define TWD_WDOG_RESETSTAT 0x30
#define TWD_WDOG_DISABLE 0x34
#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
struct clock_event_device; struct clock_event_device;
extern void __iomem *twd_base; extern void __iomem *twd_base;
......
...@@ -46,6 +46,9 @@ ...@@ -46,6 +46,9 @@
#define TLB_V7_UIS_FULL (1 << 20) #define TLB_V7_UIS_FULL (1 << 20)
#define TLB_V7_UIS_ASID (1 << 21) #define TLB_V7_UIS_ASID (1 << 21)
/* Inner Shareable BTB operation (ARMv7 MP extensions) */
#define TLB_V7_IS_BTB (1 << 22)
#define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */ #define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */
#define TLB_DCLEAN (1 << 30) #define TLB_DCLEAN (1 << 30)
#define TLB_WB (1 << 31) #define TLB_WB (1 << 31)
...@@ -183,7 +186,7 @@ ...@@ -183,7 +186,7 @@
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ #define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID) TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
#else #else
#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ #define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
...@@ -339,6 +342,12 @@ static inline void local_flush_tlb_all(void) ...@@ -339,6 +342,12 @@ static inline void local_flush_tlb_all(void)
dsb(); dsb();
isb(); isb();
} }
if (tlb_flag(TLB_V7_IS_BTB)) {
/* flush the branch target cache */
asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
dsb();
isb();
}
} }
static inline void local_flush_tlb_mm(struct mm_struct *mm) static inline void local_flush_tlb_mm(struct mm_struct *mm)
...@@ -376,6 +385,12 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm) ...@@ -376,6 +385,12 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
dsb(); dsb();
} }
if (tlb_flag(TLB_V7_IS_BTB)) {
/* flush the branch target cache */
asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
dsb();
isb();
}
} }
static inline void static inline void
...@@ -416,6 +431,12 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) ...@@ -416,6 +431,12 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
dsb(); dsb();
} }
if (tlb_flag(TLB_V7_IS_BTB)) {
/* flush the branch target cache */
asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
dsb();
isb();
}
} }
static inline void local_flush_tlb_kernel_page(unsigned long kaddr) static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
...@@ -454,6 +475,12 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) ...@@ -454,6 +475,12 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
dsb(); dsb();
isb(); isb();
} }
if (tlb_flag(TLB_V7_IS_BTB)) {
/* flush the branch target cache */
asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
dsb();
isb();
}
} }
/* /*
......
...@@ -21,23 +21,6 @@ ...@@ -21,23 +21,6 @@
#include <asm/smp_twd.h> #include <asm/smp_twd.h>
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#define TWD_TIMER_LOAD 0x00
#define TWD_TIMER_COUNTER 0x04
#define TWD_TIMER_CONTROL 0x08
#define TWD_TIMER_INTSTAT 0x0C
#define TWD_WDOG_LOAD 0x20
#define TWD_WDOG_COUNTER 0x24
#define TWD_WDOG_CONTROL 0x28
#define TWD_WDOG_INTSTAT 0x2C
#define TWD_WDOG_RESETSTAT 0x30
#define TWD_WDOG_DISABLE 0x34
#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
/* set up by the platform code */ /* set up by the platform code */
void __iomem *twd_base; void __iomem *twd_base;
......
...@@ -45,6 +45,7 @@ USER( strnebt r2, [r0]) ...@@ -45,6 +45,7 @@ USER( strnebt r2, [r0])
mov r0, #0 mov r0, #0
ldmfd sp!, {r1, pc} ldmfd sp!, {r1, pc}
ENDPROC(__clear_user) ENDPROC(__clear_user)
ENDPROC(__clear_user_std)
.pushsection .fixup,"ax" .pushsection .fixup,"ax"
.align 0 .align 0
......
...@@ -93,6 +93,7 @@ WEAK(__copy_to_user) ...@@ -93,6 +93,7 @@ WEAK(__copy_to_user)
#include "copy_template.S" #include "copy_template.S"
ENDPROC(__copy_to_user) ENDPROC(__copy_to_user)
ENDPROC(__copy_to_user_std)
.pushsection .fixup,"ax" .pushsection .fixup,"ax"
.align 0 .align 0
......
...@@ -211,6 +211,9 @@ v6_dma_inv_range: ...@@ -211,6 +211,9 @@ v6_dma_inv_range:
mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line
#endif #endif
1: 1:
#ifdef CONFIG_SMP
str r0, [r0] @ write for ownership
#endif
#ifdef HARVARD_CACHE #ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c6, 1 @ invalidate D line mcr p15, 0, r0, c7, c6, 1 @ invalidate D line
#else #else
...@@ -231,6 +234,9 @@ v6_dma_inv_range: ...@@ -231,6 +234,9 @@ v6_dma_inv_range:
v6_dma_clean_range: v6_dma_clean_range:
bic r0, r0, #D_CACHE_LINE_SIZE - 1 bic r0, r0, #D_CACHE_LINE_SIZE - 1
1: 1:
#ifdef CONFIG_SMP
ldr r2, [r0] @ read for ownership
#endif
#ifdef HARVARD_CACHE #ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c10, 1 @ clean D line mcr p15, 0, r0, c7, c10, 1 @ clean D line
#else #else
...@@ -251,6 +257,10 @@ v6_dma_clean_range: ...@@ -251,6 +257,10 @@ v6_dma_clean_range:
ENTRY(v6_dma_flush_range) ENTRY(v6_dma_flush_range)
bic r0, r0, #D_CACHE_LINE_SIZE - 1 bic r0, r0, #D_CACHE_LINE_SIZE - 1
1: 1:
#ifdef CONFIG_SMP
ldr r2, [r0] @ read for ownership
str r2, [r0] @ write for ownership
#endif
#ifdef HARVARD_CACHE #ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line
#else #else
...@@ -273,7 +283,9 @@ ENTRY(v6_dma_map_area) ...@@ -273,7 +283,9 @@ ENTRY(v6_dma_map_area)
add r1, r1, r0 add r1, r1, r0
teq r2, #DMA_FROM_DEVICE teq r2, #DMA_FROM_DEVICE
beq v6_dma_inv_range beq v6_dma_inv_range
b v6_dma_clean_range teq r2, #DMA_TO_DEVICE
beq v6_dma_clean_range
b v6_dma_flush_range
ENDPROC(v6_dma_map_area) ENDPROC(v6_dma_map_area)
/* /*
...@@ -283,9 +295,6 @@ ENDPROC(v6_dma_map_area) ...@@ -283,9 +295,6 @@ ENDPROC(v6_dma_map_area)
* - dir - DMA direction * - dir - DMA direction
*/ */
ENTRY(v6_dma_unmap_area) ENTRY(v6_dma_unmap_area)
add r1, r1, r0
teq r2, #DMA_TO_DEVICE
bne v6_dma_inv_range
mov pc, lr mov pc, lr
ENDPROC(v6_dma_unmap_area) ENDPROC(v6_dma_unmap_area)
......
...@@ -167,7 +167,11 @@ ENTRY(v7_coherent_user_range) ...@@ -167,7 +167,11 @@ ENTRY(v7_coherent_user_range)
cmp r0, r1 cmp r0, r1
blo 1b blo 1b
mov r0, #0 mov r0, #0
#ifdef CONFIG_SMP
mcr p15, 0, r0, c7, c1, 6 @ invalidate BTB Inner Shareable
#else
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
#endif
dsb dsb
isb isb
mov pc, lr mov pc, lr
......
...@@ -65,6 +65,15 @@ void flush_dcache_page(struct page *page) ...@@ -65,6 +65,15 @@ void flush_dcache_page(struct page *page)
} }
EXPORT_SYMBOL(flush_dcache_page); EXPORT_SYMBOL(flush_dcache_page);
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long uaddr, void *dst, const void *src,
unsigned long len)
{
memcpy(dst, src, len);
if (vma->vm_flags & VM_EXEC)
__cpuc_coherent_user_range(uaddr, uaddr + len);
}
void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset,
size_t size, unsigned int mtype) size_t size, unsigned int mtype)
{ {
...@@ -87,8 +96,8 @@ void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, ...@@ -87,8 +96,8 @@ void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size,
} }
EXPORT_SYMBOL(__arm_ioremap); EXPORT_SYMBOL(__arm_ioremap);
void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size,
unsigned int mtype, void *caller) unsigned int mtype, void *caller)
{ {
return __arm_ioremap(phys_addr, size, mtype); return __arm_ioremap(phys_addr, size, mtype);
} }
......
...@@ -50,7 +50,11 @@ ENTRY(v7wbi_flush_user_tlb_range) ...@@ -50,7 +50,11 @@ ENTRY(v7wbi_flush_user_tlb_range)
cmp r0, r1 cmp r0, r1
blo 1b blo 1b
mov ip, #0 mov ip, #0
#ifdef CONFIG_SMP
mcr p15, 0, ip, c7, c1, 6 @ flush BTAC/BTB Inner Shareable
#else
mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB
#endif
dsb dsb
mov pc, lr mov pc, lr
ENDPROC(v7wbi_flush_user_tlb_range) ENDPROC(v7wbi_flush_user_tlb_range)
...@@ -79,7 +83,11 @@ ENTRY(v7wbi_flush_kern_tlb_range) ...@@ -79,7 +83,11 @@ ENTRY(v7wbi_flush_kern_tlb_range)
cmp r0, r1 cmp r0, r1
blo 1b blo 1b
mov r2, #0 mov r2, #0
#ifdef CONFIG_SMP
mcr p15, 0, r2, c7, c1, 6 @ flush BTAC/BTB Inner Shareable
#else
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
#endif
dsb dsb
isb isb
mov pc, lr mov pc, lr
......
...@@ -175,7 +175,7 @@ config SA1100_WATCHDOG ...@@ -175,7 +175,7 @@ config SA1100_WATCHDOG
config MPCORE_WATCHDOG config MPCORE_WATCHDOG
tristate "MPcore watchdog" tristate "MPcore watchdog"
depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS depends on HAVE_ARM_TWD
help help
Watchdog timer embedded into the MPcore system. Watchdog timer embedded into the MPcore system.
......
...@@ -31,8 +31,9 @@ ...@@ -31,8 +31,9 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io.h>
#include <asm/hardware/arm_twd.h> #include <asm/smp_twd.h>
struct mpcore_wdt { struct mpcore_wdt {
unsigned long timer_alive; unsigned long timer_alive;
...@@ -44,7 +45,7 @@ struct mpcore_wdt { ...@@ -44,7 +45,7 @@ struct mpcore_wdt {
}; };
static struct platform_device *mpcore_wdt_dev; static struct platform_device *mpcore_wdt_dev;
extern unsigned int mpcore_timer_rate; static DEFINE_SPINLOCK(wdt_lock);
#define TIMER_MARGIN 60 #define TIMER_MARGIN 60
static int mpcore_margin = TIMER_MARGIN; static int mpcore_margin = TIMER_MARGIN;
...@@ -94,13 +95,15 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg) ...@@ -94,13 +95,15 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg)
*/ */
static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
{ {
unsigned int count; unsigned long count;
spin_lock(&wdt_lock);
/* Assume prescale is set to 256 */ /* Assume prescale is set to 256 */
count = (mpcore_timer_rate / 256) * mpcore_margin; count = __raw_readl(wdt->base + TWD_WDOG_COUNTER);
count = (0xFFFFFFFFU - count) * (HZ / 5);
count = (count / 256) * mpcore_margin;
/* Reload the counter */ /* Reload the counter */
spin_lock(&wdt_lock);
writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
wdt->perturb = wdt->perturb ? 0 : 1; wdt->perturb = wdt->perturb ? 0 : 1;
spin_unlock(&wdt_lock); spin_unlock(&wdt_lock);
...@@ -119,7 +122,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) ...@@ -119,7 +122,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt)
{ {
dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
spin_lock(&wdt_lock);
/* This loads the count register but does NOT start the count yet */ /* This loads the count register but does NOT start the count yet */
mpcore_wdt_keepalive(wdt); mpcore_wdt_keepalive(wdt);
...@@ -130,7 +132,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) ...@@ -130,7 +132,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt)
/* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
} }
spin_unlock(&wdt_lock);
} }
static int mpcore_wdt_set_heartbeat(int t) static int mpcore_wdt_set_heartbeat(int t)
...@@ -360,7 +361,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) ...@@ -360,7 +361,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)
mpcore_wdt_miscdev.parent = &dev->dev; mpcore_wdt_miscdev.parent = &dev->dev;
ret = misc_register(&mpcore_wdt_miscdev); ret = misc_register(&mpcore_wdt_miscdev);
if (ret) { if (ret) {
dev_printk(KERN_ERR, _dev, dev_printk(KERN_ERR, wdt->dev,
"cannot register miscdev on minor=%d (err=%d)\n", "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret); WATCHDOG_MINOR, ret);
goto err_misc; goto err_misc;
...@@ -369,13 +370,13 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) ...@@ -369,13 +370,13 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)
ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED,
"mpcore_wdt", wdt); "mpcore_wdt", wdt);
if (ret) { if (ret) {
dev_printk(KERN_ERR, _dev, dev_printk(KERN_ERR, wdt->dev,
"cannot register IRQ%d for watchdog\n", wdt->irq); "cannot register IRQ%d for watchdog\n", wdt->irq);
goto err_irq; goto err_irq;
} }
mpcore_wdt_stop(wdt); mpcore_wdt_stop(wdt);
platform_set_drvdata(&dev->dev, wdt); platform_set_drvdata(dev, wdt);
mpcore_wdt_dev = dev; mpcore_wdt_dev = dev;
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册