* 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
Unified · Split
| @@ -371,6 +371,10 @@ static inline void __flush_icache_all(void) · 370 unmodified lines | ||
| 371 | 371 | #ifdef CONFIG_ARM_ERRATA_411920 |
| 372 | 372 | extern void v6_icache_inval_all(void); |
| 373 | 373 | v6_icache_inval_all(); |
| 374 | +#elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7 | |
| 375 | + asm("mcr p15, 0, %0, c7, c1, 0 @ invalidate I-cache inner shareable\n" | |
| 376 | + : | |
| 377 | + : "r" (0)); | |
| 374 | 378 | #else |
| 375 | 379 | asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" |
| 376 | 380 | : |
| @@ -1,6 +1,23 @@ | ||
| 1 | 1 | #ifndef __ASMARM_SMP_TWD_H |
| 2 | 2 | #define __ASMARM_SMP_TWD_H |
| 3 | 3 | |
| 4 | +#define TWD_TIMER_LOAD 0x00 | |
| 5 | +#define TWD_TIMER_COUNTER 0x04 | |
| 6 | +#define TWD_TIMER_CONTROL 0x08 | |
| 7 | +#define TWD_TIMER_INTSTAT 0x0C | |
| 8 | + | |
| 9 | +#define TWD_WDOG_LOAD 0x20 | |
| 10 | +#define TWD_WDOG_COUNTER 0x24 | |
| 11 | +#define TWD_WDOG_CONTROL 0x28 | |
| 12 | +#define TWD_WDOG_INTSTAT 0x2C | |
| 13 | +#define TWD_WDOG_RESETSTAT 0x30 | |
| 14 | +#define TWD_WDOG_DISABLE 0x34 | |
| 15 | + | |
| 16 | +#define TWD_TIMER_CONTROL_ENABLE (1 << 0) | |
| 17 | +#define TWD_TIMER_CONTROL_ONESHOT (0 << 1) | |
| 18 | +#define TWD_TIMER_CONTROL_PERIODIC (1 << 1) | |
| 19 | +#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) | |
| 20 | + | |
| 4 | 21 | struct clock_event_device; |
| 5 | 22 | |
| 6 | 23 | extern void __iomem *twd_base; |
| @@ -46,6 +46,9 @@ · 45 unmodified lines | ||
| 46 | 46 | #define TLB_V7_UIS_FULL (1 << 20) |
| 47 | 47 | #define TLB_V7_UIS_ASID (1 << 21) |
| 48 | 48 | |
| 49 | +/* Inner Shareable BTB operation (ARMv7 MP extensions) */ | |
| 50 | +#define TLB_V7_IS_BTB (1 << 22) | |
| 51 | + | |
| 49 | 52 | #define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */ |
| 50 | 53 | #define TLB_DCLEAN (1 << 30) |
| 51 | 54 | #define TLB_WB (1 << 31) |
| @@ -183,7 +186,7 @@ · 131 unmodified lines | ||
| 183 | 186 | #endif |
| 184 | 187 | |
| 185 | 188 | #ifdef CONFIG_SMP |
| 186 | −#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ | |
| 189 | +#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \ | |
| 187 | 190 | TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID) |
| 188 | 191 | #else |
| 189 | 192 | #define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ |
| @@ -339,6 +342,12 @@ static inline void local_flush_tlb_all(void) · 149 unmodified lines | ||
| 339 | 342 | dsb(); |
| 340 | 343 | isb(); |
| 341 | 344 | } |
| 345 | + if (tlb_flag(TLB_V7_IS_BTB)) { | |
| 346 | + /* flush the branch target cache */ | |
| 347 | + asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); | |
| 348 | + dsb(); | |
| 349 | + isb(); | |
| 350 | + } | |
| 342 | 351 | } |
| 343 | 352 | |
| 344 | 353 | 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) · 31 unmodified lines | ||
| 376 | 385 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); |
| 377 | 386 | dsb(); |
| 378 | 387 | } |
| 388 | + if (tlb_flag(TLB_V7_IS_BTB)) { | |
| 389 | + /* flush the branch target cache */ | |
| 390 | + asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); | |
| 391 | + dsb(); | |
| 392 | + isb(); | |
| 393 | + } | |
| 379 | 394 | } |
| 380 | 395 | |
| 381 | 396 | static inline void |
| @@ -416,6 +431,12 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) · 34 unmodified lines | ||
| 416 | 431 | asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); |
| 417 | 432 | dsb(); |
| 418 | 433 | } |
| 434 | + if (tlb_flag(TLB_V7_IS_BTB)) { | |
| 435 | + /* flush the branch target cache */ | |
| 436 | + asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); | |
| 437 | + dsb(); | |
| 438 | + isb(); | |
| 439 | + } | |
| 419 | 440 | } |
| 420 | 441 | |
| 421 | 442 | 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) · 32 unmodified lines | ||
| 454 | 475 | dsb(); |
| 455 | 476 | isb(); |
| 456 | 477 | } |
| 478 | + if (tlb_flag(TLB_V7_IS_BTB)) { | |
| 479 | + /* flush the branch target cache */ | |
| 480 | + asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); | |
| 481 | + dsb(); | |
| 482 | + isb(); | |
| 483 | + } | |
| 457 | 484 | } |
| 458 | 485 | |
| 459 | 486 | /* |
| @@ -21,23 +21,6 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <asm/smp_twd.h> |
| 22 | 22 | #include <asm/hardware/gic.h> |
| 23 | 23 | |
| 24 | −#define TWD_TIMER_LOAD 0x00 | |
| 25 | −#define TWD_TIMER_COUNTER 0x04 | |
| 26 | −#define TWD_TIMER_CONTROL 0x08 | |
| 27 | −#define TWD_TIMER_INTSTAT 0x0C | |
| 28 | − | |
| 29 | −#define TWD_WDOG_LOAD 0x20 | |
| 30 | −#define TWD_WDOG_COUNTER 0x24 | |
| 31 | −#define TWD_WDOG_CONTROL 0x28 | |
| 32 | −#define TWD_WDOG_INTSTAT 0x2C | |
| 33 | −#define TWD_WDOG_RESETSTAT 0x30 | |
| 34 | −#define TWD_WDOG_DISABLE 0x34 | |
| 35 | − | |
| 36 | −#define TWD_TIMER_CONTROL_ENABLE (1 << 0) | |
| 37 | −#define TWD_TIMER_CONTROL_ONESHOT (0 << 1) | |
| 38 | −#define TWD_TIMER_CONTROL_PERIODIC (1 << 1) | |
| 39 | −#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) | |
| 40 | − | |
| 41 | 24 | /* set up by the platform code */ |
| 42 | 25 | void __iomem *twd_base; |
| 43 | 26 | |
| @@ -45,6 +45,7 @@ USER( strnebt r2, [r0]) · 44 unmodified lines | ||
| 45 | 45 | mov r0, #0 |
| 46 | 46 | ldmfd sp!, {r1, pc} |
| 47 | 47 | ENDPROC(__clear_user) |
| 48 | +ENDPROC(__clear_user_std) | |
| 48 | 49 | |
| 49 | 50 | .pushsection .fixup,"ax" |
| 50 | 51 | .align 0 |
| @@ -93,6 +93,7 @@ WEAK(__copy_to_user) · 92 unmodified lines | ||
| 93 | 93 | #include "copy_template.S" |
| 94 | 94 | |
| 95 | 95 | ENDPROC(__copy_to_user) |
| 96 | +ENDPROC(__copy_to_user_std) | |
| 96 | 97 | |
| 97 | 98 | .pushsection .fixup,"ax" |
| 98 | 99 | .align 0 |
| @@ -211,6 +211,9 @@ v6_dma_inv_range: · 210 unmodified lines | ||
| 211 | 211 | mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line |
| 212 | 212 | #endif |
| 213 | 213 | 1: |
| 214 | +#ifdef CONFIG_SMP | |
| 215 | + str r0, [r0] @ write for ownership | |
| 216 | +#endif | |
| 214 | 217 | #ifdef HARVARD_CACHE |
| 215 | 218 | mcr p15, 0, r0, c7, c6, 1 @ invalidate D line |
| 216 | 219 | #else |
| @@ -231,6 +234,9 @@ v6_dma_inv_range: · 14 unmodified lines | ||
| 231 | 234 | v6_dma_clean_range: |
| 232 | 235 | bic r0, r0, #D_CACHE_LINE_SIZE - 1 |
| 233 | 236 | 1: |
| 237 | +#ifdef CONFIG_SMP | |
| 238 | + ldr r2, [r0] @ read for ownership | |
| 239 | +#endif | |
| 234 | 240 | #ifdef HARVARD_CACHE |
| 235 | 241 | mcr p15, 0, r0, c7, c10, 1 @ clean D line |
| 236 | 242 | #else |
| @@ -251,6 +257,10 @@ v6_dma_clean_range: · 14 unmodified lines | ||
| 251 | 257 | ENTRY(v6_dma_flush_range) |
| 252 | 258 | bic r0, r0, #D_CACHE_LINE_SIZE - 1 |
| 253 | 259 | 1: |
| 260 | +#ifdef CONFIG_SMP | |
| 261 | + ldr r2, [r0] @ read for ownership | |
| 262 | + str r2, [r0] @ write for ownership | |
| 263 | +#endif | |
| 254 | 264 | #ifdef HARVARD_CACHE |
| 255 | 265 | mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line |
| 256 | 266 | #else |
| @@ -273,7 +283,9 @@ ENTRY(v6_dma_map_area) · 16 unmodified lines | ||
| 273 | 283 | add r1, r1, r0 |
| 274 | 284 | teq r2, #DMA_FROM_DEVICE |
| 275 | 285 | beq v6_dma_inv_range |
| 276 | − b v6_dma_clean_range | |
| 286 | + teq r2, #DMA_TO_DEVICE | |
| 287 | + beq v6_dma_clean_range | |
| 288 | + b v6_dma_flush_range | |
| 277 | 289 | ENDPROC(v6_dma_map_area) |
| 278 | 290 | |
| 279 | 291 | /* |
| @@ -283,9 +295,6 @@ ENDPROC(v6_dma_map_area) · 3 unmodified lines | ||
| 283 | 295 | * - dir - DMA direction |
| 284 | 296 | */ |
| 285 | 297 | ENTRY(v6_dma_unmap_area) |
| 286 | − add r1, r1, r0 | |
| 287 | − teq r2, #DMA_TO_DEVICE | |
| 288 | − bne v6_dma_inv_range | |
| 289 | 298 | mov pc, lr |
| 290 | 299 | ENDPROC(v6_dma_unmap_area) |
| 291 | 300 | |
| @@ -167,7 +167,11 @@ ENTRY(v7_coherent_user_range) · 166 unmodified lines | ||
| 167 | 167 | cmp r0, r1 |
| 168 | 168 | blo 1b |
| 169 | 169 | mov r0, #0 |
| 170 | +#ifdef CONFIG_SMP | |
| 171 | + mcr p15, 0, r0, c7, c1, 6 @ invalidate BTB Inner Shareable | |
| 172 | +#else | |
| 170 | 173 | mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB |
| 174 | +#endif | |
| 171 | 175 | dsb |
| 172 | 176 | isb |
| 173 | 177 | mov pc, lr |
| @@ -65,6 +65,15 @@ void flush_dcache_page(struct page *page) · 64 unmodified lines | ||
| 65 | 65 | } |
| 66 | 66 | EXPORT_SYMBOL(flush_dcache_page); |
| 67 | 67 | |
| 68 | +void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | |
| 69 | + unsigned long uaddr, void *dst, const void *src, | |
| 70 | + unsigned long len) | |
| 71 | +{ | |
| 72 | + memcpy(dst, src, len); | |
| 73 | + if (vma->vm_flags & VM_EXEC) | |
| 74 | + __cpuc_coherent_user_range(uaddr, uaddr + len); | |
| 75 | +} | |
| 76 | + | |
| 68 | 77 | void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, |
| 69 | 78 | size_t size, unsigned int mtype) |
| 70 | 79 | { |
| @@ -87,8 +96,8 @@ void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, · 16 unmodified lines | ||
| 87 | 96 | } |
| 88 | 97 | EXPORT_SYMBOL(__arm_ioremap); |
| 89 | 98 | |
| 90 | −void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, | |
| 91 | − unsigned int mtype, void *caller) | |
| 99 | +void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size, | |
| 100 | + unsigned int mtype, void *caller) | |
| 92 | 101 | { |
| 93 | 102 | return __arm_ioremap(phys_addr, size, mtype); |
| 94 | 103 | } |
| @@ -50,7 +50,11 @@ ENTRY(v7wbi_flush_user_tlb_range) · 49 unmodified lines | ||
| 50 | 50 | cmp r0, r1 |
| 51 | 51 | blo 1b |
| 52 | 52 | mov ip, #0 |
| 53 | +#ifdef CONFIG_SMP | |
| 54 | + mcr p15, 0, ip, c7, c1, 6 @ flush BTAC/BTB Inner Shareable | |
| 55 | +#else | |
| 53 | 56 | mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB |
| 57 | +#endif | |
| 54 | 58 | dsb |
| 55 | 59 | mov pc, lr |
| 56 | 60 | ENDPROC(v7wbi_flush_user_tlb_range) |
| @@ -79,7 +83,11 @@ ENTRY(v7wbi_flush_kern_tlb_range) · 22 unmodified lines | ||
| 79 | 83 | cmp r0, r1 |
| 80 | 84 | blo 1b |
| 81 | 85 | mov r2, #0 |
| 86 | +#ifdef CONFIG_SMP | |
| 87 | + mcr p15, 0, r2, c7, c1, 6 @ flush BTAC/BTB Inner Shareable | |
| 88 | +#else | |
| 82 | 89 | mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB |
| 90 | +#endif | |
| 83 | 91 | dsb |
| 84 | 92 | isb |
| 85 | 93 | mov pc, lr |
| @@ -175,7 +175,7 @@ config SA1100_WATCHDOG · 174 unmodified lines | ||
| 175 | 175 | |
| 176 | 176 | config MPCORE_WATCHDOG |
| 177 | 177 | tristate "MPcore watchdog" |
| 178 | − depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS | |
| 178 | + depends on HAVE_ARM_TWD | |
| 179 | 179 | help |
| 180 | 180 | Watchdog timer embedded into the MPcore system. |
| 181 | 181 | |
| @@ -31,8 +31,9 @@ · 30 unmodified lines | ||
| 31 | 31 | #include <linux/platform_device.h> |
| 32 | 32 | #include <linux/uaccess.h> |
| 33 | 33 | #include <linux/slab.h> |
| 34 | +#include <linux/io.h> | |
| 34 | 35 | |
| 35 | −#include <asm/hardware/arm_twd.h> | |
| 36 | +#include <asm/smp_twd.h> | |
| 36 | 37 | |
| 37 | 38 | struct mpcore_wdt { |
| 38 | 39 | unsigned long timer_alive; |
| @@ -44,7 +45,7 @@ struct mpcore_wdt { · 5 unmodified lines | ||
| 44 | 45 | }; |
| 45 | 46 | |
| 46 | 47 | static struct platform_device *mpcore_wdt_dev; |
| 47 | −extern unsigned int mpcore_timer_rate; | |
| 48 | +static DEFINE_SPINLOCK(wdt_lock); | |
| 48 | 49 | |
| 49 | 50 | #define TIMER_MARGIN 60 |
| 50 | 51 | static int mpcore_margin = TIMER_MARGIN; |
| @@ -94,13 +95,15 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg) · 43 unmodified lines | ||
| 94 | 95 | */ |
| 95 | 96 | static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) |
| 96 | 97 | { |
| 97 | − unsigned int count; | |
| 98 | + unsigned long count; | |
| 98 | 99 | |
| 100 | + spin_lock(&wdt_lock); | |
| 99 | 101 | /* Assume prescale is set to 256 */ |
| 100 | − count = (mpcore_timer_rate / 256) * mpcore_margin; | |
| 102 | + count = __raw_readl(wdt->base + TWD_WDOG_COUNTER); | |
| 103 | + count = (0xFFFFFFFFU - count) * (HZ / 5); | |
| 104 | + count = (count / 256) * mpcore_margin; | |
| 101 | 105 | |
| 102 | 106 | /* Reload the counter */ |
| 103 | − spin_lock(&wdt_lock); | |
| 104 | 107 | writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); |
| 105 | 108 | wdt->perturb = wdt->perturb ? 0 : 1; |
| 106 | 109 | spin_unlock(&wdt_lock); |
| @@ -119,7 +122,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) · 12 unmodified lines | ||
| 119 | 122 | { |
| 120 | 123 | dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); |
| 121 | 124 | |
| 122 | − spin_lock(&wdt_lock); | |
| 123 | 125 | /* This loads the count register but does NOT start the count yet */ |
| 124 | 126 | mpcore_wdt_keepalive(wdt); |
| 125 | 127 | |
| @@ -130,7 +132,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) · 4 unmodified lines | ||
| 130 | 132 | /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ |
| 131 | 133 | writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); |
| 132 | 134 | } |
| 133 | − spin_unlock(&wdt_lock); | |
| 134 | 135 | } |
| 135 | 136 | |
| 136 | 137 | static int mpcore_wdt_set_heartbeat(int t) |
| @@ -360,7 +361,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) · 223 unmodified lines | ||
| 360 | 361 | mpcore_wdt_miscdev.parent = &dev->dev; |
| 361 | 362 | ret = misc_register(&mpcore_wdt_miscdev); |
| 362 | 363 | if (ret) { |
| 363 | − dev_printk(KERN_ERR, _dev, | |
| 364 | + dev_printk(KERN_ERR, wdt->dev, | |
| 364 | 365 | "cannot register miscdev on minor=%d (err=%d)\n", |
| 365 | 366 | WATCHDOG_MINOR, ret); |
| 366 | 367 | goto err_misc; |
| @@ -369,13 +370,13 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) · 2 unmodified lines | ||
| 369 | 370 | ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, |
| 370 | 371 | "mpcore_wdt", wdt); |
| 371 | 372 | if (ret) { |
| 372 | − dev_printk(KERN_ERR, _dev, | |
| 373 | + dev_printk(KERN_ERR, wdt->dev, | |
| 373 | 374 | "cannot register IRQ%d for watchdog\n", wdt->irq); |
| 374 | 375 | goto err_irq; |
| 375 | 376 | } |
| 376 | 377 | |
| 377 | 378 | mpcore_wdt_stop(wdt); |
| 378 | − platform_set_drvdata(&dev->dev, wdt); | |
| 379 | + platform_set_drvdata(dev, wdt); | |
| 379 | 380 | mpcore_wdt_dev = dev; |
| 380 | 381 | |
| 381 | 382 | return 0; |