diff options
Diffstat (limited to 'arch')
601 files changed, 12590 insertions, 7739 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c8424a85bc04..0bee1fe209b1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -687,7 +687,9 @@ config ARCH_SA1100 | |||
687 | select CPU_SA1100 | 687 | select CPU_SA1100 |
688 | select GENERIC_CLOCKEVENTS | 688 | select GENERIC_CLOCKEVENTS |
689 | select HAVE_IDE | 689 | select HAVE_IDE |
690 | select IRQ_DOMAIN | ||
690 | select ISA | 691 | select ISA |
692 | select MULTI_IRQ_HANDLER | ||
691 | select NEED_MACH_MEMORY_H | 693 | select NEED_MACH_MEMORY_H |
692 | select SPARSE_IRQ | 694 | select SPARSE_IRQ |
693 | help | 695 | help |
diff --git a/arch/arm/boot/dts/bcm63138.dtsi b/arch/arm/boot/dts/bcm63138.dtsi index f3bb2dd6269e..d2d8e94e0aa2 100644 --- a/arch/arm/boot/dts/bcm63138.dtsi +++ b/arch/arm/boot/dts/bcm63138.dtsi | |||
@@ -102,7 +102,7 @@ | |||
102 | twd_watchdog: watchdog@1e620 { | 102 | twd_watchdog: watchdog@1e620 { |
103 | compatible = "arm,cortex-a9-twd-wdt"; | 103 | compatible = "arm,cortex-a9-twd-wdt"; |
104 | reg = <0x1e620 0x20>; | 104 | reg = <0x1e620 0x20>; |
105 | interupts = <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>; | 105 | interrupts = <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>; |
106 | }; | 106 | }; |
107 | }; | 107 | }; |
108 | 108 | ||
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index e57d7e5bf96a..7b69c5f9cd74 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c | |||
@@ -282,8 +282,8 @@ static int sa1111_retrigger_lowirq(struct irq_data *d) | |||
282 | } | 282 | } |
283 | 283 | ||
284 | if (i == 8) | 284 | if (i == 8) |
285 | printk(KERN_ERR "Danger Will Robinson: failed to " | 285 | pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n", |
286 | "re-trigger IRQ%d\n", d->irq); | 286 | d->irq); |
287 | return i == 8 ? -1 : 0; | 287 | return i == 8 ? -1 : 0; |
288 | } | 288 | } |
289 | 289 | ||
@@ -384,8 +384,8 @@ static int sa1111_retrigger_highirq(struct irq_data *d) | |||
384 | } | 384 | } |
385 | 385 | ||
386 | if (i == 8) | 386 | if (i == 8) |
387 | printk(KERN_ERR "Danger Will Robinson: failed to " | 387 | pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n", |
388 | "re-trigger IRQ%d\n", d->irq); | 388 | d->irq); |
389 | return i == 8 ? -1 : 0; | 389 | return i == 8 ? -1 : 0; |
390 | } | 390 | } |
391 | 391 | ||
@@ -740,9 +740,8 @@ static int __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
740 | goto err_unmap; | 740 | goto err_unmap; |
741 | } | 741 | } |
742 | 742 | ||
743 | printk(KERN_INFO "SA1111 Microprocessor Companion Chip: " | 743 | pr_info("SA1111 Microprocessor Companion Chip: silicon revision %lx, metal revision %lx\n", |
744 | "silicon revision %lx, metal revision %lx\n", | 744 | (id & SKID_SIREV_MASK) >> 4, id & SKID_MTREV_MASK); |
745 | (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK)); | ||
746 | 745 | ||
747 | /* | 746 | /* |
748 | * We found it. Wake the chip up, and initialise. | 747 | * We found it. Wake the chip up, and initialise. |
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 10e78d00a0bb..2d46862e7bef 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h | |||
@@ -487,6 +487,16 @@ int set_memory_rw(unsigned long addr, int numpages); | |||
487 | int set_memory_x(unsigned long addr, int numpages); | 487 | int set_memory_x(unsigned long addr, int numpages); |
488 | int set_memory_nx(unsigned long addr, int numpages); | 488 | int set_memory_nx(unsigned long addr, int numpages); |
489 | 489 | ||
490 | #ifdef CONFIG_DEBUG_RODATA | ||
491 | void mark_rodata_ro(void); | ||
492 | void set_kernel_text_rw(void); | ||
493 | void set_kernel_text_ro(void); | ||
494 | #else | ||
495 | static inline void set_kernel_text_rw(void) { } | ||
496 | static inline void set_kernel_text_ro(void) { } | ||
497 | #endif | ||
498 | |||
490 | void flush_uprobe_xol_access(struct page *page, unsigned long uaddr, | 499 | void flush_uprobe_xol_access(struct page *page, unsigned long uaddr, |
491 | void *kaddr, unsigned long len); | 500 | void *kaddr, unsigned long len); |
501 | |||
492 | #endif | 502 | #endif |
diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h index dc662fca9230..4111592f0130 100644 --- a/arch/arm/include/asm/device.h +++ b/arch/arm/include/asm/device.h | |||
@@ -17,6 +17,7 @@ struct dev_archdata { | |||
17 | #ifdef CONFIG_ARM_DMA_USE_IOMMU | 17 | #ifdef CONFIG_ARM_DMA_USE_IOMMU |
18 | struct dma_iommu_mapping *mapping; | 18 | struct dma_iommu_mapping *mapping; |
19 | #endif | 19 | #endif |
20 | bool dma_coherent; | ||
20 | }; | 21 | }; |
21 | 22 | ||
22 | struct omap_device; | 23 | struct omap_device; |
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 85738b200023..e6e3446abdf6 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -123,11 +123,18 @@ static inline unsigned long dma_max_pfn(struct device *dev) | |||
123 | 123 | ||
124 | static inline int set_arch_dma_coherent_ops(struct device *dev) | 124 | static inline int set_arch_dma_coherent_ops(struct device *dev) |
125 | { | 125 | { |
126 | dev->archdata.dma_coherent = true; | ||
126 | set_dma_ops(dev, &arm_coherent_dma_ops); | 127 | set_dma_ops(dev, &arm_coherent_dma_ops); |
127 | return 0; | 128 | return 0; |
128 | } | 129 | } |
129 | #define set_arch_dma_coherent_ops(dev) set_arch_dma_coherent_ops(dev) | 130 | #define set_arch_dma_coherent_ops(dev) set_arch_dma_coherent_ops(dev) |
130 | 131 | ||
132 | /* do not use this function in a driver */ | ||
133 | static inline bool is_device_dma_coherent(struct device *dev) | ||
134 | { | ||
135 | return dev->archdata.dma_coherent; | ||
136 | } | ||
137 | |||
131 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | 138 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) |
132 | { | 139 | { |
133 | unsigned int offset = paddr & ~PAGE_MASK; | 140 | unsigned int offset = paddr & ~PAGE_MASK; |
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index 74124b0d0d79..0415eae1df27 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h | |||
@@ -2,27 +2,24 @@ | |||
2 | #define _ASM_FIXMAP_H | 2 | #define _ASM_FIXMAP_H |
3 | 3 | ||
4 | #define FIXADDR_START 0xffc00000UL | 4 | #define FIXADDR_START 0xffc00000UL |
5 | #define FIXADDR_TOP 0xffe00000UL | 5 | #define FIXADDR_END 0xfff00000UL |
6 | #define FIXADDR_SIZE (FIXADDR_TOP - FIXADDR_START) | 6 | #define FIXADDR_TOP (FIXADDR_END - PAGE_SIZE) |
7 | 7 | ||
8 | #define FIX_KMAP_NR_PTES (FIXADDR_SIZE >> PAGE_SHIFT) | 8 | #include <asm/kmap_types.h> |
9 | 9 | ||
10 | #define __fix_to_virt(x) (FIXADDR_START + ((x) << PAGE_SHIFT)) | 10 | enum fixed_addresses { |
11 | #define __virt_to_fix(x) (((x) - FIXADDR_START) >> PAGE_SHIFT) | 11 | FIX_KMAP_BEGIN, |
12 | FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, | ||
12 | 13 | ||
13 | extern void __this_fixmap_does_not_exist(void); | 14 | /* Support writing RO kernel text via kprobes, jump labels, etc. */ |
15 | FIX_TEXT_POKE0, | ||
16 | FIX_TEXT_POKE1, | ||
14 | 17 | ||
15 | static inline unsigned long fix_to_virt(const unsigned int idx) | 18 | __end_of_fixed_addresses |
16 | { | 19 | }; |
17 | if (idx >= FIX_KMAP_NR_PTES) | ||
18 | __this_fixmap_does_not_exist(); | ||
19 | return __fix_to_virt(idx); | ||
20 | } | ||
21 | 20 | ||
22 | static inline unsigned int virt_to_fix(const unsigned long vaddr) | 21 | void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot); |
23 | { | 22 | |
24 | BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); | 23 | #include <asm-generic/fixmap.h> |
25 | return __virt_to_fix(vaddr); | ||
26 | } | ||
27 | 24 | ||
28 | #endif | 25 | #endif |
diff --git a/arch/arm/include/asm/hw_irq.h b/arch/arm/include/asm/hw_irq.h index a71b417b1856..af79da40af2a 100644 --- a/arch/arm/include/asm/hw_irq.h +++ b/arch/arm/include/asm/hw_irq.h | |||
@@ -8,6 +8,7 @@ static inline void ack_bad_irq(int irq) | |||
8 | { | 8 | { |
9 | extern unsigned long irq_err_count; | 9 | extern unsigned long irq_err_count; |
10 | irq_err_count++; | 10 | irq_err_count++; |
11 | pr_crit("unexpected IRQ trap at vector %02x\n", irq); | ||
11 | } | 12 | } |
12 | 13 | ||
13 | void set_irq_flags(unsigned int irq, unsigned int flags); | 14 | void set_irq_flags(unsigned int irq, unsigned int flags); |
diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h index d428e386c88e..3446f6a1d9fa 100644 --- a/arch/arm/include/asm/mcpm.h +++ b/arch/arm/include/asm/mcpm.h | |||
@@ -219,6 +219,23 @@ void __mcpm_outbound_leave_critical(unsigned int cluster, int state); | |||
219 | bool __mcpm_outbound_enter_critical(unsigned int this_cpu, unsigned int cluster); | 219 | bool __mcpm_outbound_enter_critical(unsigned int this_cpu, unsigned int cluster); |
220 | int __mcpm_cluster_state(unsigned int cluster); | 220 | int __mcpm_cluster_state(unsigned int cluster); |
221 | 221 | ||
222 | /** | ||
223 | * mcpm_sync_init - Initialize the cluster synchronization support | ||
224 | * | ||
225 | * @power_up_setup: platform specific function invoked during very | ||
226 | * early CPU/cluster bringup stage. | ||
227 | * | ||
228 | * This prepares memory used by vlocks and the MCPM state machine used | ||
229 | * across CPUs that may have their caches active or inactive. Must be | ||
230 | * called only after a successful call to mcpm_platform_register(). | ||
231 | * | ||
232 | * The power_up_setup argument is a pointer to assembly code called when | ||
233 | * the MMU and caches are still disabled during boot and no stack space is | ||
234 | * available. The affinity level passed to that code corresponds to the | ||
235 | * resource that needs to be initialized (e.g. 1 for cluster level, 0 for | ||
236 | * CPU level). Proper exclusion mechanisms are already activated at that | ||
237 | * point. | ||
238 | */ | ||
222 | int __init mcpm_sync_init( | 239 | int __init mcpm_sync_init( |
223 | void (*power_up_setup)(unsigned int affinity_level)); | 240 | void (*power_up_setup)(unsigned int affinity_level)); |
224 | 241 | ||
diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h index 209e6504922e..a89b4076cde4 100644 --- a/arch/arm/include/asm/percpu.h +++ b/arch/arm/include/asm/percpu.h | |||
@@ -30,14 +30,14 @@ static inline void set_my_cpu_offset(unsigned long off) | |||
30 | static inline unsigned long __my_cpu_offset(void) | 30 | static inline unsigned long __my_cpu_offset(void) |
31 | { | 31 | { |
32 | unsigned long off; | 32 | unsigned long off; |
33 | register unsigned long *sp asm ("sp"); | ||
34 | 33 | ||
35 | /* | 34 | /* |
36 | * Read TPIDRPRW. | 35 | * Read TPIDRPRW. |
37 | * We want to allow caching the value, so avoid using volatile and | 36 | * We want to allow caching the value, so avoid using volatile and |
38 | * instead use a fake stack read to hazard against barrier(). | 37 | * instead use a fake stack read to hazard against barrier(). |
39 | */ | 38 | */ |
40 | asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : "Q" (*sp)); | 39 | asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) |
40 | : "Q" (*(const unsigned long *)current_stack_pointer)); | ||
41 | 41 | ||
42 | return off; | 42 | return off; |
43 | } | 43 | } |
diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 78a779361682..19cfab526d13 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h | |||
@@ -157,7 +157,15 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) | |||
157 | static inline void | 157 | static inline void |
158 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) | 158 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) |
159 | { | 159 | { |
160 | __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE); | 160 | extern pmdval_t user_pmd_table; |
161 | pmdval_t prot; | ||
162 | |||
163 | if (__LINUX_ARM_ARCH__ >= 6 && !IS_ENABLED(CONFIG_ARM_LPAE)) | ||
164 | prot = user_pmd_table; | ||
165 | else | ||
166 | prot = _PAGE_USER_TABLE; | ||
167 | |||
168 | __pmd_populate(pmdp, page_to_phys(ptep), prot); | ||
161 | } | 169 | } |
162 | #define pmd_pgtable(pmd) pmd_page(pmd) | 170 | #define pmd_pgtable(pmd) pmd_page(pmd) |
163 | 171 | ||
diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h index 5cfba15cb401..5e68278e953e 100644 --- a/arch/arm/include/asm/pgtable-2level-hwdef.h +++ b/arch/arm/include/asm/pgtable-2level-hwdef.h | |||
@@ -20,12 +20,14 @@ | |||
20 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) | 20 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) |
21 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0) | 21 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0) |
22 | #define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0) | 22 | #define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0) |
23 | #define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2) /* v7 */ | ||
23 | #define PMD_BIT4 (_AT(pmdval_t, 1) << 4) | 24 | #define PMD_BIT4 (_AT(pmdval_t, 1) << 4) |
24 | #define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) | 25 | #define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) |
25 | #define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ | 26 | #define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ |
26 | /* | 27 | /* |
27 | * - section | 28 | * - section |
28 | */ | 29 | */ |
30 | #define PMD_SECT_PXN (_AT(pmdval_t, 1) << 0) /* v7 */ | ||
29 | #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) | 31 | #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) |
30 | #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) | 32 | #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) |
31 | #define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */ | 33 | #define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */ |
diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h index 9fd61c72a33a..f8f1cff62065 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h | |||
@@ -76,6 +76,7 @@ | |||
76 | #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ | 76 | #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ |
77 | #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ | 77 | #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ |
78 | #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ | 78 | #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ |
79 | #define PTE_EXT_PXN (_AT(pteval_t, 1) << 53) /* PXN */ | ||
79 | #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */ | 80 | #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */ |
80 | 81 | ||
81 | /* | 82 | /* |
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 3b30062975b2..d5cac545ba33 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -252,17 +252,57 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
252 | set_pte_ext(ptep, pteval, ext); | 252 | set_pte_ext(ptep, pteval, ext); |
253 | } | 253 | } |
254 | 254 | ||
255 | #define PTE_BIT_FUNC(fn,op) \ | 255 | static inline pte_t clear_pte_bit(pte_t pte, pgprot_t prot) |
256 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | 256 | { |
257 | 257 | pte_val(pte) &= ~pgprot_val(prot); | |
258 | PTE_BIT_FUNC(wrprotect, |= L_PTE_RDONLY); | 258 | return pte; |
259 | PTE_BIT_FUNC(mkwrite, &= ~L_PTE_RDONLY); | 259 | } |
260 | PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); | 260 | |
261 | PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); | 261 | static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot) |
262 | PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); | 262 | { |
263 | PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); | 263 | pte_val(pte) |= pgprot_val(prot); |
264 | PTE_BIT_FUNC(mkexec, &= ~L_PTE_XN); | 264 | return pte; |
265 | PTE_BIT_FUNC(mknexec, |= L_PTE_XN); | 265 | } |
266 | |||
267 | static inline pte_t pte_wrprotect(pte_t pte) | ||
268 | { | ||
269 | return set_pte_bit(pte, __pgprot(L_PTE_RDONLY)); | ||
270 | } | ||
271 | |||
272 | static inline pte_t pte_mkwrite(pte_t pte) | ||
273 | { | ||
274 | return clear_pte_bit(pte, __pgprot(L_PTE_RDONLY)); | ||
275 | } | ||
276 | |||
277 | static inline pte_t pte_mkclean(pte_t pte) | ||
278 | { | ||
279 | return clear_pte_bit(pte, __pgprot(L_PTE_DIRTY)); | ||
280 | } | ||
281 | |||
282 | static inline pte_t pte_mkdirty(pte_t pte) | ||
283 | { | ||
284 | return set_pte_bit(pte, __pgprot(L_PTE_DIRTY)); | ||
285 | } | ||
286 | |||
287 | static inline pte_t pte_mkold(pte_t pte) | ||
288 | { | ||
289 | return clear_pte_bit(pte, __pgprot(L_PTE_YOUNG)); | ||
290 | } | ||
291 | |||
292 | static inline pte_t pte_mkyoung(pte_t pte) | ||
293 | { | ||
294 | return set_pte_bit(pte, __pgprot(L_PTE_YOUNG)); | ||
295 | } | ||
296 | |||
297 | static inline pte_t pte_mkexec(pte_t pte) | ||
298 | { | ||
299 | return clear_pte_bit(pte, __pgprot(L_PTE_XN)); | ||
300 | } | ||
301 | |||
302 | static inline pte_t pte_mknexec(pte_t pte) | ||
303 | { | ||
304 | return set_pte_bit(pte, __pgprot(L_PTE_XN)); | ||
305 | } | ||
266 | 306 | ||
267 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 307 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
268 | { | 308 | { |
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 601264d983fa..51622ba7c4a6 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h | |||
@@ -154,9 +154,8 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) | |||
154 | return regs->ARM_sp; | 154 | return regs->ARM_sp; |
155 | } | 155 | } |
156 | 156 | ||
157 | #define current_pt_regs(void) ({ \ | 157 | #define current_pt_regs(void) ({ (struct pt_regs *) \ |
158 | register unsigned long sp asm ("sp"); \ | 158 | ((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1; \ |
159 | (struct pt_regs *)((sp | (THREAD_SIZE - 1)) - 7) - 1; \ | ||
160 | }) | 159 | }) |
161 | 160 | ||
162 | #endif /* __ASSEMBLY__ */ | 161 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index ce73ab635414..d890e41f5520 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h | |||
@@ -90,14 +90,19 @@ struct thread_info { | |||
90 | #define init_stack (init_thread_union.stack) | 90 | #define init_stack (init_thread_union.stack) |
91 | 91 | ||
92 | /* | 92 | /* |
93 | * how to get the current stack pointer in C | ||
94 | */ | ||
95 | register unsigned long current_stack_pointer asm ("sp"); | ||
96 | |||
97 | /* | ||
93 | * how to get the thread information struct from C | 98 | * how to get the thread information struct from C |
94 | */ | 99 | */ |
95 | static inline struct thread_info *current_thread_info(void) __attribute_const__; | 100 | static inline struct thread_info *current_thread_info(void) __attribute_const__; |
96 | 101 | ||
97 | static inline struct thread_info *current_thread_info(void) | 102 | static inline struct thread_info *current_thread_info(void) |
98 | { | 103 | { |
99 | register unsigned long sp asm ("sp"); | 104 | return (struct thread_info *) |
100 | return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); | 105 | (current_stack_pointer & ~(THREAD_SIZE - 1)); |
101 | } | 106 | } |
102 | 107 | ||
103 | #define thread_saved_pc(tsk) \ | 108 | #define thread_saved_pc(tsk) \ |
diff --git a/arch/arm/include/asm/vfp.h b/arch/arm/include/asm/vfp.h index f4ab34fd4f72..ee5f3084243c 100644 --- a/arch/arm/include/asm/vfp.h +++ b/arch/arm/include/asm/vfp.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define FPSID_NODOUBLE (1<<20) | 22 | #define FPSID_NODOUBLE (1<<20) |
23 | #define FPSID_ARCH_BIT (16) | 23 | #define FPSID_ARCH_BIT (16) |
24 | #define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) | 24 | #define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) |
25 | #define FPSID_CPUID_ARCH_MASK (0x7F << FPSID_ARCH_BIT) | ||
25 | #define FPSID_PART_BIT (8) | 26 | #define FPSID_PART_BIT (8) |
26 | #define FPSID_PART_MASK (0xFF << FPSID_PART_BIT) | 27 | #define FPSID_PART_MASK (0xFF << FPSID_PART_BIT) |
27 | #define FPSID_VARIANT_BIT (4) | 28 | #define FPSID_VARIANT_BIT (4) |
@@ -75,6 +76,10 @@ | |||
75 | /* MVFR0 bits */ | 76 | /* MVFR0 bits */ |
76 | #define MVFR0_A_SIMD_BIT (0) | 77 | #define MVFR0_A_SIMD_BIT (0) |
77 | #define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT) | 78 | #define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT) |
79 | #define MVFR0_SP_BIT (4) | ||
80 | #define MVFR0_SP_MASK (0xf << MVFR0_SP_BIT) | ||
81 | #define MVFR0_DP_BIT (8) | ||
82 | #define MVFR0_DP_MASK (0xf << MVFR0_DP_BIT) | ||
78 | 83 | ||
79 | /* Bit patterns for decoding the packaged operation descriptors */ | 84 | /* Bit patterns for decoding the packaged operation descriptors */ |
80 | #define VFPOPDESC_LENGTH_BIT (9) | 85 | #define VFPOPDESC_LENGTH_BIT (9) |
diff --git a/arch/arm/include/asm/xen/page-coherent.h b/arch/arm/include/asm/xen/page-coherent.h index e8275ea88e88..efd562412850 100644 --- a/arch/arm/include/asm/xen/page-coherent.h +++ b/arch/arm/include/asm/xen/page-coherent.h | |||
@@ -5,6 +5,18 @@ | |||
5 | #include <linux/dma-attrs.h> | 5 | #include <linux/dma-attrs.h> |
6 | #include <linux/dma-mapping.h> | 6 | #include <linux/dma-mapping.h> |
7 | 7 | ||
8 | void __xen_dma_map_page(struct device *hwdev, struct page *page, | ||
9 | dma_addr_t dev_addr, unsigned long offset, size_t size, | ||
10 | enum dma_data_direction dir, struct dma_attrs *attrs); | ||
11 | void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, | ||
12 | size_t size, enum dma_data_direction dir, | ||
13 | struct dma_attrs *attrs); | ||
14 | void __xen_dma_sync_single_for_cpu(struct device *hwdev, | ||
15 | dma_addr_t handle, size_t size, enum dma_data_direction dir); | ||
16 | |||
17 | void __xen_dma_sync_single_for_device(struct device *hwdev, | ||
18 | dma_addr_t handle, size_t size, enum dma_data_direction dir); | ||
19 | |||
8 | static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size, | 20 | static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size, |
9 | dma_addr_t *dma_handle, gfp_t flags, | 21 | dma_addr_t *dma_handle, gfp_t flags, |
10 | struct dma_attrs *attrs) | 22 | struct dma_attrs *attrs) |
@@ -20,20 +32,56 @@ static inline void xen_free_coherent_pages(struct device *hwdev, size_t size, | |||
20 | } | 32 | } |
21 | 33 | ||
22 | static inline void xen_dma_map_page(struct device *hwdev, struct page *page, | 34 | static inline void xen_dma_map_page(struct device *hwdev, struct page *page, |
23 | unsigned long offset, size_t size, enum dma_data_direction dir, | 35 | dma_addr_t dev_addr, unsigned long offset, size_t size, |
24 | struct dma_attrs *attrs) | 36 | enum dma_data_direction dir, struct dma_attrs *attrs) |
25 | { | 37 | { |
26 | __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs); | 38 | bool local = PFN_DOWN(dev_addr) == page_to_pfn(page); |
39 | /* Dom0 is mapped 1:1, so if pfn == mfn the page is local otherwise | ||
40 | * is a foreign page grant-mapped in dom0. If the page is local we | ||
41 | * can safely call the native dma_ops function, otherwise we call | ||
42 | * the xen specific function. */ | ||
43 | if (local) | ||
44 | __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs); | ||
45 | else | ||
46 | __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs); | ||
27 | } | 47 | } |
28 | 48 | ||
29 | void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, | 49 | static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, |
30 | size_t size, enum dma_data_direction dir, | 50 | size_t size, enum dma_data_direction dir, |
31 | struct dma_attrs *attrs); | 51 | struct dma_attrs *attrs) |
52 | { | ||
53 | unsigned long pfn = PFN_DOWN(handle); | ||
54 | /* Dom0 is mapped 1:1, so calling pfn_valid on a foreign mfn will | ||
55 | * always return false. If the page is local we can safely call the | ||
56 | * native dma_ops function, otherwise we call the xen specific | ||
57 | * function. */ | ||
58 | if (pfn_valid(pfn)) { | ||
59 | if (__generic_dma_ops(hwdev)->unmap_page) | ||
60 | __generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs); | ||
61 | } else | ||
62 | __xen_dma_unmap_page(hwdev, handle, size, dir, attrs); | ||
63 | } | ||
32 | 64 | ||
33 | void xen_dma_sync_single_for_cpu(struct device *hwdev, | 65 | static inline void xen_dma_sync_single_for_cpu(struct device *hwdev, |
34 | dma_addr_t handle, size_t size, enum dma_data_direction dir); | 66 | dma_addr_t handle, size_t size, enum dma_data_direction dir) |
67 | { | ||
68 | unsigned long pfn = PFN_DOWN(handle); | ||
69 | if (pfn_valid(pfn)) { | ||
70 | if (__generic_dma_ops(hwdev)->sync_single_for_cpu) | ||
71 | __generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir); | ||
72 | } else | ||
73 | __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir); | ||
74 | } | ||
35 | 75 | ||
36 | void xen_dma_sync_single_for_device(struct device *hwdev, | 76 | static inline void xen_dma_sync_single_for_device(struct device *hwdev, |
37 | dma_addr_t handle, size_t size, enum dma_data_direction dir); | 77 | dma_addr_t handle, size_t size, enum dma_data_direction dir) |
78 | { | ||
79 | unsigned long pfn = PFN_DOWN(handle); | ||
80 | if (pfn_valid(pfn)) { | ||
81 | if (__generic_dma_ops(hwdev)->sync_single_for_device) | ||
82 | __generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir); | ||
83 | } else | ||
84 | __xen_dma_sync_single_for_device(hwdev, handle, size, dir); | ||
85 | } | ||
38 | 86 | ||
39 | #endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */ | 87 | #endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */ |
diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h index 135c24a5ba26..68c739b3fdf4 100644 --- a/arch/arm/include/asm/xen/page.h +++ b/arch/arm/include/asm/xen/page.h | |||
@@ -107,4 +107,8 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) | |||
107 | #define xen_remap(cookie, size) ioremap_cache((cookie), (size)) | 107 | #define xen_remap(cookie, size) ioremap_cache((cookie), (size)) |
108 | #define xen_unmap(cookie) iounmap((cookie)) | 108 | #define xen_unmap(cookie) iounmap((cookie)) |
109 | 109 | ||
110 | bool xen_arch_need_swiotlb(struct device *dev, | ||
111 | unsigned long pfn, | ||
112 | unsigned long mfn); | ||
113 | |||
110 | #endif /* _ASM_ARM_XEN_PAGE_H */ | 114 | #endif /* _ASM_ARM_XEN_PAGE_H */ |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 8dcbed5016ac..f290ac892a95 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -47,6 +47,7 @@ endif | |||
47 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o | 47 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o |
48 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o | 48 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o |
49 | obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o | 49 | obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o |
50 | obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o | ||
50 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o | 51 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o |
51 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o | 52 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o |
52 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o | 53 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o |
@@ -67,7 +68,7 @@ test-kprobes-objs += kprobes-test-arm.o | |||
67 | endif | 68 | endif |
68 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o | 69 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o |
69 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o | 70 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o |
70 | obj-$(CONFIG_KGDB) += kgdb.o | 71 | obj-$(CONFIG_KGDB) += kgdb.o patch.o |
71 | obj-$(CONFIG_ARM_UNWIND) += unwind.o | 72 | obj-$(CONFIG_ARM_UNWIND) += unwind.o |
72 | obj-$(CONFIG_HAVE_TCM) += tcm.o | 73 | obj-$(CONFIG_HAVE_TCM) += tcm.o |
73 | obj-$(CONFIG_OF) += devtree.o | 74 | obj-$(CONFIG_OF) += devtree.o |
@@ -84,6 +85,7 @@ obj-$(CONFIG_CPU_PJ4B) += pj4-cp0.o | |||
84 | obj-$(CONFIG_IWMMXT) += iwmmxt.o | 85 | obj-$(CONFIG_IWMMXT) += iwmmxt.o |
85 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o | 86 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o |
86 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_event_cpu.o | 87 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_event_cpu.o |
88 | CFLAGS_pj4-cp0.o := -marm | ||
87 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt | 89 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt |
88 | obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o | 90 | obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o |
89 | 91 | ||
diff --git a/arch/arm/kernel/atags_compat.c b/arch/arm/kernel/atags_compat.c index 5236ad38f417..05c28b12353c 100644 --- a/arch/arm/kernel/atags_compat.c +++ b/arch/arm/kernel/atags_compat.c | |||
@@ -97,8 +97,7 @@ static void __init build_tag_list(struct param_struct *params, void *taglist) | |||
97 | struct tag *tag = taglist; | 97 | struct tag *tag = taglist; |
98 | 98 | ||
99 | if (params->u1.s.page_size != PAGE_SIZE) { | 99 | if (params->u1.s.page_size != PAGE_SIZE) { |
100 | printk(KERN_WARNING "Warning: bad configuration page, " | 100 | pr_warn("Warning: bad configuration page, trying to continue\n"); |
101 | "trying to continue\n"); | ||
102 | return; | 101 | return; |
103 | } | 102 | } |
104 | 103 | ||
@@ -109,8 +108,7 @@ static void __init build_tag_list(struct param_struct *params, void *taglist) | |||
109 | params->u1.s.nr_pages != 0x04000 && | 108 | params->u1.s.nr_pages != 0x04000 && |
110 | params->u1.s.nr_pages != 0x08000 && | 109 | params->u1.s.nr_pages != 0x08000 && |
111 | params->u1.s.nr_pages != 0x10000) { | 110 | params->u1.s.nr_pages != 0x10000) { |
112 | printk(KERN_WARNING "Warning: bad NeTTrom parameters " | 111 | pr_warn("Warning: bad NeTTrom parameters detected, using defaults\n"); |
113 | "detected, using defaults\n"); | ||
114 | 112 | ||
115 | params->u1.s.nr_pages = 0x1000; /* 16MB */ | 113 | params->u1.s.nr_pages = 0x1000; /* 16MB */ |
116 | params->u1.s.ramdisk_size = 0; | 114 | params->u1.s.ramdisk_size = 0; |
diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c index 528f8af2addb..68c6ae0b9e4c 100644 --- a/arch/arm/kernel/atags_parse.c +++ b/arch/arm/kernel/atags_parse.c | |||
@@ -167,8 +167,7 @@ static void __init parse_tags(const struct tag *t) | |||
167 | { | 167 | { |
168 | for (; t->hdr.size; t = tag_next(t)) | 168 | for (; t->hdr.size; t = tag_next(t)) |
169 | if (!parse_tag(t)) | 169 | if (!parse_tag(t)) |
170 | printk(KERN_WARNING | 170 | pr_warn("Ignoring unrecognised tag 0x%08x\n", |
171 | "Ignoring unrecognised tag 0x%08x\n", | ||
172 | t->hdr.tag); | 171 | t->hdr.tag); |
173 | } | 172 | } |
174 | 173 | ||
@@ -193,7 +192,7 @@ setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr) | |||
193 | */ | 192 | */ |
194 | for_each_machine_desc(p) | 193 | for_each_machine_desc(p) |
195 | if (machine_nr == p->nr) { | 194 | if (machine_nr == p->nr) { |
196 | printk("Machine: %s\n", p->name); | 195 | pr_info("Machine: %s\n", p->name); |
197 | mdesc = p; | 196 | mdesc = p; |
198 | break; | 197 | break; |
199 | } | 198 | } |
diff --git a/arch/arm/kernel/atags_proc.c b/arch/arm/kernel/atags_proc.c index c7ff8073416f..5a3379055f55 100644 --- a/arch/arm/kernel/atags_proc.c +++ b/arch/arm/kernel/atags_proc.c | |||
@@ -41,7 +41,7 @@ static int __init init_atags_procfs(void) | |||
41 | size_t size; | 41 | size_t size; |
42 | 42 | ||
43 | if (tag->hdr.tag != ATAG_CORE) { | 43 | if (tag->hdr.tag != ATAG_CORE) { |
44 | printk(KERN_INFO "No ATAGs?"); | 44 | pr_info("No ATAGs?"); |
45 | return -EINVAL; | 45 | return -EINVAL; |
46 | } | 46 | } |
47 | 47 | ||
@@ -68,7 +68,7 @@ static int __init init_atags_procfs(void) | |||
68 | 68 | ||
69 | nomem: | 69 | nomem: |
70 | kfree(b); | 70 | kfree(b); |
71 | printk(KERN_ERR "Exporting ATAGs: not enough memory\n"); | 71 | pr_err("Exporting ATAGs: not enough memory\n"); |
72 | 72 | ||
73 | return -ENOMEM; | 73 | return -ENOMEM; |
74 | } | 74 | } |
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index daaff73bc776..a4effd6d8f2f 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c | |||
@@ -364,7 +364,7 @@ void pcibios_fixup_bus(struct pci_bus *bus) | |||
364 | /* | 364 | /* |
365 | * Report what we did for this bus | 365 | * Report what we did for this bus |
366 | */ | 366 | */ |
367 | printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n", | 367 | pr_info("PCI: bus%d: Fast back to back transfers %sabled\n", |
368 | bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); | 368 | bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); |
369 | } | 369 | } |
370 | EXPORT_SYMBOL(pcibios_fixup_bus); | 370 | EXPORT_SYMBOL(pcibios_fixup_bus); |
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c index 360bb6d701f5..84363fe7bad2 100644 --- a/arch/arm/kernel/dma-isa.c +++ b/arch/arm/kernel/dma-isa.c | |||
@@ -213,8 +213,8 @@ void __init isa_init_dma(void) | |||
213 | for (chan = 0; chan < 8; chan++) { | 213 | for (chan = 0; chan < 8; chan++) { |
214 | int ret = isa_dma_add(chan, &isa_dma[chan]); | 214 | int ret = isa_dma_add(chan, &isa_dma[chan]); |
215 | if (ret) | 215 | if (ret) |
216 | printk(KERN_ERR "ISADMA%u: unable to register: %d\n", | 216 | pr_err("ISADMA%u: unable to register: %d\n", |
217 | chan, ret); | 217 | chan, ret); |
218 | } | 218 | } |
219 | 219 | ||
220 | request_dma(DMA_ISA_CASCADE, "cascade"); | 220 | request_dma(DMA_ISA_CASCADE, "cascade"); |
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index 7b829d9663b1..e651c4d0a0d9 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c | |||
@@ -79,7 +79,7 @@ int request_dma(unsigned int chan, const char *device_id) | |||
79 | return ret; | 79 | return ret; |
80 | 80 | ||
81 | bad_dma: | 81 | bad_dma: |
82 | printk(KERN_ERR "dma: trying to allocate DMA%d\n", chan); | 82 | pr_err("dma: trying to allocate DMA%d\n", chan); |
83 | return -EINVAL; | 83 | return -EINVAL; |
84 | 84 | ||
85 | busy: | 85 | busy: |
@@ -100,7 +100,7 @@ void free_dma(unsigned int chan) | |||
100 | goto bad_dma; | 100 | goto bad_dma; |
101 | 101 | ||
102 | if (dma->active) { | 102 | if (dma->active) { |
103 | printk(KERN_ERR "dma%d: freeing active DMA\n", chan); | 103 | pr_err("dma%d: freeing active DMA\n", chan); |
104 | dma->d_ops->disable(chan, dma); | 104 | dma->d_ops->disable(chan, dma); |
105 | dma->active = 0; | 105 | dma->active = 0; |
106 | } | 106 | } |
@@ -111,11 +111,11 @@ void free_dma(unsigned int chan) | |||
111 | return; | 111 | return; |
112 | } | 112 | } |
113 | 113 | ||
114 | printk(KERN_ERR "dma%d: trying to free free DMA\n", chan); | 114 | pr_err("dma%d: trying to free free DMA\n", chan); |
115 | return; | 115 | return; |
116 | 116 | ||
117 | bad_dma: | 117 | bad_dma: |
118 | printk(KERN_ERR "dma: trying to free DMA%d\n", chan); | 118 | pr_err("dma: trying to free DMA%d\n", chan); |
119 | } | 119 | } |
120 | EXPORT_SYMBOL(free_dma); | 120 | EXPORT_SYMBOL(free_dma); |
121 | 121 | ||
@@ -126,8 +126,7 @@ void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg) | |||
126 | dma_t *dma = dma_channel(chan); | 126 | dma_t *dma = dma_channel(chan); |
127 | 127 | ||
128 | if (dma->active) | 128 | if (dma->active) |
129 | printk(KERN_ERR "dma%d: altering DMA SG while " | 129 | pr_err("dma%d: altering DMA SG while DMA active\n", chan); |
130 | "DMA active\n", chan); | ||
131 | 130 | ||
132 | dma->sg = sg; | 131 | dma->sg = sg; |
133 | dma->sgcount = nr_sg; | 132 | dma->sgcount = nr_sg; |
@@ -144,8 +143,7 @@ void __set_dma_addr (unsigned int chan, void *addr) | |||
144 | dma_t *dma = dma_channel(chan); | 143 | dma_t *dma = dma_channel(chan); |
145 | 144 | ||
146 | if (dma->active) | 145 | if (dma->active) |
147 | printk(KERN_ERR "dma%d: altering DMA address while " | 146 | pr_err("dma%d: altering DMA address while DMA active\n", chan); |
148 | "DMA active\n", chan); | ||
149 | 147 | ||
150 | dma->sg = NULL; | 148 | dma->sg = NULL; |
151 | dma->addr = addr; | 149 | dma->addr = addr; |
@@ -162,8 +160,7 @@ void set_dma_count (unsigned int chan, unsigned long count) | |||
162 | dma_t *dma = dma_channel(chan); | 160 | dma_t *dma = dma_channel(chan); |
163 | 161 | ||
164 | if (dma->active) | 162 | if (dma->active) |
165 | printk(KERN_ERR "dma%d: altering DMA count while " | 163 | pr_err("dma%d: altering DMA count while DMA active\n", chan); |
166 | "DMA active\n", chan); | ||
167 | 164 | ||
168 | dma->sg = NULL; | 165 | dma->sg = NULL; |
169 | dma->count = count; | 166 | dma->count = count; |
@@ -178,8 +175,7 @@ void set_dma_mode (unsigned int chan, unsigned int mode) | |||
178 | dma_t *dma = dma_channel(chan); | 175 | dma_t *dma = dma_channel(chan); |
179 | 176 | ||
180 | if (dma->active) | 177 | if (dma->active) |
181 | printk(KERN_ERR "dma%d: altering DMA mode while " | 178 | pr_err("dma%d: altering DMA mode while DMA active\n", chan); |
182 | "DMA active\n", chan); | ||
183 | 179 | ||
184 | dma->dma_mode = mode; | 180 | dma->dma_mode = mode; |
185 | dma->invalid = 1; | 181 | dma->invalid = 1; |
@@ -202,7 +198,7 @@ void enable_dma (unsigned int chan) | |||
202 | return; | 198 | return; |
203 | 199 | ||
204 | free_dma: | 200 | free_dma: |
205 | printk(KERN_ERR "dma%d: trying to enable free DMA\n", chan); | 201 | pr_err("dma%d: trying to enable free DMA\n", chan); |
206 | BUG(); | 202 | BUG(); |
207 | } | 203 | } |
208 | EXPORT_SYMBOL(enable_dma); | 204 | EXPORT_SYMBOL(enable_dma); |
@@ -223,7 +219,7 @@ void disable_dma (unsigned int chan) | |||
223 | return; | 219 | return; |
224 | 220 | ||
225 | free_dma: | 221 | free_dma: |
226 | printk(KERN_ERR "dma%d: trying to disable free DMA\n", chan); | 222 | pr_err("dma%d: trying to disable free DMA\n", chan); |
227 | BUG(); | 223 | BUG(); |
228 | } | 224 | } |
229 | EXPORT_SYMBOL(disable_dma); | 225 | EXPORT_SYMBOL(disable_dma); |
@@ -240,7 +236,7 @@ EXPORT_SYMBOL(dma_channel_active); | |||
240 | 236 | ||
241 | void set_dma_page(unsigned int chan, char pagenr) | 237 | void set_dma_page(unsigned int chan, char pagenr) |
242 | { | 238 | { |
243 | printk(KERN_ERR "dma%d: trying to set_dma_page\n", chan); | 239 | pr_err("dma%d: trying to set_dma_page\n", chan); |
244 | } | 240 | } |
245 | EXPORT_SYMBOL(set_dma_page); | 241 | EXPORT_SYMBOL(set_dma_page); |
246 | 242 | ||
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 6bb09d4abdea..f8ccc21fa032 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -109,241 +109,6 @@ ENDPROC(ret_from_fork) | |||
109 | #undef CALL | 109 | #undef CALL |
110 | #define CALL(x) .long x | 110 | #define CALL(x) .long x |
111 | 111 | ||
112 | #ifdef CONFIG_FUNCTION_TRACER | ||
113 | /* | ||
114 | * When compiling with -pg, gcc inserts a call to the mcount routine at the | ||
115 | * start of every function. In mcount, apart from the function's address (in | ||
116 | * lr), we need to get hold of the function's caller's address. | ||
117 | * | ||
118 | * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: | ||
119 | * | ||
120 | * bl mcount | ||
121 | * | ||
122 | * These versions have the limitation that in order for the mcount routine to | ||
123 | * be able to determine the function's caller's address, an APCS-style frame | ||
124 | * pointer (which is set up with something like the code below) is required. | ||
125 | * | ||
126 | * mov ip, sp | ||
127 | * push {fp, ip, lr, pc} | ||
128 | * sub fp, ip, #4 | ||
129 | * | ||
130 | * With EABI, these frame pointers are not available unless -mapcs-frame is | ||
131 | * specified, and if building as Thumb-2, not even then. | ||
132 | * | ||
133 | * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, | ||
134 | * with call sites like: | ||
135 | * | ||
136 | * push {lr} | ||
137 | * bl __gnu_mcount_nc | ||
138 | * | ||
139 | * With these compilers, frame pointers are not necessary. | ||
140 | * | ||
141 | * mcount can be thought of as a function called in the middle of a subroutine | ||
142 | * call. As such, it needs to be transparent for both the caller and the | ||
143 | * callee: the original lr needs to be restored when leaving mcount, and no | ||
144 | * registers should be clobbered. (In the __gnu_mcount_nc implementation, we | ||
145 | * clobber the ip register. This is OK because the ARM calling convention | ||
146 | * allows it to be clobbered in subroutines and doesn't use it to hold | ||
147 | * parameters.) | ||
148 | * | ||
149 | * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" | ||
150 | * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see | ||
151 | * arch/arm/kernel/ftrace.c). | ||
152 | */ | ||
153 | |||
154 | #ifndef CONFIG_OLD_MCOUNT | ||
155 | #if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) | ||
156 | #error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. | ||
157 | #endif | ||
158 | #endif | ||
159 | |||
160 | .macro mcount_adjust_addr rd, rn | ||
161 | bic \rd, \rn, #1 @ clear the Thumb bit if present | ||
162 | sub \rd, \rd, #MCOUNT_INSN_SIZE | ||
163 | .endm | ||
164 | |||
165 | .macro __mcount suffix | ||
166 | mcount_enter | ||
167 | ldr r0, =ftrace_trace_function | ||
168 | ldr r2, [r0] | ||
169 | adr r0, .Lftrace_stub | ||
170 | cmp r0, r2 | ||
171 | bne 1f | ||
172 | |||
173 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
174 | ldr r1, =ftrace_graph_return | ||
175 | ldr r2, [r1] | ||
176 | cmp r0, r2 | ||
177 | bne ftrace_graph_caller\suffix | ||
178 | |||
179 | ldr r1, =ftrace_graph_entry | ||
180 | ldr r2, [r1] | ||
181 | ldr r0, =ftrace_graph_entry_stub | ||
182 | cmp r0, r2 | ||
183 | bne ftrace_graph_caller\suffix | ||
184 | #endif | ||
185 | |||
186 | mcount_exit | ||
187 | |||
188 | 1: mcount_get_lr r1 @ lr of instrumented func | ||
189 | mcount_adjust_addr r0, lr @ instrumented function | ||
190 | adr lr, BSYM(2f) | ||
191 | mov pc, r2 | ||
192 | 2: mcount_exit | ||
193 | .endm | ||
194 | |||
195 | .macro __ftrace_caller suffix | ||
196 | mcount_enter | ||
197 | |||
198 | mcount_get_lr r1 @ lr of instrumented func | ||
199 | mcount_adjust_addr r0, lr @ instrumented function | ||
200 | |||
201 | .globl ftrace_call\suffix | ||
202 | ftrace_call\suffix: | ||
203 | bl ftrace_stub | ||
204 | |||
205 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
206 | .globl ftrace_graph_call\suffix | ||
207 | ftrace_graph_call\suffix: | ||
208 | mov r0, r0 | ||
209 | #endif | ||
210 | |||
211 | mcount_exit | ||
212 | .endm | ||
213 | |||
214 | .macro __ftrace_graph_caller | ||
215 | sub r0, fp, #4 @ &lr of instrumented routine (&parent) | ||
216 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
217 | @ called from __ftrace_caller, saved in mcount_enter | ||
218 | ldr r1, [sp, #16] @ instrumented routine (func) | ||
219 | mcount_adjust_addr r1, r1 | ||
220 | #else | ||
221 | @ called from __mcount, untouched in lr | ||
222 | mcount_adjust_addr r1, lr @ instrumented routine (func) | ||
223 | #endif | ||
224 | mov r2, fp @ frame pointer | ||
225 | bl prepare_ftrace_return | ||
226 | mcount_exit | ||
227 | .endm | ||
228 | |||
229 | #ifdef CONFIG_OLD_MCOUNT | ||
230 | /* | ||
231 | * mcount | ||
232 | */ | ||
233 | |||
234 | .macro mcount_enter | ||
235 | stmdb sp!, {r0-r3, lr} | ||
236 | .endm | ||
237 | |||
238 | .macro mcount_get_lr reg | ||
239 | ldr \reg, [fp, #-4] | ||
240 | .endm | ||
241 | |||
242 | .macro mcount_exit | ||
243 | ldr lr, [fp, #-4] | ||
244 | ldmia sp!, {r0-r3, pc} | ||
245 | .endm | ||
246 | |||
247 | ENTRY(mcount) | ||
248 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
249 | stmdb sp!, {lr} | ||
250 | ldr lr, [fp, #-4] | ||
251 | ldmia sp!, {pc} | ||
252 | #else | ||
253 | __mcount _old | ||
254 | #endif | ||
255 | ENDPROC(mcount) | ||
256 | |||
257 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
258 | ENTRY(ftrace_caller_old) | ||
259 | __ftrace_caller _old | ||
260 | ENDPROC(ftrace_caller_old) | ||
261 | #endif | ||
262 | |||
263 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
264 | ENTRY(ftrace_graph_caller_old) | ||
265 | __ftrace_graph_caller | ||
266 | ENDPROC(ftrace_graph_caller_old) | ||
267 | #endif | ||
268 | |||
269 | .purgem mcount_enter | ||
270 | .purgem mcount_get_lr | ||
271 | .purgem mcount_exit | ||
272 | #endif | ||
273 | |||
274 | /* | ||
275 | * __gnu_mcount_nc | ||
276 | */ | ||
277 | |||
278 | .macro mcount_enter | ||
279 | /* | ||
280 | * This pad compensates for the push {lr} at the call site. Note that we are | ||
281 | * unable to unwind through a function which does not otherwise save its lr. | ||
282 | */ | ||
283 | UNWIND(.pad #4) | ||
284 | stmdb sp!, {r0-r3, lr} | ||
285 | UNWIND(.save {r0-r3, lr}) | ||
286 | .endm | ||
287 | |||
288 | .macro mcount_get_lr reg | ||
289 | ldr \reg, [sp, #20] | ||
290 | .endm | ||
291 | |||
292 | .macro mcount_exit | ||
293 | ldmia sp!, {r0-r3, ip, lr} | ||
294 | ret ip | ||
295 | .endm | ||
296 | |||
297 | ENTRY(__gnu_mcount_nc) | ||
298 | UNWIND(.fnstart) | ||
299 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
300 | mov ip, lr | ||
301 | ldmia sp!, {lr} | ||
302 | ret ip | ||
303 | #else | ||
304 | __mcount | ||
305 | #endif | ||
306 | UNWIND(.fnend) | ||
307 | ENDPROC(__gnu_mcount_nc) | ||
308 | |||
309 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
310 | ENTRY(ftrace_caller) | ||
311 | UNWIND(.fnstart) | ||
312 | __ftrace_caller | ||
313 | UNWIND(.fnend) | ||
314 | ENDPROC(ftrace_caller) | ||
315 | #endif | ||
316 | |||
317 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
318 | ENTRY(ftrace_graph_caller) | ||
319 | UNWIND(.fnstart) | ||
320 | __ftrace_graph_caller | ||
321 | UNWIND(.fnend) | ||
322 | ENDPROC(ftrace_graph_caller) | ||
323 | #endif | ||
324 | |||
325 | .purgem mcount_enter | ||
326 | .purgem mcount_get_lr | ||
327 | .purgem mcount_exit | ||
328 | |||
329 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
330 | .globl return_to_handler | ||
331 | return_to_handler: | ||
332 | stmdb sp!, {r0-r3} | ||
333 | mov r0, fp @ frame pointer | ||
334 | bl ftrace_return_to_handler | ||
335 | mov lr, r0 @ r0 has real ret addr | ||
336 | ldmia sp!, {r0-r3} | ||
337 | ret lr | ||
338 | #endif | ||
339 | |||
340 | ENTRY(ftrace_stub) | ||
341 | .Lftrace_stub: | ||
342 | ret lr | ||
343 | ENDPROC(ftrace_stub) | ||
344 | |||
345 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
346 | |||
347 | /*============================================================================= | 112 | /*============================================================================= |
348 | * SWI handler | 113 | * SWI handler |
349 | *----------------------------------------------------------------------------- | 114 | *----------------------------------------------------------------------------- |
diff --git a/arch/arm/kernel/entry-ftrace.S b/arch/arm/kernel/entry-ftrace.S new file mode 100644 index 000000000000..fe57c73e70a4 --- /dev/null +++ b/arch/arm/kernel/entry-ftrace.S | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License version 2 as | ||
4 | * published by the Free Software Foundation. | ||
5 | */ | ||
6 | |||
7 | #include <asm/assembler.h> | ||
8 | #include <asm/ftrace.h> | ||
9 | #include <asm/unwind.h> | ||
10 | |||
11 | #include "entry-header.S" | ||
12 | |||
13 | /* | ||
14 | * When compiling with -pg, gcc inserts a call to the mcount routine at the | ||
15 | * start of every function. In mcount, apart from the function's address (in | ||
16 | * lr), we need to get hold of the function's caller's address. | ||
17 | * | ||
18 | * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: | ||
19 | * | ||
20 | * bl mcount | ||
21 | * | ||
22 | * These versions have the limitation that in order for the mcount routine to | ||
23 | * be able to determine the function's caller's address, an APCS-style frame | ||
24 | * pointer (which is set up with something like the code below) is required. | ||
25 | * | ||
26 | * mov ip, sp | ||
27 | * push {fp, ip, lr, pc} | ||
28 | * sub fp, ip, #4 | ||
29 | * | ||
30 | * With EABI, these frame pointers are not available unless -mapcs-frame is | ||
31 | * specified, and if building as Thumb-2, not even then. | ||
32 | * | ||
33 | * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, | ||
34 | * with call sites like: | ||
35 | * | ||
36 | * push {lr} | ||
37 | * bl __gnu_mcount_nc | ||
38 | * | ||
39 | * With these compilers, frame pointers are not necessary. | ||
40 | * | ||
41 | * mcount can be thought of as a function called in the middle of a subroutine | ||
42 | * call. As such, it needs to be transparent for both the caller and the | ||
43 | * callee: the original lr needs to be restored when leaving mcount, and no | ||
44 | * registers should be clobbered. (In the __gnu_mcount_nc implementation, we | ||
45 | * clobber the ip register. This is OK because the ARM calling convention | ||
46 | * allows it to be clobbered in subroutines and doesn't use it to hold | ||
47 | * parameters.) | ||
48 | * | ||
49 | * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" | ||
50 | * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see | ||
51 | * arch/arm/kernel/ftrace.c). | ||
52 | */ | ||
53 | |||
54 | #ifndef CONFIG_OLD_MCOUNT | ||
55 | #if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) | ||
56 | #error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. | ||
57 | #endif | ||
58 | #endif | ||
59 | |||
60 | .macro mcount_adjust_addr rd, rn | ||
61 | bic \rd, \rn, #1 @ clear the Thumb bit if present | ||
62 | sub \rd, \rd, #MCOUNT_INSN_SIZE | ||
63 | .endm | ||
64 | |||
65 | .macro __mcount suffix | ||
66 | mcount_enter | ||
67 | ldr r0, =ftrace_trace_function | ||
68 | ldr r2, [r0] | ||
69 | adr r0, .Lftrace_stub | ||
70 | cmp r0, r2 | ||
71 | bne 1f | ||
72 | |||
73 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
74 | ldr r1, =ftrace_graph_return | ||
75 | ldr r2, [r1] | ||
76 | cmp r0, r2 | ||
77 | bne ftrace_graph_caller\suffix | ||
78 | |||
79 | ldr r1, =ftrace_graph_entry | ||
80 | ldr r2, [r1] | ||
81 | ldr r0, =ftrace_graph_entry_stub | ||
82 | cmp r0, r2 | ||
83 | bne ftrace_graph_caller\suffix | ||
84 | #endif | ||
85 | |||
86 | mcount_exit | ||
87 | |||
88 | 1: mcount_get_lr r1 @ lr of instrumented func | ||
89 | mcount_adjust_addr r0, lr @ instrumented function | ||
90 | adr lr, BSYM(2f) | ||
91 | mov pc, r2 | ||
92 | 2: mcount_exit | ||
93 | .endm | ||
94 | |||
95 | .macro __ftrace_caller suffix | ||
96 | mcount_enter | ||
97 | |||
98 | mcount_get_lr r1 @ lr of instrumented func | ||
99 | mcount_adjust_addr r0, lr @ instrumented function | ||
100 | |||
101 | .globl ftrace_call\suffix | ||
102 | ftrace_call\suffix: | ||
103 | bl ftrace_stub | ||
104 | |||
105 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
106 | .globl ftrace_graph_call\suffix | ||
107 | ftrace_graph_call\suffix: | ||
108 | mov r0, r0 | ||
109 | #endif | ||
110 | |||
111 | mcount_exit | ||
112 | .endm | ||
113 | |||
114 | .macro __ftrace_graph_caller | ||
115 | sub r0, fp, #4 @ &lr of instrumented routine (&parent) | ||
116 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
117 | @ called from __ftrace_caller, saved in mcount_enter | ||
118 | ldr r1, [sp, #16] @ instrumented routine (func) | ||
119 | mcount_adjust_addr r1, r1 | ||
120 | #else | ||
121 | @ called from __mcount, untouched in lr | ||
122 | mcount_adjust_addr r1, lr @ instrumented routine (func) | ||
123 | #endif | ||
124 | mov r2, fp @ frame pointer | ||
125 | bl prepare_ftrace_return | ||
126 | mcount_exit | ||
127 | .endm | ||
128 | |||
129 | #ifdef CONFIG_OLD_MCOUNT | ||
130 | /* | ||
131 | * mcount | ||
132 | */ | ||
133 | |||
134 | .macro mcount_enter | ||
135 | stmdb sp!, {r0-r3, lr} | ||
136 | .endm | ||
137 | |||
138 | .macro mcount_get_lr reg | ||
139 | ldr \reg, [fp, #-4] | ||
140 | .endm | ||
141 | |||
142 | .macro mcount_exit | ||
143 | ldr lr, [fp, #-4] | ||
144 | ldmia sp!, {r0-r3, pc} | ||
145 | .endm | ||
146 | |||
147 | ENTRY(mcount) | ||
148 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
149 | stmdb sp!, {lr} | ||
150 | ldr lr, [fp, #-4] | ||
151 | ldmia sp!, {pc} | ||
152 | #else | ||
153 | __mcount _old | ||
154 | #endif | ||
155 | ENDPROC(mcount) | ||
156 | |||
157 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
158 | ENTRY(ftrace_caller_old) | ||
159 | __ftrace_caller _old | ||
160 | ENDPROC(ftrace_caller_old) | ||
161 | #endif | ||
162 | |||
163 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
164 | ENTRY(ftrace_graph_caller_old) | ||
165 | __ftrace_graph_caller | ||
166 | ENDPROC(ftrace_graph_caller_old) | ||
167 | #endif | ||
168 | |||
169 | .purgem mcount_enter | ||
170 | .purgem mcount_get_lr | ||
171 | .purgem mcount_exit | ||
172 | #endif | ||
173 | |||
174 | /* | ||
175 | * __gnu_mcount_nc | ||
176 | */ | ||
177 | |||
178 | .macro mcount_enter | ||
179 | /* | ||
180 | * This pad compensates for the push {lr} at the call site. Note that we are | ||
181 | * unable to unwind through a function which does not otherwise save its lr. | ||
182 | */ | ||
183 | UNWIND(.pad #4) | ||
184 | stmdb sp!, {r0-r3, lr} | ||
185 | UNWIND(.save {r0-r3, lr}) | ||
186 | .endm | ||
187 | |||
188 | .macro mcount_get_lr reg | ||
189 | ldr \reg, [sp, #20] | ||
190 | .endm | ||
191 | |||
192 | .macro mcount_exit | ||
193 | ldmia sp!, {r0-r3, ip, lr} | ||
194 | ret ip | ||
195 | .endm | ||
196 | |||
197 | ENTRY(__gnu_mcount_nc) | ||
198 | UNWIND(.fnstart) | ||
199 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
200 | mov ip, lr | ||
201 | ldmia sp!, {lr} | ||
202 | ret ip | ||
203 | #else | ||
204 | __mcount | ||
205 | #endif | ||
206 | UNWIND(.fnend) | ||
207 | ENDPROC(__gnu_mcount_nc) | ||
208 | |||
209 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
210 | ENTRY(ftrace_caller) | ||
211 | UNWIND(.fnstart) | ||
212 | __ftrace_caller | ||
213 | UNWIND(.fnend) | ||
214 | ENDPROC(ftrace_caller) | ||
215 | #endif | ||
216 | |||
217 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
218 | ENTRY(ftrace_graph_caller) | ||
219 | UNWIND(.fnstart) | ||
220 | __ftrace_graph_caller | ||
221 | UNWIND(.fnend) | ||
222 | ENDPROC(ftrace_graph_caller) | ||
223 | #endif | ||
224 | |||
225 | .purgem mcount_enter | ||
226 | .purgem mcount_get_lr | ||
227 | .purgem mcount_exit | ||
228 | |||
229 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
230 | .globl return_to_handler | ||
231 | return_to_handler: | ||
232 | stmdb sp!, {r0-r3} | ||
233 | mov r0, fp @ frame pointer | ||
234 | bl ftrace_return_to_handler | ||
235 | mov lr, r0 @ r0 has real ret addr | ||
236 | ldmia sp!, {r0-r3} | ||
237 | ret lr | ||
238 | #endif | ||
239 | |||
240 | ENTRY(ftrace_stub) | ||
241 | .Lftrace_stub: | ||
242 | ret lr | ||
243 | ENDPROC(ftrace_stub) | ||
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 131a6ab5f355..8b96972dcb1d 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c | |||
@@ -213,7 +213,7 @@ static void etm_dump(void) | |||
213 | int length; | 213 | int length; |
214 | 214 | ||
215 | if (!t->etb_regs) { | 215 | if (!t->etb_regs) { |
216 | printk(KERN_INFO "No tracing hardware found\n"); | 216 | pr_info("No tracing hardware found\n"); |
217 | return; | 217 | return; |
218 | } | 218 | } |
219 | 219 | ||
@@ -229,11 +229,11 @@ static void etm_dump(void) | |||
229 | 229 | ||
230 | etb_writel(t, first, ETBR_READADDR); | 230 | etb_writel(t, first, ETBR_READADDR); |
231 | 231 | ||
232 | printk(KERN_INFO "Trace buffer contents length: %d\n", length); | 232 | pr_info("Trace buffer contents length: %d\n", length); |
233 | printk(KERN_INFO "--- ETB buffer begin ---\n"); | 233 | pr_info("--- ETB buffer begin ---\n"); |
234 | for (; length; length--) | 234 | for (; length; length--) |
235 | printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM))); | 235 | printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM))); |
236 | printk(KERN_INFO "\n--- ETB buffer end ---\n"); | 236 | pr_info("\n--- ETB buffer end ---\n"); |
237 | 237 | ||
238 | /* deassert the overflow bit */ | 238 | /* deassert the overflow bit */ |
239 | etb_writel(t, 1, ETBR_CTRL); | 239 | etb_writel(t, 1, ETBR_CTRL); |
@@ -633,14 +633,14 @@ static int __init etm_init(void) | |||
633 | 633 | ||
634 | retval = amba_driver_register(&etb_driver); | 634 | retval = amba_driver_register(&etb_driver); |
635 | if (retval) { | 635 | if (retval) { |
636 | printk(KERN_ERR "Failed to register etb\n"); | 636 | pr_err("Failed to register etb\n"); |
637 | return retval; | 637 | return retval; |
638 | } | 638 | } |
639 | 639 | ||
640 | retval = amba_driver_register(&etm_driver); | 640 | retval = amba_driver_register(&etm_driver); |
641 | if (retval) { | 641 | if (retval) { |
642 | amba_driver_unregister(&etb_driver); | 642 | amba_driver_unregister(&etb_driver); |
643 | printk(KERN_ERR "Failed to probe etm\n"); | 643 | pr_err("Failed to probe etm\n"); |
644 | return retval; | 644 | return retval; |
645 | } | 645 | } |
646 | 646 | ||
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index b37752a96652..059c3da0fee3 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c | |||
@@ -124,7 +124,7 @@ int claim_fiq(struct fiq_handler *f) | |||
124 | void release_fiq(struct fiq_handler *f) | 124 | void release_fiq(struct fiq_handler *f) |
125 | { | 125 | { |
126 | if (current_fiq != f) { | 126 | if (current_fiq != f) { |
127 | printk(KERN_ERR "%s FIQ trying to release %s FIQ\n", | 127 | pr_err("%s FIQ trying to release %s FIQ\n", |
128 | f->name, current_fiq->name); | 128 | f->name, current_fiq->name); |
129 | dump_stack(); | 129 | dump_stack(); |
130 | return; | 130 | return; |
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index af9a8a927a4e..b8c75e45a950 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/ftrace.h> | 15 | #include <linux/ftrace.h> |
16 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/stop_machine.h> | ||
18 | 19 | ||
19 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
20 | #include <asm/opcodes.h> | 21 | #include <asm/opcodes.h> |
@@ -35,6 +36,22 @@ | |||
35 | 36 | ||
36 | #define OLD_NOP 0xe1a00000 /* mov r0, r0 */ | 37 | #define OLD_NOP 0xe1a00000 /* mov r0, r0 */ |
37 | 38 | ||
39 | static int __ftrace_modify_code(void *data) | ||
40 | { | ||
41 | int *command = data; | ||
42 | |||
43 | set_kernel_text_rw(); | ||
44 | ftrace_modify_all_code(*command); | ||
45 | set_kernel_text_ro(); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | void arch_ftrace_update_code(int command) | ||
51 | { | ||
52 | stop_machine(__ftrace_modify_code, &command, NULL); | ||
53 | } | ||
54 | |||
38 | static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) | 55 | static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) |
39 | { | 56 | { |
40 | return rec->arch.old_mcount ? OLD_NOP : NOP; | 57 | return rec->arch.old_mcount ? OLD_NOP : NOP; |
@@ -73,6 +90,8 @@ int ftrace_arch_code_modify_prepare(void) | |||
73 | int ftrace_arch_code_modify_post_process(void) | 90 | int ftrace_arch_code_modify_post_process(void) |
74 | { | 91 | { |
75 | set_all_modules_text_ro(); | 92 | set_all_modules_text_ro(); |
93 | /* Make sure any TLB misses during machine stop are cleared. */ | ||
94 | flush_tlb_all(); | ||
76 | return 0; | 95 | return 0; |
77 | } | 96 | } |
78 | 97 | ||
diff --git a/arch/arm/kernel/io.c b/arch/arm/kernel/io.c index 9203cf883330..eedefe050022 100644 --- a/arch/arm/kernel/io.c +++ b/arch/arm/kernel/io.c | |||
@@ -51,6 +51,7 @@ void _memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) | |||
51 | from++; | 51 | from++; |
52 | } | 52 | } |
53 | } | 53 | } |
54 | EXPORT_SYMBOL(_memcpy_fromio); | ||
54 | 55 | ||
55 | /* | 56 | /* |
56 | * Copy data from "real" memory space to IO memory space. | 57 | * Copy data from "real" memory space to IO memory space. |
@@ -66,6 +67,7 @@ void _memcpy_toio(volatile void __iomem *to, const void *from, size_t count) | |||
66 | to++; | 67 | to++; |
67 | } | 68 | } |
68 | } | 69 | } |
70 | EXPORT_SYMBOL(_memcpy_toio); | ||
69 | 71 | ||
70 | /* | 72 | /* |
71 | * "memset" on IO memory space. | 73 | * "memset" on IO memory space. |
@@ -79,7 +81,4 @@ void _memset_io(volatile void __iomem *dst, int c, size_t count) | |||
79 | dst++; | 81 | dst++; |
80 | } | 82 | } |
81 | } | 83 | } |
82 | |||
83 | EXPORT_SYMBOL(_memcpy_fromio); | ||
84 | EXPORT_SYMBOL(_memcpy_toio); | ||
85 | EXPORT_SYMBOL(_memset_io); | 84 | EXPORT_SYMBOL(_memset_io); |
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 7c81ec428b9b..ad857bada96c 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/smp.h> | 31 | #include <linux/smp.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
34 | #include <linux/ratelimit.h> | ||
34 | #include <linux/errno.h> | 35 | #include <linux/errno.h> |
35 | #include <linux/list.h> | 36 | #include <linux/list.h> |
36 | #include <linux/kallsyms.h> | 37 | #include <linux/kallsyms.h> |
@@ -82,7 +83,7 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) | |||
82 | unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; | 83 | unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; |
83 | 84 | ||
84 | if (irq >= nr_irqs) { | 85 | if (irq >= nr_irqs) { |
85 | printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq); | 86 | pr_err("Trying to set irq flags for IRQ%d\n", irq); |
86 | return; | 87 | return; |
87 | } | 88 | } |
88 | 89 | ||
@@ -135,7 +136,6 @@ int __init arch_probe_nr_irqs(void) | |||
135 | #endif | 136 | #endif |
136 | 137 | ||
137 | #ifdef CONFIG_HOTPLUG_CPU | 138 | #ifdef CONFIG_HOTPLUG_CPU |
138 | |||
139 | static bool migrate_one_irq(struct irq_desc *desc) | 139 | static bool migrate_one_irq(struct irq_desc *desc) |
140 | { | 140 | { |
141 | struct irq_data *d = irq_desc_get_irq_data(desc); | 141 | struct irq_data *d = irq_desc_get_irq_data(desc); |
@@ -187,8 +187,8 @@ void migrate_irqs(void) | |||
187 | affinity_broken = migrate_one_irq(desc); | 187 | affinity_broken = migrate_one_irq(desc); |
188 | raw_spin_unlock(&desc->lock); | 188 | raw_spin_unlock(&desc->lock); |
189 | 189 | ||
190 | if (affinity_broken && printk_ratelimit()) | 190 | if (affinity_broken) |
191 | pr_warn("IRQ%u no longer affine to CPU%u\n", | 191 | pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n", |
192 | i, smp_processor_id()); | 192 | i, smp_processor_id()); |
193 | } | 193 | } |
194 | 194 | ||
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index ad58e565fe98..49fadbda8c63 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S | |||
@@ -58,6 +58,7 @@ | |||
58 | #define MMX_SIZE (0x98) | 58 | #define MMX_SIZE (0x98) |
59 | 59 | ||
60 | .text | 60 | .text |
61 | .arm | ||
61 | 62 | ||
62 | /* | 63 | /* |
63 | * Lazy switching of Concan coprocessor context | 64 | * Lazy switching of Concan coprocessor context |
@@ -182,6 +183,8 @@ concan_load: | |||
182 | tmcr wCon, r2 | 183 | tmcr wCon, r2 |
183 | ret lr | 184 | ret lr |
184 | 185 | ||
186 | ENDPROC(iwmmxt_task_enable) | ||
187 | |||
185 | /* | 188 | /* |
186 | * Back up Concan regs to save area and disable access to them | 189 | * Back up Concan regs to save area and disable access to them |
187 | * (mainly for gdb or sleep mode usage) | 190 | * (mainly for gdb or sleep mode usage) |
@@ -232,6 +235,8 @@ ENTRY(iwmmxt_task_disable) | |||
232 | 1: msr cpsr_c, ip @ restore interrupt mode | 235 | 1: msr cpsr_c, ip @ restore interrupt mode |
233 | ldmfd sp!, {r4, pc} | 236 | ldmfd sp!, {r4, pc} |
234 | 237 | ||
238 | ENDPROC(iwmmxt_task_disable) | ||
239 | |||
235 | /* | 240 | /* |
236 | * Copy Concan state to given memory address | 241 | * Copy Concan state to given memory address |
237 | * | 242 | * |
@@ -268,6 +273,8 @@ ENTRY(iwmmxt_task_copy) | |||
268 | msr cpsr_c, ip @ restore interrupt mode | 273 | msr cpsr_c, ip @ restore interrupt mode |
269 | ret r3 | 274 | ret r3 |
270 | 275 | ||
276 | ENDPROC(iwmmxt_task_copy) | ||
277 | |||
271 | /* | 278 | /* |
272 | * Restore Concan state from given memory address | 279 | * Restore Concan state from given memory address |
273 | * | 280 | * |
@@ -304,6 +311,8 @@ ENTRY(iwmmxt_task_restore) | |||
304 | msr cpsr_c, ip @ restore interrupt mode | 311 | msr cpsr_c, ip @ restore interrupt mode |
305 | ret r3 | 312 | ret r3 |
306 | 313 | ||
314 | ENDPROC(iwmmxt_task_restore) | ||
315 | |||
307 | /* | 316 | /* |
308 | * Concan handling on task switch | 317 | * Concan handling on task switch |
309 | * | 318 | * |
@@ -335,6 +344,8 @@ ENTRY(iwmmxt_task_switch) | |||
335 | mrc p15, 0, r1, c2, c0, 0 | 344 | mrc p15, 0, r1, c2, c0, 0 |
336 | sub pc, lr, r1, lsr #32 @ cpwait and return | 345 | sub pc, lr, r1, lsr #32 @ cpwait and return |
337 | 346 | ||
347 | ENDPROC(iwmmxt_task_switch) | ||
348 | |||
338 | /* | 349 | /* |
339 | * Remove Concan ownership of given task | 350 | * Remove Concan ownership of given task |
340 | * | 351 | * |
@@ -353,6 +364,8 @@ ENTRY(iwmmxt_task_release) | |||
353 | msr cpsr_c, r2 @ restore interrupts | 364 | msr cpsr_c, r2 @ restore interrupts |
354 | ret lr | 365 | ret lr |
355 | 366 | ||
367 | ENDPROC(iwmmxt_task_release) | ||
368 | |||
356 | .data | 369 | .data |
357 | concan_owner: | 370 | concan_owner: |
358 | .word 0 | 371 | .word 0 |
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c index 4ce4f789446d..afeeb9ea6f43 100644 --- a/arch/arm/kernel/jump_label.c +++ b/arch/arm/kernel/jump_label.c | |||
@@ -19,7 +19,7 @@ static void __arch_jump_label_transform(struct jump_entry *entry, | |||
19 | insn = arm_gen_nop(); | 19 | insn = arm_gen_nop(); |
20 | 20 | ||
21 | if (is_static) | 21 | if (is_static) |
22 | __patch_text(addr, insn); | 22 | __patch_text_early(addr, insn); |
23 | else | 23 | else |
24 | patch_text(addr, insn); | 24 | patch_text(addr, insn); |
25 | } | 25 | } |
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index a74b53c1b7df..07db2f8a1b45 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c | |||
@@ -12,8 +12,12 @@ | |||
12 | #include <linux/irq.h> | 12 | #include <linux/irq.h> |
13 | #include <linux/kdebug.h> | 13 | #include <linux/kdebug.h> |
14 | #include <linux/kgdb.h> | 14 | #include <linux/kgdb.h> |
15 | #include <linux/uaccess.h> | ||
16 | |||
15 | #include <asm/traps.h> | 17 | #include <asm/traps.h> |
16 | 18 | ||
19 | #include "patch.h" | ||
20 | |||
17 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = | 21 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = |
18 | { | 22 | { |
19 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, | 23 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, |
@@ -244,6 +248,31 @@ void kgdb_arch_exit(void) | |||
244 | unregister_die_notifier(&kgdb_notifier); | 248 | unregister_die_notifier(&kgdb_notifier); |
245 | } | 249 | } |
246 | 250 | ||
251 | int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) | ||
252 | { | ||
253 | int err; | ||
254 | |||
255 | /* patch_text() only supports int-sized breakpoints */ | ||
256 | BUILD_BUG_ON(sizeof(int) != BREAK_INSTR_SIZE); | ||
257 | |||
258 | err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, | ||
259 | BREAK_INSTR_SIZE); | ||
260 | if (err) | ||
261 | return err; | ||
262 | |||
263 | patch_text((void *)bpt->bpt_addr, | ||
264 | *(unsigned int *)arch_kgdb_ops.gdb_bpt_instr); | ||
265 | |||
266 | return err; | ||
267 | } | ||
268 | |||
269 | int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) | ||
270 | { | ||
271 | patch_text((void *)bpt->bpt_addr, *(unsigned int *)bpt->saved_instr); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
247 | /* | 276 | /* |
248 | * Register our undef instruction hooks with ARM undef core. | 277 | * Register our undef instruction hooks with ARM undef core. |
249 | * We regsiter a hook specifically looking for the KGB break inst | 278 | * We regsiter a hook specifically looking for the KGB break inst |
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 8cf0996aa1a8..de2b085ad753 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -29,6 +29,7 @@ extern unsigned long kexec_boot_atags; | |||
29 | 29 | ||
30 | static atomic_t waiting_for_crash_ipi; | 30 | static atomic_t waiting_for_crash_ipi; |
31 | 31 | ||
32 | static unsigned long dt_mem; | ||
32 | /* | 33 | /* |
33 | * Provide a dummy crash_notes definition while crash dump arrives to arm. | 34 | * Provide a dummy crash_notes definition while crash dump arrives to arm. |
34 | * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. | 35 | * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. |
@@ -64,7 +65,7 @@ int machine_kexec_prepare(struct kimage *image) | |||
64 | return err; | 65 | return err; |
65 | 66 | ||
66 | if (be32_to_cpu(header) == OF_DT_HEADER) | 67 | if (be32_to_cpu(header) == OF_DT_HEADER) |
67 | kexec_boot_atags = current_segment->mem; | 68 | dt_mem = current_segment->mem; |
68 | } | 69 | } |
69 | return 0; | 70 | return 0; |
70 | } | 71 | } |
@@ -126,12 +127,12 @@ void machine_crash_shutdown(struct pt_regs *regs) | |||
126 | msecs--; | 127 | msecs--; |
127 | } | 128 | } |
128 | if (atomic_read(&waiting_for_crash_ipi) > 0) | 129 | if (atomic_read(&waiting_for_crash_ipi) > 0) |
129 | printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n"); | 130 | pr_warn("Non-crashing CPUs did not react to IPI\n"); |
130 | 131 | ||
131 | crash_save_cpu(regs, smp_processor_id()); | 132 | crash_save_cpu(regs, smp_processor_id()); |
132 | machine_kexec_mask_interrupts(); | 133 | machine_kexec_mask_interrupts(); |
133 | 134 | ||
134 | printk(KERN_INFO "Loading crashdump kernel...\n"); | 135 | pr_info("Loading crashdump kernel...\n"); |
135 | } | 136 | } |
136 | 137 | ||
137 | /* | 138 | /* |
@@ -163,12 +164,12 @@ void machine_kexec(struct kimage *image) | |||
163 | reboot_code_buffer = page_address(image->control_code_page); | 164 | reboot_code_buffer = page_address(image->control_code_page); |
164 | 165 | ||
165 | /* Prepare parameters for reboot_code_buffer*/ | 166 | /* Prepare parameters for reboot_code_buffer*/ |
167 | set_kernel_text_rw(); | ||
166 | kexec_start_address = image->start; | 168 | kexec_start_address = image->start; |
167 | kexec_indirection_page = page_list; | 169 | kexec_indirection_page = page_list; |
168 | kexec_mach_type = machine_arch_type; | 170 | kexec_mach_type = machine_arch_type; |
169 | if (!kexec_boot_atags) | 171 | kexec_boot_atags = dt_mem ?: image->start - KEXEC_ARM_ZIMAGE_OFFSET |
170 | kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; | 172 | + KEXEC_ARM_ATAGS_OFFSET; |
171 | |||
172 | 173 | ||
173 | /* copy our kernel relocation code to the control code page */ | 174 | /* copy our kernel relocation code to the control code page */ |
174 | reboot_entry = fncpy(reboot_code_buffer, | 175 | reboot_entry = fncpy(reboot_code_buffer, |
@@ -177,7 +178,7 @@ void machine_kexec(struct kimage *image) | |||
177 | reboot_entry_phys = (unsigned long)reboot_entry + | 178 | reboot_entry_phys = (unsigned long)reboot_entry + |
178 | (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer); | 179 | (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer); |
179 | 180 | ||
180 | printk(KERN_INFO "Bye!\n"); | 181 | pr_info("Bye!\n"); |
181 | 182 | ||
182 | if (kexec_reinit) | 183 | if (kexec_reinit) |
183 | kexec_reinit(); | 184 | kexec_reinit(); |
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 6a4dffefd357..bea7db9e5b80 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c | |||
@@ -251,7 +251,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, | |||
251 | #endif | 251 | #endif |
252 | 252 | ||
253 | default: | 253 | default: |
254 | printk(KERN_ERR "%s: unknown relocation: %u\n", | 254 | pr_err("%s: unknown relocation: %u\n", |
255 | module->name, ELF32_R_TYPE(rel->r_info)); | 255 | module->name, ELF32_R_TYPE(rel->r_info)); |
256 | return -ENOEXEC; | 256 | return -ENOEXEC; |
257 | } | 257 | } |
diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c index 07314af47733..5038960e3c55 100644 --- a/arch/arm/kernel/patch.c +++ b/arch/arm/kernel/patch.c | |||
@@ -1,8 +1,11 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/spinlock.h> | ||
2 | #include <linux/kprobes.h> | 3 | #include <linux/kprobes.h> |
4 | #include <linux/mm.h> | ||
3 | #include <linux/stop_machine.h> | 5 | #include <linux/stop_machine.h> |
4 | 6 | ||
5 | #include <asm/cacheflush.h> | 7 | #include <asm/cacheflush.h> |
8 | #include <asm/fixmap.h> | ||
6 | #include <asm/smp_plat.h> | 9 | #include <asm/smp_plat.h> |
7 | #include <asm/opcodes.h> | 10 | #include <asm/opcodes.h> |
8 | 11 | ||
@@ -13,21 +16,77 @@ struct patch { | |||
13 | unsigned int insn; | 16 | unsigned int insn; |
14 | }; | 17 | }; |
15 | 18 | ||
16 | void __kprobes __patch_text(void *addr, unsigned int insn) | 19 | static DEFINE_SPINLOCK(patch_lock); |
20 | |||
21 | static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags) | ||
22 | __acquires(&patch_lock) | ||
23 | { | ||
24 | unsigned int uintaddr = (uintptr_t) addr; | ||
25 | bool module = !core_kernel_text(uintaddr); | ||
26 | struct page *page; | ||
27 | |||
28 | if (module && IS_ENABLED(CONFIG_DEBUG_SET_MODULE_RONX)) | ||
29 | page = vmalloc_to_page(addr); | ||
30 | else if (!module && IS_ENABLED(CONFIG_DEBUG_RODATA)) | ||
31 | page = virt_to_page(addr); | ||
32 | else | ||
33 | return addr; | ||
34 | |||
35 | if (flags) | ||
36 | spin_lock_irqsave(&patch_lock, *flags); | ||
37 | else | ||
38 | __acquire(&patch_lock); | ||
39 | |||
40 | set_fixmap(fixmap, page_to_phys(page)); | ||
41 | |||
42 | return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK)); | ||
43 | } | ||
44 | |||
45 | static void __kprobes patch_unmap(int fixmap, unsigned long *flags) | ||
46 | __releases(&patch_lock) | ||
47 | { | ||
48 | clear_fixmap(fixmap); | ||
49 | |||
50 | if (flags) | ||
51 | spin_unlock_irqrestore(&patch_lock, *flags); | ||
52 | else | ||
53 | __release(&patch_lock); | ||
54 | } | ||
55 | |||
56 | void __kprobes __patch_text_real(void *addr, unsigned int insn, bool remap) | ||
17 | { | 57 | { |
18 | bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL); | 58 | bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL); |
59 | unsigned int uintaddr = (uintptr_t) addr; | ||
60 | bool twopage = false; | ||
61 | unsigned long flags; | ||
62 | void *waddr = addr; | ||
19 | int size; | 63 | int size; |
20 | 64 | ||
65 | if (remap) | ||
66 | waddr = patch_map(addr, FIX_TEXT_POKE0, &flags); | ||
67 | else | ||
68 | __acquire(&patch_lock); | ||
69 | |||
21 | if (thumb2 && __opcode_is_thumb16(insn)) { | 70 | if (thumb2 && __opcode_is_thumb16(insn)) { |
22 | *(u16 *)addr = __opcode_to_mem_thumb16(insn); | 71 | *(u16 *)waddr = __opcode_to_mem_thumb16(insn); |
23 | size = sizeof(u16); | 72 | size = sizeof(u16); |
24 | } else if (thumb2 && ((uintptr_t)addr & 2)) { | 73 | } else if (thumb2 && (uintaddr & 2)) { |
25 | u16 first = __opcode_thumb32_first(insn); | 74 | u16 first = __opcode_thumb32_first(insn); |
26 | u16 second = __opcode_thumb32_second(insn); | 75 | u16 second = __opcode_thumb32_second(insn); |
27 | u16 *addrh = addr; | 76 | u16 *addrh0 = waddr; |
77 | u16 *addrh1 = waddr + 2; | ||
78 | |||
79 | twopage = (uintaddr & ~PAGE_MASK) == PAGE_SIZE - 2; | ||
80 | if (twopage && remap) | ||
81 | addrh1 = patch_map(addr + 2, FIX_TEXT_POKE1, NULL); | ||
82 | |||
83 | *addrh0 = __opcode_to_mem_thumb16(first); | ||
84 | *addrh1 = __opcode_to_mem_thumb16(second); | ||
28 | 85 | ||
29 | addrh[0] = __opcode_to_mem_thumb16(first); | 86 | if (twopage && addrh1 != addr + 2) { |
30 | addrh[1] = __opcode_to_mem_thumb16(second); | 87 | flush_kernel_vmap_range(addrh1, 2); |
88 | patch_unmap(FIX_TEXT_POKE1, NULL); | ||
89 | } | ||
31 | 90 | ||
32 | size = sizeof(u32); | 91 | size = sizeof(u32); |
33 | } else { | 92 | } else { |
@@ -36,10 +95,16 @@ void __kprobes __patch_text(void *addr, unsigned int insn) | |||
36 | else | 95 | else |
37 | insn = __opcode_to_mem_arm(insn); | 96 | insn = __opcode_to_mem_arm(insn); |
38 | 97 | ||
39 | *(u32 *)addr = insn; | 98 | *(u32 *)waddr = insn; |
40 | size = sizeof(u32); | 99 | size = sizeof(u32); |
41 | } | 100 | } |
42 | 101 | ||
102 | if (waddr != addr) { | ||
103 | flush_kernel_vmap_range(waddr, twopage ? size / 2 : size); | ||
104 | patch_unmap(FIX_TEXT_POKE0, &flags); | ||
105 | } else | ||
106 | __release(&patch_lock); | ||
107 | |||
43 | flush_icache_range((uintptr_t)(addr), | 108 | flush_icache_range((uintptr_t)(addr), |
44 | (uintptr_t)(addr) + size); | 109 | (uintptr_t)(addr) + size); |
45 | } | 110 | } |
@@ -60,16 +125,5 @@ void __kprobes patch_text(void *addr, unsigned int insn) | |||
60 | .insn = insn, | 125 | .insn = insn, |
61 | }; | 126 | }; |
62 | 127 | ||
63 | if (cache_ops_need_broadcast()) { | 128 | stop_machine(patch_text_stop_machine, &patch, NULL); |
64 | stop_machine(patch_text_stop_machine, &patch, cpu_online_mask); | ||
65 | } else { | ||
66 | bool straddles_word = IS_ENABLED(CONFIG_THUMB2_KERNEL) | ||
67 | && __opcode_is_thumb32(insn) | ||
68 | && ((uintptr_t)addr & 2); | ||
69 | |||
70 | if (straddles_word) | ||
71 | stop_machine(patch_text_stop_machine, &patch, NULL); | ||
72 | else | ||
73 | __patch_text(addr, insn); | ||
74 | } | ||
75 | } | 129 | } |
diff --git a/arch/arm/kernel/patch.h b/arch/arm/kernel/patch.h index b4731f2dac38..77e054c2f6cd 100644 --- a/arch/arm/kernel/patch.h +++ b/arch/arm/kernel/patch.h | |||
@@ -2,6 +2,16 @@ | |||
2 | #define _ARM_KERNEL_PATCH_H | 2 | #define _ARM_KERNEL_PATCH_H |
3 | 3 | ||
4 | void patch_text(void *addr, unsigned int insn); | 4 | void patch_text(void *addr, unsigned int insn); |
5 | void __patch_text(void *addr, unsigned int insn); | 5 | void __patch_text_real(void *addr, unsigned int insn, bool remap); |
6 | |||
7 | static inline void __patch_text(void *addr, unsigned int insn) | ||
8 | { | ||
9 | __patch_text_real(addr, insn, true); | ||
10 | } | ||
11 | |||
12 | static inline void __patch_text_early(void *addr, unsigned int insn) | ||
13 | { | ||
14 | __patch_text_real(addr, insn, false); | ||
15 | } | ||
6 | 16 | ||
7 | #endif | 17 | #endif |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index fe972a2f3df3..fdfa3a78ec8c 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -51,8 +51,8 @@ EXPORT_SYMBOL(__stack_chk_guard); | |||
51 | static const char *processor_modes[] __maybe_unused = { | 51 | static const char *processor_modes[] __maybe_unused = { |
52 | "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , | 52 | "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , |
53 | "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", | 53 | "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", |
54 | "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , | 54 | "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "MON_32" , "ABT_32" , |
55 | "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" | 55 | "UK8_32" , "UK9_32" , "HYP_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static const char *isa_modes[] __maybe_unused = { | 58 | static const char *isa_modes[] __maybe_unused = { |
diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c index 98ea4b7eb406..24b4a04846eb 100644 --- a/arch/arm/kernel/return_address.c +++ b/arch/arm/kernel/return_address.c | |||
@@ -39,13 +39,12 @@ void *return_address(unsigned int level) | |||
39 | { | 39 | { |
40 | struct return_address_data data; | 40 | struct return_address_data data; |
41 | struct stackframe frame; | 41 | struct stackframe frame; |
42 | register unsigned long current_sp asm ("sp"); | ||
43 | 42 | ||
44 | data.level = level + 2; | 43 | data.level = level + 2; |
45 | data.addr = NULL; | 44 | data.addr = NULL; |
46 | 45 | ||
47 | frame.fp = (unsigned long)__builtin_frame_address(0); | 46 | frame.fp = (unsigned long)__builtin_frame_address(0); |
48 | frame.sp = current_sp; | 47 | frame.sp = current_stack_pointer; |
49 | frame.lr = (unsigned long)__builtin_return_address(0); | 48 | frame.lr = (unsigned long)__builtin_return_address(0); |
50 | frame.pc = (unsigned long)return_address; | 49 | frame.pc = (unsigned long)return_address; |
51 | 50 | ||
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index c03106378b49..8361652b6dab 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -900,6 +900,7 @@ void __init setup_arch(char **cmdline_p) | |||
900 | mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type); | 900 | mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type); |
901 | machine_desc = mdesc; | 901 | machine_desc = mdesc; |
902 | machine_name = mdesc->name; | 902 | machine_name = mdesc->name; |
903 | dump_stack_set_arch_desc("%s", mdesc->name); | ||
903 | 904 | ||
904 | if (mdesc->reboot_mode != REBOOT_HARD) | 905 | if (mdesc->reboot_mode != REBOOT_HARD) |
905 | reboot_mode = mdesc->reboot_mode; | 906 | reboot_mode = mdesc->reboot_mode; |
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index bd1983437205..8aa6f1b87c9e 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -592,7 +592,6 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) | |||
592 | } | 592 | } |
593 | syscall = 0; | 593 | syscall = 0; |
594 | } else if (thread_flags & _TIF_UPROBE) { | 594 | } else if (thread_flags & _TIF_UPROBE) { |
595 | clear_thread_flag(TIF_UPROBE); | ||
596 | uprobe_notify_resume(regs); | 595 | uprobe_notify_resume(regs); |
597 | } else { | 596 | } else { |
598 | clear_thread_flag(TIF_NOTIFY_RESUME); | 597 | clear_thread_flag(TIF_NOTIFY_RESUME); |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 13396d3d600e..5e6052e18850 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -225,7 +225,7 @@ void __cpu_die(unsigned int cpu) | |||
225 | pr_err("CPU%u: cpu didn't die\n", cpu); | 225 | pr_err("CPU%u: cpu didn't die\n", cpu); |
226 | return; | 226 | return; |
227 | } | 227 | } |
228 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | 228 | pr_notice("CPU%u: shutdown\n", cpu); |
229 | 229 | ||
230 | /* | 230 | /* |
231 | * platform_cpu_kill() is generally expected to do the powering off | 231 | * platform_cpu_kill() is generally expected to do the powering off |
@@ -235,7 +235,7 @@ void __cpu_die(unsigned int cpu) | |||
235 | * the requesting CPU and the dying CPU actually losing power. | 235 | * the requesting CPU and the dying CPU actually losing power. |
236 | */ | 236 | */ |
237 | if (!platform_cpu_kill(cpu)) | 237 | if (!platform_cpu_kill(cpu)) |
238 | printk("CPU%u: unable to kill\n", cpu); | 238 | pr_err("CPU%u: unable to kill\n", cpu); |
239 | } | 239 | } |
240 | 240 | ||
241 | /* | 241 | /* |
@@ -351,7 +351,7 @@ asmlinkage void secondary_start_kernel(void) | |||
351 | 351 | ||
352 | cpu_init(); | 352 | cpu_init(); |
353 | 353 | ||
354 | printk("CPU%u: Booted secondary processor\n", cpu); | 354 | pr_debug("CPU%u: Booted secondary processor\n", cpu); |
355 | 355 | ||
356 | preempt_disable(); | 356 | preempt_disable(); |
357 | trace_hardirqs_off(); | 357 | trace_hardirqs_off(); |
@@ -387,9 +387,6 @@ asmlinkage void secondary_start_kernel(void) | |||
387 | 387 | ||
388 | void __init smp_cpus_done(unsigned int max_cpus) | 388 | void __init smp_cpus_done(unsigned int max_cpus) |
389 | { | 389 | { |
390 | printk(KERN_INFO "SMP: Total of %d processors activated.\n", | ||
391 | num_online_cpus()); | ||
392 | |||
393 | hyp_mode_check(); | 390 | hyp_mode_check(); |
394 | } | 391 | } |
395 | 392 | ||
@@ -521,7 +518,7 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
521 | if (system_state == SYSTEM_BOOTING || | 518 | if (system_state == SYSTEM_BOOTING || |
522 | system_state == SYSTEM_RUNNING) { | 519 | system_state == SYSTEM_RUNNING) { |
523 | raw_spin_lock(&stop_lock); | 520 | raw_spin_lock(&stop_lock); |
524 | printk(KERN_CRIT "CPU%u: stopping\n", cpu); | 521 | pr_crit("CPU%u: stopping\n", cpu); |
525 | dump_stack(); | 522 | dump_stack(); |
526 | raw_spin_unlock(&stop_lock); | 523 | raw_spin_unlock(&stop_lock); |
527 | } | 524 | } |
@@ -615,8 +612,8 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
615 | break; | 612 | break; |
616 | 613 | ||
617 | default: | 614 | default: |
618 | printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", | 615 | pr_crit("CPU%u: Unknown IPI message 0x%x\n", |
619 | cpu, ipinr); | 616 | cpu, ipinr); |
620 | break; | 617 | break; |
621 | } | 618 | } |
622 | 619 | ||
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 93090213c71c..172c6a05d27f 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -199,7 +199,7 @@ static void twd_calibrate_rate(void) | |||
199 | * the timer ticks | 199 | * the timer ticks |
200 | */ | 200 | */ |
201 | if (twd_timer_rate == 0) { | 201 | if (twd_timer_rate == 0) { |
202 | printk(KERN_INFO "Calibrating local timer... "); | 202 | pr_info("Calibrating local timer... "); |
203 | 203 | ||
204 | /* Wait for a tick to start */ | 204 | /* Wait for a tick to start */ |
205 | waitjiffies = get_jiffies_64() + 1; | 205 | waitjiffies = get_jiffies_64() + 1; |
@@ -223,7 +223,7 @@ static void twd_calibrate_rate(void) | |||
223 | 223 | ||
224 | twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); | 224 | twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); |
225 | 225 | ||
226 | printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000, | 226 | pr_cont("%lu.%02luMHz.\n", twd_timer_rate / 1000000, |
227 | (twd_timer_rate / 10000) % 100); | 227 | (twd_timer_rate / 10000) % 100); |
228 | } | 228 | } |
229 | } | 229 | } |
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index f065eb05d254..92b72375c4c7 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c | |||
@@ -134,12 +134,10 @@ static noinline void __save_stack_trace(struct task_struct *tsk, | |||
134 | frame.pc = thread_saved_pc(tsk); | 134 | frame.pc = thread_saved_pc(tsk); |
135 | #endif | 135 | #endif |
136 | } else { | 136 | } else { |
137 | register unsigned long current_sp asm ("sp"); | ||
138 | |||
139 | /* We don't want this function nor the caller */ | 137 | /* We don't want this function nor the caller */ |
140 | data.skip += 2; | 138 | data.skip += 2; |
141 | frame.fp = (unsigned long)__builtin_frame_address(0); | 139 | frame.fp = (unsigned long)__builtin_frame_address(0); |
142 | frame.sp = current_sp; | 140 | frame.sp = current_stack_pointer; |
143 | frame.lr = (unsigned long)__builtin_return_address(0); | 141 | frame.lr = (unsigned long)__builtin_return_address(0); |
144 | frame.pc = (unsigned long)__save_stack_trace; | 142 | frame.pc = (unsigned long)__save_stack_trace; |
145 | } | 143 | } |
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c index 587fdfe1a72c..afdd51e30bec 100644 --- a/arch/arm/kernel/swp_emulate.c +++ b/arch/arm/kernel/swp_emulate.c | |||
@@ -260,7 +260,7 @@ static int __init swp_emulation_init(void) | |||
260 | return -ENOMEM; | 260 | return -ENOMEM; |
261 | #endif /* CONFIG_PROC_FS */ | 261 | #endif /* CONFIG_PROC_FS */ |
262 | 262 | ||
263 | printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n"); | 263 | pr_notice("Registering SWP/SWPB emulation handler\n"); |
264 | register_undef_hook(&swp_hook); | 264 | register_undef_hook(&swp_hook); |
265 | 265 | ||
266 | return 0; | 266 | return 0; |
diff --git a/arch/arm/kernel/thumbee.c b/arch/arm/kernel/thumbee.c index 80f0d69205e7..8ff8dbfbe9fb 100644 --- a/arch/arm/kernel/thumbee.c +++ b/arch/arm/kernel/thumbee.c | |||
@@ -72,7 +72,7 @@ static int __init thumbee_init(void) | |||
72 | if ((pfr0 & 0x0000f000) != 0x00001000) | 72 | if ((pfr0 & 0x0000f000) != 0x00001000) |
73 | return 0; | 73 | return 0; |
74 | 74 | ||
75 | printk(KERN_INFO "ThumbEE CPU extension supported.\n"); | 75 | pr_info("ThumbEE CPU extension supported.\n"); |
76 | elf_hwcap |= HWCAP_THUMBEE; | 76 | elf_hwcap |= HWCAP_THUMBEE; |
77 | thread_register_notifier(&thumbee_notifier_block); | 77 | thread_register_notifier(&thumbee_notifier_block); |
78 | 78 | ||
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 89cfdd6e50cb..08b7847bf912 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c | |||
@@ -165,7 +165,7 @@ static void update_cpu_capacity(unsigned int cpu) | |||
165 | 165 | ||
166 | set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity); | 166 | set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity); |
167 | 167 | ||
168 | printk(KERN_INFO "CPU%u: update cpu_capacity %lu\n", | 168 | pr_info("CPU%u: update cpu_capacity %lu\n", |
169 | cpu, arch_scale_cpu_capacity(NULL, cpu)); | 169 | cpu, arch_scale_cpu_capacity(NULL, cpu)); |
170 | } | 170 | } |
171 | 171 | ||
@@ -269,7 +269,7 @@ void store_cpu_topology(unsigned int cpuid) | |||
269 | 269 | ||
270 | update_cpu_capacity(cpuid); | 270 | update_cpu_capacity(cpuid); |
271 | 271 | ||
272 | printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", | 272 | pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", |
273 | cpuid, cpu_topology[cpuid].thread_id, | 273 | cpuid, cpu_topology[cpuid].thread_id, |
274 | cpu_topology[cpuid].core_id, | 274 | cpu_topology[cpuid].core_id, |
275 | cpu_topology[cpuid].socket_id, mpidr); | 275 | cpu_topology[cpuid].socket_id, mpidr); |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 9f5d81881eb6..788e23fe64d8 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -198,14 +198,14 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | if (!fp) { | 200 | if (!fp) { |
201 | printk("no frame pointer"); | 201 | pr_cont("no frame pointer"); |
202 | ok = 0; | 202 | ok = 0; |
203 | } else if (verify_stack(fp)) { | 203 | } else if (verify_stack(fp)) { |
204 | printk("invalid frame pointer 0x%08x", fp); | 204 | pr_cont("invalid frame pointer 0x%08x", fp); |
205 | ok = 0; | 205 | ok = 0; |
206 | } else if (fp < (unsigned long)end_of_stack(tsk)) | 206 | } else if (fp < (unsigned long)end_of_stack(tsk)) |
207 | printk("frame pointer underflow"); | 207 | pr_cont("frame pointer underflow"); |
208 | printk("\n"); | 208 | pr_cont("\n"); |
209 | 209 | ||
210 | if (ok) | 210 | if (ok) |
211 | c_backtrace(fp, mode); | 211 | c_backtrace(fp, mode); |
@@ -240,8 +240,8 @@ static int __die(const char *str, int err, struct pt_regs *regs) | |||
240 | static int die_counter; | 240 | static int die_counter; |
241 | int ret; | 241 | int ret; |
242 | 242 | ||
243 | printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP | 243 | pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP S_ISA "\n", |
244 | S_ISA "\n", str, err, ++die_counter); | 244 | str, err, ++die_counter); |
245 | 245 | ||
246 | /* trap and error numbers are mostly meaningless on ARM */ | 246 | /* trap and error numbers are mostly meaningless on ARM */ |
247 | ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); | 247 | ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); |
@@ -250,8 +250,8 @@ static int __die(const char *str, int err, struct pt_regs *regs) | |||
250 | 250 | ||
251 | print_modules(); | 251 | print_modules(); |
252 | __show_regs(regs); | 252 | __show_regs(regs); |
253 | printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", | 253 | pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", |
254 | TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); | 254 | TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); |
255 | 255 | ||
256 | if (!user_mode(regs) || in_interrupt()) { | 256 | if (!user_mode(regs) || in_interrupt()) { |
257 | dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, | 257 | dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, |
@@ -446,7 +446,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
446 | die_sig: | 446 | die_sig: |
447 | #ifdef CONFIG_DEBUG_USER | 447 | #ifdef CONFIG_DEBUG_USER |
448 | if (user_debug & UDBG_UNDEFINED) { | 448 | if (user_debug & UDBG_UNDEFINED) { |
449 | printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", | 449 | pr_info("%s (%d): undefined instruction: pc=%p\n", |
450 | current->comm, task_pid_nr(current), pc); | 450 | current->comm, task_pid_nr(current), pc); |
451 | __show_regs(regs); | 451 | __show_regs(regs); |
452 | dump_instr(KERN_INFO, regs); | 452 | dump_instr(KERN_INFO, regs); |
@@ -496,7 +496,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason) | |||
496 | { | 496 | { |
497 | console_verbose(); | 497 | console_verbose(); |
498 | 498 | ||
499 | printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]); | 499 | pr_crit("Bad mode in %s handler detected\n", handler[reason]); |
500 | 500 | ||
501 | die("Oops - bad mode", regs, 0); | 501 | die("Oops - bad mode", regs, 0); |
502 | local_irq_disable(); | 502 | local_irq_disable(); |
@@ -516,7 +516,7 @@ static int bad_syscall(int n, struct pt_regs *regs) | |||
516 | 516 | ||
517 | #ifdef CONFIG_DEBUG_USER | 517 | #ifdef CONFIG_DEBUG_USER |
518 | if (user_debug & UDBG_SYSCALL) { | 518 | if (user_debug & UDBG_SYSCALL) { |
519 | printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", | 519 | pr_err("[%d] %s: obsolete system call %08x.\n", |
520 | task_pid_nr(current), current->comm, n); | 520 | task_pid_nr(current), current->comm, n); |
521 | dump_instr(KERN_ERR, regs); | 521 | dump_instr(KERN_ERR, regs); |
522 | } | 522 | } |
@@ -694,7 +694,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) | |||
694 | * something catastrophic has happened | 694 | * something catastrophic has happened |
695 | */ | 695 | */ |
696 | if (user_debug & UDBG_SYSCALL) { | 696 | if (user_debug & UDBG_SYSCALL) { |
697 | printk("[%d] %s: arm syscall %d\n", | 697 | pr_err("[%d] %s: arm syscall %d\n", |
698 | task_pid_nr(current), current->comm, no); | 698 | task_pid_nr(current), current->comm, no); |
699 | dump_instr("", regs); | 699 | dump_instr("", regs); |
700 | if (user_mode(regs)) { | 700 | if (user_mode(regs)) { |
@@ -753,8 +753,8 @@ late_initcall(arm_mrc_hook_init); | |||
753 | 753 | ||
754 | void __bad_xchg(volatile void *ptr, int size) | 754 | void __bad_xchg(volatile void *ptr, int size) |
755 | { | 755 | { |
756 | printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", | 756 | pr_err("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", |
757 | __builtin_return_address(0), ptr, size); | 757 | __builtin_return_address(0), ptr, size); |
758 | BUG(); | 758 | BUG(); |
759 | } | 759 | } |
760 | EXPORT_SYMBOL(__bad_xchg); | 760 | EXPORT_SYMBOL(__bad_xchg); |
@@ -771,8 +771,8 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) | |||
771 | 771 | ||
772 | #ifdef CONFIG_DEBUG_USER | 772 | #ifdef CONFIG_DEBUG_USER |
773 | if (user_debug & UDBG_BADABORT) { | 773 | if (user_debug & UDBG_BADABORT) { |
774 | printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n", | 774 | pr_err("[%d] %s: bad data abort: code %d instr 0x%08lx\n", |
775 | task_pid_nr(current), current->comm, code, instr); | 775 | task_pid_nr(current), current->comm, code, instr); |
776 | dump_instr(KERN_ERR, regs); | 776 | dump_instr(KERN_ERR, regs); |
777 | show_pte(current->mm, addr); | 777 | show_pte(current->mm, addr); |
778 | } | 778 | } |
@@ -788,29 +788,29 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) | |||
788 | 788 | ||
789 | void __readwrite_bug(const char *fn) | 789 | void __readwrite_bug(const char *fn) |
790 | { | 790 | { |
791 | printk("%s called, but not implemented\n", fn); | 791 | pr_err("%s called, but not implemented\n", fn); |
792 | BUG(); | 792 | BUG(); |
793 | } | 793 | } |
794 | EXPORT_SYMBOL(__readwrite_bug); | 794 | EXPORT_SYMBOL(__readwrite_bug); |
795 | 795 | ||
796 | void __pte_error(const char *file, int line, pte_t pte) | 796 | void __pte_error(const char *file, int line, pte_t pte) |
797 | { | 797 | { |
798 | printk("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); | 798 | pr_err("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); |
799 | } | 799 | } |
800 | 800 | ||
801 | void __pmd_error(const char *file, int line, pmd_t pmd) | 801 | void __pmd_error(const char *file, int line, pmd_t pmd) |
802 | { | 802 | { |
803 | printk("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd)); | 803 | pr_err("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd)); |
804 | } | 804 | } |
805 | 805 | ||
806 | void __pgd_error(const char *file, int line, pgd_t pgd) | 806 | void __pgd_error(const char *file, int line, pgd_t pgd) |
807 | { | 807 | { |
808 | printk("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); | 808 | pr_err("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); |
809 | } | 809 | } |
810 | 810 | ||
811 | asmlinkage void __div0(void) | 811 | asmlinkage void __div0(void) |
812 | { | 812 | { |
813 | printk("Division by zero in kernel.\n"); | 813 | pr_err("Division by zero in kernel.\n"); |
814 | dump_stack(); | 814 | dump_stack(); |
815 | } | 815 | } |
816 | EXPORT_SYMBOL(__div0); | 816 | EXPORT_SYMBOL(__div0); |
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index cbb85c5fabf9..0bee233fef9a 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c | |||
@@ -471,7 +471,6 @@ int unwind_frame(struct stackframe *frame) | |||
471 | void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) | 471 | void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) |
472 | { | 472 | { |
473 | struct stackframe frame; | 473 | struct stackframe frame; |
474 | register unsigned long current_sp asm ("sp"); | ||
475 | 474 | ||
476 | pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); | 475 | pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); |
477 | 476 | ||
@@ -485,7 +484,7 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
485 | frame.pc = regs->ARM_lr; | 484 | frame.pc = regs->ARM_lr; |
486 | } else if (tsk == current) { | 485 | } else if (tsk == current) { |
487 | frame.fp = (unsigned long)__builtin_frame_address(0); | 486 | frame.fp = (unsigned long)__builtin_frame_address(0); |
488 | frame.sp = current_sp; | 487 | frame.sp = current_stack_pointer; |
489 | frame.lr = (unsigned long)__builtin_return_address(0); | 488 | frame.lr = (unsigned long)__builtin_return_address(0); |
490 | frame.pc = (unsigned long)unwind_backtrace; | 489 | frame.pc = (unsigned long)unwind_backtrace; |
491 | } else { | 490 | } else { |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 8e95aa47457a..b31aa73e8076 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -8,6 +8,9 @@ | |||
8 | #include <asm/thread_info.h> | 8 | #include <asm/thread_info.h> |
9 | #include <asm/memory.h> | 9 | #include <asm/memory.h> |
10 | #include <asm/page.h> | 10 | #include <asm/page.h> |
11 | #ifdef CONFIG_ARM_KERNMEM_PERMS | ||
12 | #include <asm/pgtable.h> | ||
13 | #endif | ||
11 | 14 | ||
12 | #define PROC_INFO \ | 15 | #define PROC_INFO \ |
13 | . = ALIGN(4); \ | 16 | . = ALIGN(4); \ |
@@ -90,6 +93,11 @@ SECTIONS | |||
90 | _text = .; | 93 | _text = .; |
91 | HEAD_TEXT | 94 | HEAD_TEXT |
92 | } | 95 | } |
96 | |||
97 | #ifdef CONFIG_ARM_KERNMEM_PERMS | ||
98 | . = ALIGN(1<<SECTION_SHIFT); | ||
99 | #endif | ||
100 | |||
93 | .text : { /* Real text segment */ | 101 | .text : { /* Real text segment */ |
94 | _stext = .; /* Text and read-only data */ | 102 | _stext = .; /* Text and read-only data */ |
95 | __exception_text_start = .; | 103 | __exception_text_start = .; |
@@ -112,6 +120,9 @@ SECTIONS | |||
112 | ARM_CPU_KEEP(PROC_INFO) | 120 | ARM_CPU_KEEP(PROC_INFO) |
113 | } | 121 | } |
114 | 122 | ||
123 | #ifdef CONFIG_DEBUG_RODATA | ||
124 | . = ALIGN(1<<SECTION_SHIFT); | ||
125 | #endif | ||
115 | RO_DATA(PAGE_SIZE) | 126 | RO_DATA(PAGE_SIZE) |
116 | 127 | ||
117 | . = ALIGN(4); | 128 | . = ALIGN(4); |
@@ -145,7 +156,11 @@ SECTIONS | |||
145 | _etext = .; /* End of text and rodata section */ | 156 | _etext = .; /* End of text and rodata section */ |
146 | 157 | ||
147 | #ifndef CONFIG_XIP_KERNEL | 158 | #ifndef CONFIG_XIP_KERNEL |
159 | # ifdef CONFIG_ARM_KERNMEM_PERMS | ||
160 | . = ALIGN(1<<SECTION_SHIFT); | ||
161 | # else | ||
148 | . = ALIGN(PAGE_SIZE); | 162 | . = ALIGN(PAGE_SIZE); |
163 | # endif | ||
149 | __init_begin = .; | 164 | __init_begin = .; |
150 | #endif | 165 | #endif |
151 | /* | 166 | /* |
@@ -219,7 +234,11 @@ SECTIONS | |||
219 | __data_loc = ALIGN(4); /* location in binary */ | 234 | __data_loc = ALIGN(4); /* location in binary */ |
220 | . = PAGE_OFFSET + TEXT_OFFSET; | 235 | . = PAGE_OFFSET + TEXT_OFFSET; |
221 | #else | 236 | #else |
237 | #ifdef CONFIG_ARM_KERNMEM_PERMS | ||
238 | . = ALIGN(1<<SECTION_SHIFT); | ||
239 | #else | ||
222 | . = ALIGN(THREAD_SIZE); | 240 | . = ALIGN(THREAD_SIZE); |
241 | #endif | ||
223 | __init_end = .; | 242 | __init_end = .; |
224 | __data_loc = .; | 243 | __data_loc = .; |
225 | #endif | 244 | #endif |
diff --git a/arch/arm/kernel/xscale-cp0.c b/arch/arm/kernel/xscale-cp0.c index e42adc6bcdb1..bdbb8853a19b 100644 --- a/arch/arm/kernel/xscale-cp0.c +++ b/arch/arm/kernel/xscale-cp0.c | |||
@@ -157,15 +157,14 @@ static int __init xscale_cp0_init(void) | |||
157 | 157 | ||
158 | if (cpu_has_iwmmxt()) { | 158 | if (cpu_has_iwmmxt()) { |
159 | #ifndef CONFIG_IWMMXT | 159 | #ifndef CONFIG_IWMMXT |
160 | printk(KERN_WARNING "CAUTION: XScale iWMMXt coprocessor " | 160 | pr_warn("CAUTION: XScale iWMMXt coprocessor detected, but kernel support is missing.\n"); |
161 | "detected, but kernel support is missing.\n"); | ||
162 | #else | 161 | #else |
163 | printk(KERN_INFO "XScale iWMMXt coprocessor detected.\n"); | 162 | pr_info("XScale iWMMXt coprocessor detected.\n"); |
164 | elf_hwcap |= HWCAP_IWMMXT; | 163 | elf_hwcap |= HWCAP_IWMMXT; |
165 | thread_register_notifier(&iwmmxt_notifier_block); | 164 | thread_register_notifier(&iwmmxt_notifier_block); |
166 | #endif | 165 | #endif |
167 | } else { | 166 | } else { |
168 | printk(KERN_INFO "XScale DSP coprocessor detected.\n"); | 167 | pr_info("XScale DSP coprocessor detected.\n"); |
169 | thread_register_notifier(&dsp_notifier_block); | 168 | thread_register_notifier(&dsp_notifier_block); |
170 | cp_access |= 1; | 169 | cp_access |= 1; |
171 | } | 170 | } |
diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S index 66a477a3e3cc..7a235b9952be 100644 --- a/arch/arm/lib/copy_from_user.S +++ b/arch/arm/lib/copy_from_user.S | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <asm/assembler.h> | 14 | #include <asm/assembler.h> |
15 | #include <asm/unwind.h> | ||
15 | 16 | ||
16 | /* | 17 | /* |
17 | * Prototype: | 18 | * Prototype: |
@@ -77,6 +78,10 @@ | |||
77 | stmdb sp!, {r0, r2, r3, \reg1, \reg2} | 78 | stmdb sp!, {r0, r2, r3, \reg1, \reg2} |
78 | .endm | 79 | .endm |
79 | 80 | ||
81 | .macro usave reg1 reg2 | ||
82 | UNWIND( .save {r0, r2, r3, \reg1, \reg2} ) | ||
83 | .endm | ||
84 | |||
80 | .macro exit reg1 reg2 | 85 | .macro exit reg1 reg2 |
81 | add sp, sp, #8 | 86 | add sp, sp, #8 |
82 | ldmfd sp!, {r0, \reg1, \reg2} | 87 | ldmfd sp!, {r0, \reg1, \reg2} |
diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S index 3bc8eb811a73..652e4d98cd47 100644 --- a/arch/arm/lib/copy_template.S +++ b/arch/arm/lib/copy_template.S | |||
@@ -53,6 +53,12 @@ | |||
53 | * data as needed by the implementation including this code. Called | 53 | * data as needed by the implementation including this code. Called |
54 | * upon code entry. | 54 | * upon code entry. |
55 | * | 55 | * |
56 | * usave reg1 reg2 | ||
57 | * | ||
58 | * Unwind annotation macro is corresponding for 'enter' macro. | ||
59 | * It tell unwinder that preserved some provided registers on the stack | ||
60 | * and additional data by a prior 'enter' macro. | ||
61 | * | ||
56 | * exit reg1 reg2 | 62 | * exit reg1 reg2 |
57 | * | 63 | * |
58 | * Restore registers with the values previously saved with the | 64 | * Restore registers with the values previously saved with the |
@@ -67,7 +73,12 @@ | |||
67 | */ | 73 | */ |
68 | 74 | ||
69 | 75 | ||
76 | UNWIND( .fnstart ) | ||
70 | enter r4, lr | 77 | enter r4, lr |
78 | UNWIND( .fnend ) | ||
79 | |||
80 | UNWIND( .fnstart ) | ||
81 | usave r4, lr @ in first stmdb block | ||
71 | 82 | ||
72 | subs r2, r2, #4 | 83 | subs r2, r2, #4 |
73 | blt 8f | 84 | blt 8f |
@@ -79,6 +90,11 @@ | |||
79 | 90 | ||
80 | 1: subs r2, r2, #(28) | 91 | 1: subs r2, r2, #(28) |
81 | stmfd sp!, {r5 - r8} | 92 | stmfd sp!, {r5 - r8} |
93 | UNWIND( .fnend ) | ||
94 | |||
95 | UNWIND( .fnstart ) | ||
96 | usave r4, lr | ||
97 | UNWIND( .save {r5 - r8} ) @ in second stmfd block | ||
82 | blt 5f | 98 | blt 5f |
83 | 99 | ||
84 | CALGN( ands ip, r0, #31 ) | 100 | CALGN( ands ip, r0, #31 ) |
@@ -144,7 +160,10 @@ | |||
144 | CALGN( bcs 2b ) | 160 | CALGN( bcs 2b ) |
145 | 161 | ||
146 | 7: ldmfd sp!, {r5 - r8} | 162 | 7: ldmfd sp!, {r5 - r8} |
163 | UNWIND( .fnend ) @ end of second stmfd block | ||
147 | 164 | ||
165 | UNWIND( .fnstart ) | ||
166 | usave r4, lr @ still in first stmdb block | ||
148 | 8: movs r2, r2, lsl #31 | 167 | 8: movs r2, r2, lsl #31 |
149 | ldr1b r1, r3, ne, abort=21f | 168 | ldr1b r1, r3, ne, abort=21f |
150 | ldr1b r1, r4, cs, abort=21f | 169 | ldr1b r1, r4, cs, abort=21f |
@@ -173,10 +192,13 @@ | |||
173 | ldr1w r1, lr, abort=21f | 192 | ldr1w r1, lr, abort=21f |
174 | beq 17f | 193 | beq 17f |
175 | bgt 18f | 194 | bgt 18f |
195 | UNWIND( .fnend ) | ||
176 | 196 | ||
177 | 197 | ||
178 | .macro forward_copy_shift pull push | 198 | .macro forward_copy_shift pull push |
179 | 199 | ||
200 | UNWIND( .fnstart ) | ||
201 | usave r4, lr @ still in first stmdb block | ||
180 | subs r2, r2, #28 | 202 | subs r2, r2, #28 |
181 | blt 14f | 203 | blt 14f |
182 | 204 | ||
@@ -187,7 +209,11 @@ | |||
187 | CALGN( bcc 15f ) | 209 | CALGN( bcc 15f ) |
188 | 210 | ||
189 | 11: stmfd sp!, {r5 - r9} | 211 | 11: stmfd sp!, {r5 - r9} |
212 | UNWIND( .fnend ) | ||
190 | 213 | ||
214 | UNWIND( .fnstart ) | ||
215 | usave r4, lr | ||
216 | UNWIND( .save {r5 - r9} ) @ in new second stmfd block | ||
191 | PLD( pld [r1, #0] ) | 217 | PLD( pld [r1, #0] ) |
192 | PLD( subs r2, r2, #96 ) | 218 | PLD( subs r2, r2, #96 ) |
193 | PLD( pld [r1, #28] ) | 219 | PLD( pld [r1, #28] ) |
@@ -221,7 +247,10 @@ | |||
221 | PLD( bge 13b ) | 247 | PLD( bge 13b ) |
222 | 248 | ||
223 | ldmfd sp!, {r5 - r9} | 249 | ldmfd sp!, {r5 - r9} |
250 | UNWIND( .fnend ) @ end of the second stmfd block | ||
224 | 251 | ||
252 | UNWIND( .fnstart ) | ||
253 | usave r4, lr @ still in first stmdb block | ||
225 | 14: ands ip, r2, #28 | 254 | 14: ands ip, r2, #28 |
226 | beq 16f | 255 | beq 16f |
227 | 256 | ||
@@ -236,6 +265,7 @@ | |||
236 | 265 | ||
237 | 16: sub r1, r1, #(\push / 8) | 266 | 16: sub r1, r1, #(\push / 8) |
238 | b 8b | 267 | b 8b |
268 | UNWIND( .fnend ) | ||
239 | 269 | ||
240 | .endm | 270 | .endm |
241 | 271 | ||
diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S index d066df686e17..a9d3db16ecb5 100644 --- a/arch/arm/lib/copy_to_user.S +++ b/arch/arm/lib/copy_to_user.S | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <asm/assembler.h> | 14 | #include <asm/assembler.h> |
15 | #include <asm/unwind.h> | ||
15 | 16 | ||
16 | /* | 17 | /* |
17 | * Prototype: | 18 | * Prototype: |
@@ -80,6 +81,10 @@ | |||
80 | stmdb sp!, {r0, r2, r3, \reg1, \reg2} | 81 | stmdb sp!, {r0, r2, r3, \reg1, \reg2} |
81 | .endm | 82 | .endm |
82 | 83 | ||
84 | .macro usave reg1 reg2 | ||
85 | UNWIND( .save {r0, r2, r3, \reg1, \reg2} ) | ||
86 | .endm | ||
87 | |||
83 | .macro exit reg1 reg2 | 88 | .macro exit reg1 reg2 |
84 | add sp, sp, #8 | 89 | add sp, sp, #8 |
85 | ldmfd sp!, {r0, \reg1, \reg2} | 90 | ldmfd sp!, {r0, \reg1, \reg2} |
diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S index a9b9e2287a09..7797e81e40e0 100644 --- a/arch/arm/lib/memcpy.S +++ b/arch/arm/lib/memcpy.S | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <asm/assembler.h> | 14 | #include <asm/assembler.h> |
15 | #include <asm/unwind.h> | ||
15 | 16 | ||
16 | #define LDR1W_SHIFT 0 | 17 | #define LDR1W_SHIFT 0 |
17 | #define STR1W_SHIFT 0 | 18 | #define STR1W_SHIFT 0 |
@@ -48,6 +49,10 @@ | |||
48 | stmdb sp!, {r0, \reg1, \reg2} | 49 | stmdb sp!, {r0, \reg1, \reg2} |
49 | .endm | 50 | .endm |
50 | 51 | ||
52 | .macro usave reg1 reg2 | ||
53 | UNWIND( .save {r0, \reg1, \reg2} ) | ||
54 | .endm | ||
55 | |||
51 | .macro exit reg1 reg2 | 56 | .macro exit reg1 reg2 |
52 | ldmfd sp!, {r0, \reg1, \reg2} | 57 | ldmfd sp!, {r0, \reg1, \reg2} |
53 | .endm | 58 | .endm |
diff --git a/arch/arm/lib/memmove.S b/arch/arm/lib/memmove.S index d1fc0c0c342c..69a9d47fc5ab 100644 --- a/arch/arm/lib/memmove.S +++ b/arch/arm/lib/memmove.S | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <asm/assembler.h> | 14 | #include <asm/assembler.h> |
15 | #include <asm/unwind.h> | ||
15 | 16 | ||
16 | .text | 17 | .text |
17 | 18 | ||
@@ -27,12 +28,17 @@ | |||
27 | */ | 28 | */ |
28 | 29 | ||
29 | ENTRY(memmove) | 30 | ENTRY(memmove) |
31 | UNWIND( .fnstart ) | ||
30 | 32 | ||
31 | subs ip, r0, r1 | 33 | subs ip, r0, r1 |
32 | cmphi r2, ip | 34 | cmphi r2, ip |
33 | bls memcpy | 35 | bls memcpy |
34 | 36 | ||
35 | stmfd sp!, {r0, r4, lr} | 37 | stmfd sp!, {r0, r4, lr} |
38 | UNWIND( .fnend ) | ||
39 | |||
40 | UNWIND( .fnstart ) | ||
41 | UNWIND( .save {r0, r4, lr} ) @ in first stmfd block | ||
36 | add r1, r1, r2 | 42 | add r1, r1, r2 |
37 | add r0, r0, r2 | 43 | add r0, r0, r2 |
38 | subs r2, r2, #4 | 44 | subs r2, r2, #4 |
@@ -45,6 +51,11 @@ ENTRY(memmove) | |||
45 | 51 | ||
46 | 1: subs r2, r2, #(28) | 52 | 1: subs r2, r2, #(28) |
47 | stmfd sp!, {r5 - r8} | 53 | stmfd sp!, {r5 - r8} |
54 | UNWIND( .fnend ) | ||
55 | |||
56 | UNWIND( .fnstart ) | ||
57 | UNWIND( .save {r0, r4, lr} ) | ||
58 | UNWIND( .save {r5 - r8} ) @ in second stmfd block | ||
48 | blt 5f | 59 | blt 5f |
49 | 60 | ||
50 | CALGN( ands ip, r0, #31 ) | 61 | CALGN( ands ip, r0, #31 ) |
@@ -97,6 +108,10 @@ ENTRY(memmove) | |||
97 | CALGN( bcs 2b ) | 108 | CALGN( bcs 2b ) |
98 | 109 | ||
99 | 7: ldmfd sp!, {r5 - r8} | 110 | 7: ldmfd sp!, {r5 - r8} |
111 | UNWIND( .fnend ) @ end of second stmfd block | ||
112 | |||
113 | UNWIND( .fnstart ) | ||
114 | UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block | ||
100 | 115 | ||
101 | 8: movs r2, r2, lsl #31 | 116 | 8: movs r2, r2, lsl #31 |
102 | ldrneb r3, [r1, #-1]! | 117 | ldrneb r3, [r1, #-1]! |
@@ -124,10 +139,13 @@ ENTRY(memmove) | |||
124 | ldr r3, [r1, #0] | 139 | ldr r3, [r1, #0] |
125 | beq 17f | 140 | beq 17f |
126 | blt 18f | 141 | blt 18f |
142 | UNWIND( .fnend ) | ||
127 | 143 | ||
128 | 144 | ||
129 | .macro backward_copy_shift push pull | 145 | .macro backward_copy_shift push pull |
130 | 146 | ||
147 | UNWIND( .fnstart ) | ||
148 | UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block | ||
131 | subs r2, r2, #28 | 149 | subs r2, r2, #28 |
132 | blt 14f | 150 | blt 14f |
133 | 151 | ||
@@ -137,6 +155,11 @@ ENTRY(memmove) | |||
137 | CALGN( bcc 15f ) | 155 | CALGN( bcc 15f ) |
138 | 156 | ||
139 | 11: stmfd sp!, {r5 - r9} | 157 | 11: stmfd sp!, {r5 - r9} |
158 | UNWIND( .fnend ) | ||
159 | |||
160 | UNWIND( .fnstart ) | ||
161 | UNWIND( .save {r0, r4, lr} ) | ||
162 | UNWIND( .save {r5 - r9} ) @ in new second stmfd block | ||
140 | 163 | ||
141 | PLD( pld [r1, #-4] ) | 164 | PLD( pld [r1, #-4] ) |
142 | PLD( subs r2, r2, #96 ) | 165 | PLD( subs r2, r2, #96 ) |
@@ -171,6 +194,10 @@ ENTRY(memmove) | |||
171 | PLD( bge 13b ) | 194 | PLD( bge 13b ) |
172 | 195 | ||
173 | ldmfd sp!, {r5 - r9} | 196 | ldmfd sp!, {r5 - r9} |
197 | UNWIND( .fnend ) @ end of the second stmfd block | ||
198 | |||
199 | UNWIND( .fnstart ) | ||
200 | UNWIND( .save {r0, r4, lr} ) @ still in first stmfd block | ||
174 | 201 | ||
175 | 14: ands ip, r2, #28 | 202 | 14: ands ip, r2, #28 |
176 | beq 16f | 203 | beq 16f |
@@ -186,6 +213,7 @@ ENTRY(memmove) | |||
186 | 213 | ||
187 | 16: add r1, r1, #(\pull / 8) | 214 | 16: add r1, r1, #(\pull / 8) |
188 | b 8b | 215 | b 8b |
216 | UNWIND( .fnend ) | ||
189 | 217 | ||
190 | .endm | 218 | .endm |
191 | 219 | ||
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index 671455c854fa..a4ee97b5a2bf 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S | |||
@@ -11,11 +11,13 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/linkage.h> | 12 | #include <linux/linkage.h> |
13 | #include <asm/assembler.h> | 13 | #include <asm/assembler.h> |
14 | #include <asm/unwind.h> | ||
14 | 15 | ||
15 | .text | 16 | .text |
16 | .align 5 | 17 | .align 5 |
17 | 18 | ||
18 | ENTRY(memset) | 19 | ENTRY(memset) |
20 | UNWIND( .fnstart ) | ||
19 | ands r3, r0, #3 @ 1 unaligned? | 21 | ands r3, r0, #3 @ 1 unaligned? |
20 | mov ip, r0 @ preserve r0 as return value | 22 | mov ip, r0 @ preserve r0 as return value |
21 | bne 6f @ 1 | 23 | bne 6f @ 1 |
@@ -34,6 +36,9 @@ ENTRY(memset) | |||
34 | * We need 2 extra registers for this loop - use r8 and the LR | 36 | * We need 2 extra registers for this loop - use r8 and the LR |
35 | */ | 37 | */ |
36 | stmfd sp!, {r8, lr} | 38 | stmfd sp!, {r8, lr} |
39 | UNWIND( .fnend ) | ||
40 | UNWIND( .fnstart ) | ||
41 | UNWIND( .save {r8, lr} ) | ||
37 | mov r8, r1 | 42 | mov r8, r1 |
38 | mov lr, r1 | 43 | mov lr, r1 |
39 | 44 | ||
@@ -53,6 +58,7 @@ ENTRY(memset) | |||
53 | tst r2, #16 | 58 | tst r2, #16 |
54 | stmneia ip!, {r1, r3, r8, lr} | 59 | stmneia ip!, {r1, r3, r8, lr} |
55 | ldmfd sp!, {r8, lr} | 60 | ldmfd sp!, {r8, lr} |
61 | UNWIND( .fnend ) | ||
56 | 62 | ||
57 | #else | 63 | #else |
58 | 64 | ||
@@ -62,6 +68,9 @@ ENTRY(memset) | |||
62 | */ | 68 | */ |
63 | 69 | ||
64 | stmfd sp!, {r4-r8, lr} | 70 | stmfd sp!, {r4-r8, lr} |
71 | UNWIND( .fnend ) | ||
72 | UNWIND( .fnstart ) | ||
73 | UNWIND( .save {r4-r8, lr} ) | ||
65 | mov r4, r1 | 74 | mov r4, r1 |
66 | mov r5, r1 | 75 | mov r5, r1 |
67 | mov r6, r1 | 76 | mov r6, r1 |
@@ -94,9 +103,11 @@ ENTRY(memset) | |||
94 | tst r2, #16 | 103 | tst r2, #16 |
95 | stmneia ip!, {r4-r7} | 104 | stmneia ip!, {r4-r7} |
96 | ldmfd sp!, {r4-r8, lr} | 105 | ldmfd sp!, {r4-r8, lr} |
106 | UNWIND( .fnend ) | ||
97 | 107 | ||
98 | #endif | 108 | #endif |
99 | 109 | ||
110 | UNWIND( .fnstart ) | ||
100 | 4: tst r2, #8 | 111 | 4: tst r2, #8 |
101 | stmneia ip!, {r1, r3} | 112 | stmneia ip!, {r1, r3} |
102 | tst r2, #4 | 113 | tst r2, #4 |
@@ -120,4 +131,5 @@ ENTRY(memset) | |||
120 | strb r1, [ip], #1 @ 1 | 131 | strb r1, [ip], #1 @ 1 |
121 | add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) | 132 | add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) |
122 | b 1b | 133 | b 1b |
134 | UNWIND( .fnend ) | ||
123 | ENDPROC(memset) | 135 | ENDPROC(memset) |
diff --git a/arch/arm/lib/memzero.S b/arch/arm/lib/memzero.S index 385ccb306fa2..0eded952e089 100644 --- a/arch/arm/lib/memzero.S +++ b/arch/arm/lib/memzero.S | |||
@@ -9,6 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | #include <linux/linkage.h> | 10 | #include <linux/linkage.h> |
11 | #include <asm/assembler.h> | 11 | #include <asm/assembler.h> |
12 | #include <asm/unwind.h> | ||
12 | 13 | ||
13 | .text | 14 | .text |
14 | .align 5 | 15 | .align 5 |
@@ -18,6 +19,7 @@ | |||
18 | * mis-aligned by, and r1 is the number of bytes. If r1 < 4, then we | 19 | * mis-aligned by, and r1 is the number of bytes. If r1 < 4, then we |
19 | * don't bother; we use byte stores instead. | 20 | * don't bother; we use byte stores instead. |
20 | */ | 21 | */ |
22 | UNWIND( .fnstart ) | ||
21 | 1: subs r1, r1, #4 @ 1 do we have enough | 23 | 1: subs r1, r1, #4 @ 1 do we have enough |
22 | blt 5f @ 1 bytes to align with? | 24 | blt 5f @ 1 bytes to align with? |
23 | cmp r3, #2 @ 1 | 25 | cmp r3, #2 @ 1 |
@@ -47,6 +49,9 @@ ENTRY(__memzero) | |||
47 | * use the LR | 49 | * use the LR |
48 | */ | 50 | */ |
49 | str lr, [sp, #-4]! @ 1 | 51 | str lr, [sp, #-4]! @ 1 |
52 | UNWIND( .fnend ) | ||
53 | UNWIND( .fnstart ) | ||
54 | UNWIND( .save {lr} ) | ||
50 | mov ip, r2 @ 1 | 55 | mov ip, r2 @ 1 |
51 | mov lr, r2 @ 1 | 56 | mov lr, r2 @ 1 |
52 | 57 | ||
@@ -66,6 +71,7 @@ ENTRY(__memzero) | |||
66 | tst r1, #16 @ 1 16 bytes or more? | 71 | tst r1, #16 @ 1 16 bytes or more? |
67 | stmneia r0!, {r2, r3, ip, lr} @ 4 | 72 | stmneia r0!, {r2, r3, ip, lr} @ 4 |
68 | ldr lr, [sp], #4 @ 1 | 73 | ldr lr, [sp], #4 @ 1 |
74 | UNWIND( .fnend ) | ||
69 | 75 | ||
70 | #else | 76 | #else |
71 | 77 | ||
@@ -75,6 +81,9 @@ ENTRY(__memzero) | |||
75 | */ | 81 | */ |
76 | 82 | ||
77 | stmfd sp!, {r4-r7, lr} | 83 | stmfd sp!, {r4-r7, lr} |
84 | UNWIND( .fnend ) | ||
85 | UNWIND( .fnstart ) | ||
86 | UNWIND( .save {r4-r7, lr} ) | ||
78 | mov r4, r2 | 87 | mov r4, r2 |
79 | mov r5, r2 | 88 | mov r5, r2 |
80 | mov r6, r2 | 89 | mov r6, r2 |
@@ -105,9 +114,11 @@ ENTRY(__memzero) | |||
105 | tst r1, #16 | 114 | tst r1, #16 |
106 | stmneia r0!, {r4-r7} | 115 | stmneia r0!, {r4-r7} |
107 | ldmfd sp!, {r4-r7, lr} | 116 | ldmfd sp!, {r4-r7, lr} |
117 | UNWIND( .fnend ) | ||
108 | 118 | ||
109 | #endif | 119 | #endif |
110 | 120 | ||
121 | UNWIND( .fnstart ) | ||
111 | 4: tst r1, #8 @ 1 8 bytes or more? | 122 | 4: tst r1, #8 @ 1 8 bytes or more? |
112 | stmneia r0!, {r2, r3} @ 2 | 123 | stmneia r0!, {r2, r3} @ 2 |
113 | tst r1, #4 @ 1 4 bytes or more? | 124 | tst r1, #4 @ 1 4 bytes or more? |
@@ -122,4 +133,5 @@ ENTRY(__memzero) | |||
122 | tst r1, #1 @ 1 a byte left over | 133 | tst r1, #1 @ 1 a byte left over |
123 | strneb r2, [r0], #1 @ 1 | 134 | strneb r2, [r0], #1 @ 1 |
124 | ret lr @ 1 | 135 | ret lr @ 1 |
136 | UNWIND( .fnend ) | ||
125 | ENDPROC(__memzero) | 137 | ENDPROC(__memzero) |
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index b9e3f1c61baf..e4a00bafffc1 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig | |||
@@ -34,7 +34,7 @@ config ARCH_EXYNOS3 | |||
34 | bool "SAMSUNG EXYNOS3" | 34 | bool "SAMSUNG EXYNOS3" |
35 | select ARM_CPU_SUSPEND if PM | 35 | select ARM_CPU_SUSPEND if PM |
36 | help | 36 | help |
37 | Samsung EXYNOS3 (Crotex-A7) SoC based systems | 37 | Samsung EXYNOS3 (Cortex-A7) SoC based systems |
38 | 38 | ||
39 | config ARCH_EXYNOS4 | 39 | config ARCH_EXYNOS4 |
40 | bool "SAMSUNG EXYNOS4" | 40 | bool "SAMSUNG EXYNOS4" |
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c index 9fa6a990cf03..03c75a811cb0 100644 --- a/arch/arm/mach-sa1100/clock.c +++ b/arch/arm/mach-sa1100/clock.c | |||
@@ -15,10 +15,12 @@ | |||
15 | #include <linux/clkdev.h> | 15 | #include <linux/clkdev.h> |
16 | 16 | ||
17 | #include <mach/hardware.h> | 17 | #include <mach/hardware.h> |
18 | #include <mach/generic.h> | ||
18 | 19 | ||
19 | struct clkops { | 20 | struct clkops { |
20 | void (*enable)(struct clk *); | 21 | void (*enable)(struct clk *); |
21 | void (*disable)(struct clk *); | 22 | void (*disable)(struct clk *); |
23 | unsigned long (*get_rate)(struct clk *); | ||
22 | }; | 24 | }; |
23 | 25 | ||
24 | struct clk { | 26 | struct clk { |
@@ -33,13 +35,6 @@ struct clk clk_##_name = { \ | |||
33 | 35 | ||
34 | static DEFINE_SPINLOCK(clocks_lock); | 36 | static DEFINE_SPINLOCK(clocks_lock); |
35 | 37 | ||
36 | /* Dummy clk routine to build generic kernel parts that may be using them */ | ||
37 | unsigned long clk_get_rate(struct clk *clk) | ||
38 | { | ||
39 | return 0; | ||
40 | } | ||
41 | EXPORT_SYMBOL(clk_get_rate); | ||
42 | |||
43 | static void clk_gpio27_enable(struct clk *clk) | 38 | static void clk_gpio27_enable(struct clk *clk) |
44 | { | 39 | { |
45 | /* | 40 | /* |
@@ -58,6 +53,19 @@ static void clk_gpio27_disable(struct clk *clk) | |||
58 | GAFR &= ~GPIO_32_768kHz; | 53 | GAFR &= ~GPIO_32_768kHz; |
59 | } | 54 | } |
60 | 55 | ||
56 | static void clk_cpu_enable(struct clk *clk) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | static void clk_cpu_disable(struct clk *clk) | ||
61 | { | ||
62 | } | ||
63 | |||
64 | static unsigned long clk_cpu_get_rate(struct clk *clk) | ||
65 | { | ||
66 | return sa11x0_getspeed(0) * 1000; | ||
67 | } | ||
68 | |||
61 | int clk_enable(struct clk *clk) | 69 | int clk_enable(struct clk *clk) |
62 | { | 70 | { |
63 | unsigned long flags; | 71 | unsigned long flags; |
@@ -87,16 +95,37 @@ void clk_disable(struct clk *clk) | |||
87 | } | 95 | } |
88 | EXPORT_SYMBOL(clk_disable); | 96 | EXPORT_SYMBOL(clk_disable); |
89 | 97 | ||
98 | unsigned long clk_get_rate(struct clk *clk) | ||
99 | { | ||
100 | if (clk && clk->ops && clk->ops->get_rate) | ||
101 | return clk->ops->get_rate(clk); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | EXPORT_SYMBOL(clk_get_rate); | ||
106 | |||
90 | const struct clkops clk_gpio27_ops = { | 107 | const struct clkops clk_gpio27_ops = { |
91 | .enable = clk_gpio27_enable, | 108 | .enable = clk_gpio27_enable, |
92 | .disable = clk_gpio27_disable, | 109 | .disable = clk_gpio27_disable, |
93 | }; | 110 | }; |
94 | 111 | ||
112 | const struct clkops clk_cpu_ops = { | ||
113 | .enable = clk_cpu_enable, | ||
114 | .disable = clk_cpu_disable, | ||
115 | .get_rate = clk_cpu_get_rate, | ||
116 | }; | ||
117 | |||
95 | static DEFINE_CLK(gpio27, &clk_gpio27_ops); | 118 | static DEFINE_CLK(gpio27, &clk_gpio27_ops); |
96 | 119 | ||
120 | static DEFINE_CLK(cpu, &clk_cpu_ops); | ||
121 | |||
97 | static struct clk_lookup sa11xx_clkregs[] = { | 122 | static struct clk_lookup sa11xx_clkregs[] = { |
98 | CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27), | 123 | CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27), |
99 | CLKDEV_INIT("sa1100-rtc", NULL, NULL), | 124 | CLKDEV_INIT("sa1100-rtc", NULL, NULL), |
125 | CLKDEV_INIT("sa11x0-fb", NULL, &clk_cpu), | ||
126 | CLKDEV_INIT("sa11x0-pcmcia", NULL, &clk_cpu), | ||
127 | /* sa1111 names devices using internal offsets, PCMCIA is at 0x1800 */ | ||
128 | CLKDEV_INIT("1800", NULL, &clk_cpu), | ||
100 | }; | 129 | }; |
101 | 130 | ||
102 | static int __init sa11xx_clk_init(void) | 131 | static int __init sa11xx_clk_init(void) |
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 108939f8d053..b90c7d828391 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/gpio_keys.h> | 30 | #include <linux/gpio_keys.h> |
31 | #include <linux/input.h> | 31 | #include <linux/input.h> |
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/pda_power.h> | 33 | #include <linux/power/gpio-charger.h> |
34 | 34 | ||
35 | #include <video/sa1100fb.h> | 35 | #include <video/sa1100fb.h> |
36 | 36 | ||
@@ -131,62 +131,24 @@ static struct irda_platform_data collie_ir_data = { | |||
131 | /* | 131 | /* |
132 | * Collie AC IN | 132 | * Collie AC IN |
133 | */ | 133 | */ |
134 | static int collie_power_init(struct device *dev) | ||
135 | { | ||
136 | int ret = gpio_request(COLLIE_GPIO_AC_IN, "ac in"); | ||
137 | if (ret) | ||
138 | goto err_gpio_req; | ||
139 | |||
140 | ret = gpio_direction_input(COLLIE_GPIO_AC_IN); | ||
141 | if (ret) | ||
142 | goto err_gpio_in; | ||
143 | |||
144 | return 0; | ||
145 | |||
146 | err_gpio_in: | ||
147 | gpio_free(COLLIE_GPIO_AC_IN); | ||
148 | err_gpio_req: | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | static void collie_power_exit(struct device *dev) | ||
153 | { | ||
154 | gpio_free(COLLIE_GPIO_AC_IN); | ||
155 | } | ||
156 | |||
157 | static int collie_power_ac_online(void) | ||
158 | { | ||
159 | return gpio_get_value(COLLIE_GPIO_AC_IN) == 2; | ||
160 | } | ||
161 | |||
162 | static char *collie_ac_supplied_to[] = { | 134 | static char *collie_ac_supplied_to[] = { |
163 | "main-battery", | 135 | "main-battery", |
164 | "backup-battery", | 136 | "backup-battery", |
165 | }; | 137 | }; |
166 | 138 | ||
167 | static struct pda_power_pdata collie_power_data = { | 139 | |
168 | .init = collie_power_init, | 140 | static struct gpio_charger_platform_data collie_power_data = { |
169 | .is_ac_online = collie_power_ac_online, | 141 | .name = "charger", |
170 | .exit = collie_power_exit, | 142 | .type = POWER_SUPPLY_TYPE_MAINS, |
143 | .gpio = COLLIE_GPIO_AC_IN, | ||
171 | .supplied_to = collie_ac_supplied_to, | 144 | .supplied_to = collie_ac_supplied_to, |
172 | .num_supplicants = ARRAY_SIZE(collie_ac_supplied_to), | 145 | .num_supplicants = ARRAY_SIZE(collie_ac_supplied_to), |
173 | }; | 146 | }; |
174 | 147 | ||
175 | static struct resource collie_power_resource[] = { | ||
176 | { | ||
177 | .name = "ac", | ||
178 | .flags = IORESOURCE_IRQ | | ||
179 | IORESOURCE_IRQ_HIGHEDGE | | ||
180 | IORESOURCE_IRQ_LOWEDGE, | ||
181 | }, | ||
182 | }; | ||
183 | |||
184 | static struct platform_device collie_power_device = { | 148 | static struct platform_device collie_power_device = { |
185 | .name = "pda-power", | 149 | .name = "gpio-charger", |
186 | .id = -1, | 150 | .id = -1, |
187 | .dev.platform_data = &collie_power_data, | 151 | .dev.platform_data = &collie_power_data, |
188 | .resource = collie_power_resource, | ||
189 | .num_resources = ARRAY_SIZE(collie_power_resource), | ||
190 | }; | 152 | }; |
191 | 153 | ||
192 | #ifdef CONFIG_SHARP_LOCOMO | 154 | #ifdef CONFIG_SHARP_LOCOMO |
@@ -420,9 +382,6 @@ static void __init collie_init(void) | |||
420 | 382 | ||
421 | GPSR |= _COLLIE_GPIO_UCB1x00_RESET; | 383 | GPSR |= _COLLIE_GPIO_UCB1x00_RESET; |
422 | 384 | ||
423 | collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN); | ||
424 | collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN); | ||
425 | |||
426 | sa11x0_ppc_configure_mcp(); | 385 | sa11x0_ppc_configure_mcp(); |
427 | 386 | ||
428 | 387 | ||
diff --git a/arch/arm/mach-sa1100/include/mach/entry-macro.S b/arch/arm/mach-sa1100/include/mach/entry-macro.S deleted file mode 100644 index 8cf7630bf024..000000000000 --- a/arch/arm/mach-sa1100/include/mach/entry-macro.S +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-sa1100/include/mach/entry-macro.S | ||
3 | * | ||
4 | * Low-level IRQ helper macros for SA1100-based platforms | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | .macro get_irqnr_preamble, base, tmp | ||
12 | mov \base, #0xfa000000 @ ICIP = 0xfa050000 | ||
13 | add \base, \base, #0x00050000 | ||
14 | .endm | ||
15 | |||
16 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
17 | ldr \irqstat, [\base] @ get irqs | ||
18 | ldr \irqnr, [\base, #4] @ ICMR = 0xfa050004 | ||
19 | ands \irqstat, \irqstat, \irqnr | ||
20 | mov \irqnr, #0 | ||
21 | beq 1001f | ||
22 | tst \irqstat, #0xff | ||
23 | moveq \irqstat, \irqstat, lsr #8 | ||
24 | addeq \irqnr, \irqnr, #8 | ||
25 | tsteq \irqstat, #0xff | ||
26 | moveq \irqstat, \irqstat, lsr #8 | ||
27 | addeq \irqnr, \irqnr, #8 | ||
28 | tsteq \irqstat, #0xff | ||
29 | moveq \irqstat, \irqstat, lsr #8 | ||
30 | addeq \irqnr, \irqnr, #8 | ||
31 | tst \irqstat, #0x0f | ||
32 | moveq \irqstat, \irqstat, lsr #4 | ||
33 | addeq \irqnr, \irqnr, #4 | ||
34 | tst \irqstat, #0x03 | ||
35 | moveq \irqstat, \irqstat, lsr #2 | ||
36 | addeq \irqnr, \irqnr, #2 | ||
37 | tst \irqstat, #0x01 | ||
38 | addeqs \irqnr, \irqnr, #1 | ||
39 | 1001: | ||
40 | .endm | ||
41 | |||
diff --git a/arch/arm/mach-sa1100/include/mach/irqs.h b/arch/arm/mach-sa1100/include/mach/irqs.h index 3790298b7142..de0983494c7e 100644 --- a/arch/arm/mach-sa1100/include/mach/irqs.h +++ b/arch/arm/mach-sa1100/include/mach/irqs.h | |||
@@ -8,56 +8,56 @@ | |||
8 | * 2001/11/14 RMK Cleaned up and standardised a lot of the IRQs. | 8 | * 2001/11/14 RMK Cleaned up and standardised a lot of the IRQs. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define IRQ_GPIO0 0 | 11 | #define IRQ_GPIO0 1 |
12 | #define IRQ_GPIO1 1 | 12 | #define IRQ_GPIO1 2 |
13 | #define IRQ_GPIO2 2 | 13 | #define IRQ_GPIO2 3 |
14 | #define IRQ_GPIO3 3 | 14 | #define IRQ_GPIO3 4 |
15 | #define IRQ_GPIO4 4 | 15 | #define IRQ_GPIO4 5 |
16 | #define IRQ_GPIO5 5 | 16 | #define IRQ_GPIO5 6 |
17 | #define IRQ_GPIO6 6 | 17 | #define IRQ_GPIO6 7 |
18 | #define IRQ_GPIO7 7 | 18 | #define IRQ_GPIO7 8 |
19 | #define IRQ_GPIO8 8 | 19 | #define IRQ_GPIO8 9 |
20 | #define IRQ_GPIO9 9 | 20 | #define IRQ_GPIO9 10 |
21 | #define IRQ_GPIO10 10 | 21 | #define IRQ_GPIO10 11 |
22 | #define IRQ_GPIO11_27 11 | 22 | #define IRQ_GPIO11_27 12 |
23 | #define IRQ_LCD 12 /* LCD controller */ | 23 | #define IRQ_LCD 13 /* LCD controller */ |
24 | #define IRQ_Ser0UDC 13 /* Ser. port 0 UDC */ | 24 | #define IRQ_Ser0UDC 14 /* Ser. port 0 UDC */ |
25 | #define IRQ_Ser1SDLC 14 /* Ser. port 1 SDLC */ | 25 | #define IRQ_Ser1SDLC 15 /* Ser. port 1 SDLC */ |
26 | #define IRQ_Ser1UART 15 /* Ser. port 1 UART */ | 26 | #define IRQ_Ser1UART 16 /* Ser. port 1 UART */ |
27 | #define IRQ_Ser2ICP 16 /* Ser. port 2 ICP */ | 27 | #define IRQ_Ser2ICP 17 /* Ser. port 2 ICP */ |
28 | #define IRQ_Ser3UART 17 /* Ser. port 3 UART */ | 28 | #define IRQ_Ser3UART 18 /* Ser. port 3 UART */ |
29 | #define IRQ_Ser4MCP 18 /* Ser. port 4 MCP */ | 29 | #define IRQ_Ser4MCP 19 /* Ser. port 4 MCP */ |
30 | #define IRQ_Ser4SSP 19 /* Ser. port 4 SSP */ | 30 | #define IRQ_Ser4SSP 20 /* Ser. port 4 SSP */ |
31 | #define IRQ_DMA0 20 /* DMA controller channel 0 */ | 31 | #define IRQ_DMA0 21 /* DMA controller channel 0 */ |
32 | #define IRQ_DMA1 21 /* DMA controller channel 1 */ | 32 | #define IRQ_DMA1 22 /* DMA controller channel 1 */ |
33 | #define IRQ_DMA2 22 /* DMA controller channel 2 */ | 33 | #define IRQ_DMA2 23 /* DMA controller channel 2 */ |
34 | #define IRQ_DMA3 23 /* DMA controller channel 3 */ | 34 | #define IRQ_DMA3 24 /* DMA controller channel 3 */ |
35 | #define IRQ_DMA4 24 /* DMA controller channel 4 */ | 35 | #define IRQ_DMA4 25 /* DMA controller channel 4 */ |
36 | #define IRQ_DMA5 25 /* DMA controller channel 5 */ | 36 | #define IRQ_DMA5 26 /* DMA controller channel 5 */ |
37 | #define IRQ_OST0 26 /* OS Timer match 0 */ | 37 | #define IRQ_OST0 27 /* OS Timer match 0 */ |
38 | #define IRQ_OST1 27 /* OS Timer match 1 */ | 38 | #define IRQ_OST1 28 /* OS Timer match 1 */ |
39 | #define IRQ_OST2 28 /* OS Timer match 2 */ | 39 | #define IRQ_OST2 29 /* OS Timer match 2 */ |
40 | #define IRQ_OST3 29 /* OS Timer match 3 */ | 40 | #define IRQ_OST3 30 /* OS Timer match 3 */ |
41 | #define IRQ_RTC1Hz 30 /* RTC 1 Hz clock */ | 41 | #define IRQ_RTC1Hz 31 /* RTC 1 Hz clock */ |
42 | #define IRQ_RTCAlrm 31 /* RTC Alarm */ | 42 | #define IRQ_RTCAlrm 32 /* RTC Alarm */ |
43 | 43 | ||
44 | #define IRQ_GPIO11 32 | 44 | #define IRQ_GPIO11 33 |
45 | #define IRQ_GPIO12 33 | 45 | #define IRQ_GPIO12 34 |
46 | #define IRQ_GPIO13 34 | 46 | #define IRQ_GPIO13 35 |
47 | #define IRQ_GPIO14 35 | 47 | #define IRQ_GPIO14 36 |
48 | #define IRQ_GPIO15 36 | 48 | #define IRQ_GPIO15 37 |
49 | #define IRQ_GPIO16 37 | 49 | #define IRQ_GPIO16 38 |
50 | #define IRQ_GPIO17 38 | 50 | #define IRQ_GPIO17 39 |
51 | #define IRQ_GPIO18 39 | 51 | #define IRQ_GPIO18 40 |
52 | #define IRQ_GPIO19 40 | 52 | #define IRQ_GPIO19 41 |
53 | #define IRQ_GPIO20 41 | 53 | #define IRQ_GPIO20 42 |
54 | #define IRQ_GPIO21 42 | 54 | #define IRQ_GPIO21 43 |
55 | #define IRQ_GPIO22 43 | 55 | #define IRQ_GPIO22 44 |
56 | #define IRQ_GPIO23 44 | 56 | #define IRQ_GPIO23 45 |
57 | #define IRQ_GPIO24 45 | 57 | #define IRQ_GPIO24 46 |
58 | #define IRQ_GPIO25 46 | 58 | #define IRQ_GPIO25 47 |
59 | #define IRQ_GPIO26 47 | 59 | #define IRQ_GPIO26 48 |
60 | #define IRQ_GPIO27 48 | 60 | #define IRQ_GPIO27 49 |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * The next 16 interrupts are for board specific purposes. Since | 63 | * The next 16 interrupts are for board specific purposes. Since |
@@ -65,8 +65,8 @@ | |||
65 | * these. If you need more, increase IRQ_BOARD_END, but keep it | 65 | * these. If you need more, increase IRQ_BOARD_END, but keep it |
66 | * within sensible limits. IRQs 49 to 64 are available. | 66 | * within sensible limits. IRQs 49 to 64 are available. |
67 | */ | 67 | */ |
68 | #define IRQ_BOARD_START 49 | 68 | #define IRQ_BOARD_START 50 |
69 | #define IRQ_BOARD_END 65 | 69 | #define IRQ_BOARD_END 66 |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * Figure out the MAX IRQ number. | 72 | * Figure out the MAX IRQ number. |
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index 2124f1fc2fbe..63e2901db416 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c | |||
@@ -14,17 +14,73 @@ | |||
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
17 | #include <linux/irqdomain.h> | ||
17 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
18 | #include <linux/syscore_ops.h> | 19 | #include <linux/syscore_ops.h> |
19 | 20 | ||
20 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
21 | #include <mach/irqs.h> | 22 | #include <mach/irqs.h> |
22 | #include <asm/mach/irq.h> | 23 | #include <asm/mach/irq.h> |
24 | #include <asm/exception.h> | ||
23 | 25 | ||
24 | #include "generic.h" | 26 | #include "generic.h" |
25 | 27 | ||
26 | 28 | ||
27 | /* | 29 | /* |
30 | * We don't need to ACK IRQs on the SA1100 unless they're GPIOs | ||
31 | * this is for internal IRQs i.e. from IRQ LCD to RTCAlrm. | ||
32 | */ | ||
33 | static void sa1100_mask_irq(struct irq_data *d) | ||
34 | { | ||
35 | ICMR &= ~BIT(d->hwirq); | ||
36 | } | ||
37 | |||
38 | static void sa1100_unmask_irq(struct irq_data *d) | ||
39 | { | ||
40 | ICMR |= BIT(d->hwirq); | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * Apart form GPIOs, only the RTC alarm can be a wakeup event. | ||
45 | */ | ||
46 | static int sa1100_set_wake(struct irq_data *d, unsigned int on) | ||
47 | { | ||
48 | if (BIT(d->hwirq) == IC_RTCAlrm) { | ||
49 | if (on) | ||
50 | PWER |= PWER_RTC; | ||
51 | else | ||
52 | PWER &= ~PWER_RTC; | ||
53 | return 0; | ||
54 | } | ||
55 | return -EINVAL; | ||
56 | } | ||
57 | |||
58 | static struct irq_chip sa1100_normal_chip = { | ||
59 | .name = "SC", | ||
60 | .irq_ack = sa1100_mask_irq, | ||
61 | .irq_mask = sa1100_mask_irq, | ||
62 | .irq_unmask = sa1100_unmask_irq, | ||
63 | .irq_set_wake = sa1100_set_wake, | ||
64 | }; | ||
65 | |||
66 | static int sa1100_normal_irqdomain_map(struct irq_domain *d, | ||
67 | unsigned int irq, irq_hw_number_t hwirq) | ||
68 | { | ||
69 | irq_set_chip_and_handler(irq, &sa1100_normal_chip, | ||
70 | handle_level_irq); | ||
71 | set_irq_flags(irq, IRQF_VALID); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static struct irq_domain_ops sa1100_normal_irqdomain_ops = { | ||
77 | .map = sa1100_normal_irqdomain_map, | ||
78 | .xlate = irq_domain_xlate_onetwocell, | ||
79 | }; | ||
80 | |||
81 | static struct irq_domain *sa1100_normal_irqdomain; | ||
82 | |||
83 | /* | ||
28 | * SA1100 GPIO edge detection for IRQs: | 84 | * SA1100 GPIO edge detection for IRQs: |
29 | * IRQs are generated on Falling-Edge, Rising-Edge, or both. | 85 | * IRQs are generated on Falling-Edge, Rising-Edge, or both. |
30 | * Use this instead of directly setting GRER/GFER. | 86 | * Use this instead of directly setting GRER/GFER. |
@@ -33,20 +89,11 @@ static int GPIO_IRQ_rising_edge; | |||
33 | static int GPIO_IRQ_falling_edge; | 89 | static int GPIO_IRQ_falling_edge; |
34 | static int GPIO_IRQ_mask = (1 << 11) - 1; | 90 | static int GPIO_IRQ_mask = (1 << 11) - 1; |
35 | 91 | ||
36 | /* | ||
37 | * To get the GPIO number from an IRQ number | ||
38 | */ | ||
39 | #define GPIO_11_27_IRQ(i) ((i) - 21) | ||
40 | #define GPIO11_27_MASK(irq) (1 << GPIO_11_27_IRQ(irq)) | ||
41 | |||
42 | static int sa1100_gpio_type(struct irq_data *d, unsigned int type) | 92 | static int sa1100_gpio_type(struct irq_data *d, unsigned int type) |
43 | { | 93 | { |
44 | unsigned int mask; | 94 | unsigned int mask; |
45 | 95 | ||
46 | if (d->irq <= 10) | 96 | mask = BIT(d->hwirq); |
47 | mask = 1 << d->irq; | ||
48 | else | ||
49 | mask = GPIO11_27_MASK(d->irq); | ||
50 | 97 | ||
51 | if (type == IRQ_TYPE_PROBE) { | 98 | if (type == IRQ_TYPE_PROBE) { |
52 | if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask) | 99 | if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask) |
@@ -70,41 +117,51 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type) | |||
70 | } | 117 | } |
71 | 118 | ||
72 | /* | 119 | /* |
73 | * GPIO IRQs must be acknowledged. This is for IRQs from 0 to 10. | 120 | * GPIO IRQs must be acknowledged. |
74 | */ | 121 | */ |
75 | static void sa1100_low_gpio_ack(struct irq_data *d) | 122 | static void sa1100_gpio_ack(struct irq_data *d) |
76 | { | ||
77 | GEDR = (1 << d->irq); | ||
78 | } | ||
79 | |||
80 | static void sa1100_low_gpio_mask(struct irq_data *d) | ||
81 | { | ||
82 | ICMR &= ~(1 << d->irq); | ||
83 | } | ||
84 | |||
85 | static void sa1100_low_gpio_unmask(struct irq_data *d) | ||
86 | { | 123 | { |
87 | ICMR |= 1 << d->irq; | 124 | GEDR = BIT(d->hwirq); |
88 | } | 125 | } |
89 | 126 | ||
90 | static int sa1100_low_gpio_wake(struct irq_data *d, unsigned int on) | 127 | static int sa1100_gpio_wake(struct irq_data *d, unsigned int on) |
91 | { | 128 | { |
92 | if (on) | 129 | if (on) |
93 | PWER |= 1 << d->irq; | 130 | PWER |= BIT(d->hwirq); |
94 | else | 131 | else |
95 | PWER &= ~(1 << d->irq); | 132 | PWER &= ~BIT(d->hwirq); |
96 | return 0; | 133 | return 0; |
97 | } | 134 | } |
98 | 135 | ||
136 | /* | ||
137 | * This is for IRQs from 0 to 10. | ||
138 | */ | ||
99 | static struct irq_chip sa1100_low_gpio_chip = { | 139 | static struct irq_chip sa1100_low_gpio_chip = { |
100 | .name = "GPIO-l", | 140 | .name = "GPIO-l", |
101 | .irq_ack = sa1100_low_gpio_ack, | 141 | .irq_ack = sa1100_gpio_ack, |
102 | .irq_mask = sa1100_low_gpio_mask, | 142 | .irq_mask = sa1100_mask_irq, |
103 | .irq_unmask = sa1100_low_gpio_unmask, | 143 | .irq_unmask = sa1100_unmask_irq, |
104 | .irq_set_type = sa1100_gpio_type, | 144 | .irq_set_type = sa1100_gpio_type, |
105 | .irq_set_wake = sa1100_low_gpio_wake, | 145 | .irq_set_wake = sa1100_gpio_wake, |
146 | }; | ||
147 | |||
148 | static int sa1100_low_gpio_irqdomain_map(struct irq_domain *d, | ||
149 | unsigned int irq, irq_hw_number_t hwirq) | ||
150 | { | ||
151 | irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip, | ||
152 | handle_edge_irq); | ||
153 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct irq_domain_ops sa1100_low_gpio_irqdomain_ops = { | ||
159 | .map = sa1100_low_gpio_irqdomain_map, | ||
160 | .xlate = irq_domain_xlate_onetwocell, | ||
106 | }; | 161 | }; |
107 | 162 | ||
163 | static struct irq_domain *sa1100_low_gpio_irqdomain; | ||
164 | |||
108 | /* | 165 | /* |
109 | * IRQ11 (GPIO11 through 27) handler. We enter here with the | 166 | * IRQ11 (GPIO11 through 27) handler. We enter here with the |
110 | * irq_controller_lock held, and IRQs disabled. Decode the IRQ | 167 | * irq_controller_lock held, and IRQs disabled. Decode the IRQ |
@@ -141,16 +198,9 @@ sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc) | |||
141 | * In addition, the IRQs are all collected up into one bit in the | 198 | * In addition, the IRQs are all collected up into one bit in the |
142 | * interrupt controller registers. | 199 | * interrupt controller registers. |
143 | */ | 200 | */ |
144 | static void sa1100_high_gpio_ack(struct irq_data *d) | ||
145 | { | ||
146 | unsigned int mask = GPIO11_27_MASK(d->irq); | ||
147 | |||
148 | GEDR = mask; | ||
149 | } | ||
150 | |||
151 | static void sa1100_high_gpio_mask(struct irq_data *d) | 201 | static void sa1100_high_gpio_mask(struct irq_data *d) |
152 | { | 202 | { |
153 | unsigned int mask = GPIO11_27_MASK(d->irq); | 203 | unsigned int mask = BIT(d->hwirq); |
154 | 204 | ||
155 | GPIO_IRQ_mask &= ~mask; | 205 | GPIO_IRQ_mask &= ~mask; |
156 | 206 | ||
@@ -160,7 +210,7 @@ static void sa1100_high_gpio_mask(struct irq_data *d) | |||
160 | 210 | ||
161 | static void sa1100_high_gpio_unmask(struct irq_data *d) | 211 | static void sa1100_high_gpio_unmask(struct irq_data *d) |
162 | { | 212 | { |
163 | unsigned int mask = GPIO11_27_MASK(d->irq); | 213 | unsigned int mask = BIT(d->hwirq); |
164 | 214 | ||
165 | GPIO_IRQ_mask |= mask; | 215 | GPIO_IRQ_mask |= mask; |
166 | 216 | ||
@@ -168,61 +218,32 @@ static void sa1100_high_gpio_unmask(struct irq_data *d) | |||
168 | GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; | 218 | GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; |
169 | } | 219 | } |
170 | 220 | ||
171 | static int sa1100_high_gpio_wake(struct irq_data *d, unsigned int on) | ||
172 | { | ||
173 | if (on) | ||
174 | PWER |= GPIO11_27_MASK(d->irq); | ||
175 | else | ||
176 | PWER &= ~GPIO11_27_MASK(d->irq); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static struct irq_chip sa1100_high_gpio_chip = { | 221 | static struct irq_chip sa1100_high_gpio_chip = { |
181 | .name = "GPIO-h", | 222 | .name = "GPIO-h", |
182 | .irq_ack = sa1100_high_gpio_ack, | 223 | .irq_ack = sa1100_gpio_ack, |
183 | .irq_mask = sa1100_high_gpio_mask, | 224 | .irq_mask = sa1100_high_gpio_mask, |
184 | .irq_unmask = sa1100_high_gpio_unmask, | 225 | .irq_unmask = sa1100_high_gpio_unmask, |
185 | .irq_set_type = sa1100_gpio_type, | 226 | .irq_set_type = sa1100_gpio_type, |
186 | .irq_set_wake = sa1100_high_gpio_wake, | 227 | .irq_set_wake = sa1100_gpio_wake, |
187 | }; | 228 | }; |
188 | 229 | ||
189 | /* | 230 | static int sa1100_high_gpio_irqdomain_map(struct irq_domain *d, |
190 | * We don't need to ACK IRQs on the SA1100 unless they're GPIOs | 231 | unsigned int irq, irq_hw_number_t hwirq) |
191 | * this is for internal IRQs i.e. from 11 to 31. | ||
192 | */ | ||
193 | static void sa1100_mask_irq(struct irq_data *d) | ||
194 | { | ||
195 | ICMR &= ~(1 << d->irq); | ||
196 | } | ||
197 | |||
198 | static void sa1100_unmask_irq(struct irq_data *d) | ||
199 | { | 232 | { |
200 | ICMR |= (1 << d->irq); | 233 | irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip, |
201 | } | 234 | handle_edge_irq); |
235 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
202 | 236 | ||
203 | /* | 237 | return 0; |
204 | * Apart form GPIOs, only the RTC alarm can be a wakeup event. | ||
205 | */ | ||
206 | static int sa1100_set_wake(struct irq_data *d, unsigned int on) | ||
207 | { | ||
208 | if (d->irq == IRQ_RTCAlrm) { | ||
209 | if (on) | ||
210 | PWER |= PWER_RTC; | ||
211 | else | ||
212 | PWER &= ~PWER_RTC; | ||
213 | return 0; | ||
214 | } | ||
215 | return -EINVAL; | ||
216 | } | 238 | } |
217 | 239 | ||
218 | static struct irq_chip sa1100_normal_chip = { | 240 | static struct irq_domain_ops sa1100_high_gpio_irqdomain_ops = { |
219 | .name = "SC", | 241 | .map = sa1100_high_gpio_irqdomain_map, |
220 | .irq_ack = sa1100_mask_irq, | 242 | .xlate = irq_domain_xlate_onetwocell, |
221 | .irq_mask = sa1100_mask_irq, | ||
222 | .irq_unmask = sa1100_unmask_irq, | ||
223 | .irq_set_wake = sa1100_set_wake, | ||
224 | }; | 243 | }; |
225 | 244 | ||
245 | static struct irq_domain *sa1100_high_gpio_irqdomain; | ||
246 | |||
226 | static struct resource irq_resource = | 247 | static struct resource irq_resource = |
227 | DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); | 248 | DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); |
228 | 249 | ||
@@ -291,10 +312,25 @@ static int __init sa1100irq_init_devicefs(void) | |||
291 | 312 | ||
292 | device_initcall(sa1100irq_init_devicefs); | 313 | device_initcall(sa1100irq_init_devicefs); |
293 | 314 | ||
294 | void __init sa1100_init_irq(void) | 315 | static asmlinkage void __exception_irq_entry |
316 | sa1100_handle_irq(struct pt_regs *regs) | ||
295 | { | 317 | { |
296 | unsigned int irq; | 318 | uint32_t icip, icmr, mask; |
319 | |||
320 | do { | ||
321 | icip = (ICIP); | ||
322 | icmr = (ICMR); | ||
323 | mask = icip & icmr; | ||
324 | |||
325 | if (mask == 0) | ||
326 | break; | ||
327 | |||
328 | handle_IRQ(ffs(mask) - 1 + IRQ_GPIO0, regs); | ||
329 | } while (1); | ||
330 | } | ||
297 | 331 | ||
332 | void __init sa1100_init_irq(void) | ||
333 | { | ||
298 | request_resource(&iomem_resource, &irq_resource); | 334 | request_resource(&iomem_resource, &irq_resource); |
299 | 335 | ||
300 | /* disable all IRQs */ | 336 | /* disable all IRQs */ |
@@ -314,29 +350,24 @@ void __init sa1100_init_irq(void) | |||
314 | */ | 350 | */ |
315 | ICCR = 1; | 351 | ICCR = 1; |
316 | 352 | ||
317 | for (irq = 0; irq <= 10; irq++) { | 353 | sa1100_low_gpio_irqdomain = irq_domain_add_legacy(NULL, |
318 | irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip, | 354 | 11, IRQ_GPIO0, 0, |
319 | handle_edge_irq); | 355 | &sa1100_low_gpio_irqdomain_ops, NULL); |
320 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
321 | } | ||
322 | 356 | ||
323 | for (irq = 12; irq <= 31; irq++) { | 357 | sa1100_normal_irqdomain = irq_domain_add_legacy(NULL, |
324 | irq_set_chip_and_handler(irq, &sa1100_normal_chip, | 358 | 21, IRQ_GPIO11_27, 11, |
325 | handle_level_irq); | 359 | &sa1100_normal_irqdomain_ops, NULL); |
326 | set_irq_flags(irq, IRQF_VALID); | ||
327 | } | ||
328 | 360 | ||
329 | for (irq = 32; irq <= 48; irq++) { | 361 | sa1100_high_gpio_irqdomain = irq_domain_add_legacy(NULL, |
330 | irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip, | 362 | 17, IRQ_GPIO11, 11, |
331 | handle_edge_irq); | 363 | &sa1100_high_gpio_irqdomain_ops, NULL); |
332 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
333 | } | ||
334 | 364 | ||
335 | /* | 365 | /* |
336 | * Install handler for GPIO 11-27 edge detect interrupts | 366 | * Install handler for GPIO 11-27 edge detect interrupts |
337 | */ | 367 | */ |
338 | irq_set_chip(IRQ_GPIO11_27, &sa1100_normal_chip); | ||
339 | irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler); | 368 | irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler); |
340 | 369 | ||
370 | set_handle_irq(sa1100_handle_irq); | ||
371 | |||
341 | sa1100_init_gpio(); | 372 | sa1100_init_gpio(); |
342 | } | 373 | } |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ab906b801047..03823e784f63 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -1009,3 +1009,24 @@ config ARCH_SUPPORTS_BIG_ENDIAN | |||
1009 | help | 1009 | help |
1010 | This option specifies the architecture can support big endian | 1010 | This option specifies the architecture can support big endian |
1011 | operation. | 1011 | operation. |
1012 | |||
1013 | config ARM_KERNMEM_PERMS | ||
1014 | bool "Restrict kernel memory permissions" | ||
1015 | help | ||
1016 | If this is set, kernel memory other than kernel text (and rodata) | ||
1017 | will be made non-executable. The tradeoff is that each region is | ||
1018 | padded to section-size (1MiB) boundaries (because their permissions | ||
1019 | are different and splitting the 1M pages into 4K ones causes TLB | ||
1020 | performance problems), wasting memory. | ||
1021 | |||
1022 | config DEBUG_RODATA | ||
1023 | bool "Make kernel text and rodata read-only" | ||
1024 | depends on ARM_KERNMEM_PERMS | ||
1025 | default y | ||
1026 | help | ||
1027 | If this is set, kernel text and rodata will be made read-only. This | ||
1028 | is to help catch accidental or malicious attempts to change the | ||
1029 | kernel's executable code. Additionally splits rodata from kernel | ||
1030 | text so it can be made explicitly non-executable. This creates | ||
1031 | another section-size padded region, so it can waste more memory | ||
1032 | space while gaining the read-only protections. | ||
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 91da64de440f..d3afdf9eb65a 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
@@ -6,7 +6,7 @@ obj-y := dma-mapping.o extable.o fault.o init.o \ | |||
6 | iomap.o | 6 | iomap.o |
7 | 7 | ||
8 | obj-$(CONFIG_MMU) += fault-armv.o flush.o idmap.o ioremap.o \ | 8 | obj-$(CONFIG_MMU) += fault-armv.o flush.o idmap.o ioremap.o \ |
9 | mmap.o pgd.o mmu.o | 9 | mmap.o pgd.o mmu.o pageattr.o |
10 | 10 | ||
11 | ifneq ($(CONFIG_MMU),y) | 11 | ifneq ($(CONFIG_MMU),y) |
12 | obj-y += nommu.o | 12 | obj-y += nommu.o |
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 83792f4324ea..2c0c541c60ca 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c | |||
@@ -113,7 +113,7 @@ static int safe_usermode(int new_usermode, bool warn) | |||
113 | new_usermode |= UM_FIXUP; | 113 | new_usermode |= UM_FIXUP; |
114 | 114 | ||
115 | if (warn) | 115 | if (warn) |
116 | printk(KERN_WARNING "alignment: ignoring faults is unsafe on this CPU. Defaulting to fixup mode.\n"); | 116 | pr_warn("alignment: ignoring faults is unsafe on this CPU. Defaulting to fixup mode.\n"); |
117 | } | 117 | } |
118 | 118 | ||
119 | return new_usermode; | 119 | return new_usermode; |
@@ -523,7 +523,7 @@ do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *reg | |||
523 | * processor for us. | 523 | * processor for us. |
524 | */ | 524 | */ |
525 | if (addr != eaddr) { | 525 | if (addr != eaddr) { |
526 | printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, " | 526 | pr_err("LDMSTM: PC = %08lx, instr = %08lx, " |
527 | "addr = %08lx, eaddr = %08lx\n", | 527 | "addr = %08lx, eaddr = %08lx\n", |
528 | instruction_pointer(regs), instr, addr, eaddr); | 528 | instruction_pointer(regs), instr, addr, eaddr); |
529 | show_regs(regs); | 529 | show_regs(regs); |
@@ -567,7 +567,7 @@ fault: | |||
567 | return TYPE_FAULT; | 567 | return TYPE_FAULT; |
568 | 568 | ||
569 | bad: | 569 | bad: |
570 | printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n"); | 570 | pr_err("Alignment trap: not handling ldm with s-bit set\n"); |
571 | return TYPE_ERROR; | 571 | return TYPE_ERROR; |
572 | } | 572 | } |
573 | 573 | ||
@@ -899,13 +899,13 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
899 | return 0; | 899 | return 0; |
900 | 900 | ||
901 | swp: | 901 | swp: |
902 | printk(KERN_ERR "Alignment trap: not handling swp instruction\n"); | 902 | pr_err("Alignment trap: not handling swp instruction\n"); |
903 | 903 | ||
904 | bad: | 904 | bad: |
905 | /* | 905 | /* |
906 | * Oops, we didn't handle the instruction. | 906 | * Oops, we didn't handle the instruction. |
907 | */ | 907 | */ |
908 | printk(KERN_ERR "Alignment trap: not handling instruction " | 908 | pr_err("Alignment trap: not handling instruction " |
909 | "%0*lx at [<%08lx>]\n", | 909 | "%0*lx at [<%08lx>]\n", |
910 | isize << 1, | 910 | isize << 1, |
911 | isize == 2 ? tinstr : instr, instrptr); | 911 | isize == 2 ? tinstr : instr, instrptr); |
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index e028a7f2ebcc..097181e08c25 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c | |||
@@ -313,7 +313,7 @@ static void __init disable_l2_prefetch(void) | |||
313 | */ | 313 | */ |
314 | u = read_extra_features(); | 314 | u = read_extra_features(); |
315 | if (!(u & 0x01000000)) { | 315 | if (!(u & 0x01000000)) { |
316 | printk(KERN_INFO "Feroceon L2: Disabling L2 prefetch.\n"); | 316 | pr_info("Feroceon L2: Disabling L2 prefetch.\n"); |
317 | write_extra_features(u | 0x01000000); | 317 | write_extra_features(u | 0x01000000); |
318 | } | 318 | } |
319 | } | 319 | } |
@@ -326,7 +326,7 @@ static void __init enable_l2(void) | |||
326 | if (!(u & 0x00400000)) { | 326 | if (!(u & 0x00400000)) { |
327 | int i, d; | 327 | int i, d; |
328 | 328 | ||
329 | printk(KERN_INFO "Feroceon L2: Enabling L2\n"); | 329 | pr_info("Feroceon L2: Enabling L2\n"); |
330 | 330 | ||
331 | d = flush_and_disable_dcache(); | 331 | d = flush_and_disable_dcache(); |
332 | i = invalidate_and_disable_icache(); | 332 | i = invalidate_and_disable_icache(); |
@@ -353,7 +353,7 @@ void __init feroceon_l2_init(int __l2_wt_override) | |||
353 | 353 | ||
354 | enable_l2(); | 354 | enable_l2(); |
355 | 355 | ||
356 | printk(KERN_INFO "Feroceon L2: Cache support initialised%s.\n", | 356 | pr_info("Feroceon L2: Cache support initialised%s.\n", |
357 | l2_wt_override ? ", in WT override mode" : ""); | 357 | l2_wt_override ? ", in WT override mode" : ""); |
358 | } | 358 | } |
359 | #ifdef CONFIG_OF | 359 | #ifdef CONFIG_OF |
diff --git a/arch/arm/mm/cache-tauros2.c b/arch/arm/mm/cache-tauros2.c index b273739e6359..1e373d268c04 100644 --- a/arch/arm/mm/cache-tauros2.c +++ b/arch/arm/mm/cache-tauros2.c | |||
@@ -185,7 +185,7 @@ static void enable_extra_feature(unsigned int features) | |||
185 | u &= ~0x01000000; | 185 | u &= ~0x01000000; |
186 | else | 186 | else |
187 | u |= 0x01000000; | 187 | u |= 0x01000000; |
188 | printk(KERN_INFO "Tauros2: %s L2 prefetch.\n", | 188 | pr_info("Tauros2: %s L2 prefetch.\n", |
189 | (features & CACHE_TAUROS2_PREFETCH_ON) | 189 | (features & CACHE_TAUROS2_PREFETCH_ON) |
190 | ? "Enabling" : "Disabling"); | 190 | ? "Enabling" : "Disabling"); |
191 | 191 | ||
@@ -193,7 +193,7 @@ static void enable_extra_feature(unsigned int features) | |||
193 | u |= 0x00100000; | 193 | u |= 0x00100000; |
194 | else | 194 | else |
195 | u &= ~0x00100000; | 195 | u &= ~0x00100000; |
196 | printk(KERN_INFO "Tauros2: %s line fill burt8.\n", | 196 | pr_info("Tauros2: %s line fill burt8.\n", |
197 | (features & CACHE_TAUROS2_LINEFILL_BURST8) | 197 | (features & CACHE_TAUROS2_LINEFILL_BURST8) |
198 | ? "Enabling" : "Disabling"); | 198 | ? "Enabling" : "Disabling"); |
199 | 199 | ||
@@ -216,7 +216,7 @@ static void __init tauros2_internal_init(unsigned int features) | |||
216 | */ | 216 | */ |
217 | feat = read_extra_features(); | 217 | feat = read_extra_features(); |
218 | if (!(feat & 0x00400000)) { | 218 | if (!(feat & 0x00400000)) { |
219 | printk(KERN_INFO "Tauros2: Enabling L2 cache.\n"); | 219 | pr_info("Tauros2: Enabling L2 cache.\n"); |
220 | write_extra_features(feat | 0x00400000); | 220 | write_extra_features(feat | 0x00400000); |
221 | } | 221 | } |
222 | 222 | ||
@@ -253,7 +253,7 @@ static void __init tauros2_internal_init(unsigned int features) | |||
253 | */ | 253 | */ |
254 | actlr = read_actlr(); | 254 | actlr = read_actlr(); |
255 | if (!(actlr & 0x00000002)) { | 255 | if (!(actlr & 0x00000002)) { |
256 | printk(KERN_INFO "Tauros2: Enabling L2 cache.\n"); | 256 | pr_info("Tauros2: Enabling L2 cache.\n"); |
257 | write_actlr(actlr | 0x00000002); | 257 | write_actlr(actlr | 0x00000002); |
258 | } | 258 | } |
259 | 259 | ||
@@ -262,11 +262,11 @@ static void __init tauros2_internal_init(unsigned int features) | |||
262 | #endif | 262 | #endif |
263 | 263 | ||
264 | if (mode == NULL) { | 264 | if (mode == NULL) { |
265 | printk(KERN_CRIT "Tauros2: Unable to detect CPU mode.\n"); | 265 | pr_crit("Tauros2: Unable to detect CPU mode.\n"); |
266 | return; | 266 | return; |
267 | } | 267 | } |
268 | 268 | ||
269 | printk(KERN_INFO "Tauros2: L2 cache support initialised " | 269 | pr_info("Tauros2: L2 cache support initialised " |
270 | "in %s mode.\n", mode); | 270 | "in %s mode.\n", mode); |
271 | } | 271 | } |
272 | 272 | ||
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 6eb97b3a7481..91892569710f 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c | |||
@@ -184,36 +184,46 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) | |||
184 | u64 asid = atomic64_read(&mm->context.id); | 184 | u64 asid = atomic64_read(&mm->context.id); |
185 | u64 generation = atomic64_read(&asid_generation); | 185 | u64 generation = atomic64_read(&asid_generation); |
186 | 186 | ||
187 | if (asid != 0 && is_reserved_asid(asid)) { | 187 | if (asid != 0) { |
188 | /* | 188 | /* |
189 | * Our current ASID was active during a rollover, we can | 189 | * If our current ASID was active during a rollover, we |
190 | * continue to use it and this was just a false alarm. | 190 | * can continue to use it and this was just a false alarm. |
191 | */ | 191 | */ |
192 | asid = generation | (asid & ~ASID_MASK); | 192 | if (is_reserved_asid(asid)) |
193 | } else { | 193 | return generation | (asid & ~ASID_MASK); |
194 | |||
194 | /* | 195 | /* |
195 | * Allocate a free ASID. If we can't find one, take a | 196 | * We had a valid ASID in a previous life, so try to re-use |
196 | * note of the currently active ASIDs and mark the TLBs | 197 | * it if possible., |
197 | * as requiring flushes. We always count from ASID #1, | ||
198 | * as we reserve ASID #0 to switch via TTBR0 and to | ||
199 | * avoid speculative page table walks from hitting in | ||
200 | * any partial walk caches, which could be populated | ||
201 | * from overlapping level-1 descriptors used to map both | ||
202 | * the module area and the userspace stack. | ||
203 | */ | 198 | */ |
204 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx); | 199 | asid &= ~ASID_MASK; |
205 | if (asid == NUM_USER_ASIDS) { | 200 | if (!__test_and_set_bit(asid, asid_map)) |
206 | generation = atomic64_add_return(ASID_FIRST_VERSION, | 201 | goto bump_gen; |
207 | &asid_generation); | ||
208 | flush_context(cpu); | ||
209 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); | ||
210 | } | ||
211 | __set_bit(asid, asid_map); | ||
212 | cur_idx = asid; | ||
213 | asid |= generation; | ||
214 | cpumask_clear(mm_cpumask(mm)); | ||
215 | } | 202 | } |
216 | 203 | ||
204 | /* | ||
205 | * Allocate a free ASID. If we can't find one, take a note of the | ||
206 | * currently active ASIDs and mark the TLBs as requiring flushes. | ||
207 | * We always count from ASID #1, as we reserve ASID #0 to switch | ||
208 | * via TTBR0 and to avoid speculative page table walks from hitting | ||
209 | * in any partial walk caches, which could be populated from | ||
210 | * overlapping level-1 descriptors used to map both the module | ||
211 | * area and the userspace stack. | ||
212 | */ | ||
213 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx); | ||
214 | if (asid == NUM_USER_ASIDS) { | ||
215 | generation = atomic64_add_return(ASID_FIRST_VERSION, | ||
216 | &asid_generation); | ||
217 | flush_context(cpu); | ||
218 | asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); | ||
219 | } | ||
220 | |||
221 | __set_bit(asid, asid_map); | ||
222 | cur_idx = asid; | ||
223 | |||
224 | bump_gen: | ||
225 | asid |= generation; | ||
226 | cpumask_clear(mm_cpumask(mm)); | ||
217 | return asid; | 227 | return asid; |
218 | } | 228 | } |
219 | 229 | ||
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index b9bcc9d79176..70423345da26 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c | |||
@@ -62,7 +62,7 @@ static void discard_old_kernel_data(void *kto) | |||
62 | __asm__("mcrr p15, 0, %1, %0, c6 @ 0xec401f06" | 62 | __asm__("mcrr p15, 0, %1, %0, c6 @ 0xec401f06" |
63 | : | 63 | : |
64 | : "r" (kto), | 64 | : "r" (kto), |
65 | "r" ((unsigned long)kto + PAGE_SIZE - L1_CACHE_BYTES) | 65 | "r" ((unsigned long)kto + PAGE_SIZE - 1) |
66 | : "cc"); | 66 | : "cc"); |
67 | } | 67 | } |
68 | 68 | ||
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index ff379ac115df..d9e0d00a6699 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -235,7 +235,7 @@ void __init check_writebuffer_bugs(void) | |||
235 | const char *reason; | 235 | const char *reason; |
236 | unsigned long v = 1; | 236 | unsigned long v = 1; |
237 | 237 | ||
238 | printk(KERN_INFO "CPU: Testing write buffer coherency: "); | 238 | pr_info("CPU: Testing write buffer coherency: "); |
239 | 239 | ||
240 | page = alloc_page(GFP_KERNEL); | 240 | page = alloc_page(GFP_KERNEL); |
241 | if (page) { | 241 | if (page) { |
@@ -261,9 +261,9 @@ void __init check_writebuffer_bugs(void) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | if (v) { | 263 | if (v) { |
264 | printk("failed, %s\n", reason); | 264 | pr_cont("failed, %s\n", reason); |
265 | shared_pte_mask = L_PTE_MT_UNCACHED; | 265 | shared_pte_mask = L_PTE_MT_UNCACHED; |
266 | } else { | 266 | } else { |
267 | printk("ok\n"); | 267 | pr_cont("ok\n"); |
268 | } | 268 | } |
269 | } | 269 | } |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index eb8830a4c5ed..a982dc3190df 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -63,9 +63,9 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
63 | if (!mm) | 63 | if (!mm) |
64 | mm = &init_mm; | 64 | mm = &init_mm; |
65 | 65 | ||
66 | printk(KERN_ALERT "pgd = %p\n", mm->pgd); | 66 | pr_alert("pgd = %p\n", mm->pgd); |
67 | pgd = pgd_offset(mm, addr); | 67 | pgd = pgd_offset(mm, addr); |
68 | printk(KERN_ALERT "[%08lx] *pgd=%08llx", | 68 | pr_alert("[%08lx] *pgd=%08llx", |
69 | addr, (long long)pgd_val(*pgd)); | 69 | addr, (long long)pgd_val(*pgd)); |
70 | 70 | ||
71 | do { | 71 | do { |
@@ -77,31 +77,31 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
77 | break; | 77 | break; |
78 | 78 | ||
79 | if (pgd_bad(*pgd)) { | 79 | if (pgd_bad(*pgd)) { |
80 | printk("(bad)"); | 80 | pr_cont("(bad)"); |
81 | break; | 81 | break; |
82 | } | 82 | } |
83 | 83 | ||
84 | pud = pud_offset(pgd, addr); | 84 | pud = pud_offset(pgd, addr); |
85 | if (PTRS_PER_PUD != 1) | 85 | if (PTRS_PER_PUD != 1) |
86 | printk(", *pud=%08llx", (long long)pud_val(*pud)); | 86 | pr_cont(", *pud=%08llx", (long long)pud_val(*pud)); |
87 | 87 | ||
88 | if (pud_none(*pud)) | 88 | if (pud_none(*pud)) |
89 | break; | 89 | break; |
90 | 90 | ||
91 | if (pud_bad(*pud)) { | 91 | if (pud_bad(*pud)) { |
92 | printk("(bad)"); | 92 | pr_cont("(bad)"); |
93 | break; | 93 | break; |
94 | } | 94 | } |
95 | 95 | ||
96 | pmd = pmd_offset(pud, addr); | 96 | pmd = pmd_offset(pud, addr); |
97 | if (PTRS_PER_PMD != 1) | 97 | if (PTRS_PER_PMD != 1) |
98 | printk(", *pmd=%08llx", (long long)pmd_val(*pmd)); | 98 | pr_cont(", *pmd=%08llx", (long long)pmd_val(*pmd)); |
99 | 99 | ||
100 | if (pmd_none(*pmd)) | 100 | if (pmd_none(*pmd)) |
101 | break; | 101 | break; |
102 | 102 | ||
103 | if (pmd_bad(*pmd)) { | 103 | if (pmd_bad(*pmd)) { |
104 | printk("(bad)"); | 104 | pr_cont("(bad)"); |
105 | break; | 105 | break; |
106 | } | 106 | } |
107 | 107 | ||
@@ -110,15 +110,15 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
110 | break; | 110 | break; |
111 | 111 | ||
112 | pte = pte_offset_map(pmd, addr); | 112 | pte = pte_offset_map(pmd, addr); |
113 | printk(", *pte=%08llx", (long long)pte_val(*pte)); | 113 | pr_cont(", *pte=%08llx", (long long)pte_val(*pte)); |
114 | #ifndef CONFIG_ARM_LPAE | 114 | #ifndef CONFIG_ARM_LPAE |
115 | printk(", *ppte=%08llx", | 115 | pr_cont(", *ppte=%08llx", |
116 | (long long)pte_val(pte[PTE_HWTABLE_PTRS])); | 116 | (long long)pte_val(pte[PTE_HWTABLE_PTRS])); |
117 | #endif | 117 | #endif |
118 | pte_unmap(pte); | 118 | pte_unmap(pte); |
119 | } while(0); | 119 | } while(0); |
120 | 120 | ||
121 | printk("\n"); | 121 | pr_cont("\n"); |
122 | } | 122 | } |
123 | #else /* CONFIG_MMU */ | 123 | #else /* CONFIG_MMU */ |
124 | void show_pte(struct mm_struct *mm, unsigned long addr) | 124 | void show_pte(struct mm_struct *mm, unsigned long addr) |
@@ -142,10 +142,9 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, | |||
142 | * No handler, we'll have to terminate things with extreme prejudice. | 142 | * No handler, we'll have to terminate things with extreme prejudice. |
143 | */ | 143 | */ |
144 | bust_spinlocks(1); | 144 | bust_spinlocks(1); |
145 | printk(KERN_ALERT | 145 | pr_alert("Unable to handle kernel %s at virtual address %08lx\n", |
146 | "Unable to handle kernel %s at virtual address %08lx\n", | 146 | (addr < PAGE_SIZE) ? "NULL pointer dereference" : |
147 | (addr < PAGE_SIZE) ? "NULL pointer dereference" : | 147 | "paging request", addr); |
148 | "paging request", addr); | ||
149 | 148 | ||
150 | show_pte(mm, addr); | 149 | show_pte(mm, addr); |
151 | die("Oops", regs, fsr); | 150 | die("Oops", regs, fsr); |
@@ -551,7 +550,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
551 | if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) | 550 | if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) |
552 | return; | 551 | return; |
553 | 552 | ||
554 | printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", | 553 | pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n", |
555 | inf->name, fsr, addr); | 554 | inf->name, fsr, addr); |
556 | 555 | ||
557 | info.si_signo = inf->sig; | 556 | info.si_signo = inf->sig; |
@@ -583,7 +582,7 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) | |||
583 | if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) | 582 | if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) |
584 | return; | 583 | return; |
585 | 584 | ||
586 | printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", | 585 | pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", |
587 | inf->name, ifsr, addr); | 586 | inf->name, ifsr, addr); |
588 | 587 | ||
589 | info.si_signo = inf->sig; | 588 | info.si_signo = inf->sig; |
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 265b836b3bd1..34b66af516ea 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
@@ -33,7 +33,7 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) | |||
33 | asm( "mcrr p15, 0, %1, %0, c14\n" | 33 | asm( "mcrr p15, 0, %1, %0, c14\n" |
34 | " mcr p15, 0, %2, c7, c10, 4" | 34 | " mcr p15, 0, %2, c7, c10, 4" |
35 | : | 35 | : |
36 | : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero) | 36 | : "r" (to), "r" (to + PAGE_SIZE - 1), "r" (zero) |
37 | : "cc"); | 37 | : "cc"); |
38 | } | 38 | } |
39 | 39 | ||
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index e17ed00828d7..b98895d9fe57 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c | |||
@@ -18,19 +18,20 @@ | |||
18 | #include <asm/tlbflush.h> | 18 | #include <asm/tlbflush.h> |
19 | #include "mm.h" | 19 | #include "mm.h" |
20 | 20 | ||
21 | pte_t *fixmap_page_table; | ||
22 | |||
23 | static inline void set_fixmap_pte(int idx, pte_t pte) | 21 | static inline void set_fixmap_pte(int idx, pte_t pte) |
24 | { | 22 | { |
25 | unsigned long vaddr = __fix_to_virt(idx); | 23 | unsigned long vaddr = __fix_to_virt(idx); |
26 | set_pte_ext(fixmap_page_table + idx, pte, 0); | 24 | pte_t *ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); |
25 | |||
26 | set_pte_ext(ptep, pte, 0); | ||
27 | local_flush_tlb_kernel_page(vaddr); | 27 | local_flush_tlb_kernel_page(vaddr); |
28 | } | 28 | } |
29 | 29 | ||
30 | static inline pte_t get_fixmap_pte(unsigned long vaddr) | 30 | static inline pte_t get_fixmap_pte(unsigned long vaddr) |
31 | { | 31 | { |
32 | unsigned long idx = __virt_to_fix(vaddr); | 32 | pte_t *ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); |
33 | return *(fixmap_page_table + idx); | 33 | |
34 | return *ptep; | ||
34 | } | 35 | } |
35 | 36 | ||
36 | void *kmap(struct page *page) | 37 | void *kmap(struct page *page) |
@@ -84,7 +85,7 @@ void *kmap_atomic(struct page *page) | |||
84 | * With debugging enabled, kunmap_atomic forces that entry to 0. | 85 | * With debugging enabled, kunmap_atomic forces that entry to 0. |
85 | * Make sure it was indeed properly unmapped. | 86 | * Make sure it was indeed properly unmapped. |
86 | */ | 87 | */ |
87 | BUG_ON(!pte_none(*(fixmap_page_table + idx))); | 88 | BUG_ON(!pte_none(get_fixmap_pte(vaddr))); |
88 | #endif | 89 | #endif |
89 | /* | 90 | /* |
90 | * When debugging is off, kunmap_atomic leaves the previous mapping | 91 | * When debugging is off, kunmap_atomic leaves the previous mapping |
@@ -137,7 +138,7 @@ void *kmap_atomic_pfn(unsigned long pfn) | |||
137 | idx = type + KM_TYPE_NR * smp_processor_id(); | 138 | idx = type + KM_TYPE_NR * smp_processor_id(); |
138 | vaddr = __fix_to_virt(idx); | 139 | vaddr = __fix_to_virt(idx); |
139 | #ifdef CONFIG_DEBUG_HIGHMEM | 140 | #ifdef CONFIG_DEBUG_HIGHMEM |
140 | BUG_ON(!pte_none(*(fixmap_page_table + idx))); | 141 | BUG_ON(!pte_none(get_fixmap_pte(vaddr))); |
141 | #endif | 142 | #endif |
142 | set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot)); | 143 | set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot)); |
143 | 144 | ||
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 9481f85c56e6..98ad9c79ea0e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
30 | #include <asm/sections.h> | 30 | #include <asm/sections.h> |
31 | #include <asm/setup.h> | 31 | #include <asm/setup.h> |
32 | #include <asm/system_info.h> | ||
32 | #include <asm/tlb.h> | 33 | #include <asm/tlb.h> |
33 | #include <asm/fixmap.h> | 34 | #include <asm/fixmap.h> |
34 | 35 | ||
@@ -67,7 +68,7 @@ early_param("initrd", early_initrd); | |||
67 | 68 | ||
68 | static int __init parse_tag_initrd(const struct tag *tag) | 69 | static int __init parse_tag_initrd(const struct tag *tag) |
69 | { | 70 | { |
70 | printk(KERN_WARNING "ATAG_INITRD is deprecated; " | 71 | pr_warn("ATAG_INITRD is deprecated; " |
71 | "please update your bootloader.\n"); | 72 | "please update your bootloader.\n"); |
72 | phys_initrd_start = __virt_to_phys(tag->u.initrd.start); | 73 | phys_initrd_start = __virt_to_phys(tag->u.initrd.start); |
73 | phys_initrd_size = tag->u.initrd.size; | 74 | phys_initrd_size = tag->u.initrd.size; |
@@ -544,7 +545,7 @@ void __init mem_init(void) | |||
544 | #define MLM(b, t) b, t, ((t) - (b)) >> 20 | 545 | #define MLM(b, t) b, t, ((t) - (b)) >> 20 |
545 | #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) | 546 | #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) |
546 | 547 | ||
547 | printk(KERN_NOTICE "Virtual kernel memory layout:\n" | 548 | pr_notice("Virtual kernel memory layout:\n" |
548 | " vector : 0x%08lx - 0x%08lx (%4ld kB)\n" | 549 | " vector : 0x%08lx - 0x%08lx (%4ld kB)\n" |
549 | #ifdef CONFIG_HAVE_TCM | 550 | #ifdef CONFIG_HAVE_TCM |
550 | " DTCM : 0x%08lx - 0x%08lx (%4ld kB)\n" | 551 | " DTCM : 0x%08lx - 0x%08lx (%4ld kB)\n" |
@@ -570,7 +571,7 @@ void __init mem_init(void) | |||
570 | MLK(DTCM_OFFSET, (unsigned long) dtcm_end), | 571 | MLK(DTCM_OFFSET, (unsigned long) dtcm_end), |
571 | MLK(ITCM_OFFSET, (unsigned long) itcm_end), | 572 | MLK(ITCM_OFFSET, (unsigned long) itcm_end), |
572 | #endif | 573 | #endif |
573 | MLK(FIXADDR_START, FIXADDR_TOP), | 574 | MLK(FIXADDR_START, FIXADDR_END), |
574 | MLM(VMALLOC_START, VMALLOC_END), | 575 | MLM(VMALLOC_START, VMALLOC_END), |
575 | MLM(PAGE_OFFSET, (unsigned long)high_memory), | 576 | MLM(PAGE_OFFSET, (unsigned long)high_memory), |
576 | #ifdef CONFIG_HIGHMEM | 577 | #ifdef CONFIG_HIGHMEM |
@@ -615,7 +616,145 @@ void __init mem_init(void) | |||
615 | } | 616 | } |
616 | } | 617 | } |
617 | 618 | ||
618 | void free_initmem(void) | 619 | #ifdef CONFIG_ARM_KERNMEM_PERMS |
620 | struct section_perm { | ||
621 | unsigned long start; | ||
622 | unsigned long end; | ||
623 | pmdval_t mask; | ||
624 | pmdval_t prot; | ||
625 | pmdval_t clear; | ||
626 | }; | ||
627 | |||
628 | static struct section_perm nx_perms[] = { | ||
629 | /* Make pages tables, etc before _stext RW (set NX). */ | ||
630 | { | ||
631 | .start = PAGE_OFFSET, | ||
632 | .end = (unsigned long)_stext, | ||
633 | .mask = ~PMD_SECT_XN, | ||
634 | .prot = PMD_SECT_XN, | ||
635 | }, | ||
636 | /* Make init RW (set NX). */ | ||
637 | { | ||
638 | .start = (unsigned long)__init_begin, | ||
639 | .end = (unsigned long)_sdata, | ||
640 | .mask = ~PMD_SECT_XN, | ||
641 | .prot = PMD_SECT_XN, | ||
642 | }, | ||
643 | #ifdef CONFIG_DEBUG_RODATA | ||
644 | /* Make rodata NX (set RO in ro_perms below). */ | ||
645 | { | ||
646 | .start = (unsigned long)__start_rodata, | ||
647 | .end = (unsigned long)__init_begin, | ||
648 | .mask = ~PMD_SECT_XN, | ||
649 | .prot = PMD_SECT_XN, | ||
650 | }, | ||
651 | #endif | ||
652 | }; | ||
653 | |||
654 | #ifdef CONFIG_DEBUG_RODATA | ||
655 | static struct section_perm ro_perms[] = { | ||
656 | /* Make kernel code and rodata RX (set RO). */ | ||
657 | { | ||
658 | .start = (unsigned long)_stext, | ||
659 | .end = (unsigned long)__init_begin, | ||
660 | #ifdef CONFIG_ARM_LPAE | ||
661 | .mask = ~PMD_SECT_RDONLY, | ||
662 | .prot = PMD_SECT_RDONLY, | ||
663 | #else | ||
664 | .mask = ~(PMD_SECT_APX | PMD_SECT_AP_WRITE), | ||
665 | .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, | ||
666 | .clear = PMD_SECT_AP_WRITE, | ||
667 | #endif | ||
668 | }, | ||
669 | }; | ||
670 | #endif | ||
671 | |||
672 | /* | ||
673 | * Updates section permissions only for the current mm (sections are | ||
674 | * copied into each mm). During startup, this is the init_mm. Is only | ||
675 | * safe to be called with preemption disabled, as under stop_machine(). | ||
676 | */ | ||
677 | static inline void section_update(unsigned long addr, pmdval_t mask, | ||
678 | pmdval_t prot) | ||
679 | { | ||
680 | struct mm_struct *mm; | ||
681 | pmd_t *pmd; | ||
682 | |||
683 | mm = current->active_mm; | ||
684 | pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr); | ||
685 | |||
686 | #ifdef CONFIG_ARM_LPAE | ||
687 | pmd[0] = __pmd((pmd_val(pmd[0]) & mask) | prot); | ||
688 | #else | ||
689 | if (addr & SECTION_SIZE) | ||
690 | pmd[1] = __pmd((pmd_val(pmd[1]) & mask) | prot); | ||
691 | else | ||
692 | pmd[0] = __pmd((pmd_val(pmd[0]) & mask) | prot); | ||
693 | #endif | ||
694 | flush_pmd_entry(pmd); | ||
695 | local_flush_tlb_kernel_range(addr, addr + SECTION_SIZE); | ||
696 | } | ||
697 | |||
698 | /* Make sure extended page tables are in use. */ | ||
699 | static inline bool arch_has_strict_perms(void) | ||
700 | { | ||
701 | if (cpu_architecture() < CPU_ARCH_ARMv6) | ||
702 | return false; | ||
703 | |||
704 | return !!(get_cr() & CR_XP); | ||
705 | } | ||
706 | |||
707 | #define set_section_perms(perms, field) { \ | ||
708 | size_t i; \ | ||
709 | unsigned long addr; \ | ||
710 | \ | ||
711 | if (!arch_has_strict_perms()) \ | ||
712 | return; \ | ||
713 | \ | ||
714 | for (i = 0; i < ARRAY_SIZE(perms); i++) { \ | ||
715 | if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) || \ | ||
716 | !IS_ALIGNED(perms[i].end, SECTION_SIZE)) { \ | ||
717 | pr_err("BUG: section %lx-%lx not aligned to %lx\n", \ | ||
718 | perms[i].start, perms[i].end, \ | ||
719 | SECTION_SIZE); \ | ||
720 | continue; \ | ||
721 | } \ | ||
722 | \ | ||
723 | for (addr = perms[i].start; \ | ||
724 | addr < perms[i].end; \ | ||
725 | addr += SECTION_SIZE) \ | ||
726 | section_update(addr, perms[i].mask, \ | ||
727 | perms[i].field); \ | ||
728 | } \ | ||
729 | } | ||
730 | |||
731 | static inline void fix_kernmem_perms(void) | ||
732 | { | ||
733 | set_section_perms(nx_perms, prot); | ||
734 | } | ||
735 | |||
736 | #ifdef CONFIG_DEBUG_RODATA | ||
737 | void mark_rodata_ro(void) | ||
738 | { | ||
739 | set_section_perms(ro_perms, prot); | ||
740 | } | ||
741 | |||
742 | void set_kernel_text_rw(void) | ||
743 | { | ||
744 | set_section_perms(ro_perms, clear); | ||
745 | } | ||
746 | |||
747 | void set_kernel_text_ro(void) | ||
748 | { | ||
749 | set_section_perms(ro_perms, prot); | ||
750 | } | ||
751 | #endif /* CONFIG_DEBUG_RODATA */ | ||
752 | |||
753 | #else | ||
754 | static inline void fix_kernmem_perms(void) { } | ||
755 | #endif /* CONFIG_ARM_KERNMEM_PERMS */ | ||
756 | |||
757 | void free_tcmmem(void) | ||
619 | { | 758 | { |
620 | #ifdef CONFIG_HAVE_TCM | 759 | #ifdef CONFIG_HAVE_TCM |
621 | extern char __tcm_start, __tcm_end; | 760 | extern char __tcm_start, __tcm_end; |
@@ -623,6 +762,12 @@ void free_initmem(void) | |||
623 | poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start); | 762 | poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start); |
624 | free_reserved_area(&__tcm_start, &__tcm_end, -1, "TCM link"); | 763 | free_reserved_area(&__tcm_start, &__tcm_end, -1, "TCM link"); |
625 | #endif | 764 | #endif |
765 | } | ||
766 | |||
767 | void free_initmem(void) | ||
768 | { | ||
769 | fix_kernmem_perms(); | ||
770 | free_tcmmem(); | ||
626 | 771 | ||
627 | poison_init_mem(__init_begin, __init_end - __init_begin); | 772 | poison_init_mem(__init_begin, __init_end - __init_begin); |
628 | if (!machine_is_integrator() && !machine_is_cintegrator()) | 773 | if (!machine_is_integrator() && !machine_is_cintegrator()) |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9f98cec7fe1e..cda7c40999b6 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/cputype.h> | 22 | #include <asm/cputype.h> |
23 | #include <asm/sections.h> | 23 | #include <asm/sections.h> |
24 | #include <asm/cachetype.h> | 24 | #include <asm/cachetype.h> |
25 | #include <asm/fixmap.h> | ||
25 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
26 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
27 | #include <asm/smp_plat.h> | 28 | #include <asm/smp_plat.h> |
@@ -52,6 +53,8 @@ EXPORT_SYMBOL(empty_zero_page); | |||
52 | */ | 53 | */ |
53 | pmd_t *top_pmd; | 54 | pmd_t *top_pmd; |
54 | 55 | ||
56 | pmdval_t user_pmd_table = _PAGE_USER_TABLE; | ||
57 | |||
55 | #define CPOLICY_UNCACHED 0 | 58 | #define CPOLICY_UNCACHED 0 |
56 | #define CPOLICY_BUFFERED 1 | 59 | #define CPOLICY_BUFFERED 1 |
57 | #define CPOLICY_WRITETHROUGH 2 | 60 | #define CPOLICY_WRITETHROUGH 2 |
@@ -192,7 +195,7 @@ early_param("cachepolicy", early_cachepolicy); | |||
192 | static int __init early_nocache(char *__unused) | 195 | static int __init early_nocache(char *__unused) |
193 | { | 196 | { |
194 | char *p = "buffered"; | 197 | char *p = "buffered"; |
195 | printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p); | 198 | pr_warn("nocache is deprecated; use cachepolicy=%s\n", p); |
196 | early_cachepolicy(p); | 199 | early_cachepolicy(p); |
197 | return 0; | 200 | return 0; |
198 | } | 201 | } |
@@ -201,7 +204,7 @@ early_param("nocache", early_nocache); | |||
201 | static int __init early_nowrite(char *__unused) | 204 | static int __init early_nowrite(char *__unused) |
202 | { | 205 | { |
203 | char *p = "uncached"; | 206 | char *p = "uncached"; |
204 | printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p); | 207 | pr_warn("nowb is deprecated; use cachepolicy=%s\n", p); |
205 | early_cachepolicy(p); | 208 | early_cachepolicy(p); |
206 | return 0; | 209 | return 0; |
207 | } | 210 | } |
@@ -354,43 +357,28 @@ const struct mem_type *get_mem_type(unsigned int type) | |||
354 | } | 357 | } |
355 | EXPORT_SYMBOL(get_mem_type); | 358 | EXPORT_SYMBOL(get_mem_type); |
356 | 359 | ||
357 | #define PTE_SET_FN(_name, pteop) \ | 360 | /* |
358 | static int pte_set_##_name(pte_t *ptep, pgtable_t token, unsigned long addr, \ | 361 | * To avoid TLB flush broadcasts, this uses local_flush_tlb_kernel_range(). |
359 | void *data) \ | 362 | * As a result, this can only be called with preemption disabled, as under |
360 | { \ | 363 | * stop_machine(). |
361 | pte_t pte = pteop(*ptep); \ | 364 | */ |
362 | \ | 365 | void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) |
363 | set_pte_ext(ptep, pte, 0); \ | 366 | { |
364 | return 0; \ | 367 | unsigned long vaddr = __fix_to_virt(idx); |
365 | } \ | 368 | pte_t *pte = pte_offset_kernel(pmd_off_k(vaddr), vaddr); |
366 | |||
367 | #define SET_MEMORY_FN(_name, callback) \ | ||
368 | int set_memory_##_name(unsigned long addr, int numpages) \ | ||
369 | { \ | ||
370 | unsigned long start = addr; \ | ||
371 | unsigned long size = PAGE_SIZE*numpages; \ | ||
372 | unsigned end = start + size; \ | ||
373 | \ | ||
374 | if (start < MODULES_VADDR || start >= MODULES_END) \ | ||
375 | return -EINVAL;\ | ||
376 | \ | ||
377 | if (end < MODULES_VADDR || end >= MODULES_END) \ | ||
378 | return -EINVAL; \ | ||
379 | \ | ||
380 | apply_to_page_range(&init_mm, start, size, callback, NULL); \ | ||
381 | flush_tlb_kernel_range(start, end); \ | ||
382 | return 0;\ | ||
383 | } | ||
384 | 369 | ||
385 | PTE_SET_FN(ro, pte_wrprotect) | 370 | /* Make sure fixmap region does not exceed available allocation. */ |
386 | PTE_SET_FN(rw, pte_mkwrite) | 371 | BUILD_BUG_ON(FIXADDR_START + (__end_of_fixed_addresses * PAGE_SIZE) > |
387 | PTE_SET_FN(x, pte_mkexec) | 372 | FIXADDR_END); |
388 | PTE_SET_FN(nx, pte_mknexec) | 373 | BUG_ON(idx >= __end_of_fixed_addresses); |
389 | 374 | ||
390 | SET_MEMORY_FN(ro, pte_set_ro) | 375 | if (pgprot_val(prot)) |
391 | SET_MEMORY_FN(rw, pte_set_rw) | 376 | set_pte_at(NULL, vaddr, pte, |
392 | SET_MEMORY_FN(x, pte_set_x) | 377 | pfn_pte(phys >> PAGE_SHIFT, prot)); |
393 | SET_MEMORY_FN(nx, pte_set_nx) | 378 | else |
379 | pte_clear(NULL, vaddr, pte); | ||
380 | local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); | ||
381 | } | ||
394 | 382 | ||
395 | /* | 383 | /* |
396 | * Adjust the PMD section entries according to the CPU in use. | 384 | * Adjust the PMD section entries according to the CPU in use. |
@@ -528,14 +516,23 @@ static void __init build_mem_type_table(void) | |||
528 | hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte; | 516 | hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte; |
529 | s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2; | 517 | s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2; |
530 | 518 | ||
519 | #ifndef CONFIG_ARM_LPAE | ||
531 | /* | 520 | /* |
532 | * We don't use domains on ARMv6 (since this causes problems with | 521 | * We don't use domains on ARMv6 (since this causes problems with |
533 | * v6/v7 kernels), so we must use a separate memory type for user | 522 | * v6/v7 kernels), so we must use a separate memory type for user |
534 | * r/o, kernel r/w to map the vectors page. | 523 | * r/o, kernel r/w to map the vectors page. |
535 | */ | 524 | */ |
536 | #ifndef CONFIG_ARM_LPAE | ||
537 | if (cpu_arch == CPU_ARCH_ARMv6) | 525 | if (cpu_arch == CPU_ARCH_ARMv6) |
538 | vecs_pgprot |= L_PTE_MT_VECTORS; | 526 | vecs_pgprot |= L_PTE_MT_VECTORS; |
527 | |||
528 | /* | ||
529 | * Check is it with support for the PXN bit | ||
530 | * in the Short-descriptor translation table format descriptors. | ||
531 | */ | ||
532 | if (cpu_arch == CPU_ARCH_ARMv7 && | ||
533 | (read_cpuid_ext(CPUID_EXT_MMFR0) & 0xF) == 4) { | ||
534 | user_pmd_table |= PMD_PXNTABLE; | ||
535 | } | ||
539 | #endif | 536 | #endif |
540 | 537 | ||
541 | /* | 538 | /* |
@@ -605,6 +602,11 @@ static void __init build_mem_type_table(void) | |||
605 | } | 602 | } |
606 | kern_pgprot |= PTE_EXT_AF; | 603 | kern_pgprot |= PTE_EXT_AF; |
607 | vecs_pgprot |= PTE_EXT_AF; | 604 | vecs_pgprot |= PTE_EXT_AF; |
605 | |||
606 | /* | ||
607 | * Set PXN for user mappings | ||
608 | */ | ||
609 | user_pgprot |= PTE_EXT_PXN; | ||
608 | #endif | 610 | #endif |
609 | 611 | ||
610 | for (i = 0; i < 16; i++) { | 612 | for (i = 0; i < 16; i++) { |
@@ -786,8 +788,7 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
786 | length = PAGE_ALIGN(md->length); | 788 | length = PAGE_ALIGN(md->length); |
787 | 789 | ||
788 | if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) { | 790 | if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) { |
789 | printk(KERN_ERR "MM: CPU does not support supersection " | 791 | pr_err("MM: CPU does not support supersection mapping for 0x%08llx at 0x%08lx\n", |
790 | "mapping for 0x%08llx at 0x%08lx\n", | ||
791 | (long long)__pfn_to_phys((u64)md->pfn), addr); | 792 | (long long)__pfn_to_phys((u64)md->pfn), addr); |
792 | return; | 793 | return; |
793 | } | 794 | } |
@@ -799,15 +800,13 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
799 | * of the actual domain assignments in use. | 800 | * of the actual domain assignments in use. |
800 | */ | 801 | */ |
801 | if (type->domain) { | 802 | if (type->domain) { |
802 | printk(KERN_ERR "MM: invalid domain in supersection " | 803 | pr_err("MM: invalid domain in supersection mapping for 0x%08llx at 0x%08lx\n", |
803 | "mapping for 0x%08llx at 0x%08lx\n", | ||
804 | (long long)__pfn_to_phys((u64)md->pfn), addr); | 804 | (long long)__pfn_to_phys((u64)md->pfn), addr); |
805 | return; | 805 | return; |
806 | } | 806 | } |
807 | 807 | ||
808 | if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) { | 808 | if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) { |
809 | printk(KERN_ERR "MM: cannot create mapping for 0x%08llx" | 809 | pr_err("MM: cannot create mapping for 0x%08llx at 0x%08lx invalid alignment\n", |
810 | " at 0x%08lx invalid alignment\n", | ||
811 | (long long)__pfn_to_phys((u64)md->pfn), addr); | 810 | (long long)__pfn_to_phys((u64)md->pfn), addr); |
812 | return; | 811 | return; |
813 | } | 812 | } |
@@ -850,18 +849,16 @@ static void __init create_mapping(struct map_desc *md) | |||
850 | pgd_t *pgd; | 849 | pgd_t *pgd; |
851 | 850 | ||
852 | if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { | 851 | if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { |
853 | printk(KERN_WARNING "BUG: not creating mapping for 0x%08llx" | 852 | pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n", |
854 | " at 0x%08lx in user region\n", | 853 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); |
855 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); | ||
856 | return; | 854 | return; |
857 | } | 855 | } |
858 | 856 | ||
859 | if ((md->type == MT_DEVICE || md->type == MT_ROM) && | 857 | if ((md->type == MT_DEVICE || md->type == MT_ROM) && |
860 | md->virtual >= PAGE_OFFSET && | 858 | md->virtual >= PAGE_OFFSET && |
861 | (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { | 859 | (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { |
862 | printk(KERN_WARNING "BUG: mapping for 0x%08llx" | 860 | pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n", |
863 | " at 0x%08lx out of vmalloc space\n", | 861 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); |
864 | (long long)__pfn_to_phys((u64)md->pfn), md->virtual); | ||
865 | } | 862 | } |
866 | 863 | ||
867 | type = &mem_types[md->type]; | 864 | type = &mem_types[md->type]; |
@@ -881,9 +878,8 @@ static void __init create_mapping(struct map_desc *md) | |||
881 | length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); | 878 | length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); |
882 | 879 | ||
883 | if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) { | 880 | if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) { |
884 | printk(KERN_WARNING "BUG: map for 0x%08llx at 0x%08lx can not " | 881 | pr_warn("BUG: map for 0x%08llx at 0x%08lx can not be mapped using pages, ignoring.\n", |
885 | "be mapped using pages, ignoring.\n", | 882 | (long long)__pfn_to_phys(md->pfn), addr); |
886 | (long long)__pfn_to_phys(md->pfn), addr); | ||
887 | return; | 883 | return; |
888 | } | 884 | } |
889 | 885 | ||
@@ -1053,15 +1049,13 @@ static int __init early_vmalloc(char *arg) | |||
1053 | 1049 | ||
1054 | if (vmalloc_reserve < SZ_16M) { | 1050 | if (vmalloc_reserve < SZ_16M) { |
1055 | vmalloc_reserve = SZ_16M; | 1051 | vmalloc_reserve = SZ_16M; |
1056 | printk(KERN_WARNING | 1052 | pr_warn("vmalloc area too small, limiting to %luMB\n", |
1057 | "vmalloc area too small, limiting to %luMB\n", | ||
1058 | vmalloc_reserve >> 20); | 1053 | vmalloc_reserve >> 20); |
1059 | } | 1054 | } |
1060 | 1055 | ||
1061 | if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) { | 1056 | if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) { |
1062 | vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M); | 1057 | vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M); |
1063 | printk(KERN_WARNING | 1058 | pr_warn("vmalloc area is too big, limiting to %luMB\n", |
1064 | "vmalloc area is too big, limiting to %luMB\n", | ||
1065 | vmalloc_reserve >> 20); | 1059 | vmalloc_reserve >> 20); |
1066 | } | 1060 | } |
1067 | 1061 | ||
@@ -1094,7 +1088,7 @@ void __init sanity_check_meminfo(void) | |||
1094 | 1088 | ||
1095 | if (highmem) { | 1089 | if (highmem) { |
1096 | pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n", | 1090 | pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n", |
1097 | &block_start, &block_end); | 1091 | &block_start, &block_end); |
1098 | memblock_remove(reg->base, reg->size); | 1092 | memblock_remove(reg->base, reg->size); |
1099 | continue; | 1093 | continue; |
1100 | } | 1094 | } |
@@ -1103,7 +1097,7 @@ void __init sanity_check_meminfo(void) | |||
1103 | phys_addr_t overlap_size = reg->size - size_limit; | 1097 | phys_addr_t overlap_size = reg->size - size_limit; |
1104 | 1098 | ||
1105 | pr_notice("Truncating RAM at %pa-%pa to -%pa", | 1099 | pr_notice("Truncating RAM at %pa-%pa to -%pa", |
1106 | &block_start, &block_end, &vmalloc_limit); | 1100 | &block_start, &block_end, &vmalloc_limit); |
1107 | memblock_remove(vmalloc_limit, overlap_size); | 1101 | memblock_remove(vmalloc_limit, overlap_size); |
1108 | block_end = vmalloc_limit; | 1102 | block_end = vmalloc_limit; |
1109 | } | 1103 | } |
@@ -1326,10 +1320,10 @@ static void __init kmap_init(void) | |||
1326 | #ifdef CONFIG_HIGHMEM | 1320 | #ifdef CONFIG_HIGHMEM |
1327 | pkmap_page_table = early_pte_alloc(pmd_off_k(PKMAP_BASE), | 1321 | pkmap_page_table = early_pte_alloc(pmd_off_k(PKMAP_BASE), |
1328 | PKMAP_BASE, _PAGE_KERNEL_TABLE); | 1322 | PKMAP_BASE, _PAGE_KERNEL_TABLE); |
1329 | |||
1330 | fixmap_page_table = early_pte_alloc(pmd_off_k(FIXADDR_START), | ||
1331 | FIXADDR_START, _PAGE_KERNEL_TABLE); | ||
1332 | #endif | 1323 | #endif |
1324 | |||
1325 | early_pte_alloc(pmd_off_k(FIXADDR_START), FIXADDR_START, | ||
1326 | _PAGE_KERNEL_TABLE); | ||
1333 | } | 1327 | } |
1334 | 1328 | ||
1335 | static void __init map_lowmem(void) | 1329 | static void __init map_lowmem(void) |
@@ -1349,13 +1343,20 @@ static void __init map_lowmem(void) | |||
1349 | if (start >= end) | 1343 | if (start >= end) |
1350 | break; | 1344 | break; |
1351 | 1345 | ||
1352 | if (end < kernel_x_start || start >= kernel_x_end) { | 1346 | if (end < kernel_x_start) { |
1353 | map.pfn = __phys_to_pfn(start); | 1347 | map.pfn = __phys_to_pfn(start); |
1354 | map.virtual = __phys_to_virt(start); | 1348 | map.virtual = __phys_to_virt(start); |
1355 | map.length = end - start; | 1349 | map.length = end - start; |
1356 | map.type = MT_MEMORY_RWX; | 1350 | map.type = MT_MEMORY_RWX; |
1357 | 1351 | ||
1358 | create_mapping(&map); | 1352 | create_mapping(&map); |
1353 | } else if (start >= kernel_x_end) { | ||
1354 | map.pfn = __phys_to_pfn(start); | ||
1355 | map.virtual = __phys_to_virt(start); | ||
1356 | map.length = end - start; | ||
1357 | map.type = MT_MEMORY_RW; | ||
1358 | |||
1359 | create_mapping(&map); | ||
1359 | } else { | 1360 | } else { |
1360 | /* This better cover the entire kernel */ | 1361 | /* This better cover the entire kernel */ |
1361 | if (start < kernel_x_start) { | 1362 | if (start < kernel_x_start) { |
diff --git a/arch/arm/mm/pageattr.c b/arch/arm/mm/pageattr.c new file mode 100644 index 000000000000..004e35cdcfff --- /dev/null +++ b/arch/arm/mm/pageattr.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014, The Linux Foundation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | #include <linux/mm.h> | ||
14 | #include <linux/module.h> | ||
15 | |||
16 | #include <asm/pgtable.h> | ||
17 | #include <asm/tlbflush.h> | ||
18 | |||
19 | struct page_change_data { | ||
20 | pgprot_t set_mask; | ||
21 | pgprot_t clear_mask; | ||
22 | }; | ||
23 | |||
24 | static int change_page_range(pte_t *ptep, pgtable_t token, unsigned long addr, | ||
25 | void *data) | ||
26 | { | ||
27 | struct page_change_data *cdata = data; | ||
28 | pte_t pte = *ptep; | ||
29 | |||
30 | pte = clear_pte_bit(pte, cdata->clear_mask); | ||
31 | pte = set_pte_bit(pte, cdata->set_mask); | ||
32 | |||
33 | set_pte_ext(ptep, pte, 0); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int change_memory_common(unsigned long addr, int numpages, | ||
38 | pgprot_t set_mask, pgprot_t clear_mask) | ||
39 | { | ||
40 | unsigned long start = addr; | ||
41 | unsigned long size = PAGE_SIZE*numpages; | ||
42 | unsigned long end = start + size; | ||
43 | int ret; | ||
44 | struct page_change_data data; | ||
45 | |||
46 | if (!IS_ALIGNED(addr, PAGE_SIZE)) { | ||
47 | start &= PAGE_MASK; | ||
48 | end = start + size; | ||
49 | WARN_ON_ONCE(1); | ||
50 | } | ||
51 | |||
52 | if (!is_module_address(start) || !is_module_address(end - 1)) | ||
53 | return -EINVAL; | ||
54 | |||
55 | data.set_mask = set_mask; | ||
56 | data.clear_mask = clear_mask; | ||
57 | |||
58 | ret = apply_to_page_range(&init_mm, start, size, change_page_range, | ||
59 | &data); | ||
60 | |||
61 | flush_tlb_kernel_range(start, end); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | int set_memory_ro(unsigned long addr, int numpages) | ||
66 | { | ||
67 | return change_memory_common(addr, numpages, | ||
68 | __pgprot(L_PTE_RDONLY), | ||
69 | __pgprot(0)); | ||
70 | } | ||
71 | |||
72 | int set_memory_rw(unsigned long addr, int numpages) | ||
73 | { | ||
74 | return change_memory_common(addr, numpages, | ||
75 | __pgprot(0), | ||
76 | __pgprot(L_PTE_RDONLY)); | ||
77 | } | ||
78 | |||
79 | int set_memory_nx(unsigned long addr, int numpages) | ||
80 | { | ||
81 | return change_memory_common(addr, numpages, | ||
82 | __pgprot(L_PTE_XN), | ||
83 | __pgprot(0)); | ||
84 | } | ||
85 | |||
86 | int set_memory_x(unsigned long addr, int numpages) | ||
87 | { | ||
88 | return change_memory_common(addr, numpages, | ||
89 | __pgprot(0), | ||
90 | __pgprot(L_PTE_XN)); | ||
91 | } | ||
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 22ac2a6fbfe3..8b4ee5e81c14 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -591,9 +591,10 @@ __krait_proc_info: | |||
591 | /* | 591 | /* |
592 | * Some Krait processors don't indicate support for SDIV and UDIV | 592 | * Some Krait processors don't indicate support for SDIV and UDIV |
593 | * instructions in the ARM instruction set, even though they actually | 593 | * instructions in the ARM instruction set, even though they actually |
594 | * do support them. | 594 | * do support them. They also don't indicate support for fused multiply |
595 | * instructions even though they actually do support them. | ||
595 | */ | 596 | */ |
596 | __v7_proc __v7_setup, hwcaps = HWCAP_IDIV | 597 | __v7_proc __v7_setup, hwcaps = HWCAP_IDIV | HWCAP_VFPv4 |
597 | .size __krait_proc_info, . - __krait_proc_info | 598 | .size __krait_proc_info, . - __krait_proc_info |
598 | 599 | ||
599 | /* | 600 | /* |
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index 4e729f055a81..ec717c190e2c 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c | |||
@@ -86,20 +86,20 @@ extern void nwfpe_enter(void); | |||
86 | static int __init fpe_init(void) | 86 | static int __init fpe_init(void) |
87 | { | 87 | { |
88 | if (sizeof(FPA11) > sizeof(union fp_state)) { | 88 | if (sizeof(FPA11) > sizeof(union fp_state)) { |
89 | printk(KERN_ERR "nwfpe: bad structure size\n"); | 89 | pr_err("nwfpe: bad structure size\n"); |
90 | return -EINVAL; | 90 | return -EINVAL; |
91 | } | 91 | } |
92 | 92 | ||
93 | if (sizeof(FPREG) != 12) { | 93 | if (sizeof(FPREG) != 12) { |
94 | printk(KERN_ERR "nwfpe: bad register size\n"); | 94 | pr_err("nwfpe: bad register size\n"); |
95 | return -EINVAL; | 95 | return -EINVAL; |
96 | } | 96 | } |
97 | if (fpe_type[0] && strcmp(fpe_type, "nwfpe")) | 97 | if (fpe_type[0] && strcmp(fpe_type, "nwfpe")) |
98 | return 0; | 98 | return 0; |
99 | 99 | ||
100 | /* Display title, version and copyright information. */ | 100 | /* Display title, version and copyright information. */ |
101 | printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 (" | 101 | pr_info("NetWinder Floating Point Emulator V0.97 (" |
102 | NWFPE_BITS " precision)\n"); | 102 | NWFPE_BITS " precision)\n"); |
103 | 103 | ||
104 | thread_register_notifier(&nwfpe_notifier_block); | 104 | thread_register_notifier(&nwfpe_notifier_block); |
105 | 105 | ||
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index cda654cbf2c2..f74a8f7e5f84 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S | |||
@@ -197,6 +197,12 @@ look_for_VFP_exceptions: | |||
197 | tst r5, #FPSCR_IXE | 197 | tst r5, #FPSCR_IXE |
198 | bne process_exception | 198 | bne process_exception |
199 | 199 | ||
200 | tst r5, #FPSCR_LENGTH_MASK | ||
201 | beq skip | ||
202 | orr r1, r1, #FPEXC_DEX | ||
203 | b process_exception | ||
204 | skip: | ||
205 | |||
200 | @ Fall into hand on to next handler - appropriate coproc instr | 206 | @ Fall into hand on to next handler - appropriate coproc instr |
201 | @ not recognised by VFP | 207 | @ not recognised by VFP |
202 | 208 | ||
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 2f37e1d6cb45..f6e4d56eda00 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c | |||
@@ -738,63 +738,73 @@ static int __init vfp_init(void) | |||
738 | vfp_vector = vfp_null_entry; | 738 | vfp_vector = vfp_null_entry; |
739 | 739 | ||
740 | pr_info("VFP support v0.3: "); | 740 | pr_info("VFP support v0.3: "); |
741 | if (VFP_arch) | 741 | if (VFP_arch) { |
742 | pr_cont("not present\n"); | 742 | pr_cont("not present\n"); |
743 | else if (vfpsid & FPSID_NODOUBLE) { | 743 | return 0; |
744 | pr_cont("no double precision support\n"); | 744 | /* Extract the architecture on CPUID scheme */ |
745 | } else { | 745 | } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) { |
746 | hotcpu_notifier(vfp_hotplug, 0); | 746 | VFP_arch = vfpsid & FPSID_CPUID_ARCH_MASK; |
747 | 747 | VFP_arch >>= FPSID_ARCH_BIT; | |
748 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ | ||
749 | pr_cont("implementor %02x architecture %d part %02x variant %x rev %x\n", | ||
750 | (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, | ||
751 | (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT, | ||
752 | (vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT, | ||
753 | (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, | ||
754 | (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); | ||
755 | |||
756 | vfp_vector = vfp_support_entry; | ||
757 | |||
758 | thread_register_notifier(&vfp_notifier_block); | ||
759 | vfp_pm_init(); | ||
760 | |||
761 | /* | ||
762 | * We detected VFP, and the support code is | ||
763 | * in place; report VFP support to userspace. | ||
764 | */ | ||
765 | elf_hwcap |= HWCAP_VFP; | ||
766 | #ifdef CONFIG_VFPv3 | ||
767 | if (VFP_arch >= 2) { | ||
768 | elf_hwcap |= HWCAP_VFPv3; | ||
769 | |||
770 | /* | ||
771 | * Check for VFPv3 D16 and VFPv4 D16. CPUs in | ||
772 | * this configuration only have 16 x 64bit | ||
773 | * registers. | ||
774 | */ | ||
775 | if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) | ||
776 | elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */ | ||
777 | else | ||
778 | elf_hwcap |= HWCAP_VFPD32; | ||
779 | } | ||
780 | #endif | ||
781 | /* | 748 | /* |
782 | * Check for the presence of the Advanced SIMD | 749 | * Check for the presence of the Advanced SIMD |
783 | * load/store instructions, integer and single | 750 | * load/store instructions, integer and single |
784 | * precision floating point operations. Only check | 751 | * precision floating point operations. Only check |
785 | * for NEON if the hardware has the MVFR registers. | 752 | * for NEON if the hardware has the MVFR registers. |
786 | */ | 753 | */ |
787 | if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) { | 754 | if (IS_ENABLED(CONFIG_NEON) && |
788 | #ifdef CONFIG_NEON | 755 | (fmrx(MVFR1) & 0x000fff00) == 0x00011100) |
789 | if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) | 756 | elf_hwcap |= HWCAP_NEON; |
790 | elf_hwcap |= HWCAP_NEON; | 757 | |
791 | #endif | 758 | if (IS_ENABLED(CONFIG_VFPv3)) { |
792 | #ifdef CONFIG_VFPv3 | 759 | u32 mvfr0 = fmrx(MVFR0); |
760 | if (((mvfr0 & MVFR0_DP_MASK) >> MVFR0_DP_BIT) == 0x2 || | ||
761 | ((mvfr0 & MVFR0_SP_MASK) >> MVFR0_SP_BIT) == 0x2) { | ||
762 | elf_hwcap |= HWCAP_VFPv3; | ||
763 | /* | ||
764 | * Check for VFPv3 D16 and VFPv4 D16. CPUs in | ||
765 | * this configuration only have 16 x 64bit | ||
766 | * registers. | ||
767 | */ | ||
768 | if ((mvfr0 & MVFR0_A_SIMD_MASK) == 1) | ||
769 | /* also v4-D16 */ | ||
770 | elf_hwcap |= HWCAP_VFPv3D16; | ||
771 | else | ||
772 | elf_hwcap |= HWCAP_VFPD32; | ||
773 | } | ||
774 | |||
793 | if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000) | 775 | if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000) |
794 | elf_hwcap |= HWCAP_VFPv4; | 776 | elf_hwcap |= HWCAP_VFPv4; |
795 | #endif | ||
796 | } | 777 | } |
778 | /* Extract the architecture version on pre-cpuid scheme */ | ||
779 | } else { | ||
780 | if (vfpsid & FPSID_NODOUBLE) { | ||
781 | pr_cont("no double precision support\n"); | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; | ||
797 | } | 786 | } |
787 | |||
788 | hotcpu_notifier(vfp_hotplug, 0); | ||
789 | |||
790 | vfp_vector = vfp_support_entry; | ||
791 | |||
792 | thread_register_notifier(&vfp_notifier_block); | ||
793 | vfp_pm_init(); | ||
794 | |||
795 | /* | ||
796 | * We detected VFP, and the support code is | ||
797 | * in place; report VFP support to userspace. | ||
798 | */ | ||
799 | elf_hwcap |= HWCAP_VFP; | ||
800 | |||
801 | pr_cont("implementor %02x architecture %d part %02x variant %x rev %x\n", | ||
802 | (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, | ||
803 | VFP_arch, | ||
804 | (vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT, | ||
805 | (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, | ||
806 | (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); | ||
807 | |||
798 | return 0; | 808 | return 0; |
799 | } | 809 | } |
800 | 810 | ||
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c index 4f96c1617aae..f0465ba0f221 100644 --- a/arch/arm/vfp/vfpsingle.c +++ b/arch/arm/vfp/vfpsingle.c | |||
@@ -290,7 +290,7 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) | |||
290 | u32 z, a; | 290 | u32 z, a; |
291 | 291 | ||
292 | if ((significand & 0xc0000000) != 0x40000000) { | 292 | if ((significand & 0xc0000000) != 0x40000000) { |
293 | printk(KERN_WARNING "VFP: estimate_sqrt: invalid significand\n"); | 293 | pr_warn("VFP: estimate_sqrt: invalid significand\n"); |
294 | } | 294 | } |
295 | 295 | ||
296 | a = significand << 1; | 296 | a = significand << 1; |
diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile index 1f85bfe6b470..12969523414c 100644 --- a/arch/arm/xen/Makefile +++ b/arch/arm/xen/Makefile | |||
@@ -1 +1 @@ | |||
obj-y := enlighten.o hypercall.o grant-table.o p2m.o mm.o mm32.o | obj-y := enlighten.o hypercall.o grant-table.o p2m.o mm.o | ||
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 0e15f011f9c8..c7ca936ebd99 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
@@ -261,11 +261,6 @@ static int __init xen_guest_init(void) | |||
261 | 261 | ||
262 | xen_setup_features(); | 262 | xen_setup_features(); |
263 | 263 | ||
264 | if (!xen_feature(XENFEAT_grant_map_identity)) { | ||
265 | pr_warn("Please upgrade your Xen.\n" | ||
266 | "If your platform has any non-coherent DMA devices, they won't work properly.\n"); | ||
267 | } | ||
268 | |||
269 | if (xen_feature(XENFEAT_dom0)) | 264 | if (xen_feature(XENFEAT_dom0)) |
270 | xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED; | 265 | xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED; |
271 | else | 266 | else |
diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c index b0e77de99148..351b24a979d4 100644 --- a/arch/arm/xen/mm.c +++ b/arch/arm/xen/mm.c | |||
@@ -1,6 +1,10 @@ | |||
1 | #include <linux/cpu.h> | ||
2 | #include <linux/dma-mapping.h> | ||
1 | #include <linux/bootmem.h> | 3 | #include <linux/bootmem.h> |
2 | #include <linux/gfp.h> | 4 | #include <linux/gfp.h> |
5 | #include <linux/highmem.h> | ||
3 | #include <linux/export.h> | 6 | #include <linux/export.h> |
7 | #include <linux/of_address.h> | ||
4 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
5 | #include <linux/types.h> | 9 | #include <linux/types.h> |
6 | #include <linux/dma-mapping.h> | 10 | #include <linux/dma-mapping.h> |
@@ -8,6 +12,7 @@ | |||
8 | #include <linux/swiotlb.h> | 12 | #include <linux/swiotlb.h> |
9 | 13 | ||
10 | #include <xen/xen.h> | 14 | #include <xen/xen.h> |
15 | #include <xen/interface/grant_table.h> | ||
11 | #include <xen/interface/memory.h> | 16 | #include <xen/interface/memory.h> |
12 | #include <xen/swiotlb-xen.h> | 17 | #include <xen/swiotlb-xen.h> |
13 | 18 | ||
@@ -16,6 +21,114 @@ | |||
16 | #include <asm/xen/hypercall.h> | 21 | #include <asm/xen/hypercall.h> |
17 | #include <asm/xen/interface.h> | 22 | #include <asm/xen/interface.h> |
18 | 23 | ||
24 | enum dma_cache_op { | ||
25 | DMA_UNMAP, | ||
26 | DMA_MAP, | ||
27 | }; | ||
28 | static bool hypercall_cflush = false; | ||
29 | |||
30 | /* functions called by SWIOTLB */ | ||
31 | |||
32 | static void dma_cache_maint(dma_addr_t handle, unsigned long offset, | ||
33 | size_t size, enum dma_data_direction dir, enum dma_cache_op op) | ||
34 | { | ||
35 | struct gnttab_cache_flush cflush; | ||
36 | unsigned long pfn; | ||
37 | size_t left = size; | ||
38 | |||
39 | pfn = (handle >> PAGE_SHIFT) + offset / PAGE_SIZE; | ||
40 | offset %= PAGE_SIZE; | ||
41 | |||
42 | do { | ||
43 | size_t len = left; | ||
44 | |||
45 | /* buffers in highmem or foreign pages cannot cross page | ||
46 | * boundaries */ | ||
47 | if (len + offset > PAGE_SIZE) | ||
48 | len = PAGE_SIZE - offset; | ||
49 | |||
50 | cflush.op = 0; | ||
51 | cflush.a.dev_bus_addr = pfn << PAGE_SHIFT; | ||
52 | cflush.offset = offset; | ||
53 | cflush.length = len; | ||
54 | |||
55 | if (op == DMA_UNMAP && dir != DMA_TO_DEVICE) | ||
56 | cflush.op = GNTTAB_CACHE_INVAL; | ||
57 | if (op == DMA_MAP) { | ||
58 | if (dir == DMA_FROM_DEVICE) | ||
59 | cflush.op = GNTTAB_CACHE_INVAL; | ||
60 | else | ||
61 | cflush.op = GNTTAB_CACHE_CLEAN; | ||
62 | } | ||
63 | if (cflush.op) | ||
64 | HYPERVISOR_grant_table_op(GNTTABOP_cache_flush, &cflush, 1); | ||
65 | |||
66 | offset = 0; | ||
67 | pfn++; | ||
68 | left -= len; | ||
69 | } while (left); | ||
70 | } | ||
71 | |||
72 | static void __xen_dma_page_dev_to_cpu(struct device *hwdev, dma_addr_t handle, | ||
73 | size_t size, enum dma_data_direction dir) | ||
74 | { | ||
75 | dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, DMA_UNMAP); | ||
76 | } | ||
77 | |||
78 | static void __xen_dma_page_cpu_to_dev(struct device *hwdev, dma_addr_t handle, | ||
79 | size_t size, enum dma_data_direction dir) | ||
80 | { | ||
81 | dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, DMA_MAP); | ||
82 | } | ||
83 | |||
84 | void __xen_dma_map_page(struct device *hwdev, struct page *page, | ||
85 | dma_addr_t dev_addr, unsigned long offset, size_t size, | ||
86 | enum dma_data_direction dir, struct dma_attrs *attrs) | ||
87 | { | ||
88 | if (is_device_dma_coherent(hwdev)) | ||
89 | return; | ||
90 | if (dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) | ||
91 | return; | ||
92 | |||
93 | __xen_dma_page_cpu_to_dev(hwdev, dev_addr, size, dir); | ||
94 | } | ||
95 | |||
96 | void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, | ||
97 | size_t size, enum dma_data_direction dir, | ||
98 | struct dma_attrs *attrs) | ||
99 | |||
100 | { | ||
101 | if (is_device_dma_coherent(hwdev)) | ||
102 | return; | ||
103 | if (dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) | ||
104 | return; | ||
105 | |||
106 | __xen_dma_page_dev_to_cpu(hwdev, handle, size, dir); | ||
107 | } | ||
108 | |||
109 | void __xen_dma_sync_single_for_cpu(struct device *hwdev, | ||
110 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
111 | { | ||
112 | if (is_device_dma_coherent(hwdev)) | ||
113 | return; | ||
114 | __xen_dma_page_dev_to_cpu(hwdev, handle, size, dir); | ||
115 | } | ||
116 | |||
117 | void __xen_dma_sync_single_for_device(struct device *hwdev, | ||
118 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
119 | { | ||
120 | if (is_device_dma_coherent(hwdev)) | ||
121 | return; | ||
122 | __xen_dma_page_cpu_to_dev(hwdev, handle, size, dir); | ||
123 | } | ||
124 | |||
125 | bool xen_arch_need_swiotlb(struct device *dev, | ||
126 | unsigned long pfn, | ||
127 | unsigned long mfn) | ||
128 | { | ||
129 | return (!hypercall_cflush && (pfn != mfn) && !is_device_dma_coherent(dev)); | ||
130 | } | ||
131 | |||
19 | int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, | 132 | int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, |
20 | unsigned int address_bits, | 133 | unsigned int address_bits, |
21 | dma_addr_t *dma_handle) | 134 | dma_addr_t *dma_handle) |
@@ -56,10 +169,18 @@ static struct dma_map_ops xen_swiotlb_dma_ops = { | |||
56 | 169 | ||
57 | int __init xen_mm_init(void) | 170 | int __init xen_mm_init(void) |
58 | { | 171 | { |
172 | struct gnttab_cache_flush cflush; | ||
59 | if (!xen_initial_domain()) | 173 | if (!xen_initial_domain()) |
60 | return 0; | 174 | return 0; |
61 | xen_swiotlb_init(1, false); | 175 | xen_swiotlb_init(1, false); |
62 | xen_dma_ops = &xen_swiotlb_dma_ops; | 176 | xen_dma_ops = &xen_swiotlb_dma_ops; |
177 | |||
178 | cflush.op = 0; | ||
179 | cflush.a.dev_bus_addr = 0; | ||
180 | cflush.offset = 0; | ||
181 | cflush.length = 0; | ||
182 | if (HYPERVISOR_grant_table_op(GNTTABOP_cache_flush, &cflush, 1) != -ENOSYS) | ||
183 | hypercall_cflush = true; | ||
63 | return 0; | 184 | return 0; |
64 | } | 185 | } |
65 | arch_initcall(xen_mm_init); | 186 | arch_initcall(xen_mm_init); |
diff --git a/arch/arm/xen/mm32.c b/arch/arm/xen/mm32.c deleted file mode 100644 index 3b99860fd7ae..000000000000 --- a/arch/arm/xen/mm32.c +++ /dev/null | |||
@@ -1,202 +0,0 @@ | |||
1 | #include <linux/cpu.h> | ||
2 | #include <linux/dma-mapping.h> | ||
3 | #include <linux/gfp.h> | ||
4 | #include <linux/highmem.h> | ||
5 | |||
6 | #include <xen/features.h> | ||
7 | |||
8 | static DEFINE_PER_CPU(unsigned long, xen_mm32_scratch_virt); | ||
9 | static DEFINE_PER_CPU(pte_t *, xen_mm32_scratch_ptep); | ||
10 | |||
11 | static int alloc_xen_mm32_scratch_page(int cpu) | ||
12 | { | ||
13 | struct page *page; | ||
14 | unsigned long virt; | ||
15 | pmd_t *pmdp; | ||
16 | pte_t *ptep; | ||
17 | |||
18 | if (per_cpu(xen_mm32_scratch_ptep, cpu) != NULL) | ||
19 | return 0; | ||
20 | |||
21 | page = alloc_page(GFP_KERNEL); | ||
22 | if (page == NULL) { | ||
23 | pr_warn("Failed to allocate xen_mm32_scratch_page for cpu %d\n", cpu); | ||
24 | return -ENOMEM; | ||
25 | } | ||
26 | |||
27 | virt = (unsigned long)__va(page_to_phys(page)); | ||
28 | pmdp = pmd_offset(pud_offset(pgd_offset_k(virt), virt), virt); | ||
29 | ptep = pte_offset_kernel(pmdp, virt); | ||
30 | |||
31 | per_cpu(xen_mm32_scratch_virt, cpu) = virt; | ||
32 | per_cpu(xen_mm32_scratch_ptep, cpu) = ptep; | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int xen_mm32_cpu_notify(struct notifier_block *self, | ||
38 | unsigned long action, void *hcpu) | ||
39 | { | ||
40 | int cpu = (long)hcpu; | ||
41 | switch (action) { | ||
42 | case CPU_UP_PREPARE: | ||
43 | if (alloc_xen_mm32_scratch_page(cpu)) | ||
44 | return NOTIFY_BAD; | ||
45 | break; | ||
46 | default: | ||
47 | break; | ||
48 | } | ||
49 | return NOTIFY_OK; | ||
50 | } | ||
51 | |||
52 | static struct notifier_block xen_mm32_cpu_notifier = { | ||
53 | .notifier_call = xen_mm32_cpu_notify, | ||
54 | }; | ||
55 | |||
56 | static void* xen_mm32_remap_page(dma_addr_t handle) | ||
57 | { | ||
58 | unsigned long virt = get_cpu_var(xen_mm32_scratch_virt); | ||
59 | pte_t *ptep = __get_cpu_var(xen_mm32_scratch_ptep); | ||
60 | |||
61 | *ptep = pfn_pte(handle >> PAGE_SHIFT, PAGE_KERNEL); | ||
62 | local_flush_tlb_kernel_page(virt); | ||
63 | |||
64 | return (void*)virt; | ||
65 | } | ||
66 | |||
67 | static void xen_mm32_unmap(void *vaddr) | ||
68 | { | ||
69 | put_cpu_var(xen_mm32_scratch_virt); | ||
70 | } | ||
71 | |||
72 | |||
73 | /* functions called by SWIOTLB */ | ||
74 | |||
75 | static void dma_cache_maint(dma_addr_t handle, unsigned long offset, | ||
76 | size_t size, enum dma_data_direction dir, | ||
77 | void (*op)(const void *, size_t, int)) | ||
78 | { | ||
79 | unsigned long pfn; | ||
80 | size_t left = size; | ||
81 | |||
82 | pfn = (handle >> PAGE_SHIFT) + offset / PAGE_SIZE; | ||
83 | offset %= PAGE_SIZE; | ||
84 | |||
85 | do { | ||
86 | size_t len = left; | ||
87 | void *vaddr; | ||
88 | |||
89 | if (!pfn_valid(pfn)) | ||
90 | { | ||
91 | /* Cannot map the page, we don't know its physical address. | ||
92 | * Return and hope for the best */ | ||
93 | if (!xen_feature(XENFEAT_grant_map_identity)) | ||
94 | return; | ||
95 | vaddr = xen_mm32_remap_page(handle) + offset; | ||
96 | op(vaddr, len, dir); | ||
97 | xen_mm32_unmap(vaddr - offset); | ||
98 | } else { | ||
99 | struct page *page = pfn_to_page(pfn); | ||
100 | |||
101 | if (PageHighMem(page)) { | ||
102 | if (len + offset > PAGE_SIZE) | ||
103 | len = PAGE_SIZE - offset; | ||
104 | |||
105 | if (cache_is_vipt_nonaliasing()) { | ||
106 | vaddr = kmap_atomic(page); | ||
107 | op(vaddr + offset, len, dir); | ||
108 | kunmap_atomic(vaddr); | ||
109 | } else { | ||
110 | vaddr = kmap_high_get(page); | ||
111 | if (vaddr) { | ||
112 | op(vaddr + offset, len, dir); | ||
113 | kunmap_high(page); | ||
114 | } | ||
115 | } | ||
116 | } else { | ||
117 | vaddr = page_address(page) + offset; | ||
118 | op(vaddr, len, dir); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | offset = 0; | ||
123 | pfn++; | ||
124 | left -= len; | ||
125 | } while (left); | ||
126 | } | ||
127 | |||
128 | static void __xen_dma_page_dev_to_cpu(struct device *hwdev, dma_addr_t handle, | ||
129 | size_t size, enum dma_data_direction dir) | ||
130 | { | ||
131 | /* Cannot use __dma_page_dev_to_cpu because we don't have a | ||
132 | * struct page for handle */ | ||
133 | |||
134 | if (dir != DMA_TO_DEVICE) | ||
135 | outer_inv_range(handle, handle + size); | ||
136 | |||
137 | dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, dmac_unmap_area); | ||
138 | } | ||
139 | |||
140 | static void __xen_dma_page_cpu_to_dev(struct device *hwdev, dma_addr_t handle, | ||
141 | size_t size, enum dma_data_direction dir) | ||
142 | { | ||
143 | |||
144 | dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, dmac_map_area); | ||
145 | |||
146 | if (dir == DMA_FROM_DEVICE) { | ||
147 | outer_inv_range(handle, handle + size); | ||
148 | } else { | ||
149 | outer_clean_range(handle, handle + size); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, | ||
154 | size_t size, enum dma_data_direction dir, | ||
155 | struct dma_attrs *attrs) | ||
156 | |||
157 | { | ||
158 | if (!__generic_dma_ops(hwdev)->unmap_page) | ||
159 | return; | ||
160 | if (dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) | ||
161 | return; | ||
162 | |||
163 | __xen_dma_page_dev_to_cpu(hwdev, handle, size, dir); | ||
164 | } | ||
165 | |||
166 | void xen_dma_sync_single_for_cpu(struct device *hwdev, | ||
167 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
168 | { | ||
169 | if (!__generic_dma_ops(hwdev)->sync_single_for_cpu) | ||
170 | return; | ||
171 | __xen_dma_page_dev_to_cpu(hwdev, handle, size, dir); | ||
172 | } | ||
173 | |||
174 | void xen_dma_sync_single_for_device(struct device *hwdev, | ||
175 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
176 | { | ||
177 | if (!__generic_dma_ops(hwdev)->sync_single_for_device) | ||
178 | return; | ||
179 | __xen_dma_page_cpu_to_dev(hwdev, handle, size, dir); | ||
180 | } | ||
181 | |||
182 | int __init xen_mm32_init(void) | ||
183 | { | ||
184 | int cpu; | ||
185 | |||
186 | if (!xen_initial_domain()) | ||
187 | return 0; | ||
188 | |||
189 | register_cpu_notifier(&xen_mm32_cpu_notifier); | ||
190 | get_online_cpus(); | ||
191 | for_each_online_cpu(cpu) { | ||
192 | if (alloc_xen_mm32_scratch_page(cpu)) { | ||
193 | put_online_cpus(); | ||
194 | unregister_cpu_notifier(&xen_mm32_cpu_notifier); | ||
195 | return -ENOMEM; | ||
196 | } | ||
197 | } | ||
198 | put_online_cpus(); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | arch_initcall(xen_mm32_init); | ||
diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h index cf98b362094b..243ef256b8c9 100644 --- a/arch/arm64/include/asm/device.h +++ b/arch/arm64/include/asm/device.h | |||
@@ -21,6 +21,7 @@ struct dev_archdata { | |||
21 | #ifdef CONFIG_IOMMU_API | 21 | #ifdef CONFIG_IOMMU_API |
22 | void *iommu; /* private IOMMU data */ | 22 | void *iommu; /* private IOMMU data */ |
23 | #endif | 23 | #endif |
24 | bool dma_coherent; | ||
24 | }; | 25 | }; |
25 | 26 | ||
26 | struct pdev_archdata { | 27 | struct pdev_archdata { |
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h index adeae3f6f0fc..d34189bceff7 100644 --- a/arch/arm64/include/asm/dma-mapping.h +++ b/arch/arm64/include/asm/dma-mapping.h | |||
@@ -54,11 +54,18 @@ static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) | |||
54 | 54 | ||
55 | static inline int set_arch_dma_coherent_ops(struct device *dev) | 55 | static inline int set_arch_dma_coherent_ops(struct device *dev) |
56 | { | 56 | { |
57 | dev->archdata.dma_coherent = true; | ||
57 | set_dma_ops(dev, &coherent_swiotlb_dma_ops); | 58 | set_dma_ops(dev, &coherent_swiotlb_dma_ops); |
58 | return 0; | 59 | return 0; |
59 | } | 60 | } |
60 | #define set_arch_dma_coherent_ops set_arch_dma_coherent_ops | 61 | #define set_arch_dma_coherent_ops set_arch_dma_coherent_ops |
61 | 62 | ||
63 | /* do not use this function in a driver */ | ||
64 | static inline bool is_device_dma_coherent(struct device *dev) | ||
65 | { | ||
66 | return dev->archdata.dma_coherent; | ||
67 | } | ||
68 | |||
62 | #include <asm-generic/dma-mapping-common.h> | 69 | #include <asm-generic/dma-mapping-common.h> |
63 | 70 | ||
64 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | 71 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) |
diff --git a/arch/arm64/include/asm/xen/page-coherent.h b/arch/arm64/include/asm/xen/page-coherent.h index dde3fc9c49f0..2052102b4e02 100644 --- a/arch/arm64/include/asm/xen/page-coherent.h +++ b/arch/arm64/include/asm/xen/page-coherent.h | |||
@@ -1,43 +1 @@ | |||
1 | #ifndef _ASM_ARM64_XEN_PAGE_COHERENT_H | #include <../../arm/include/asm/xen/page-coherent.h> | |
2 | #define _ASM_ARM64_XEN_PAGE_COHERENT_H | ||
3 | |||
4 | #include <asm/page.h> | ||
5 | #include <linux/dma-attrs.h> | ||
6 | #include <linux/dma-mapping.h> | ||
7 | |||
8 | static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size, | ||
9 | dma_addr_t *dma_handle, gfp_t flags, | ||
10 | struct dma_attrs *attrs) | ||
11 | { | ||
12 | return __generic_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs); | ||
13 | } | ||
14 | |||
15 | static inline void xen_free_coherent_pages(struct device *hwdev, size_t size, | ||
16 | void *cpu_addr, dma_addr_t dma_handle, | ||
17 | struct dma_attrs *attrs) | ||
18 | { | ||
19 | __generic_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs); | ||
20 | } | ||
21 | |||
22 | static inline void xen_dma_map_page(struct device *hwdev, struct page *page, | ||
23 | unsigned long offset, size_t size, enum dma_data_direction dir, | ||
24 | struct dma_attrs *attrs) | ||
25 | { | ||
26 | } | ||
27 | |||
28 | static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, | ||
29 | size_t size, enum dma_data_direction dir, | ||
30 | struct dma_attrs *attrs) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | static inline void xen_dma_sync_single_for_cpu(struct device *hwdev, | ||
35 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | static inline void xen_dma_sync_single_for_device(struct device *hwdev, | ||
40 | dma_addr_t handle, size_t size, enum dma_data_direction dir) | ||
41 | { | ||
42 | } | ||
43 | #endif /* _ASM_ARM64_XEN_PAGE_COHERENT_H */ | ||
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index 663da771580a..3425f311c49e 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c | |||
@@ -511,7 +511,7 @@ static int cpu_psci_cpu_kill(unsigned int cpu) | |||
511 | 511 | ||
512 | static int psci_suspend_finisher(unsigned long index) | 512 | static int psci_suspend_finisher(unsigned long index) |
513 | { | 513 | { |
514 | struct psci_power_state *state = __get_cpu_var(psci_power_state); | 514 | struct psci_power_state *state = __this_cpu_read(psci_power_state); |
515 | 515 | ||
516 | return psci_ops.cpu_suspend(state[index - 1], | 516 | return psci_ops.cpu_suspend(state[index - 1], |
517 | virt_to_phys(cpu_resume)); | 517 | virt_to_phys(cpu_resume)); |
@@ -520,7 +520,7 @@ static int psci_suspend_finisher(unsigned long index) | |||
520 | static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index) | 520 | static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index) |
521 | { | 521 | { |
522 | int ret; | 522 | int ret; |
523 | struct psci_power_state *state = __get_cpu_var(psci_power_state); | 523 | struct psci_power_state *state = __this_cpu_read(psci_power_state); |
524 | /* | 524 | /* |
525 | * idle state index 0 corresponds to wfi, should never be called | 525 | * idle state index 0 corresponds to wfi, should never be called |
526 | * from the cpu_suspend operations | 526 | * from the cpu_suspend operations |
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index f5e18bf3275e..e5fc463b36d0 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms | |||
@@ -2,7 +2,9 @@ | |||
2 | 2 | ||
3 | platforms += alchemy | 3 | platforms += alchemy |
4 | platforms += ar7 | 4 | platforms += ar7 |
5 | platforms += ath25 | ||
5 | platforms += ath79 | 6 | platforms += ath79 |
7 | platforms += bcm3384 | ||
6 | platforms += bcm47xx | 8 | platforms += bcm47xx |
7 | platforms += bcm63xx | 9 | platforms += bcm63xx |
8 | platforms += cavium-octeon | 10 | platforms += cavium-octeon |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 9536ef912f59..3289969ee423 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -53,6 +53,7 @@ config MIPS | |||
53 | select HAVE_CC_STACKPROTECTOR | 53 | select HAVE_CC_STACKPROTECTOR |
54 | select CPU_PM if CPU_IDLE | 54 | select CPU_PM if CPU_IDLE |
55 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST | 55 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST |
56 | select ARCH_BINFMT_ELF_STATE | ||
56 | 57 | ||
57 | menu "Machine selection" | 58 | menu "Machine selection" |
58 | 59 | ||
@@ -62,7 +63,7 @@ choice | |||
62 | 63 | ||
63 | config MIPS_ALCHEMY | 64 | config MIPS_ALCHEMY |
64 | bool "Alchemy processor based machines" | 65 | bool "Alchemy processor based machines" |
65 | select 64BIT_PHYS_ADDR | 66 | select ARCH_PHYS_ADDR_T_64BIT |
66 | select CEVT_R4K | 67 | select CEVT_R4K |
67 | select CSRC_R4K | 68 | select CSRC_R4K |
68 | select IRQ_CPU | 69 | select IRQ_CPU |
@@ -96,6 +97,20 @@ config AR7 | |||
96 | Support for the Texas Instruments AR7 System-on-a-Chip | 97 | Support for the Texas Instruments AR7 System-on-a-Chip |
97 | family: TNETD7100, 7200 and 7300. | 98 | family: TNETD7100, 7200 and 7300. |
98 | 99 | ||
100 | config ATH25 | ||
101 | bool "Atheros AR231x/AR531x SoC support" | ||
102 | select CEVT_R4K | ||
103 | select CSRC_R4K | ||
104 | select DMA_NONCOHERENT | ||
105 | select IRQ_CPU | ||
106 | select IRQ_DOMAIN | ||
107 | select SYS_HAS_CPU_MIPS32_R1 | ||
108 | select SYS_SUPPORTS_BIG_ENDIAN | ||
109 | select SYS_SUPPORTS_32BIT_KERNEL | ||
110 | select SYS_HAS_EARLY_PRINTK | ||
111 | help | ||
112 | Support for Atheros AR231x and Atheros AR531x based boards | ||
113 | |||
99 | config ATH79 | 114 | config ATH79 |
100 | bool "Atheros AR71XX/AR724X/AR913X based boards" | 115 | bool "Atheros AR71XX/AR724X/AR913X based boards" |
101 | select ARCH_REQUIRE_GPIOLIB | 116 | select ARCH_REQUIRE_GPIOLIB |
@@ -115,6 +130,32 @@ config ATH79 | |||
115 | help | 130 | help |
116 | Support for the Atheros AR71XX/AR724X/AR913X SoCs. | 131 | Support for the Atheros AR71XX/AR724X/AR913X SoCs. |
117 | 132 | ||
133 | config BCM3384 | ||
134 | bool "Broadcom BCM3384 based boards" | ||
135 | select BOOT_RAW | ||
136 | select NO_EXCEPT_FILL | ||
137 | select USE_OF | ||
138 | select CEVT_R4K | ||
139 | select CSRC_R4K | ||
140 | select SYNC_R4K | ||
141 | select COMMON_CLK | ||
142 | select DMA_NONCOHERENT | ||
143 | select IRQ_CPU | ||
144 | select SYS_SUPPORTS_32BIT_KERNEL | ||
145 | select SYS_SUPPORTS_BIG_ENDIAN | ||
146 | select SYS_SUPPORTS_HIGHMEM | ||
147 | select SYS_HAS_CPU_BMIPS5000 | ||
148 | select SWAP_IO_SPACE | ||
149 | select USB_EHCI_BIG_ENDIAN_DESC | ||
150 | select USB_EHCI_BIG_ENDIAN_MMIO | ||
151 | select USB_OHCI_BIG_ENDIAN_DESC | ||
152 | select USB_OHCI_BIG_ENDIAN_MMIO | ||
153 | help | ||
154 | Support for BCM3384 based boards. BCM3384/BCM33843 is a cable modem | ||
155 | chipset with a Linux application processor that is often used to | ||
156 | provide Samba services, a CUPS print server, and/or advanced routing | ||
157 | features. | ||
158 | |||
118 | config BCM47XX | 159 | config BCM47XX |
119 | bool "Broadcom BCM47XX based boards" | 160 | bool "Broadcom BCM47XX based boards" |
120 | select ARCH_WANT_OPTIONAL_GPIOLIB | 161 | select ARCH_WANT_OPTIONAL_GPIOLIB |
@@ -269,6 +310,8 @@ config LANTIQ | |||
269 | select USE_OF | 310 | select USE_OF |
270 | select PINCTRL | 311 | select PINCTRL |
271 | select PINCTRL_LANTIQ | 312 | select PINCTRL_LANTIQ |
313 | select ARCH_HAS_RESET_CONTROLLER | ||
314 | select RESET_CONTROLLER | ||
272 | 315 | ||
273 | config LASAT | 316 | config LASAT |
274 | bool "LASAT Networks platforms" | 317 | bool "LASAT Networks platforms" |
@@ -315,17 +358,18 @@ config MIPS_MALTA | |||
315 | select BOOT_RAW | 358 | select BOOT_RAW |
316 | select CEVT_R4K | 359 | select CEVT_R4K |
317 | select CSRC_R4K | 360 | select CSRC_R4K |
318 | select CSRC_GIC | 361 | select CLKSRC_MIPS_GIC |
319 | select DMA_MAYBE_COHERENT | 362 | select DMA_MAYBE_COHERENT |
320 | select GENERIC_ISA_DMA | 363 | select GENERIC_ISA_DMA |
321 | select HAVE_PCSPKR_PLATFORM | 364 | select HAVE_PCSPKR_PLATFORM |
322 | select IRQ_CPU | 365 | select IRQ_CPU |
323 | select IRQ_GIC | 366 | select MIPS_GIC |
324 | select HW_HAS_PCI | 367 | select HW_HAS_PCI |
325 | select I8253 | 368 | select I8253 |
326 | select I8259 | 369 | select I8259 |
327 | select MIPS_BONITO64 | 370 | select MIPS_BONITO64 |
328 | select MIPS_CPU_SCACHE | 371 | select MIPS_CPU_SCACHE |
372 | select MIPS_L1_CACHE_SHIFT_6 | ||
329 | select PCI_GT64XXX_PCI0 | 373 | select PCI_GT64XXX_PCI0 |
330 | select MIPS_MSC | 374 | select MIPS_MSC |
331 | select SWAP_IO_SPACE | 375 | select SWAP_IO_SPACE |
@@ -340,6 +384,7 @@ config MIPS_MALTA | |||
340 | select SYS_SUPPORTS_64BIT_KERNEL | 384 | select SYS_SUPPORTS_64BIT_KERNEL |
341 | select SYS_SUPPORTS_BIG_ENDIAN | 385 | select SYS_SUPPORTS_BIG_ENDIAN |
342 | select SYS_SUPPORTS_LITTLE_ENDIAN | 386 | select SYS_SUPPORTS_LITTLE_ENDIAN |
387 | select SYS_SUPPORTS_MICROMIPS | ||
343 | select SYS_SUPPORTS_MIPS_CMP | 388 | select SYS_SUPPORTS_MIPS_CMP |
344 | select SYS_SUPPORTS_MIPS_CPS | 389 | select SYS_SUPPORTS_MIPS_CPS |
345 | select SYS_SUPPORTS_MIPS16 | 390 | select SYS_SUPPORTS_MIPS16 |
@@ -357,12 +402,12 @@ config MIPS_SEAD3 | |||
357 | select BUILTIN_DTB | 402 | select BUILTIN_DTB |
358 | select CEVT_R4K | 403 | select CEVT_R4K |
359 | select CSRC_R4K | 404 | select CSRC_R4K |
360 | select CSRC_GIC | 405 | select CLKSRC_MIPS_GIC |
361 | select CPU_MIPSR2_IRQ_VI | 406 | select CPU_MIPSR2_IRQ_VI |
362 | select CPU_MIPSR2_IRQ_EI | 407 | select CPU_MIPSR2_IRQ_EI |
363 | select DMA_NONCOHERENT | 408 | select DMA_NONCOHERENT |
364 | select IRQ_CPU | 409 | select IRQ_CPU |
365 | select IRQ_GIC | 410 | select MIPS_GIC |
366 | select LIBFDT | 411 | select LIBFDT |
367 | select MIPS_MSC | 412 | select MIPS_MSC |
368 | select SYS_HAS_CPU_MIPS32_R1 | 413 | select SYS_HAS_CPU_MIPS32_R1 |
@@ -726,7 +771,7 @@ config MIKROTIK_RB532 | |||
726 | config CAVIUM_OCTEON_SOC | 771 | config CAVIUM_OCTEON_SOC |
727 | bool "Cavium Networks Octeon SoC based boards" | 772 | bool "Cavium Networks Octeon SoC based boards" |
728 | select CEVT_R4K | 773 | select CEVT_R4K |
729 | select 64BIT_PHYS_ADDR | 774 | select ARCH_PHYS_ADDR_T_64BIT |
730 | select DMA_COHERENT | 775 | select DMA_COHERENT |
731 | select SYS_SUPPORTS_64BIT_KERNEL | 776 | select SYS_SUPPORTS_64BIT_KERNEL |
732 | select SYS_SUPPORTS_BIG_ENDIAN | 777 | select SYS_SUPPORTS_BIG_ENDIAN |
@@ -768,7 +813,7 @@ config NLM_XLR_BOARD | |||
768 | select SWAP_IO_SPACE | 813 | select SWAP_IO_SPACE |
769 | select SYS_SUPPORTS_32BIT_KERNEL | 814 | select SYS_SUPPORTS_32BIT_KERNEL |
770 | select SYS_SUPPORTS_64BIT_KERNEL | 815 | select SYS_SUPPORTS_64BIT_KERNEL |
771 | select 64BIT_PHYS_ADDR | 816 | select ARCH_PHYS_ADDR_T_64BIT |
772 | select SYS_SUPPORTS_BIG_ENDIAN | 817 | select SYS_SUPPORTS_BIG_ENDIAN |
773 | select SYS_SUPPORTS_HIGHMEM | 818 | select SYS_SUPPORTS_HIGHMEM |
774 | select DMA_COHERENT | 819 | select DMA_COHERENT |
@@ -794,7 +839,7 @@ config NLM_XLP_BOARD | |||
794 | select HW_HAS_PCI | 839 | select HW_HAS_PCI |
795 | select SYS_SUPPORTS_32BIT_KERNEL | 840 | select SYS_SUPPORTS_32BIT_KERNEL |
796 | select SYS_SUPPORTS_64BIT_KERNEL | 841 | select SYS_SUPPORTS_64BIT_KERNEL |
797 | select 64BIT_PHYS_ADDR | 842 | select ARCH_PHYS_ADDR_T_64BIT |
798 | select SYS_SUPPORTS_BIG_ENDIAN | 843 | select SYS_SUPPORTS_BIG_ENDIAN |
799 | select SYS_SUPPORTS_LITTLE_ENDIAN | 844 | select SYS_SUPPORTS_LITTLE_ENDIAN |
800 | select SYS_SUPPORTS_HIGHMEM | 845 | select SYS_SUPPORTS_HIGHMEM |
@@ -835,6 +880,7 @@ config MIPS_PARAVIRT | |||
835 | endchoice | 880 | endchoice |
836 | 881 | ||
837 | source "arch/mips/alchemy/Kconfig" | 882 | source "arch/mips/alchemy/Kconfig" |
883 | source "arch/mips/ath25/Kconfig" | ||
838 | source "arch/mips/ath79/Kconfig" | 884 | source "arch/mips/ath79/Kconfig" |
839 | source "arch/mips/bcm47xx/Kconfig" | 885 | source "arch/mips/bcm47xx/Kconfig" |
840 | source "arch/mips/bcm63xx/Kconfig" | 886 | source "arch/mips/bcm63xx/Kconfig" |
@@ -907,10 +953,6 @@ config CEVT_GT641XX | |||
907 | config CEVT_R4K | 953 | config CEVT_R4K |
908 | bool | 954 | bool |
909 | 955 | ||
910 | config CEVT_GIC | ||
911 | select MIPS_CM | ||
912 | bool | ||
913 | |||
914 | config CEVT_SB1250 | 956 | config CEVT_SB1250 |
915 | bool | 957 | bool |
916 | 958 | ||
@@ -926,10 +968,6 @@ config CSRC_IOASIC | |||
926 | config CSRC_R4K | 968 | config CSRC_R4K |
927 | bool | 969 | bool |
928 | 970 | ||
929 | config CSRC_GIC | ||
930 | select MIPS_CM | ||
931 | bool | ||
932 | |||
933 | config CSRC_SB1250 | 971 | config CSRC_SB1250 |
934 | bool | 972 | bool |
935 | 973 | ||
@@ -941,7 +979,7 @@ config FW_CFE | |||
941 | bool | 979 | bool |
942 | 980 | ||
943 | config ARCH_DMA_ADDR_T_64BIT | 981 | config ARCH_DMA_ADDR_T_64BIT |
944 | def_bool (HIGHMEM && 64BIT_PHYS_ADDR) || 64BIT | 982 | def_bool (HIGHMEM && ARCH_PHYS_ADDR_T_64BIT) || 64BIT |
945 | 983 | ||
946 | config DMA_MAYBE_COHERENT | 984 | config DMA_MAYBE_COHERENT |
947 | select DMA_NONCOHERENT | 985 | select DMA_NONCOHERENT |
@@ -975,6 +1013,7 @@ config SYS_SUPPORTS_HOTPLUG_CPU | |||
975 | 1013 | ||
976 | config I8259 | 1014 | config I8259 |
977 | bool | 1015 | bool |
1016 | select IRQ_DOMAIN | ||
978 | 1017 | ||
979 | config MIPS_BONITO64 | 1018 | config MIPS_BONITO64 |
980 | bool | 1019 | bool |
@@ -1055,6 +1094,7 @@ config MIPS_HUGE_TLB_SUPPORT | |||
1055 | 1094 | ||
1056 | config IRQ_CPU | 1095 | config IRQ_CPU |
1057 | bool | 1096 | bool |
1097 | select IRQ_DOMAIN | ||
1058 | 1098 | ||
1059 | config IRQ_CPU_RM7K | 1099 | config IRQ_CPU_RM7K |
1060 | bool | 1100 | bool |
@@ -1071,10 +1111,6 @@ config IRQ_TXX9 | |||
1071 | config IRQ_GT641XX | 1111 | config IRQ_GT641XX |
1072 | bool | 1112 | bool |
1073 | 1113 | ||
1074 | config IRQ_GIC | ||
1075 | select MIPS_CM | ||
1076 | bool | ||
1077 | |||
1078 | config PCI_GT64XXX_PCI0 | 1114 | config PCI_GT64XXX_PCI0 |
1079 | bool | 1115 | bool |
1080 | 1116 | ||
@@ -1574,6 +1610,7 @@ config CPU_LOONGSON1 | |||
1574 | select CPU_HAS_PREFETCH | 1610 | select CPU_HAS_PREFETCH |
1575 | select CPU_SUPPORTS_32BIT_KERNEL | 1611 | select CPU_SUPPORTS_32BIT_KERNEL |
1576 | select CPU_SUPPORTS_HIGHMEM | 1612 | select CPU_SUPPORTS_HIGHMEM |
1613 | select CPU_SUPPORTS_CPUFREQ | ||
1577 | 1614 | ||
1578 | config CPU_BMIPS32_3300 | 1615 | config CPU_BMIPS32_3300 |
1579 | select SMP_UP if SMP | 1616 | select SMP_UP if SMP |
@@ -1586,12 +1623,14 @@ config CPU_BMIPS4350 | |||
1586 | 1623 | ||
1587 | config CPU_BMIPS4380 | 1624 | config CPU_BMIPS4380 |
1588 | bool | 1625 | bool |
1626 | select MIPS_L1_CACHE_SHIFT_6 | ||
1589 | select SYS_SUPPORTS_SMP | 1627 | select SYS_SUPPORTS_SMP |
1590 | select SYS_SUPPORTS_HOTPLUG_CPU | 1628 | select SYS_SUPPORTS_HOTPLUG_CPU |
1591 | 1629 | ||
1592 | config CPU_BMIPS5000 | 1630 | config CPU_BMIPS5000 |
1593 | bool | 1631 | bool |
1594 | select MIPS_CPU_SCACHE | 1632 | select MIPS_CPU_SCACHE |
1633 | select MIPS_L1_CACHE_SHIFT_7 | ||
1595 | select SYS_SUPPORTS_SMP | 1634 | select SYS_SUPPORTS_SMP |
1596 | select SYS_SUPPORTS_HOTPLUG_CPU | 1635 | select SYS_SUPPORTS_HOTPLUG_CPU |
1597 | 1636 | ||
@@ -1886,15 +1925,6 @@ config FORCE_MAX_ZONEORDER | |||
1886 | The page size is not necessarily 4KB. Keep this in mind | 1925 | The page size is not necessarily 4KB. Keep this in mind |
1887 | when choosing a value for this option. | 1926 | when choosing a value for this option. |
1888 | 1927 | ||
1889 | config CEVT_GIC | ||
1890 | bool "Use GIC global counter for clock events" | ||
1891 | depends on IRQ_GIC && !MIPS_SEAD3 | ||
1892 | help | ||
1893 | Use the GIC global counter for the clock events. The R4K clock | ||
1894 | event driver is always present, so if the platform ends up not | ||
1895 | detecting a GIC, it will fall back to the R4K timer for the | ||
1896 | generation of clock events. | ||
1897 | |||
1898 | config BOARD_SCACHE | 1928 | config BOARD_SCACHE |
1899 | bool | 1929 | bool |
1900 | 1930 | ||
@@ -1908,7 +1938,6 @@ config IP22_CPU_SCACHE | |||
1908 | config MIPS_CPU_SCACHE | 1938 | config MIPS_CPU_SCACHE |
1909 | bool | 1939 | bool |
1910 | select BOARD_SCACHE | 1940 | select BOARD_SCACHE |
1911 | select MIPS_L1_CACHE_SHIFT_6 | ||
1912 | 1941 | ||
1913 | config R5000_CPU_SCACHE | 1942 | config R5000_CPU_SCACHE |
1914 | bool | 1943 | bool |
@@ -2095,11 +2124,8 @@ config SB1_PASS_2_1_WORKAROUNDS | |||
2095 | default y | 2124 | default y |
2096 | 2125 | ||
2097 | 2126 | ||
2098 | config 64BIT_PHYS_ADDR | ||
2099 | bool | ||
2100 | |||
2101 | config ARCH_PHYS_ADDR_T_64BIT | 2127 | config ARCH_PHYS_ADDR_T_64BIT |
2102 | def_bool 64BIT_PHYS_ADDR | 2128 | bool |
2103 | 2129 | ||
2104 | choice | 2130 | choice |
2105 | prompt "SmartMIPS or microMIPS ASE support" | 2131 | prompt "SmartMIPS or microMIPS ASE support" |
@@ -2122,7 +2148,7 @@ config CPU_HAS_SMARTMIPS | |||
2122 | here. | 2148 | here. |
2123 | 2149 | ||
2124 | config CPU_MICROMIPS | 2150 | config CPU_MICROMIPS |
2125 | depends on SYS_SUPPORTS_MICROMIPS | 2151 | depends on 32BIT && SYS_SUPPORTS_MICROMIPS |
2126 | bool "microMIPS" | 2152 | bool "microMIPS" |
2127 | help | 2153 | help |
2128 | When this option is enabled the kernel will be built using the | 2154 | When this option is enabled the kernel will be built using the |
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug index 3a2b775e8458..88a9f433f6fc 100644 --- a/arch/mips/Kconfig.debug +++ b/arch/mips/Kconfig.debug | |||
@@ -122,4 +122,17 @@ config SPINLOCK_TEST | |||
122 | help | 122 | help |
123 | Add several files to the debugfs to test spinlock speed. | 123 | Add several files to the debugfs to test spinlock speed. |
124 | 124 | ||
125 | config FP32XX_HYBRID_FPRS | ||
126 | bool "Run FP32 & FPXX code with hybrid FPRs" | ||
127 | depends on MIPS_O32_FP64_SUPPORT | ||
128 | help | ||
129 | The hybrid FPR scheme is normally used only when a program needs to | ||
130 | execute a mix of FP32 & FP64A code, since the trapping & emulation | ||
131 | that it entails is expensive. When enabled, this option will lead | ||
132 | to the kernel running programs which use the FP32 & FPXX FP ABIs | ||
133 | using the hybrid FPR scheme, which can be useful for debugging | ||
134 | purposes. | ||
135 | |||
136 | If unsure, say N. | ||
137 | |||
125 | endmenu | 138 | endmenu |
diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 58076472bdd8..2563a088d3b8 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile | |||
@@ -380,6 +380,7 @@ define archhelp | |||
380 | echo ' vmlinux.ecoff - ECOFF boot image' | 380 | echo ' vmlinux.ecoff - ECOFF boot image' |
381 | echo ' vmlinux.bin - Raw binary boot image' | 381 | echo ' vmlinux.bin - Raw binary boot image' |
382 | echo ' vmlinux.srec - SREC boot image' | 382 | echo ' vmlinux.srec - SREC boot image' |
383 | echo ' vmlinux.32 - 64-bit boot image wrapped in 32bits (IP22/IP32)' | ||
383 | echo ' vmlinuz - Compressed boot(zboot) image' | 384 | echo ' vmlinuz - Compressed boot(zboot) image' |
384 | echo ' vmlinuz.ecoff - ECOFF zboot image' | 385 | echo ' vmlinuz.ecoff - ECOFF zboot image' |
385 | echo ' vmlinuz.bin - Raw binary zboot image' | 386 | echo ' vmlinuz.bin - Raw binary zboot image' |
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index d7557cde271a..203e4403c366 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <linux/clk-provider.h> | 38 | #include <linux/clk-provider.h> |
39 | #include <linux/clkdev.h> | 39 | #include <linux/clkdev.h> |
40 | #include <linux/clk-private.h> | ||
41 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
42 | #include <linux/spinlock.h> | 41 | #include <linux/spinlock.h> |
43 | #include <linux/types.h> | 42 | #include <linux/types.h> |
@@ -397,10 +396,10 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate, | |||
397 | break; | 396 | break; |
398 | 397 | ||
399 | /* if this parent is currently unused, remember it. | 398 | /* if this parent is currently unused, remember it. |
400 | * XXX: I know it's a layering violation, but it works | 399 | * XXX: we would actually want clk_has_active_children() |
401 | * so well.. (if (!clk_has_active_children(pc)) ) | 400 | * but this is a good-enough approximation for now. |
402 | */ | 401 | */ |
403 | if (pc->prepare_count == 0) { | 402 | if (!__clk_is_prepared(pc)) { |
404 | if (!free) | 403 | if (!free) |
405 | free = pc; | 404 | free = pc; |
406 | } | 405 | } |
diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c index ea8f41869e56..4e72daf12c32 100644 --- a/arch/mips/alchemy/common/setup.c +++ b/arch/mips/alchemy/common/setup.c | |||
@@ -70,9 +70,9 @@ void __init plat_mem_setup(void) | |||
70 | iomem_resource.end = IOMEM_RESOURCE_END; | 70 | iomem_resource.end = IOMEM_RESOURCE_END; |
71 | } | 71 | } |
72 | 72 | ||
73 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_PCI) | 73 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_PCI) |
74 | /* This routine should be valid for all Au1x based boards */ | 74 | /* This routine should be valid for all Au1x based boards */ |
75 | phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size) | 75 | phys_addr_t __fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) |
76 | { | 76 | { |
77 | unsigned long start = ALCHEMY_PCI_MEMWIN_START; | 77 | unsigned long start = ALCHEMY_PCI_MEMWIN_START; |
78 | unsigned long end = ALCHEMY_PCI_MEMWIN_END; | 78 | unsigned long end = ALCHEMY_PCI_MEMWIN_END; |
@@ -83,7 +83,7 @@ phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size) | |||
83 | 83 | ||
84 | /* Check for PCI memory window */ | 84 | /* Check for PCI memory window */ |
85 | if (phys_addr >= start && (phys_addr + size - 1) <= end) | 85 | if (phys_addr >= start && (phys_addr + size - 1) <= end) |
86 | return (phys_t)(AU1500_PCI_MEM_PHYS_ADDR + phys_addr); | 86 | return (phys_addr_t)(AU1500_PCI_MEM_PHYS_ADDR + phys_addr); |
87 | 87 | ||
88 | /* default nop */ | 88 | /* default nop */ |
89 | return phys_addr; | 89 | return phys_addr; |
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index 7e2356fd5fd6..af2441dbfc12 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c | |||
@@ -311,8 +311,7 @@ static void __init cpmac_get_mac(int instance, unsigned char *dev_addr) | |||
311 | &dev_addr[0], &dev_addr[1], | 311 | &dev_addr[0], &dev_addr[1], |
312 | &dev_addr[2], &dev_addr[3], | 312 | &dev_addr[2], &dev_addr[3], |
313 | &dev_addr[4], &dev_addr[5]) != 6) { | 313 | &dev_addr[4], &dev_addr[5]) != 6) { |
314 | pr_warning("cannot parse mac address, " | 314 | pr_warn("cannot parse mac address, using random address\n"); |
315 | "using random address\n"); | ||
316 | eth_random_addr(dev_addr); | 315 | eth_random_addr(dev_addr); |
317 | } | 316 | } |
318 | } else | 317 | } else |
@@ -665,7 +664,7 @@ static int __init ar7_register_devices(void) | |||
665 | 664 | ||
666 | res = platform_device_register(&physmap_flash); | 665 | res = platform_device_register(&physmap_flash); |
667 | if (res) | 666 | if (res) |
668 | pr_warning("unable to register physmap-flash: %d\n", res); | 667 | pr_warn("unable to register physmap-flash: %d\n", res); |
669 | 668 | ||
670 | if (ar7_is_titan()) | 669 | if (ar7_is_titan()) |
671 | titan_fixup_devices(); | 670 | titan_fixup_devices(); |
@@ -673,13 +672,13 @@ static int __init ar7_register_devices(void) | |||
673 | ar7_device_disable(vlynq_low_data.reset_bit); | 672 | ar7_device_disable(vlynq_low_data.reset_bit); |
674 | res = platform_device_register(&vlynq_low); | 673 | res = platform_device_register(&vlynq_low); |
675 | if (res) | 674 | if (res) |
676 | pr_warning("unable to register vlynq-low: %d\n", res); | 675 | pr_warn("unable to register vlynq-low: %d\n", res); |
677 | 676 | ||
678 | if (ar7_has_high_vlynq()) { | 677 | if (ar7_has_high_vlynq()) { |
679 | ar7_device_disable(vlynq_high_data.reset_bit); | 678 | ar7_device_disable(vlynq_high_data.reset_bit); |
680 | res = platform_device_register(&vlynq_high); | 679 | res = platform_device_register(&vlynq_high); |
681 | if (res) | 680 | if (res) |
682 | pr_warning("unable to register vlynq-high: %d\n", res); | 681 | pr_warn("unable to register vlynq-high: %d\n", res); |
683 | } | 682 | } |
684 | 683 | ||
685 | if (ar7_has_high_cpmac()) { | 684 | if (ar7_has_high_cpmac()) { |
@@ -689,9 +688,10 @@ static int __init ar7_register_devices(void) | |||
689 | 688 | ||
690 | res = platform_device_register(&cpmac_high); | 689 | res = platform_device_register(&cpmac_high); |
691 | if (res) | 690 | if (res) |
692 | pr_warning("unable to register cpmac-high: %d\n", res); | 691 | pr_warn("unable to register cpmac-high: %d\n", |
692 | res); | ||
693 | } else | 693 | } else |
694 | pr_warning("unable to add cpmac-high phy: %d\n", res); | 694 | pr_warn("unable to add cpmac-high phy: %d\n", res); |
695 | } else | 695 | } else |
696 | cpmac_low_data.phy_mask = 0xffffffff; | 696 | cpmac_low_data.phy_mask = 0xffffffff; |
697 | 697 | ||
@@ -700,18 +700,18 @@ static int __init ar7_register_devices(void) | |||
700 | cpmac_get_mac(0, cpmac_low_data.dev_addr); | 700 | cpmac_get_mac(0, cpmac_low_data.dev_addr); |
701 | res = platform_device_register(&cpmac_low); | 701 | res = platform_device_register(&cpmac_low); |
702 | if (res) | 702 | if (res) |
703 | pr_warning("unable to register cpmac-low: %d\n", res); | 703 | pr_warn("unable to register cpmac-low: %d\n", res); |
704 | } else | 704 | } else |
705 | pr_warning("unable to add cpmac-low phy: %d\n", res); | 705 | pr_warn("unable to add cpmac-low phy: %d\n", res); |
706 | 706 | ||
707 | detect_leds(); | 707 | detect_leds(); |
708 | res = platform_device_register(&ar7_gpio_leds); | 708 | res = platform_device_register(&ar7_gpio_leds); |
709 | if (res) | 709 | if (res) |
710 | pr_warning("unable to register leds: %d\n", res); | 710 | pr_warn("unable to register leds: %d\n", res); |
711 | 711 | ||
712 | res = platform_device_register(&ar7_udc); | 712 | res = platform_device_register(&ar7_udc); |
713 | if (res) | 713 | if (res) |
714 | pr_warning("unable to register usb slave: %d\n", res); | 714 | pr_warn("unable to register usb slave: %d\n", res); |
715 | 715 | ||
716 | /* Register watchdog only if enabled in hardware */ | 716 | /* Register watchdog only if enabled in hardware */ |
717 | bootcr = ioremap_nocache(AR7_REGS_DCL, 4); | 717 | bootcr = ioremap_nocache(AR7_REGS_DCL, 4); |
@@ -726,7 +726,7 @@ static int __init ar7_register_devices(void) | |||
726 | ar7_wdt_res.end = ar7_wdt_res.start + 0x20; | 726 | ar7_wdt_res.end = ar7_wdt_res.start + 0x20; |
727 | res = platform_device_register(&ar7_wdt); | 727 | res = platform_device_register(&ar7_wdt); |
728 | if (res) | 728 | if (res) |
729 | pr_warning("unable to register watchdog: %d\n", res); | 729 | pr_warn("unable to register watchdog: %d\n", res); |
730 | } | 730 | } |
731 | 731 | ||
732 | return 0; | 732 | return 0; |
diff --git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig new file mode 100644 index 000000000000..fc19dd57e42d --- /dev/null +++ b/arch/mips/ath25/Kconfig | |||
@@ -0,0 +1,16 @@ | |||
1 | config SOC_AR5312 | ||
2 | bool "Atheros AR5312/AR2312+ SoC support" | ||
3 | depends on ATH25 | ||
4 | default y | ||
5 | |||
6 | config SOC_AR2315 | ||
7 | bool "Atheros AR2315+ SoC support" | ||
8 | depends on ATH25 | ||
9 | default y | ||
10 | |||
11 | config PCI_AR2315 | ||
12 | bool "Atheros AR2315 PCI controller support" | ||
13 | depends on SOC_AR2315 | ||
14 | select HW_HAS_PCI | ||
15 | select PCI | ||
16 | default y | ||
diff --git a/arch/mips/ath25/Makefile b/arch/mips/ath25/Makefile new file mode 100644 index 000000000000..eabad7da446a --- /dev/null +++ b/arch/mips/ath25/Makefile | |||
@@ -0,0 +1,16 @@ | |||
1 | # | ||
2 | # This file is subject to the terms and conditions of the GNU General Public | ||
3 | # License. See the file "COPYING" in the main directory of this archive | ||
4 | # for more details. | ||
5 | # | ||
6 | # Copyright (C) 2006 FON Technology, SL. | ||
7 | # Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> | ||
8 | # Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> | ||
9 | # | ||
10 | |||
11 | obj-y += board.o prom.o devices.o | ||
12 | |||
13 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | ||
14 | |||
15 | obj-$(CONFIG_SOC_AR5312) += ar5312.o | ||
16 | obj-$(CONFIG_SOC_AR2315) += ar2315.o | ||
diff --git a/arch/mips/ath25/Platform b/arch/mips/ath25/Platform new file mode 100644 index 000000000000..ef3f81fa080b --- /dev/null +++ b/arch/mips/ath25/Platform | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Atheros AR531X/AR231X WiSoC | ||
3 | # | ||
4 | platform-$(CONFIG_ATH25) += ath25/ | ||
5 | cflags-$(CONFIG_ATH25) += -I$(srctree)/arch/mips/include/asm/mach-ath25 | ||
6 | load-$(CONFIG_ATH25) += 0xffffffff80041000 | ||
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c new file mode 100644 index 000000000000..2befa7d766a6 --- /dev/null +++ b/arch/mips/ath25/ar2315.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. | ||
7 | * Copyright (C) 2006 FON Technology, SL. | ||
8 | * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> | ||
9 | * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> | ||
10 | * Copyright (C) 2012 Alexandros C. Couloumbis <alex@ozo.com> | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * Platform devices for Atheros AR2315 SoCs | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/bitops.h> | ||
20 | #include <linux/irqdomain.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/reboot.h> | ||
24 | #include <asm/bootinfo.h> | ||
25 | #include <asm/reboot.h> | ||
26 | #include <asm/time.h> | ||
27 | |||
28 | #include <ath25_platform.h> | ||
29 | |||
30 | #include "devices.h" | ||
31 | #include "ar2315.h" | ||
32 | #include "ar2315_regs.h" | ||
33 | |||
34 | static void __iomem *ar2315_rst_base; | ||
35 | static struct irq_domain *ar2315_misc_irq_domain; | ||
36 | |||
37 | static inline u32 ar2315_rst_reg_read(u32 reg) | ||
38 | { | ||
39 | return __raw_readl(ar2315_rst_base + reg); | ||
40 | } | ||
41 | |||
42 | static inline void ar2315_rst_reg_write(u32 reg, u32 val) | ||
43 | { | ||
44 | __raw_writel(val, ar2315_rst_base + reg); | ||
45 | } | ||
46 | |||
47 | static inline void ar2315_rst_reg_mask(u32 reg, u32 mask, u32 val) | ||
48 | { | ||
49 | u32 ret = ar2315_rst_reg_read(reg); | ||
50 | |||
51 | ret &= ~mask; | ||
52 | ret |= val; | ||
53 | ar2315_rst_reg_write(reg, ret); | ||
54 | } | ||
55 | |||
56 | static irqreturn_t ar2315_ahb_err_handler(int cpl, void *dev_id) | ||
57 | { | ||
58 | ar2315_rst_reg_write(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET); | ||
59 | ar2315_rst_reg_read(AR2315_AHB_ERR1); | ||
60 | |||
61 | pr_emerg("AHB fatal error\n"); | ||
62 | machine_restart("AHB error"); /* Catastrophic failure */ | ||
63 | |||
64 | return IRQ_HANDLED; | ||
65 | } | ||
66 | |||
67 | static struct irqaction ar2315_ahb_err_interrupt = { | ||
68 | .handler = ar2315_ahb_err_handler, | ||
69 | .name = "ar2315-ahb-error", | ||
70 | }; | ||
71 | |||
72 | static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc) | ||
73 | { | ||
74 | u32 pending = ar2315_rst_reg_read(AR2315_ISR) & | ||
75 | ar2315_rst_reg_read(AR2315_IMR); | ||
76 | unsigned nr, misc_irq = 0; | ||
77 | |||
78 | if (pending) { | ||
79 | struct irq_domain *domain = irq_get_handler_data(irq); | ||
80 | |||
81 | nr = __ffs(pending); | ||
82 | misc_irq = irq_find_mapping(domain, nr); | ||
83 | } | ||
84 | |||
85 | if (misc_irq) { | ||
86 | if (nr == AR2315_MISC_IRQ_GPIO) | ||
87 | ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_GPIO); | ||
88 | else if (nr == AR2315_MISC_IRQ_WATCHDOG) | ||
89 | ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_WD); | ||
90 | generic_handle_irq(misc_irq); | ||
91 | } else { | ||
92 | spurious_interrupt(); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static void ar2315_misc_irq_unmask(struct irq_data *d) | ||
97 | { | ||
98 | ar2315_rst_reg_mask(AR2315_IMR, 0, BIT(d->hwirq)); | ||
99 | } | ||
100 | |||
101 | static void ar2315_misc_irq_mask(struct irq_data *d) | ||
102 | { | ||
103 | ar2315_rst_reg_mask(AR2315_IMR, BIT(d->hwirq), 0); | ||
104 | } | ||
105 | |||
106 | static struct irq_chip ar2315_misc_irq_chip = { | ||
107 | .name = "ar2315-misc", | ||
108 | .irq_unmask = ar2315_misc_irq_unmask, | ||
109 | .irq_mask = ar2315_misc_irq_mask, | ||
110 | }; | ||
111 | |||
112 | static int ar2315_misc_irq_map(struct irq_domain *d, unsigned irq, | ||
113 | irq_hw_number_t hw) | ||
114 | { | ||
115 | irq_set_chip_and_handler(irq, &ar2315_misc_irq_chip, handle_level_irq); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static struct irq_domain_ops ar2315_misc_irq_domain_ops = { | ||
120 | .map = ar2315_misc_irq_map, | ||
121 | }; | ||
122 | |||
123 | /* | ||
124 | * Called when an interrupt is received, this function | ||
125 | * determines exactly which interrupt it was, and it | ||
126 | * invokes the appropriate handler. | ||
127 | * | ||
128 | * Implicitly, we also define interrupt priority by | ||
129 | * choosing which to dispatch first. | ||
130 | */ | ||
131 | static void ar2315_irq_dispatch(void) | ||
132 | { | ||
133 | u32 pending = read_c0_status() & read_c0_cause(); | ||
134 | |||
135 | if (pending & CAUSEF_IP3) | ||
136 | do_IRQ(AR2315_IRQ_WLAN0); | ||
137 | #ifdef CONFIG_PCI_AR2315 | ||
138 | else if (pending & CAUSEF_IP5) | ||
139 | do_IRQ(AR2315_IRQ_LCBUS_PCI); | ||
140 | #endif | ||
141 | else if (pending & CAUSEF_IP2) | ||
142 | do_IRQ(AR2315_IRQ_MISC); | ||
143 | else if (pending & CAUSEF_IP7) | ||
144 | do_IRQ(ATH25_IRQ_CPU_CLOCK); | ||
145 | else | ||
146 | spurious_interrupt(); | ||
147 | } | ||
148 | |||
149 | void __init ar2315_arch_init_irq(void) | ||
150 | { | ||
151 | struct irq_domain *domain; | ||
152 | unsigned irq; | ||
153 | |||
154 | ath25_irq_dispatch = ar2315_irq_dispatch; | ||
155 | |||
156 | domain = irq_domain_add_linear(NULL, AR2315_MISC_IRQ_COUNT, | ||
157 | &ar2315_misc_irq_domain_ops, NULL); | ||
158 | if (!domain) | ||
159 | panic("Failed to add IRQ domain"); | ||
160 | |||
161 | irq = irq_create_mapping(domain, AR2315_MISC_IRQ_AHB); | ||
162 | setup_irq(irq, &ar2315_ahb_err_interrupt); | ||
163 | |||
164 | irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler); | ||
165 | irq_set_handler_data(AR2315_IRQ_MISC, domain); | ||
166 | |||
167 | ar2315_misc_irq_domain = domain; | ||
168 | } | ||
169 | |||
170 | void __init ar2315_init_devices(void) | ||
171 | { | ||
172 | /* Find board configuration */ | ||
173 | ath25_find_config(AR2315_SPI_READ_BASE, AR2315_SPI_READ_SIZE); | ||
174 | |||
175 | ath25_add_wmac(0, AR2315_WLAN0_BASE, AR2315_IRQ_WLAN0); | ||
176 | } | ||
177 | |||
178 | static void ar2315_restart(char *command) | ||
179 | { | ||
180 | void (*mips_reset_vec)(void) = (void *)0xbfc00000; | ||
181 | |||
182 | local_irq_disable(); | ||
183 | |||
184 | /* try reset the system via reset control */ | ||
185 | ar2315_rst_reg_write(AR2315_COLD_RESET, AR2317_RESET_SYSTEM); | ||
186 | |||
187 | /* Cold reset does not work on the AR2315/6, use the GPIO reset bits | ||
188 | * a workaround. Give it some time to attempt a gpio based hardware | ||
189 | * reset (atheros reference design workaround) */ | ||
190 | |||
191 | /* TODO: implement the GPIO reset workaround */ | ||
192 | |||
193 | /* Some boards (e.g. Senao EOC-2610) don't implement the reset logic | ||
194 | * workaround. Attempt to jump to the mips reset location - | ||
195 | * the boot loader itself might be able to recover the system */ | ||
196 | mips_reset_vec(); | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * This table is indexed by bits 5..4 of the CLOCKCTL1 register | ||
201 | * to determine the predevisor value. | ||
202 | */ | ||
203 | static int clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 }; | ||
204 | static int pllc_divide_table[5] __initdata = { 2, 3, 4, 6, 3 }; | ||
205 | |||
206 | static unsigned __init ar2315_sys_clk(u32 clock_ctl) | ||
207 | { | ||
208 | unsigned int pllc_ctrl, cpu_div; | ||
209 | unsigned int pllc_out, refdiv, fdiv, divby2; | ||
210 | unsigned int clk_div; | ||
211 | |||
212 | pllc_ctrl = ar2315_rst_reg_read(AR2315_PLLC_CTL); | ||
213 | refdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_REF_DIV); | ||
214 | refdiv = clockctl1_predivide_table[refdiv]; | ||
215 | fdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_FDBACK_DIV); | ||
216 | divby2 = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_ADD_FDBACK_DIV) + 1; | ||
217 | pllc_out = (40000000 / refdiv) * (2 * divby2) * fdiv; | ||
218 | |||
219 | /* clkm input selected */ | ||
220 | switch (clock_ctl & AR2315_CPUCLK_CLK_SEL_M) { | ||
221 | case 0: | ||
222 | case 1: | ||
223 | clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKM_DIV); | ||
224 | clk_div = pllc_divide_table[clk_div]; | ||
225 | break; | ||
226 | case 2: | ||
227 | clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKC_DIV); | ||
228 | clk_div = pllc_divide_table[clk_div]; | ||
229 | break; | ||
230 | default: | ||
231 | pllc_out = 40000000; | ||
232 | clk_div = 1; | ||
233 | break; | ||
234 | } | ||
235 | |||
236 | cpu_div = ATH25_REG_MS(clock_ctl, AR2315_CPUCLK_CLK_DIV); | ||
237 | cpu_div = cpu_div * 2 ?: 1; | ||
238 | |||
239 | return pllc_out / (clk_div * cpu_div); | ||
240 | } | ||
241 | |||
242 | static inline unsigned ar2315_cpu_frequency(void) | ||
243 | { | ||
244 | return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_CPUCLK)); | ||
245 | } | ||
246 | |||
247 | static inline unsigned ar2315_apb_frequency(void) | ||
248 | { | ||
249 | return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_AMBACLK)); | ||
250 | } | ||
251 | |||
252 | void __init ar2315_plat_time_init(void) | ||
253 | { | ||
254 | mips_hpt_frequency = ar2315_cpu_frequency() / 2; | ||
255 | } | ||
256 | |||
257 | void __init ar2315_plat_mem_setup(void) | ||
258 | { | ||
259 | void __iomem *sdram_base; | ||
260 | u32 memsize, memcfg; | ||
261 | u32 devid; | ||
262 | u32 config; | ||
263 | |||
264 | /* Detect memory size */ | ||
265 | sdram_base = ioremap_nocache(AR2315_SDRAMCTL_BASE, | ||
266 | AR2315_SDRAMCTL_SIZE); | ||
267 | memcfg = __raw_readl(sdram_base + AR2315_MEM_CFG); | ||
268 | memsize = 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_DATA_WIDTH); | ||
269 | memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_COL_WIDTH); | ||
270 | memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_ROW_WIDTH); | ||
271 | memsize <<= 3; | ||
272 | add_memory_region(0, memsize, BOOT_MEM_RAM); | ||
273 | iounmap(sdram_base); | ||
274 | |||
275 | ar2315_rst_base = ioremap_nocache(AR2315_RST_BASE, AR2315_RST_SIZE); | ||
276 | |||
277 | /* Detect the hardware based on the device ID */ | ||
278 | devid = ar2315_rst_reg_read(AR2315_SREV) & AR2315_REV_CHIP; | ||
279 | switch (devid) { | ||
280 | case 0x91: /* Need to check */ | ||
281 | ath25_soc = ATH25_SOC_AR2318; | ||
282 | break; | ||
283 | case 0x90: | ||
284 | ath25_soc = ATH25_SOC_AR2317; | ||
285 | break; | ||
286 | case 0x87: | ||
287 | ath25_soc = ATH25_SOC_AR2316; | ||
288 | break; | ||
289 | case 0x86: | ||
290 | default: | ||
291 | ath25_soc = ATH25_SOC_AR2315; | ||
292 | break; | ||
293 | } | ||
294 | ath25_board.devid = devid; | ||
295 | |||
296 | /* Clear any lingering AHB errors */ | ||
297 | config = read_c0_config(); | ||
298 | write_c0_config(config & ~0x3); | ||
299 | ar2315_rst_reg_write(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET); | ||
300 | ar2315_rst_reg_read(AR2315_AHB_ERR1); | ||
301 | ar2315_rst_reg_write(AR2315_WDT_CTRL, AR2315_WDT_CTRL_IGNORE); | ||
302 | |||
303 | _machine_restart = ar2315_restart; | ||
304 | } | ||
305 | |||
306 | #ifdef CONFIG_PCI_AR2315 | ||
307 | static struct resource ar2315_pci_res[] = { | ||
308 | { | ||
309 | .name = "ar2315-pci-ctrl", | ||
310 | .flags = IORESOURCE_MEM, | ||
311 | .start = AR2315_PCI_BASE, | ||
312 | .end = AR2315_PCI_BASE + AR2315_PCI_SIZE - 1, | ||
313 | }, | ||
314 | { | ||
315 | .name = "ar2315-pci-ext", | ||
316 | .flags = IORESOURCE_MEM, | ||
317 | .start = AR2315_PCI_EXT_BASE, | ||
318 | .end = AR2315_PCI_EXT_BASE + AR2315_PCI_EXT_SIZE - 1, | ||
319 | }, | ||
320 | { | ||
321 | .name = "ar2315-pci", | ||
322 | .flags = IORESOURCE_IRQ, | ||
323 | .start = AR2315_IRQ_LCBUS_PCI, | ||
324 | .end = AR2315_IRQ_LCBUS_PCI, | ||
325 | }, | ||
326 | }; | ||
327 | #endif | ||
328 | |||
329 | void __init ar2315_arch_init(void) | ||
330 | { | ||
331 | unsigned irq = irq_create_mapping(ar2315_misc_irq_domain, | ||
332 | AR2315_MISC_IRQ_UART0); | ||
333 | |||
334 | ath25_serial_setup(AR2315_UART0_BASE, irq, ar2315_apb_frequency()); | ||
335 | |||
336 | #ifdef CONFIG_PCI_AR2315 | ||
337 | if (ath25_soc == ATH25_SOC_AR2315) { | ||
338 | /* Reset PCI DMA logic */ | ||
339 | ar2315_rst_reg_mask(AR2315_RESET, 0, AR2315_RESET_PCIDMA); | ||
340 | msleep(20); | ||
341 | ar2315_rst_reg_mask(AR2315_RESET, AR2315_RESET_PCIDMA, 0); | ||
342 | msleep(20); | ||
343 | |||
344 | /* Configure endians */ | ||
345 | ar2315_rst_reg_mask(AR2315_ENDIAN_CTL, 0, AR2315_CONFIG_PCIAHB | | ||
346 | AR2315_CONFIG_PCIAHB_BRIDGE); | ||
347 | |||
348 | /* Configure as PCI host with DMA */ | ||
349 | ar2315_rst_reg_write(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM | | ||
350 | (AR2315_PCICLK_IN_FREQ_DIV_6 << | ||
351 | AR2315_PCICLK_DIV_S)); | ||
352 | ar2315_rst_reg_mask(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI); | ||
353 | ar2315_rst_reg_mask(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK | | ||
354 | AR2315_IF_MASK, AR2315_IF_PCI | | ||
355 | AR2315_IF_PCI_HOST | AR2315_IF_PCI_INTR | | ||
356 | (AR2315_IF_PCI_CLK_OUTPUT_CLK << | ||
357 | AR2315_IF_PCI_CLK_SHIFT)); | ||
358 | |||
359 | platform_device_register_simple("ar2315-pci", -1, | ||
360 | ar2315_pci_res, | ||
361 | ARRAY_SIZE(ar2315_pci_res)); | ||
362 | } | ||
363 | #endif | ||
364 | } | ||
diff --git a/arch/mips/ath25/ar2315.h b/arch/mips/ath25/ar2315.h new file mode 100644 index 000000000000..877afe63eed5 --- /dev/null +++ b/arch/mips/ath25/ar2315.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef __AR2315_H | ||
2 | #define __AR2315_H | ||
3 | |||
4 | #ifdef CONFIG_SOC_AR2315 | ||
5 | |||
6 | void ar2315_arch_init_irq(void); | ||
7 | void ar2315_init_devices(void); | ||
8 | void ar2315_plat_time_init(void); | ||
9 | void ar2315_plat_mem_setup(void); | ||
10 | void ar2315_arch_init(void); | ||
11 | |||
12 | #else | ||
13 | |||
14 | static inline void ar2315_arch_init_irq(void) {} | ||
15 | static inline void ar2315_init_devices(void) {} | ||
16 | static inline void ar2315_plat_time_init(void) {} | ||
17 | static inline void ar2315_plat_mem_setup(void) {} | ||
18 | static inline void ar2315_arch_init(void) {} | ||
19 | |||
20 | #endif | ||
21 | |||
22 | #endif /* __AR2315_H */ | ||
diff --git a/arch/mips/ath25/ar2315_regs.h b/arch/mips/ath25/ar2315_regs.h new file mode 100644 index 000000000000..16e86149cb74 --- /dev/null +++ b/arch/mips/ath25/ar2315_regs.h | |||
@@ -0,0 +1,410 @@ | |||
1 | /* | ||
2 | * Register definitions for AR2315+ | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. | ||
9 | * Copyright (C) 2006 FON Technology, SL. | ||
10 | * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> | ||
11 | * Copyright (C) 2006-2008 Felix Fietkau <nbd@openwrt.org> | ||
12 | */ | ||
13 | |||
14 | #ifndef __ASM_MACH_ATH25_AR2315_REGS_H | ||
15 | #define __ASM_MACH_ATH25_AR2315_REGS_H | ||
16 | |||
17 | /* | ||
18 | * IRQs | ||
19 | */ | ||
20 | #define AR2315_IRQ_MISC (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */ | ||
21 | #define AR2315_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */ | ||
22 | #define AR2315_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */ | ||
23 | #define AR2315_IRQ_LCBUS_PCI (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */ | ||
24 | #define AR2315_IRQ_WLAN0_POLL (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */ | ||
25 | |||
26 | /* | ||
27 | * Miscellaneous interrupts, which share IP2. | ||
28 | */ | ||
29 | #define AR2315_MISC_IRQ_UART0 0 | ||
30 | #define AR2315_MISC_IRQ_I2C_RSVD 1 | ||
31 | #define AR2315_MISC_IRQ_SPI 2 | ||
32 | #define AR2315_MISC_IRQ_AHB 3 | ||
33 | #define AR2315_MISC_IRQ_APB 4 | ||
34 | #define AR2315_MISC_IRQ_TIMER 5 | ||
35 | #define AR2315_MISC_IRQ_GPIO 6 | ||
36 | #define AR2315_MISC_IRQ_WATCHDOG 7 | ||
37 | #define AR2315_MISC_IRQ_IR_RSVD 8 | ||
38 | #define AR2315_MISC_IRQ_COUNT 9 | ||
39 | |||
40 | /* | ||
41 | * Address map | ||
42 | */ | ||
43 | #define AR2315_SPI_READ_BASE 0x08000000 /* SPI flash */ | ||
44 | #define AR2315_SPI_READ_SIZE 0x01000000 | ||
45 | #define AR2315_WLAN0_BASE 0x10000000 /* Wireless MMR */ | ||
46 | #define AR2315_PCI_BASE 0x10100000 /* PCI MMR */ | ||
47 | #define AR2315_PCI_SIZE 0x00001000 | ||
48 | #define AR2315_SDRAMCTL_BASE 0x10300000 /* SDRAM MMR */ | ||
49 | #define AR2315_SDRAMCTL_SIZE 0x00000020 | ||
50 | #define AR2315_LOCAL_BASE 0x10400000 /* Local bus MMR */ | ||
51 | #define AR2315_ENET0_BASE 0x10500000 /* Ethernet MMR */ | ||
52 | #define AR2315_RST_BASE 0x11000000 /* Reset control MMR */ | ||
53 | #define AR2315_RST_SIZE 0x00000100 | ||
54 | #define AR2315_UART0_BASE 0x11100000 /* UART MMR */ | ||
55 | #define AR2315_SPI_MMR_BASE 0x11300000 /* SPI flash MMR */ | ||
56 | #define AR2315_SPI_MMR_SIZE 0x00000010 | ||
57 | #define AR2315_PCI_EXT_BASE 0x80000000 /* PCI external */ | ||
58 | #define AR2315_PCI_EXT_SIZE 0x40000000 | ||
59 | |||
60 | /* | ||
61 | * Configuration registers | ||
62 | */ | ||
63 | |||
64 | /* Cold reset register */ | ||
65 | #define AR2315_COLD_RESET 0x0000 | ||
66 | |||
67 | #define AR2315_RESET_COLD_AHB 0x00000001 | ||
68 | #define AR2315_RESET_COLD_APB 0x00000002 | ||
69 | #define AR2315_RESET_COLD_CPU 0x00000004 | ||
70 | #define AR2315_RESET_COLD_CPUWARM 0x00000008 | ||
71 | #define AR2315_RESET_SYSTEM (RESET_COLD_CPU |\ | ||
72 | RESET_COLD_APB |\ | ||
73 | RESET_COLD_AHB) /* full system */ | ||
74 | #define AR2317_RESET_SYSTEM 0x00000010 | ||
75 | |||
76 | /* Reset register */ | ||
77 | #define AR2315_RESET 0x0004 | ||
78 | |||
79 | #define AR2315_RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */ | ||
80 | #define AR2315_RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BB */ | ||
81 | #define AR2315_RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */ | ||
82 | #define AR2315_RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */ | ||
83 | #define AR2315_RESET_MEMCTL 0x00000010 /* warm reset mem control */ | ||
84 | #define AR2315_RESET_LOCAL 0x00000020 /* warm reset local bus */ | ||
85 | #define AR2315_RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */ | ||
86 | #define AR2315_RESET_SPI 0x00000080 /* warm reset SPI iface */ | ||
87 | #define AR2315_RESET_UART0 0x00000100 /* warm reset UART0 */ | ||
88 | #define AR2315_RESET_IR_RSVD 0x00000200 /* warm reset IR iface */ | ||
89 | #define AR2315_RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */ | ||
90 | #define AR2315_RESET_ENET0 0x00000800 /* cold reset ENET0 MAC */ | ||
91 | |||
92 | /* AHB master arbitration control */ | ||
93 | #define AR2315_AHB_ARB_CTL 0x0008 | ||
94 | |||
95 | #define AR2315_ARB_CPU 0x00000001 /* CPU, default */ | ||
96 | #define AR2315_ARB_WLAN 0x00000002 /* WLAN */ | ||
97 | #define AR2315_ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */ | ||
98 | #define AR2315_ARB_LOCAL 0x00000008 /* Local bus */ | ||
99 | #define AR2315_ARB_PCI 0x00000010 /* PCI bus */ | ||
100 | #define AR2315_ARB_ETHERNET 0x00000020 /* Ethernet */ | ||
101 | #define AR2315_ARB_RETRY 0x00000100 /* Retry policy (debug) */ | ||
102 | |||
103 | /* Config Register */ | ||
104 | #define AR2315_ENDIAN_CTL 0x000c | ||
105 | |||
106 | #define AR2315_CONFIG_AHB 0x00000001 /* EC-AHB bridge endian */ | ||
107 | #define AR2315_CONFIG_WLAN 0x00000002 /* WLAN byteswap */ | ||
108 | #define AR2315_CONFIG_MPEGTS_RSVD 0x00000004 /* MPEG-TS byteswap */ | ||
109 | #define AR2315_CONFIG_PCI 0x00000008 /* PCI byteswap */ | ||
110 | #define AR2315_CONFIG_MEMCTL 0x00000010 /* Mem controller endian */ | ||
111 | #define AR2315_CONFIG_LOCAL 0x00000020 /* Local bus byteswap */ | ||
112 | #define AR2315_CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */ | ||
113 | #define AR2315_CONFIG_MERGE 0x00000200 /* CPU write buffer merge */ | ||
114 | #define AR2315_CONFIG_CPU 0x00000400 /* CPU big endian */ | ||
115 | #define AR2315_CONFIG_BIG 0x00000400 | ||
116 | #define AR2315_CONFIG_PCIAHB 0x00000800 | ||
117 | #define AR2315_CONFIG_PCIAHB_BRIDGE 0x00001000 | ||
118 | #define AR2315_CONFIG_SPI 0x00008000 /* SPI byteswap */ | ||
119 | #define AR2315_CONFIG_CPU_DRAM 0x00010000 | ||
120 | #define AR2315_CONFIG_CPU_PCI 0x00020000 | ||
121 | #define AR2315_CONFIG_CPU_MMR 0x00040000 | ||
122 | |||
123 | /* NMI control */ | ||
124 | #define AR2315_NMI_CTL 0x0010 | ||
125 | |||
126 | #define AR2315_NMI_EN 1 | ||
127 | |||
128 | /* Revision Register - Initial value is 0x3010 (WMAC 3.0, AR231X 1.0). */ | ||
129 | #define AR2315_SREV 0x0014 | ||
130 | |||
131 | #define AR2315_REV_MAJ 0x000000f0 | ||
132 | #define AR2315_REV_MAJ_S 4 | ||
133 | #define AR2315_REV_MIN 0x0000000f | ||
134 | #define AR2315_REV_MIN_S 0 | ||
135 | #define AR2315_REV_CHIP (AR2315_REV_MAJ | AR2315_REV_MIN) | ||
136 | |||
137 | /* Interface Enable */ | ||
138 | #define AR2315_IF_CTL 0x0018 | ||
139 | |||
140 | #define AR2315_IF_MASK 0x00000007 | ||
141 | #define AR2315_IF_DISABLED 0 /* Disable all */ | ||
142 | #define AR2315_IF_PCI 1 /* PCI */ | ||
143 | #define AR2315_IF_TS_LOCAL 2 /* Local bus */ | ||
144 | #define AR2315_IF_ALL 3 /* Emulation only */ | ||
145 | #define AR2315_IF_LOCAL_HOST 0x00000008 | ||
146 | #define AR2315_IF_PCI_HOST 0x00000010 | ||
147 | #define AR2315_IF_PCI_INTR 0x00000020 | ||
148 | #define AR2315_IF_PCI_CLK_MASK 0x00030000 | ||
149 | #define AR2315_IF_PCI_CLK_INPUT 0 | ||
150 | #define AR2315_IF_PCI_CLK_OUTPUT_LOW 1 | ||
151 | #define AR2315_IF_PCI_CLK_OUTPUT_CLK 2 | ||
152 | #define AR2315_IF_PCI_CLK_OUTPUT_HIGH 3 | ||
153 | #define AR2315_IF_PCI_CLK_SHIFT 16 | ||
154 | |||
155 | /* APB Interrupt control */ | ||
156 | #define AR2315_ISR 0x0020 | ||
157 | #define AR2315_IMR 0x0024 | ||
158 | #define AR2315_GISR 0x0028 | ||
159 | |||
160 | #define AR2315_ISR_UART0 0x00000001 /* high speed UART */ | ||
161 | #define AR2315_ISR_I2C_RSVD 0x00000002 /* I2C bus */ | ||
162 | #define AR2315_ISR_SPI 0x00000004 /* SPI bus */ | ||
163 | #define AR2315_ISR_AHB 0x00000008 /* AHB error */ | ||
164 | #define AR2315_ISR_APB 0x00000010 /* APB error */ | ||
165 | #define AR2315_ISR_TIMER 0x00000020 /* Timer */ | ||
166 | #define AR2315_ISR_GPIO 0x00000040 /* GPIO */ | ||
167 | #define AR2315_ISR_WD 0x00000080 /* Watchdog */ | ||
168 | #define AR2315_ISR_IR_RSVD 0x00000100 /* IR */ | ||
169 | |||
170 | #define AR2315_GISR_MISC 0x00000001 /* Misc */ | ||
171 | #define AR2315_GISR_WLAN0 0x00000002 /* WLAN0 */ | ||
172 | #define AR2315_GISR_MPEGTS_RSVD 0x00000004 /* MPEG-TS */ | ||
173 | #define AR2315_GISR_LOCALPCI 0x00000008 /* Local/PCI bus */ | ||
174 | #define AR2315_GISR_WMACPOLL 0x00000010 | ||
175 | #define AR2315_GISR_TIMER 0x00000020 | ||
176 | #define AR2315_GISR_ETHERNET 0x00000040 /* Ethernet */ | ||
177 | |||
178 | /* Generic timer */ | ||
179 | #define AR2315_TIMER 0x0030 | ||
180 | #define AR2315_RELOAD 0x0034 | ||
181 | |||
182 | /* Watchdog timer */ | ||
183 | #define AR2315_WDT_TIMER 0x0038 | ||
184 | #define AR2315_WDT_CTRL 0x003c | ||
185 | |||
186 | #define AR2315_WDT_CTRL_IGNORE 0x00000000 /* ignore expiration */ | ||
187 | #define AR2315_WDT_CTRL_NMI 0x00000001 /* NMI on watchdog */ | ||
188 | #define AR2315_WDT_CTRL_RESET 0x00000002 /* reset on watchdog */ | ||
189 | |||
190 | /* CPU Performance Counters */ | ||
191 | #define AR2315_PERFCNT0 0x0048 | ||
192 | #define AR2315_PERFCNT1 0x004c | ||
193 | |||
194 | #define AR2315_PERF0_DATAHIT 0x00000001 /* Count Data Cache Hits */ | ||
195 | #define AR2315_PERF0_DATAMISS 0x00000002 /* Count Data Cache Misses */ | ||
196 | #define AR2315_PERF0_INSTHIT 0x00000004 /* Count Instruction Cache Hits */ | ||
197 | #define AR2315_PERF0_INSTMISS 0x00000008 /* Count Instruction Cache Misses */ | ||
198 | #define AR2315_PERF0_ACTIVE 0x00000010 /* Count Active Processor Cycles */ | ||
199 | #define AR2315_PERF0_WBHIT 0x00000020 /* Count CPU Write Buffer Hits */ | ||
200 | #define AR2315_PERF0_WBMISS 0x00000040 /* Count CPU Write Buffer Misses */ | ||
201 | |||
202 | #define AR2315_PERF1_EB_ARDY 0x00000001 /* Count EB_ARdy signal */ | ||
203 | #define AR2315_PERF1_EB_AVALID 0x00000002 /* Count EB_AValid signal */ | ||
204 | #define AR2315_PERF1_EB_WDRDY 0x00000004 /* Count EB_WDRdy signal */ | ||
205 | #define AR2315_PERF1_EB_RDVAL 0x00000008 /* Count EB_RdVal signal */ | ||
206 | #define AR2315_PERF1_VRADDR 0x00000010 /* Count valid read address cycles*/ | ||
207 | #define AR2315_PERF1_VWADDR 0x00000020 /* Count valid write address cycl.*/ | ||
208 | #define AR2315_PERF1_VWDATA 0x00000040 /* Count valid write data cycles */ | ||
209 | |||
210 | /* AHB Error Reporting */ | ||
211 | #define AR2315_AHB_ERR0 0x0050 /* error */ | ||
212 | #define AR2315_AHB_ERR1 0x0054 /* haddr */ | ||
213 | #define AR2315_AHB_ERR2 0x0058 /* hwdata */ | ||
214 | #define AR2315_AHB_ERR3 0x005c /* hrdata */ | ||
215 | #define AR2315_AHB_ERR4 0x0060 /* status */ | ||
216 | |||
217 | #define AR2315_AHB_ERROR_DET 1 /* AHB Error has been detected, */ | ||
218 | /* write 1 to clear all bits in ERR0 */ | ||
219 | #define AR2315_AHB_ERROR_OVR 2 /* AHB Error overflow has been detected */ | ||
220 | #define AR2315_AHB_ERROR_WDT 4 /* AHB Error due to wdt instead of hresp */ | ||
221 | |||
222 | #define AR2315_PROCERR_HMAST 0x0000000f | ||
223 | #define AR2315_PROCERR_HMAST_DFLT 0 | ||
224 | #define AR2315_PROCERR_HMAST_WMAC 1 | ||
225 | #define AR2315_PROCERR_HMAST_ENET 2 | ||
226 | #define AR2315_PROCERR_HMAST_PCIENDPT 3 | ||
227 | #define AR2315_PROCERR_HMAST_LOCAL 4 | ||
228 | #define AR2315_PROCERR_HMAST_CPU 5 | ||
229 | #define AR2315_PROCERR_HMAST_PCITGT 6 | ||
230 | #define AR2315_PROCERR_HMAST_S 0 | ||
231 | #define AR2315_PROCERR_HWRITE 0x00000010 | ||
232 | #define AR2315_PROCERR_HSIZE 0x00000060 | ||
233 | #define AR2315_PROCERR_HSIZE_S 5 | ||
234 | #define AR2315_PROCERR_HTRANS 0x00000180 | ||
235 | #define AR2315_PROCERR_HTRANS_S 7 | ||
236 | #define AR2315_PROCERR_HBURST 0x00000e00 | ||
237 | #define AR2315_PROCERR_HBURST_S 9 | ||
238 | |||
239 | /* Clock Control */ | ||
240 | #define AR2315_PLLC_CTL 0x0064 | ||
241 | #define AR2315_PLLV_CTL 0x0068 | ||
242 | #define AR2315_CPUCLK 0x006c | ||
243 | #define AR2315_AMBACLK 0x0070 | ||
244 | #define AR2315_SYNCCLK 0x0074 | ||
245 | #define AR2315_DSL_SLEEP_CTL 0x0080 | ||
246 | #define AR2315_DSL_SLEEP_DUR 0x0084 | ||
247 | |||
248 | /* PLLc Control fields */ | ||
249 | #define AR2315_PLLC_REF_DIV_M 0x00000003 | ||
250 | #define AR2315_PLLC_REF_DIV_S 0 | ||
251 | #define AR2315_PLLC_FDBACK_DIV_M 0x0000007c | ||
252 | #define AR2315_PLLC_FDBACK_DIV_S 2 | ||
253 | #define AR2315_PLLC_ADD_FDBACK_DIV_M 0x00000080 | ||
254 | #define AR2315_PLLC_ADD_FDBACK_DIV_S 7 | ||
255 | #define AR2315_PLLC_CLKC_DIV_M 0x0001c000 | ||
256 | #define AR2315_PLLC_CLKC_DIV_S 14 | ||
257 | #define AR2315_PLLC_CLKM_DIV_M 0x00700000 | ||
258 | #define AR2315_PLLC_CLKM_DIV_S 20 | ||
259 | |||
260 | /* CPU CLK Control fields */ | ||
261 | #define AR2315_CPUCLK_CLK_SEL_M 0x00000003 | ||
262 | #define AR2315_CPUCLK_CLK_SEL_S 0 | ||
263 | #define AR2315_CPUCLK_CLK_DIV_M 0x0000000c | ||
264 | #define AR2315_CPUCLK_CLK_DIV_S 2 | ||
265 | |||
266 | /* AMBA CLK Control fields */ | ||
267 | #define AR2315_AMBACLK_CLK_SEL_M 0x00000003 | ||
268 | #define AR2315_AMBACLK_CLK_SEL_S 0 | ||
269 | #define AR2315_AMBACLK_CLK_DIV_M 0x0000000c | ||
270 | #define AR2315_AMBACLK_CLK_DIV_S 2 | ||
271 | |||
272 | /* PCI Clock Control */ | ||
273 | #define AR2315_PCICLK 0x00a4 | ||
274 | |||
275 | #define AR2315_PCICLK_INPUT_M 0x00000003 | ||
276 | #define AR2315_PCICLK_INPUT_S 0 | ||
277 | #define AR2315_PCICLK_PLLC_CLKM 0 | ||
278 | #define AR2315_PCICLK_PLLC_CLKM1 1 | ||
279 | #define AR2315_PCICLK_PLLC_CLKC 2 | ||
280 | #define AR2315_PCICLK_REF_CLK 3 | ||
281 | #define AR2315_PCICLK_DIV_M 0x0000000c | ||
282 | #define AR2315_PCICLK_DIV_S 2 | ||
283 | #define AR2315_PCICLK_IN_FREQ 0 | ||
284 | #define AR2315_PCICLK_IN_FREQ_DIV_6 1 | ||
285 | #define AR2315_PCICLK_IN_FREQ_DIV_8 2 | ||
286 | #define AR2315_PCICLK_IN_FREQ_DIV_10 3 | ||
287 | |||
288 | /* Observation Control Register */ | ||
289 | #define AR2315_OCR 0x00b0 | ||
290 | |||
291 | #define AR2315_OCR_GPIO0_IRIN 0x00000040 | ||
292 | #define AR2315_OCR_GPIO1_IROUT 0x00000080 | ||
293 | #define AR2315_OCR_GPIO3_RXCLR 0x00000200 | ||
294 | |||
295 | /* General Clock Control */ | ||
296 | #define AR2315_MISCCLK 0x00b4 | ||
297 | |||
298 | #define AR2315_MISCCLK_PLLBYPASS_EN 0x00000001 | ||
299 | #define AR2315_MISCCLK_PROCREFCLK 0x00000002 | ||
300 | |||
301 | /* | ||
302 | * SDRAM Controller | ||
303 | * - No read or write buffers are included. | ||
304 | */ | ||
305 | #define AR2315_MEM_CFG 0x0000 | ||
306 | #define AR2315_MEM_CTRL 0x000c | ||
307 | #define AR2315_MEM_REF 0x0010 | ||
308 | |||
309 | #define AR2315_MEM_CFG_DATA_WIDTH_M 0x00006000 | ||
310 | #define AR2315_MEM_CFG_DATA_WIDTH_S 13 | ||
311 | #define AR2315_MEM_CFG_COL_WIDTH_M 0x00001e00 | ||
312 | #define AR2315_MEM_CFG_COL_WIDTH_S 9 | ||
313 | #define AR2315_MEM_CFG_ROW_WIDTH_M 0x000001e0 | ||
314 | #define AR2315_MEM_CFG_ROW_WIDTH_S 5 | ||
315 | #define AR2315_MEM_CFG_BANKADDR_BITS_M 0x00000018 | ||
316 | #define AR2315_MEM_CFG_BANKADDR_BITS_S 3 | ||
317 | |||
318 | /* | ||
319 | * Local Bus Interface Registers | ||
320 | */ | ||
321 | #define AR2315_LB_CONFIG 0x0000 | ||
322 | |||
323 | #define AR2315_LBCONF_OE 0x00000001 /* =1 OE is low-true */ | ||
324 | #define AR2315_LBCONF_CS0 0x00000002 /* =1 first CS is low-true */ | ||
325 | #define AR2315_LBCONF_CS1 0x00000004 /* =1 2nd CS is low-true */ | ||
326 | #define AR2315_LBCONF_RDY 0x00000008 /* =1 RDY is low-true */ | ||
327 | #define AR2315_LBCONF_WE 0x00000010 /* =1 Write En is low-true */ | ||
328 | #define AR2315_LBCONF_WAIT 0x00000020 /* =1 WAIT is low-true */ | ||
329 | #define AR2315_LBCONF_ADS 0x00000040 /* =1 Adr Strobe is low-true */ | ||
330 | #define AR2315_LBCONF_MOT 0x00000080 /* =0 Intel, =1 Motorola */ | ||
331 | #define AR2315_LBCONF_8CS 0x00000100 /* =1 8 bits CS, 0= 16bits */ | ||
332 | #define AR2315_LBCONF_8DS 0x00000200 /* =1 8 bits Data S, 0=16bits */ | ||
333 | #define AR2315_LBCONF_ADS_EN 0x00000400 /* =1 Enable ADS */ | ||
334 | #define AR2315_LBCONF_ADR_OE 0x00000800 /* =1 Adr cap on OE, WE or DS */ | ||
335 | #define AR2315_LBCONF_ADDT_MUX 0x00001000 /* =1 Adr and Data share bus */ | ||
336 | #define AR2315_LBCONF_DATA_OE 0x00002000 /* =1 Data cap on OE, WE, DS */ | ||
337 | #define AR2315_LBCONF_16DATA 0x00004000 /* =1 Data is 16 bits wide */ | ||
338 | #define AR2315_LBCONF_SWAPDT 0x00008000 /* =1 Byte swap data */ | ||
339 | #define AR2315_LBCONF_SYNC 0x00010000 /* =1 Bus synchronous to clk */ | ||
340 | #define AR2315_LBCONF_INT 0x00020000 /* =1 Intr is low true */ | ||
341 | #define AR2315_LBCONF_INT_CTR0 0x00000000 /* GND high-Z, Vdd is high-Z */ | ||
342 | #define AR2315_LBCONF_INT_CTR1 0x00040000 /* GND drive, Vdd is high-Z */ | ||
343 | #define AR2315_LBCONF_INT_CTR2 0x00080000 /* GND high-Z, Vdd drive */ | ||
344 | #define AR2315_LBCONF_INT_CTR3 0x000c0000 /* GND drive, Vdd drive */ | ||
345 | #define AR2315_LBCONF_RDY_WAIT 0x00100000 /* =1 RDY is negative of WAIT */ | ||
346 | #define AR2315_LBCONF_INT_PULSE 0x00200000 /* =1 Interrupt is a pulse */ | ||
347 | #define AR2315_LBCONF_ENABLE 0x00400000 /* =1 Falcon respond to LB */ | ||
348 | |||
349 | #define AR2315_LB_CLKSEL 0x0004 | ||
350 | |||
351 | #define AR2315_LBCLK_EXT 0x00000001 /* use external clk for lb */ | ||
352 | |||
353 | #define AR2315_LB_1MS 0x0008 | ||
354 | |||
355 | #define AR2315_LB1MS_MASK 0x0003ffff /* # of AHB clk cycles in 1ms */ | ||
356 | |||
357 | #define AR2315_LB_MISCCFG 0x000c | ||
358 | |||
359 | #define AR2315_LBM_TXD_EN 0x00000001 /* Enable TXD for fragments */ | ||
360 | #define AR2315_LBM_RX_INTEN 0x00000002 /* Enable LB ints on RX ready */ | ||
361 | #define AR2315_LBM_MBOXWR_INTEN 0x00000004 /* Enable LB ints on mbox wr */ | ||
362 | #define AR2315_LBM_MBOXRD_INTEN 0x00000008 /* Enable LB ints on mbox rd */ | ||
363 | #define AR2315_LMB_DESCSWAP_EN 0x00000010 /* Byte swap desc enable */ | ||
364 | #define AR2315_LBM_TIMEOUT_M 0x00ffff80 | ||
365 | #define AR2315_LBM_TIMEOUT_S 7 | ||
366 | #define AR2315_LBM_PORTMUX 0x07000000 | ||
367 | |||
368 | #define AR2315_LB_RXTSOFF 0x0010 | ||
369 | |||
370 | #define AR2315_LB_TX_CHAIN_EN 0x0100 | ||
371 | |||
372 | #define AR2315_LB_TXEN_0 0x00000001 | ||
373 | #define AR2315_LB_TXEN_1 0x00000002 | ||
374 | #define AR2315_LB_TXEN_2 0x00000004 | ||
375 | #define AR2315_LB_TXEN_3 0x00000008 | ||
376 | |||
377 | #define AR2315_LB_TX_CHAIN_DIS 0x0104 | ||
378 | #define AR2315_LB_TX_DESC_PTR 0x0200 | ||
379 | |||
380 | #define AR2315_LB_RX_CHAIN_EN 0x0400 | ||
381 | |||
382 | #define AR2315_LB_RXEN 0x00000001 | ||
383 | |||
384 | #define AR2315_LB_RX_CHAIN_DIS 0x0404 | ||
385 | #define AR2315_LB_RX_DESC_PTR 0x0408 | ||
386 | |||
387 | #define AR2315_LB_INT_STATUS 0x0500 | ||
388 | |||
389 | #define AR2315_LB_INT_TX_DESC 0x00000001 | ||
390 | #define AR2315_LB_INT_TX_OK 0x00000002 | ||
391 | #define AR2315_LB_INT_TX_ERR 0x00000004 | ||
392 | #define AR2315_LB_INT_TX_EOF 0x00000008 | ||
393 | #define AR2315_LB_INT_RX_DESC 0x00000010 | ||
394 | #define AR2315_LB_INT_RX_OK 0x00000020 | ||
395 | #define AR2315_LB_INT_RX_ERR 0x00000040 | ||
396 | #define AR2315_LB_INT_RX_EOF 0x00000080 | ||
397 | #define AR2315_LB_INT_TX_TRUNC 0x00000100 | ||
398 | #define AR2315_LB_INT_TX_STARVE 0x00000200 | ||
399 | #define AR2315_LB_INT_LB_TIMEOUT 0x00000400 | ||
400 | #define AR2315_LB_INT_LB_ERR 0x00000800 | ||
401 | #define AR2315_LB_INT_MBOX_WR 0x00001000 | ||
402 | #define AR2315_LB_INT_MBOX_RD 0x00002000 | ||
403 | |||
404 | /* Bit definitions for INT MASK are the same as INT_STATUS */ | ||
405 | #define AR2315_LB_INT_MASK 0x0504 | ||
406 | |||
407 | #define AR2315_LB_INT_EN 0x0508 | ||
408 | #define AR2315_LB_MBOX 0x0600 | ||
409 | |||
410 | #endif /* __ASM_MACH_ATH25_AR2315_REGS_H */ | ||
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c new file mode 100644 index 000000000000..b6887f75144c --- /dev/null +++ b/arch/mips/ath25/ar5312.c | |||
@@ -0,0 +1,393 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. | ||
7 | * Copyright (C) 2006 FON Technology, SL. | ||
8 | * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> | ||
9 | * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> | ||
10 | * Copyright (C) 2012 Alexandros C. Couloumbis <alex@ozo.com> | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * Platform devices for Atheros AR5312 SoCs | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/bitops.h> | ||
20 | #include <linux/irqdomain.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/mtd/physmap.h> | ||
24 | #include <linux/reboot.h> | ||
25 | #include <asm/bootinfo.h> | ||
26 | #include <asm/reboot.h> | ||
27 | #include <asm/time.h> | ||
28 | |||
29 | #include <ath25_platform.h> | ||
30 | |||
31 | #include "devices.h" | ||
32 | #include "ar5312.h" | ||
33 | #include "ar5312_regs.h" | ||
34 | |||
35 | static void __iomem *ar5312_rst_base; | ||
36 | static struct irq_domain *ar5312_misc_irq_domain; | ||
37 | |||
38 | static inline u32 ar5312_rst_reg_read(u32 reg) | ||
39 | { | ||
40 | return __raw_readl(ar5312_rst_base + reg); | ||
41 | } | ||
42 | |||
43 | static inline void ar5312_rst_reg_write(u32 reg, u32 val) | ||
44 | { | ||
45 | __raw_writel(val, ar5312_rst_base + reg); | ||
46 | } | ||
47 | |||
48 | static inline void ar5312_rst_reg_mask(u32 reg, u32 mask, u32 val) | ||
49 | { | ||
50 | u32 ret = ar5312_rst_reg_read(reg); | ||
51 | |||
52 | ret &= ~mask; | ||
53 | ret |= val; | ||
54 | ar5312_rst_reg_write(reg, ret); | ||
55 | } | ||
56 | |||
57 | static irqreturn_t ar5312_ahb_err_handler(int cpl, void *dev_id) | ||
58 | { | ||
59 | u32 proc1 = ar5312_rst_reg_read(AR5312_PROC1); | ||
60 | u32 proc_addr = ar5312_rst_reg_read(AR5312_PROCADDR); /* clears error */ | ||
61 | u32 dma1 = ar5312_rst_reg_read(AR5312_DMA1); | ||
62 | u32 dma_addr = ar5312_rst_reg_read(AR5312_DMAADDR); /* clears error */ | ||
63 | |||
64 | pr_emerg("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n", | ||
65 | proc_addr, proc1, dma_addr, dma1); | ||
66 | |||
67 | machine_restart("AHB error"); /* Catastrophic failure */ | ||
68 | return IRQ_HANDLED; | ||
69 | } | ||
70 | |||
71 | static struct irqaction ar5312_ahb_err_interrupt = { | ||
72 | .handler = ar5312_ahb_err_handler, | ||
73 | .name = "ar5312-ahb-error", | ||
74 | }; | ||
75 | |||
76 | static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc) | ||
77 | { | ||
78 | u32 pending = ar5312_rst_reg_read(AR5312_ISR) & | ||
79 | ar5312_rst_reg_read(AR5312_IMR); | ||
80 | unsigned nr, misc_irq = 0; | ||
81 | |||
82 | if (pending) { | ||
83 | struct irq_domain *domain = irq_get_handler_data(irq); | ||
84 | |||
85 | nr = __ffs(pending); | ||
86 | misc_irq = irq_find_mapping(domain, nr); | ||
87 | } | ||
88 | |||
89 | if (misc_irq) { | ||
90 | generic_handle_irq(misc_irq); | ||
91 | if (nr == AR5312_MISC_IRQ_TIMER) | ||
92 | ar5312_rst_reg_read(AR5312_TIMER); | ||
93 | } else { | ||
94 | spurious_interrupt(); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | /* Enable the specified AR5312_MISC_IRQ interrupt */ | ||
99 | static void ar5312_misc_irq_unmask(struct irq_data *d) | ||
100 | { | ||
101 | ar5312_rst_reg_mask(AR5312_IMR, 0, BIT(d->hwirq)); | ||
102 | } | ||
103 | |||
104 | /* Disable the specified AR5312_MISC_IRQ interrupt */ | ||
105 | static void ar5312_misc_irq_mask(struct irq_data *d) | ||
106 | { | ||
107 | ar5312_rst_reg_mask(AR5312_IMR, BIT(d->hwirq), 0); | ||
108 | ar5312_rst_reg_read(AR5312_IMR); /* flush write buffer */ | ||
109 | } | ||
110 | |||
111 | static struct irq_chip ar5312_misc_irq_chip = { | ||
112 | .name = "ar5312-misc", | ||
113 | .irq_unmask = ar5312_misc_irq_unmask, | ||
114 | .irq_mask = ar5312_misc_irq_mask, | ||
115 | }; | ||
116 | |||
117 | static int ar5312_misc_irq_map(struct irq_domain *d, unsigned irq, | ||
118 | irq_hw_number_t hw) | ||
119 | { | ||
120 | irq_set_chip_and_handler(irq, &ar5312_misc_irq_chip, handle_level_irq); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static struct irq_domain_ops ar5312_misc_irq_domain_ops = { | ||
125 | .map = ar5312_misc_irq_map, | ||
126 | }; | ||
127 | |||
128 | static void ar5312_irq_dispatch(void) | ||
129 | { | ||
130 | u32 pending = read_c0_status() & read_c0_cause(); | ||
131 | |||
132 | if (pending & CAUSEF_IP2) | ||
133 | do_IRQ(AR5312_IRQ_WLAN0); | ||
134 | else if (pending & CAUSEF_IP5) | ||
135 | do_IRQ(AR5312_IRQ_WLAN1); | ||
136 | else if (pending & CAUSEF_IP6) | ||
137 | do_IRQ(AR5312_IRQ_MISC); | ||
138 | else if (pending & CAUSEF_IP7) | ||
139 | do_IRQ(ATH25_IRQ_CPU_CLOCK); | ||
140 | else | ||
141 | spurious_interrupt(); | ||
142 | } | ||
143 | |||
144 | void __init ar5312_arch_init_irq(void) | ||
145 | { | ||
146 | struct irq_domain *domain; | ||
147 | unsigned irq; | ||
148 | |||
149 | ath25_irq_dispatch = ar5312_irq_dispatch; | ||
150 | |||
151 | domain = irq_domain_add_linear(NULL, AR5312_MISC_IRQ_COUNT, | ||
152 | &ar5312_misc_irq_domain_ops, NULL); | ||
153 | if (!domain) | ||
154 | panic("Failed to add IRQ domain"); | ||
155 | |||
156 | irq = irq_create_mapping(domain, AR5312_MISC_IRQ_AHB_PROC); | ||
157 | setup_irq(irq, &ar5312_ahb_err_interrupt); | ||
158 | |||
159 | irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler); | ||
160 | irq_set_handler_data(AR5312_IRQ_MISC, domain); | ||
161 | |||
162 | ar5312_misc_irq_domain = domain; | ||
163 | } | ||
164 | |||
165 | static struct physmap_flash_data ar5312_flash_data = { | ||
166 | .width = 2, | ||
167 | }; | ||
168 | |||
169 | static struct resource ar5312_flash_resource = { | ||
170 | .start = AR5312_FLASH_BASE, | ||
171 | .end = AR5312_FLASH_BASE + AR5312_FLASH_SIZE - 1, | ||
172 | .flags = IORESOURCE_MEM, | ||
173 | }; | ||
174 | |||
175 | static struct platform_device ar5312_physmap_flash = { | ||
176 | .name = "physmap-flash", | ||
177 | .id = 0, | ||
178 | .dev.platform_data = &ar5312_flash_data, | ||
179 | .resource = &ar5312_flash_resource, | ||
180 | .num_resources = 1, | ||
181 | }; | ||
182 | |||
183 | static void __init ar5312_flash_init(void) | ||
184 | { | ||
185 | void __iomem *flashctl_base; | ||
186 | u32 ctl; | ||
187 | |||
188 | flashctl_base = ioremap_nocache(AR5312_FLASHCTL_BASE, | ||
189 | AR5312_FLASHCTL_SIZE); | ||
190 | |||
191 | ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL0); | ||
192 | ctl &= AR5312_FLASHCTL_MW; | ||
193 | |||
194 | /* fixup flash width */ | ||
195 | switch (ctl) { | ||
196 | case AR5312_FLASHCTL_MW16: | ||
197 | ar5312_flash_data.width = 2; | ||
198 | break; | ||
199 | case AR5312_FLASHCTL_MW8: | ||
200 | default: | ||
201 | ar5312_flash_data.width = 1; | ||
202 | break; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * Configure flash bank 0. | ||
207 | * Assume 8M window size. Flash will be aliased if it's smaller | ||
208 | */ | ||
209 | ctl |= AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC_8M | AR5312_FLASHCTL_RBLE; | ||
210 | ctl |= 0x01 << AR5312_FLASHCTL_IDCY_S; | ||
211 | ctl |= 0x07 << AR5312_FLASHCTL_WST1_S; | ||
212 | ctl |= 0x07 << AR5312_FLASHCTL_WST2_S; | ||
213 | __raw_writel(ctl, flashctl_base + AR5312_FLASHCTL0); | ||
214 | |||
215 | /* Disable other flash banks */ | ||
216 | ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL1); | ||
217 | ctl &= ~(AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC); | ||
218 | __raw_writel(ctl, flashctl_base + AR5312_FLASHCTL1); | ||
219 | ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL2); | ||
220 | ctl &= ~(AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC); | ||
221 | __raw_writel(ctl, flashctl_base + AR5312_FLASHCTL2); | ||
222 | |||
223 | iounmap(flashctl_base); | ||
224 | } | ||
225 | |||
226 | void __init ar5312_init_devices(void) | ||
227 | { | ||
228 | struct ath25_boarddata *config; | ||
229 | |||
230 | ar5312_flash_init(); | ||
231 | |||
232 | /* Locate board/radio config data */ | ||
233 | ath25_find_config(AR5312_FLASH_BASE, AR5312_FLASH_SIZE); | ||
234 | config = ath25_board.config; | ||
235 | |||
236 | /* AR2313 has CPU minor rev. 10 */ | ||
237 | if ((current_cpu_data.processor_id & 0xff) == 0x0a) | ||
238 | ath25_soc = ATH25_SOC_AR2313; | ||
239 | |||
240 | /* AR2312 shares the same Silicon ID as AR5312 */ | ||
241 | else if (config->flags & BD_ISCASPER) | ||
242 | ath25_soc = ATH25_SOC_AR2312; | ||
243 | |||
244 | /* Everything else is probably AR5312 or compatible */ | ||
245 | else | ||
246 | ath25_soc = ATH25_SOC_AR5312; | ||
247 | |||
248 | platform_device_register(&ar5312_physmap_flash); | ||
249 | |||
250 | switch (ath25_soc) { | ||
251 | case ATH25_SOC_AR5312: | ||
252 | if (!ath25_board.radio) | ||
253 | return; | ||
254 | |||
255 | if (!(config->flags & BD_WLAN0)) | ||
256 | break; | ||
257 | |||
258 | ath25_add_wmac(0, AR5312_WLAN0_BASE, AR5312_IRQ_WLAN0); | ||
259 | break; | ||
260 | case ATH25_SOC_AR2312: | ||
261 | case ATH25_SOC_AR2313: | ||
262 | if (!ath25_board.radio) | ||
263 | return; | ||
264 | break; | ||
265 | default: | ||
266 | break; | ||
267 | } | ||
268 | |||
269 | if (config->flags & BD_WLAN1) | ||
270 | ath25_add_wmac(1, AR5312_WLAN1_BASE, AR5312_IRQ_WLAN1); | ||
271 | } | ||
272 | |||
273 | static void ar5312_restart(char *command) | ||
274 | { | ||
275 | /* reset the system */ | ||
276 | local_irq_disable(); | ||
277 | while (1) | ||
278 | ar5312_rst_reg_write(AR5312_RESET, AR5312_RESET_SYSTEM); | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | * This table is indexed by bits 5..4 of the CLOCKCTL1 register | ||
283 | * to determine the predevisor value. | ||
284 | */ | ||
285 | static unsigned clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 }; | ||
286 | |||
287 | static unsigned __init ar5312_cpu_frequency(void) | ||
288 | { | ||
289 | u32 scratch, devid, clock_ctl1; | ||
290 | u32 predivide_mask, multiplier_mask, doubler_mask; | ||
291 | unsigned predivide_shift, multiplier_shift; | ||
292 | unsigned predivide_select, predivisor, multiplier; | ||
293 | |||
294 | /* Trust the bootrom's idea of cpu frequency. */ | ||
295 | scratch = ar5312_rst_reg_read(AR5312_SCRATCH); | ||
296 | if (scratch) | ||
297 | return scratch; | ||
298 | |||
299 | devid = ar5312_rst_reg_read(AR5312_REV); | ||
300 | devid = (devid & AR5312_REV_MAJ) >> AR5312_REV_MAJ_S; | ||
301 | if (devid == AR5312_REV_MAJ_AR2313) { | ||
302 | predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK; | ||
303 | predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT; | ||
304 | multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK; | ||
305 | multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT; | ||
306 | doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK; | ||
307 | } else { /* AR5312 and AR2312 */ | ||
308 | predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK; | ||
309 | predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT; | ||
310 | multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK; | ||
311 | multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT; | ||
312 | doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK; | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Clocking is derived from a fixed 40MHz input clock. | ||
317 | * | ||
318 | * cpu_freq = input_clock * MULT (where MULT is PLL multiplier) | ||
319 | * sys_freq = cpu_freq / 4 (used for APB clock, serial, | ||
320 | * flash, Timer, Watchdog Timer) | ||
321 | * | ||
322 | * cnt_freq = cpu_freq / 2 (use for CPU count/compare) | ||
323 | * | ||
324 | * So, for example, with a PLL multiplier of 5, we have | ||
325 | * | ||
326 | * cpu_freq = 200MHz | ||
327 | * sys_freq = 50MHz | ||
328 | * cnt_freq = 100MHz | ||
329 | * | ||
330 | * We compute the CPU frequency, based on PLL settings. | ||
331 | */ | ||
332 | |||
333 | clock_ctl1 = ar5312_rst_reg_read(AR5312_CLOCKCTL1); | ||
334 | predivide_select = (clock_ctl1 & predivide_mask) >> predivide_shift; | ||
335 | predivisor = clockctl1_predivide_table[predivide_select]; | ||
336 | multiplier = (clock_ctl1 & multiplier_mask) >> multiplier_shift; | ||
337 | |||
338 | if (clock_ctl1 & doubler_mask) | ||
339 | multiplier <<= 1; | ||
340 | |||
341 | return (40000000 / predivisor) * multiplier; | ||
342 | } | ||
343 | |||
344 | static inline unsigned ar5312_sys_frequency(void) | ||
345 | { | ||
346 | return ar5312_cpu_frequency() / 4; | ||
347 | } | ||
348 | |||
349 | void __init ar5312_plat_time_init(void) | ||
350 | { | ||
351 | mips_hpt_frequency = ar5312_cpu_frequency() / 2; | ||
352 | } | ||
353 | |||
354 | void __init ar5312_plat_mem_setup(void) | ||
355 | { | ||
356 | void __iomem *sdram_base; | ||
357 | u32 memsize, memcfg, bank0_ac, bank1_ac; | ||
358 | u32 devid; | ||
359 | |||
360 | /* Detect memory size */ | ||
361 | sdram_base = ioremap_nocache(AR5312_SDRAMCTL_BASE, | ||
362 | AR5312_SDRAMCTL_SIZE); | ||
363 | memcfg = __raw_readl(sdram_base + AR5312_MEM_CFG1); | ||
364 | bank0_ac = ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC0); | ||
365 | bank1_ac = ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC1); | ||
366 | memsize = (bank0_ac ? (1 << (bank0_ac + 1)) : 0) + | ||
367 | (bank1_ac ? (1 << (bank1_ac + 1)) : 0); | ||
368 | memsize <<= 20; | ||
369 | add_memory_region(0, memsize, BOOT_MEM_RAM); | ||
370 | iounmap(sdram_base); | ||
371 | |||
372 | ar5312_rst_base = ioremap_nocache(AR5312_RST_BASE, AR5312_RST_SIZE); | ||
373 | |||
374 | devid = ar5312_rst_reg_read(AR5312_REV); | ||
375 | devid >>= AR5312_REV_WMAC_MIN_S; | ||
376 | devid &= AR5312_REV_CHIP; | ||
377 | ath25_board.devid = (u16)devid; | ||
378 | |||
379 | /* Clear any lingering AHB errors */ | ||
380 | ar5312_rst_reg_read(AR5312_PROCADDR); | ||
381 | ar5312_rst_reg_read(AR5312_DMAADDR); | ||
382 | ar5312_rst_reg_write(AR5312_WDT_CTRL, AR5312_WDT_CTRL_IGNORE); | ||
383 | |||
384 | _machine_restart = ar5312_restart; | ||
385 | } | ||
386 | |||
387 | void __init ar5312_arch_init(void) | ||
388 | { | ||
389 | unsigned irq = irq_create_mapping(ar5312_misc_irq_domain, | ||
390 | AR5312_MISC_IRQ_UART0); | ||
391 | |||
392 | ath25_serial_setup(AR5312_UART0_BASE, irq, ar5312_sys_frequency()); | ||
393 | } | ||
diff --git a/arch/mips/ath25/ar5312.h b/arch/mips/ath25/ar5312.h new file mode 100644 index 000000000000..470abb0052bd --- /dev/null +++ b/arch/mips/ath25/ar5312.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef __AR5312_H | ||
2 | #define __AR5312_H | ||
3 | |||
4 | #ifdef CONFIG_SOC_AR5312 | ||
5 | |||
6 | void ar5312_arch_init_irq(void); | ||
7 | void ar5312_init_devices(void); | ||
8 | void ar5312_plat_time_init(void); | ||
9 | void ar5312_plat_mem_setup(void); | ||
10 | void ar5312_arch_init(void); | ||
11 | |||
12 | #else | ||
13 | |||
14 | static inline void ar5312_arch_init_irq(void) {} | ||
15 | static inline void ar5312_init_devices(void) {} | ||
16 | static inline void ar5312_plat_time_init(void) {} | ||
17 | static inline void ar5312_plat_mem_setup(void) {} | ||
18 | static inline void ar5312_arch_init(void) {} | ||
19 | |||
20 | #endif | ||
21 | |||
22 | #endif /* __AR5312_H */ | ||
diff --git a/arch/mips/ath25/ar5312_regs.h b/arch/mips/ath25/ar5312_regs.h new file mode 100644 index 000000000000..4b947f967439 --- /dev/null +++ b/arch/mips/ath25/ar5312_regs.h | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. | ||
7 | * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> | ||
8 | * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_MACH_ATH25_AR5312_REGS_H | ||
12 | #define __ASM_MACH_ATH25_AR5312_REGS_H | ||
13 | |||
14 | /* | ||
15 | * IRQs | ||
16 | */ | ||
17 | #define AR5312_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */ | ||
18 | #define AR5312_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */ | ||
19 | #define AR5312_IRQ_ENET1 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */ | ||
20 | #define AR5312_IRQ_WLAN1 (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */ | ||
21 | #define AR5312_IRQ_MISC (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */ | ||
22 | |||
23 | /* | ||
24 | * Miscellaneous interrupts, which share IP6. | ||
25 | */ | ||
26 | #define AR5312_MISC_IRQ_TIMER 0 | ||
27 | #define AR5312_MISC_IRQ_AHB_PROC 1 | ||
28 | #define AR5312_MISC_IRQ_AHB_DMA 2 | ||
29 | #define AR5312_MISC_IRQ_GPIO 3 | ||
30 | #define AR5312_MISC_IRQ_UART0 4 | ||
31 | #define AR5312_MISC_IRQ_UART0_DMA 5 | ||
32 | #define AR5312_MISC_IRQ_WATCHDOG 6 | ||
33 | #define AR5312_MISC_IRQ_LOCAL 7 | ||
34 | #define AR5312_MISC_IRQ_SPI 8 | ||
35 | #define AR5312_MISC_IRQ_COUNT 9 | ||
36 | |||
37 | /* | ||
38 | * Address Map | ||
39 | * | ||
40 | * The AR5312 supports 2 enet MACS, even though many reference boards only | ||
41 | * actually use 1 of them (i.e. Only MAC 0 is actually connected to an enet | ||
42 | * PHY or PHY switch. The AR2312 supports 1 enet MAC. | ||
43 | */ | ||
44 | #define AR5312_WLAN0_BASE 0x18000000 | ||
45 | #define AR5312_ENET0_BASE 0x18100000 | ||
46 | #define AR5312_ENET1_BASE 0x18200000 | ||
47 | #define AR5312_SDRAMCTL_BASE 0x18300000 | ||
48 | #define AR5312_SDRAMCTL_SIZE 0x00000010 | ||
49 | #define AR5312_FLASHCTL_BASE 0x18400000 | ||
50 | #define AR5312_FLASHCTL_SIZE 0x00000010 | ||
51 | #define AR5312_WLAN1_BASE 0x18500000 | ||
52 | #define AR5312_UART0_BASE 0x1c000000 /* UART MMR */ | ||
53 | #define AR5312_GPIO_BASE 0x1c002000 | ||
54 | #define AR5312_GPIO_SIZE 0x00000010 | ||
55 | #define AR5312_RST_BASE 0x1c003000 | ||
56 | #define AR5312_RST_SIZE 0x00000100 | ||
57 | #define AR5312_FLASH_BASE 0x1e000000 | ||
58 | #define AR5312_FLASH_SIZE 0x00800000 | ||
59 | |||
60 | /* | ||
61 | * Need these defines to determine true number of ethernet MACs | ||
62 | */ | ||
63 | #define AR5312_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */ | ||
64 | #define AR5312_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */ | ||
65 | #define AR5312_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */ | ||
66 | |||
67 | /* Reset/Timer Block Address Map */ | ||
68 | #define AR5312_TIMER 0x0000 /* countdown timer */ | ||
69 | #define AR5312_RELOAD 0x0004 /* timer reload value */ | ||
70 | #define AR5312_WDT_CTRL 0x0008 /* watchdog cntrl */ | ||
71 | #define AR5312_WDT_TIMER 0x000c /* watchdog timer */ | ||
72 | #define AR5312_ISR 0x0010 /* Intr Status Reg */ | ||
73 | #define AR5312_IMR 0x0014 /* Intr Mask Reg */ | ||
74 | #define AR5312_RESET 0x0020 | ||
75 | #define AR5312_CLOCKCTL1 0x0064 | ||
76 | #define AR5312_SCRATCH 0x006c | ||
77 | #define AR5312_PROCADDR 0x0070 | ||
78 | #define AR5312_PROC1 0x0074 | ||
79 | #define AR5312_DMAADDR 0x0078 | ||
80 | #define AR5312_DMA1 0x007c | ||
81 | #define AR5312_ENABLE 0x0080 /* interface enb */ | ||
82 | #define AR5312_REV 0x0090 /* revision */ | ||
83 | |||
84 | /* AR5312_WDT_CTRL register bit field definitions */ | ||
85 | #define AR5312_WDT_CTRL_IGNORE 0x00000000 /* ignore expiration */ | ||
86 | #define AR5312_WDT_CTRL_NMI 0x00000001 | ||
87 | #define AR5312_WDT_CTRL_RESET 0x00000002 | ||
88 | |||
89 | /* AR5312_ISR register bit field definitions */ | ||
90 | #define AR5312_ISR_TIMER 0x00000001 | ||
91 | #define AR5312_ISR_AHBPROC 0x00000002 | ||
92 | #define AR5312_ISR_AHBDMA 0x00000004 | ||
93 | #define AR5312_ISR_GPIO 0x00000008 | ||
94 | #define AR5312_ISR_UART0 0x00000010 | ||
95 | #define AR5312_ISR_UART0DMA 0x00000020 | ||
96 | #define AR5312_ISR_WD 0x00000040 | ||
97 | #define AR5312_ISR_LOCAL 0x00000080 | ||
98 | |||
99 | /* AR5312_RESET register bit field definitions */ | ||
100 | #define AR5312_RESET_SYSTEM 0x00000001 /* cold reset full system */ | ||
101 | #define AR5312_RESET_PROC 0x00000002 /* cold reset MIPS core */ | ||
102 | #define AR5312_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC/BB */ | ||
103 | #define AR5312_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */ | ||
104 | #define AR5312_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */ | ||
105 | #define AR5312_RESET_ENET0 0x00000020 /* cold reset ENET0 MAC */ | ||
106 | #define AR5312_RESET_ENET1 0x00000040 /* cold reset ENET1 MAC */ | ||
107 | #define AR5312_RESET_UART0 0x00000100 /* cold reset UART0 */ | ||
108 | #define AR5312_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */ | ||
109 | #define AR5312_RESET_APB 0x00000400 /* cold reset APB ar5312 */ | ||
110 | #define AR5312_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */ | ||
111 | #define AR5312_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */ | ||
112 | #define AR5312_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BB */ | ||
113 | #define AR5312_RESET_NMI 0x00010000 /* send an NMI to the CPU */ | ||
114 | #define AR5312_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 MAC */ | ||
115 | #define AR5312_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 BB */ | ||
116 | #define AR5312_RESET_LOCAL_BUS 0x00080000 /* reset local bus */ | ||
117 | #define AR5312_RESET_WDOG 0x00100000 /* last reset was a wdt */ | ||
118 | |||
119 | #define AR5312_RESET_WMAC0_BITS (AR5312_RESET_WLAN0 |\ | ||
120 | AR5312_RESET_WARM_WLAN0_MAC |\ | ||
121 | AR5312_RESET_WARM_WLAN0_BB) | ||
122 | |||
123 | #define AR5312_RESET_WMAC1_BITS (AR5312_RESET_WLAN1 |\ | ||
124 | AR5312_RESET_WARM_WLAN1_MAC |\ | ||
125 | AR5312_RESET_WARM_WLAN1_BB) | ||
126 | |||
127 | /* AR5312_CLOCKCTL1 register bit field definitions */ | ||
128 | #define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030 | ||
129 | #define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4 | ||
130 | #define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 | ||
131 | #define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8 | ||
132 | #define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000 | ||
133 | |||
134 | /* Valid for AR5312 and AR2312 */ | ||
135 | #define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030 | ||
136 | #define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4 | ||
137 | #define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 | ||
138 | #define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8 | ||
139 | #define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000 | ||
140 | |||
141 | /* Valid for AR2313 */ | ||
142 | #define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000 | ||
143 | #define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12 | ||
144 | #define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000 | ||
145 | #define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16 | ||
146 | #define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000 | ||
147 | |||
148 | /* AR5312_ENABLE register bit field definitions */ | ||
149 | #define AR5312_ENABLE_WLAN0 0x00000001 | ||
150 | #define AR5312_ENABLE_ENET0 0x00000002 | ||
151 | #define AR5312_ENABLE_ENET1 0x00000004 | ||
152 | #define AR5312_ENABLE_UART_AND_WLAN1_PIO 0x00000008/* UART & WLAN1 PIO */ | ||
153 | #define AR5312_ENABLE_WLAN1_DMA 0x00000010/* WLAN1 DMAs */ | ||
154 | #define AR5312_ENABLE_WLAN1 (AR5312_ENABLE_UART_AND_WLAN1_PIO |\ | ||
155 | AR5312_ENABLE_WLAN1_DMA) | ||
156 | |||
157 | /* AR5312_REV register bit field definitions */ | ||
158 | #define AR5312_REV_WMAC_MAJ 0x0000f000 | ||
159 | #define AR5312_REV_WMAC_MAJ_S 12 | ||
160 | #define AR5312_REV_WMAC_MIN 0x00000f00 | ||
161 | #define AR5312_REV_WMAC_MIN_S 8 | ||
162 | #define AR5312_REV_MAJ 0x000000f0 | ||
163 | #define AR5312_REV_MAJ_S 4 | ||
164 | #define AR5312_REV_MIN 0x0000000f | ||
165 | #define AR5312_REV_MIN_S 0 | ||
166 | #define AR5312_REV_CHIP (AR5312_REV_MAJ|AR5312_REV_MIN) | ||
167 | |||
168 | /* Major revision numbers, bits 7..4 of Revision ID register */ | ||
169 | #define AR5312_REV_MAJ_AR5312 0x4 | ||
170 | #define AR5312_REV_MAJ_AR2313 0x5 | ||
171 | |||
172 | /* Minor revision numbers, bits 3..0 of Revision ID register */ | ||
173 | #define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */ | ||
174 | #define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */ | ||
175 | |||
176 | /* | ||
177 | * ARM Flash Controller -- 3 flash banks with either x8 or x16 devices | ||
178 | */ | ||
179 | #define AR5312_FLASHCTL0 0x0000 | ||
180 | #define AR5312_FLASHCTL1 0x0004 | ||
181 | #define AR5312_FLASHCTL2 0x0008 | ||
182 | |||
183 | /* AR5312_FLASHCTL register bit field definitions */ | ||
184 | #define AR5312_FLASHCTL_IDCY 0x0000000f /* Idle cycle turnaround time */ | ||
185 | #define AR5312_FLASHCTL_IDCY_S 0 | ||
186 | #define AR5312_FLASHCTL_WST1 0x000003e0 /* Wait state 1 */ | ||
187 | #define AR5312_FLASHCTL_WST1_S 5 | ||
188 | #define AR5312_FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */ | ||
189 | #define AR5312_FLASHCTL_WST2 0x0000f800 /* Wait state 2 */ | ||
190 | #define AR5312_FLASHCTL_WST2_S 11 | ||
191 | #define AR5312_FLASHCTL_AC 0x00070000 /* Flash addr check (added) */ | ||
192 | #define AR5312_FLASHCTL_AC_S 16 | ||
193 | #define AR5312_FLASHCTL_AC_128K 0x00000000 | ||
194 | #define AR5312_FLASHCTL_AC_256K 0x00010000 | ||
195 | #define AR5312_FLASHCTL_AC_512K 0x00020000 | ||
196 | #define AR5312_FLASHCTL_AC_1M 0x00030000 | ||
197 | #define AR5312_FLASHCTL_AC_2M 0x00040000 | ||
198 | #define AR5312_FLASHCTL_AC_4M 0x00050000 | ||
199 | #define AR5312_FLASHCTL_AC_8M 0x00060000 | ||
200 | #define AR5312_FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */ | ||
201 | #define AR5312_FLASHCTL_E 0x00080000 /* Flash bank enable (added) */ | ||
202 | #define AR5312_FLASHCTL_BUSERR 0x01000000 /* Bus transfer error flag */ | ||
203 | #define AR5312_FLASHCTL_WPERR 0x02000000 /* Write protect error flag */ | ||
204 | #define AR5312_FLASHCTL_WP 0x04000000 /* Write protect */ | ||
205 | #define AR5312_FLASHCTL_BM 0x08000000 /* Burst mode */ | ||
206 | #define AR5312_FLASHCTL_MW 0x30000000 /* Mem width */ | ||
207 | #define AR5312_FLASHCTL_MW8 0x00000000 /* Mem width x8 */ | ||
208 | #define AR5312_FLASHCTL_MW16 0x10000000 /* Mem width x16 */ | ||
209 | #define AR5312_FLASHCTL_MW32 0x20000000 /* Mem width x32 (not supp) */ | ||
210 | #define AR5312_FLASHCTL_ATNR 0x00000000 /* Access == no retry */ | ||
211 | #define AR5312_FLASHCTL_ATR 0x80000000 /* Access == retry every */ | ||
212 | #define AR5312_FLASHCTL_ATR4 0xc0000000 /* Access == retry every 4 */ | ||
213 | |||
214 | /* | ||
215 | * ARM SDRAM Controller -- just enough to determine memory size | ||
216 | */ | ||
217 | #define AR5312_MEM_CFG1 0x0004 | ||
218 | |||
219 | #define AR5312_MEM_CFG1_AC0_M 0x00000700 /* bank 0: SDRAM addr check */ | ||
220 | #define AR5312_MEM_CFG1_AC0_S 8 | ||
221 | #define AR5312_MEM_CFG1_AC1_M 0x00007000 /* bank 1: SDRAM addr check */ | ||
222 | #define AR5312_MEM_CFG1_AC1_S 12 | ||
223 | |||
224 | #endif /* __ASM_MACH_ATH25_AR5312_REGS_H */ | ||
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c new file mode 100644 index 000000000000..b8bb78282d6a --- /dev/null +++ b/arch/mips/ath25/board.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. | ||
7 | * Copyright (C) 2006 FON Technology, SL. | ||
8 | * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> | ||
9 | * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <asm/irq_cpu.h> | ||
15 | #include <asm/reboot.h> | ||
16 | #include <asm/bootinfo.h> | ||
17 | #include <asm/time.h> | ||
18 | |||
19 | #include <ath25_platform.h> | ||
20 | #include "devices.h" | ||
21 | #include "ar5312.h" | ||
22 | #include "ar2315.h" | ||
23 | |||
24 | void (*ath25_irq_dispatch)(void); | ||
25 | |||
26 | static inline bool check_radio_magic(const void __iomem *addr) | ||
27 | { | ||
28 | addr += 0x7a; /* offset for flash magic */ | ||
29 | return (__raw_readb(addr) == 0x5a) && (__raw_readb(addr + 1) == 0xa5); | ||
30 | } | ||
31 | |||
32 | static inline bool check_notempty(const void __iomem *addr) | ||
33 | { | ||
34 | return __raw_readl(addr) != 0xffffffff; | ||
35 | } | ||
36 | |||
37 | static inline bool check_board_data(const void __iomem *addr, bool broken) | ||
38 | { | ||
39 | /* config magic found */ | ||
40 | if (__raw_readl(addr) == ATH25_BD_MAGIC) | ||
41 | return true; | ||
42 | |||
43 | if (!broken) | ||
44 | return false; | ||
45 | |||
46 | /* broken board data detected, use radio data to find the | ||
47 | * offset, user will fix this */ | ||
48 | |||
49 | if (check_radio_magic(addr + 0x1000)) | ||
50 | return true; | ||
51 | if (check_radio_magic(addr + 0xf8)) | ||
52 | return true; | ||
53 | |||
54 | return false; | ||
55 | } | ||
56 | |||
57 | static const void __iomem * __init find_board_config(const void __iomem *limit, | ||
58 | const bool broken) | ||
59 | { | ||
60 | const void __iomem *addr; | ||
61 | const void __iomem *begin = limit - 0x1000; | ||
62 | const void __iomem *end = limit - 0x30000; | ||
63 | |||
64 | for (addr = begin; addr >= end; addr -= 0x1000) | ||
65 | if (check_board_data(addr, broken)) | ||
66 | return addr; | ||
67 | |||
68 | return NULL; | ||
69 | } | ||
70 | |||
71 | static const void __iomem * __init find_radio_config(const void __iomem *limit, | ||
72 | const void __iomem *bcfg) | ||
73 | { | ||
74 | const void __iomem *rcfg, *begin, *end; | ||
75 | |||
76 | /* | ||
77 | * Now find the start of Radio Configuration data, using heuristics: | ||
78 | * Search forward from Board Configuration data by 0x1000 bytes | ||
79 | * at a time until we find non-0xffffffff. | ||
80 | */ | ||
81 | begin = bcfg + 0x1000; | ||
82 | end = limit; | ||
83 | for (rcfg = begin; rcfg < end; rcfg += 0x1000) | ||
84 | if (check_notempty(rcfg) && check_radio_magic(rcfg)) | ||
85 | return rcfg; | ||
86 | |||
87 | /* AR2316 relocates radio config to new location */ | ||
88 | begin = bcfg + 0xf8; | ||
89 | end = limit - 0x1000 + 0xf8; | ||
90 | for (rcfg = begin; rcfg < end; rcfg += 0x1000) | ||
91 | if (check_notempty(rcfg) && check_radio_magic(rcfg)) | ||
92 | return rcfg; | ||
93 | |||
94 | return NULL; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * NB: Search region size could be larger than the actual flash size, | ||
99 | * but this shouldn't be a problem here, because the flash | ||
100 | * will simply be mapped multiple times. | ||
101 | */ | ||
102 | int __init ath25_find_config(phys_addr_t base, unsigned long size) | ||
103 | { | ||
104 | const void __iomem *flash_base, *flash_limit; | ||
105 | struct ath25_boarddata *config; | ||
106 | unsigned int rcfg_size; | ||
107 | int broken_boarddata = 0; | ||
108 | const void __iomem *bcfg, *rcfg; | ||
109 | u8 *board_data; | ||
110 | u8 *radio_data; | ||
111 | u8 *mac_addr; | ||
112 | u32 offset; | ||
113 | |||
114 | flash_base = ioremap_nocache(base, size); | ||
115 | flash_limit = flash_base + size; | ||
116 | |||
117 | ath25_board.config = NULL; | ||
118 | ath25_board.radio = NULL; | ||
119 | |||
120 | /* Copy the board and radio data to RAM, because accessing the mapped | ||
121 | * memory of the flash directly after booting is not safe */ | ||
122 | |||
123 | /* Try to find valid board and radio data */ | ||
124 | bcfg = find_board_config(flash_limit, false); | ||
125 | |||
126 | /* If that fails, try to at least find valid radio data */ | ||
127 | if (!bcfg) { | ||
128 | bcfg = find_board_config(flash_limit, true); | ||
129 | broken_boarddata = 1; | ||
130 | } | ||
131 | |||
132 | if (!bcfg) { | ||
133 | pr_warn("WARNING: No board configuration data found!\n"); | ||
134 | goto error; | ||
135 | } | ||
136 | |||
137 | board_data = kzalloc(BOARD_CONFIG_BUFSZ, GFP_KERNEL); | ||
138 | ath25_board.config = (struct ath25_boarddata *)board_data; | ||
139 | memcpy_fromio(board_data, bcfg, 0x100); | ||
140 | if (broken_boarddata) { | ||
141 | pr_warn("WARNING: broken board data detected\n"); | ||
142 | config = ath25_board.config; | ||
143 | if (is_zero_ether_addr(config->enet0_mac)) { | ||
144 | pr_info("Fixing up empty mac addresses\n"); | ||
145 | config->reset_config_gpio = 0xffff; | ||
146 | config->sys_led_gpio = 0xffff; | ||
147 | random_ether_addr(config->wlan0_mac); | ||
148 | config->wlan0_mac[0] &= ~0x06; | ||
149 | random_ether_addr(config->enet0_mac); | ||
150 | random_ether_addr(config->enet1_mac); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | /* Radio config starts 0x100 bytes after board config, regardless | ||
155 | * of what the physical layout on the flash chip looks like */ | ||
156 | |||
157 | rcfg = find_radio_config(flash_limit, bcfg); | ||
158 | if (!rcfg) { | ||
159 | pr_warn("WARNING: Could not find Radio Configuration data\n"); | ||
160 | goto error; | ||
161 | } | ||
162 | |||
163 | radio_data = board_data + 0x100 + ((rcfg - bcfg) & 0xfff); | ||
164 | ath25_board.radio = radio_data; | ||
165 | offset = radio_data - board_data; | ||
166 | pr_info("Radio config found at offset 0x%x (0x%x)\n", rcfg - bcfg, | ||
167 | offset); | ||
168 | rcfg_size = BOARD_CONFIG_BUFSZ - offset; | ||
169 | memcpy_fromio(radio_data, rcfg, rcfg_size); | ||
170 | |||
171 | mac_addr = &radio_data[0x1d * 2]; | ||
172 | if (is_broadcast_ether_addr(mac_addr)) { | ||
173 | pr_info("Radio MAC is blank; using board-data\n"); | ||
174 | ether_addr_copy(mac_addr, ath25_board.config->wlan0_mac); | ||
175 | } | ||
176 | |||
177 | iounmap(flash_base); | ||
178 | |||
179 | return 0; | ||
180 | |||
181 | error: | ||
182 | iounmap(flash_base); | ||
183 | return -ENODEV; | ||
184 | } | ||
185 | |||
186 | static void ath25_halt(void) | ||
187 | { | ||
188 | local_irq_disable(); | ||
189 | unreachable(); | ||
190 | } | ||
191 | |||
192 | void __init plat_mem_setup(void) | ||
193 | { | ||
194 | _machine_halt = ath25_halt; | ||
195 | pm_power_off = ath25_halt; | ||
196 | |||
197 | if (is_ar5312()) | ||
198 | ar5312_plat_mem_setup(); | ||
199 | else | ||
200 | ar2315_plat_mem_setup(); | ||
201 | |||
202 | /* Disable data watchpoints */ | ||
203 | write_c0_watchlo0(0); | ||
204 | } | ||
205 | |||
206 | asmlinkage void plat_irq_dispatch(void) | ||
207 | { | ||
208 | ath25_irq_dispatch(); | ||
209 | } | ||
210 | |||
211 | void __init plat_time_init(void) | ||
212 | { | ||
213 | if (is_ar5312()) | ||
214 | ar5312_plat_time_init(); | ||
215 | else | ||
216 | ar2315_plat_time_init(); | ||
217 | } | ||
218 | |||
219 | unsigned int __cpuinit get_c0_compare_int(void) | ||
220 | { | ||
221 | return CP0_LEGACY_COMPARE_IRQ; | ||
222 | } | ||
223 | |||
224 | void __init arch_init_irq(void) | ||
225 | { | ||
226 | clear_c0_status(ST0_IM); | ||
227 | mips_cpu_irq_init(); | ||
228 | |||
229 | /* Initialize interrupt controllers */ | ||
230 | if (is_ar5312()) | ||
231 | ar5312_arch_init_irq(); | ||
232 | else | ||
233 | ar2315_arch_init_irq(); | ||
234 | } | ||
diff --git a/arch/mips/ath25/devices.c b/arch/mips/ath25/devices.c new file mode 100644 index 000000000000..7a64567d1ac3 --- /dev/null +++ b/arch/mips/ath25/devices.c | |||
@@ -0,0 +1,125 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <linux/serial_8250.h> | ||
4 | #include <linux/platform_device.h> | ||
5 | #include <asm/bootinfo.h> | ||
6 | |||
7 | #include <ath25_platform.h> | ||
8 | #include "devices.h" | ||
9 | #include "ar5312.h" | ||
10 | #include "ar2315.h" | ||
11 | |||
12 | struct ar231x_board_config ath25_board; | ||
13 | enum ath25_soc_type ath25_soc = ATH25_SOC_UNKNOWN; | ||
14 | |||
15 | static struct resource ath25_wmac0_res[] = { | ||
16 | { | ||
17 | .name = "wmac0_membase", | ||
18 | .flags = IORESOURCE_MEM, | ||
19 | }, | ||
20 | { | ||
21 | .name = "wmac0_irq", | ||
22 | .flags = IORESOURCE_IRQ, | ||
23 | } | ||
24 | }; | ||
25 | |||
26 | static struct resource ath25_wmac1_res[] = { | ||
27 | { | ||
28 | .name = "wmac1_membase", | ||
29 | .flags = IORESOURCE_MEM, | ||
30 | }, | ||
31 | { | ||
32 | .name = "wmac1_irq", | ||
33 | .flags = IORESOURCE_IRQ, | ||
34 | } | ||
35 | }; | ||
36 | |||
37 | static struct platform_device ath25_wmac[] = { | ||
38 | { | ||
39 | .id = 0, | ||
40 | .name = "ar231x-wmac", | ||
41 | .resource = ath25_wmac0_res, | ||
42 | .num_resources = ARRAY_SIZE(ath25_wmac0_res), | ||
43 | .dev.platform_data = &ath25_board, | ||
44 | }, | ||
45 | { | ||
46 | .id = 1, | ||
47 | .name = "ar231x-wmac", | ||
48 | .resource = ath25_wmac1_res, | ||
49 | .num_resources = ARRAY_SIZE(ath25_wmac1_res), | ||
50 | .dev.platform_data = &ath25_board, | ||
51 | }, | ||
52 | }; | ||
53 | |||
54 | static const char * const soc_type_strings[] = { | ||
55 | [ATH25_SOC_AR5312] = "Atheros AR5312", | ||
56 | [ATH25_SOC_AR2312] = "Atheros AR2312", | ||
57 | [ATH25_SOC_AR2313] = "Atheros AR2313", | ||
58 | [ATH25_SOC_AR2315] = "Atheros AR2315", | ||
59 | [ATH25_SOC_AR2316] = "Atheros AR2316", | ||
60 | [ATH25_SOC_AR2317] = "Atheros AR2317", | ||
61 | [ATH25_SOC_AR2318] = "Atheros AR2318", | ||
62 | [ATH25_SOC_UNKNOWN] = "Atheros (unknown)", | ||
63 | }; | ||
64 | |||
65 | const char *get_system_type(void) | ||
66 | { | ||
67 | if ((ath25_soc >= ARRAY_SIZE(soc_type_strings)) || | ||
68 | !soc_type_strings[ath25_soc]) | ||
69 | return soc_type_strings[ATH25_SOC_UNKNOWN]; | ||
70 | return soc_type_strings[ath25_soc]; | ||
71 | } | ||
72 | |||
73 | void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk) | ||
74 | { | ||
75 | struct uart_port s; | ||
76 | |||
77 | memset(&s, 0, sizeof(s)); | ||
78 | |||
79 | s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP; | ||
80 | s.iotype = UPIO_MEM32; | ||
81 | s.irq = irq; | ||
82 | s.regshift = 2; | ||
83 | s.mapbase = mapbase; | ||
84 | s.uartclk = uartclk; | ||
85 | |||
86 | early_serial_setup(&s); | ||
87 | } | ||
88 | |||
89 | int __init ath25_add_wmac(int nr, u32 base, int irq) | ||
90 | { | ||
91 | struct resource *res; | ||
92 | |||
93 | ath25_wmac[nr].dev.platform_data = &ath25_board; | ||
94 | res = &ath25_wmac[nr].resource[0]; | ||
95 | res->start = base; | ||
96 | res->end = base + 0x10000 - 1; | ||
97 | res++; | ||
98 | res->start = irq; | ||
99 | res->end = irq; | ||
100 | return platform_device_register(&ath25_wmac[nr]); | ||
101 | } | ||
102 | |||
103 | static int __init ath25_register_devices(void) | ||
104 | { | ||
105 | if (is_ar5312()) | ||
106 | ar5312_init_devices(); | ||
107 | else | ||
108 | ar2315_init_devices(); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | device_initcall(ath25_register_devices); | ||
114 | |||
115 | static int __init ath25_arch_init(void) | ||
116 | { | ||
117 | if (is_ar5312()) | ||
118 | ar5312_arch_init(); | ||
119 | else | ||
120 | ar2315_arch_init(); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | arch_initcall(ath25_arch_init); | ||
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h new file mode 100644 index 000000000000..04d414115356 --- /dev/null +++ b/arch/mips/ath25/devices.h | |||
@@ -0,0 +1,43 @@ | |||
1 | #ifndef __ATH25_DEVICES_H | ||
2 | #define __ATH25_DEVICES_H | ||
3 | |||
4 | #include <linux/cpu.h> | ||
5 | |||
6 | #define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S) | ||
7 | |||
8 | #define ATH25_IRQ_CPU_CLOCK (MIPS_CPU_IRQ_BASE + 7) /* C0_CAUSE: 0x8000 */ | ||
9 | |||
10 | enum ath25_soc_type { | ||
11 | /* handled by ar5312.c */ | ||
12 | ATH25_SOC_AR2312, | ||
13 | ATH25_SOC_AR2313, | ||
14 | ATH25_SOC_AR5312, | ||
15 | |||
16 | /* handled by ar2315.c */ | ||
17 | ATH25_SOC_AR2315, | ||
18 | ATH25_SOC_AR2316, | ||
19 | ATH25_SOC_AR2317, | ||
20 | ATH25_SOC_AR2318, | ||
21 | |||
22 | ATH25_SOC_UNKNOWN | ||
23 | }; | ||
24 | |||
25 | extern enum ath25_soc_type ath25_soc; | ||
26 | extern struct ar231x_board_config ath25_board; | ||
27 | extern void (*ath25_irq_dispatch)(void); | ||
28 | |||
29 | int ath25_find_config(phys_addr_t offset, unsigned long size); | ||
30 | void ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk); | ||
31 | int ath25_add_wmac(int nr, u32 base, int irq); | ||
32 | |||
33 | static inline bool is_ar2315(void) | ||
34 | { | ||
35 | return (current_cpu_data.cputype == CPU_4KEC); | ||
36 | } | ||
37 | |||
38 | static inline bool is_ar5312(void) | ||
39 | { | ||
40 | return !is_ar2315(); | ||
41 | } | ||
42 | |||
43 | #endif | ||
diff --git a/arch/mips/ath25/early_printk.c b/arch/mips/ath25/early_printk.c new file mode 100644 index 000000000000..36035b628161 --- /dev/null +++ b/arch/mips/ath25/early_printk.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> | ||
7 | */ | ||
8 | |||
9 | #include <linux/mm.h> | ||
10 | #include <linux/io.h> | ||
11 | #include <linux/serial_reg.h> | ||
12 | |||
13 | #include "devices.h" | ||
14 | #include "ar2315_regs.h" | ||
15 | #include "ar5312_regs.h" | ||
16 | |||
17 | static inline void prom_uart_wr(void __iomem *base, unsigned reg, | ||
18 | unsigned char ch) | ||
19 | { | ||
20 | __raw_writel(ch, base + 4 * reg); | ||
21 | } | ||
22 | |||
23 | static inline unsigned char prom_uart_rr(void __iomem *base, unsigned reg) | ||
24 | { | ||
25 | return __raw_readl(base + 4 * reg); | ||
26 | } | ||
27 | |||
28 | void prom_putchar(unsigned char ch) | ||
29 | { | ||
30 | static void __iomem *base; | ||
31 | |||
32 | if (unlikely(base == NULL)) { | ||
33 | if (is_ar2315()) | ||
34 | base = (void __iomem *)(KSEG1ADDR(AR2315_UART0_BASE)); | ||
35 | else | ||
36 | base = (void __iomem *)(KSEG1ADDR(AR5312_UART0_BASE)); | ||
37 | } | ||
38 | |||
39 | while ((prom_uart_rr(base, UART_LSR) & UART_LSR_THRE) == 0) | ||
40 | ; | ||
41 | prom_uart_wr(base, UART_TX, ch); | ||
42 | while ((prom_uart_rr(base, UART_LSR) & UART_LSR_THRE) == 0) | ||
43 | ; | ||
44 | } | ||
diff --git a/arch/mips/ath25/prom.c b/arch/mips/ath25/prom.c new file mode 100644 index 000000000000..edf82be8870d --- /dev/null +++ b/arch/mips/ath25/prom.c | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright MontaVista Software Inc | ||
7 | * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. | ||
8 | * Copyright (C) 2006 FON Technology, SL. | ||
9 | * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> | ||
10 | * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * Prom setup file for AR5312/AR231x SoCs | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <asm/bootinfo.h> | ||
19 | |||
20 | void __init prom_init(void) | ||
21 | { | ||
22 | } | ||
23 | |||
24 | void __init prom_free_prom_memory(void) | ||
25 | { | ||
26 | } | ||
diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index 9c0e1761773f..6adae366f11a 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c | |||
@@ -359,7 +359,6 @@ void __init arch_init_irq(void) | |||
359 | BUG(); | 359 | BUG(); |
360 | } | 360 | } |
361 | 361 | ||
362 | cp0_perfcount_irq = ATH79_MISC_IRQ(5); | ||
363 | mips_cpu_irq_init(); | 362 | mips_cpu_irq_init(); |
364 | ath79_misc_irq_init(); | 363 | ath79_misc_irq_init(); |
365 | 364 | ||
diff --git a/arch/mips/ath79/prom.c b/arch/mips/ath79/prom.c index e9cbd7c2918f..e1fe63051136 100644 --- a/arch/mips/ath79/prom.c +++ b/arch/mips/ath79/prom.c | |||
@@ -13,42 +13,24 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <linux/initrd.h> | ||
16 | 17 | ||
17 | #include <asm/bootinfo.h> | 18 | #include <asm/bootinfo.h> |
18 | #include <asm/addrspace.h> | 19 | #include <asm/addrspace.h> |
20 | #include <asm/fw/fw.h> | ||
19 | 21 | ||
20 | #include "common.h" | 22 | #include "common.h" |
21 | 23 | ||
22 | static inline int is_valid_ram_addr(void *addr) | ||
23 | { | ||
24 | if (((u32) addr > KSEG0) && | ||
25 | ((u32) addr < (KSEG0 + ATH79_MEM_SIZE_MAX))) | ||
26 | return 1; | ||
27 | |||
28 | if (((u32) addr > KSEG1) && | ||
29 | ((u32) addr < (KSEG1 + ATH79_MEM_SIZE_MAX))) | ||
30 | return 1; | ||
31 | |||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static __init void ath79_prom_init_cmdline(int argc, char **argv) | ||
36 | { | ||
37 | int i; | ||
38 | |||
39 | if (!is_valid_ram_addr(argv)) | ||
40 | return; | ||
41 | |||
42 | for (i = 0; i < argc; i++) | ||
43 | if (is_valid_ram_addr(argv[i])) { | ||
44 | strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); | ||
45 | strlcat(arcs_cmdline, argv[i], sizeof(arcs_cmdline)); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | void __init prom_init(void) | 24 | void __init prom_init(void) |
50 | { | 25 | { |
51 | ath79_prom_init_cmdline(fw_arg0, (char **)fw_arg1); | 26 | fw_init_cmdline(); |
27 | |||
28 | /* Read the initrd address from the firmware environment */ | ||
29 | initrd_start = fw_getenvl("initrd_start"); | ||
30 | if (initrd_start) { | ||
31 | initrd_start = KSEG0ADDR(initrd_start); | ||
32 | initrd_end = initrd_start + fw_getenvl("initrd_size"); | ||
33 | } | ||
52 | } | 34 | } |
53 | 35 | ||
54 | void __init prom_free_prom_memory(void) | 36 | void __init prom_free_prom_memory(void) |
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 64807a4809d0..a73c93c3d44a 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c | |||
@@ -182,6 +182,11 @@ const char *get_system_type(void) | |||
182 | return ath79_sys_type; | 182 | return ath79_sys_type; |
183 | } | 183 | } |
184 | 184 | ||
185 | int get_c0_perfcount_int(void) | ||
186 | { | ||
187 | return ATH79_MISC_IRQ(5); | ||
188 | } | ||
189 | |||
185 | unsigned int get_c0_compare_int(void) | 190 | unsigned int get_c0_compare_int(void) |
186 | { | 191 | { |
187 | return CP0_LEGACY_COMPARE_IRQ; | 192 | return CP0_LEGACY_COMPARE_IRQ; |
diff --git a/arch/mips/bcm3384/Makefile b/arch/mips/bcm3384/Makefile new file mode 100644 index 000000000000..a393955cba08 --- /dev/null +++ b/arch/mips/bcm3384/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y += setup.o irq.o dma.o | |||
diff --git a/arch/mips/bcm3384/Platform b/arch/mips/bcm3384/Platform new file mode 100644 index 000000000000..8e1ca0819e1b --- /dev/null +++ b/arch/mips/bcm3384/Platform | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Broadcom BCM3384 boards | ||
3 | # | ||
4 | platform-$(CONFIG_BCM3384) += bcm3384/ | ||
5 | cflags-$(CONFIG_BCM3384) += \ | ||
6 | -I$(srctree)/arch/mips/include/asm/mach-bcm3384/ | ||
7 | load-$(CONFIG_BCM3384) := 0xffffffff80010000 | ||
diff --git a/arch/mips/bcm3384/dma.c b/arch/mips/bcm3384/dma.c new file mode 100644 index 000000000000..ea42012fd4f5 --- /dev/null +++ b/arch/mips/bcm3384/dma.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2014 Kevin Cernekee <cernekee@gmail.com> | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include <linux/dma-direction.h> | ||
11 | #include <linux/dma-mapping.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/mm.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <dma-coherence.h> | ||
18 | |||
19 | /* | ||
20 | * BCM3384 has configurable address translation windows which allow the | ||
21 | * peripherals' DMA addresses to be different from the Zephyr-visible | ||
22 | * physical addresses. e.g. usb_dma_addr = zephyr_pa ^ 0x08000000 | ||
23 | * | ||
24 | * If our DT "memory" node has a "dma-xor-mask" property we will enable this | ||
25 | * translation using the provided offset. | ||
26 | */ | ||
27 | static u32 bcm3384_dma_xor_mask; | ||
28 | static u32 bcm3384_dma_xor_limit = 0xffffffff; | ||
29 | |||
30 | /* | ||
31 | * PCI collapses the memory hole at 0x10000000 - 0x1fffffff. | ||
32 | * On systems with a dma-xor-mask, this range is guaranteed to live above | ||
33 | * the dma-xor-limit. | ||
34 | */ | ||
35 | #define BCM3384_MEM_HOLE_PA 0x10000000 | ||
36 | #define BCM3384_MEM_HOLE_SIZE 0x10000000 | ||
37 | |||
38 | static dma_addr_t bcm3384_phys_to_dma(struct device *dev, phys_addr_t pa) | ||
39 | { | ||
40 | if (dev && dev_is_pci(dev) && | ||
41 | pa >= (BCM3384_MEM_HOLE_PA + BCM3384_MEM_HOLE_SIZE)) | ||
42 | return pa - BCM3384_MEM_HOLE_SIZE; | ||
43 | if (pa <= bcm3384_dma_xor_limit) | ||
44 | return pa ^ bcm3384_dma_xor_mask; | ||
45 | return pa; | ||
46 | } | ||
47 | |||
48 | dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) | ||
49 | { | ||
50 | return bcm3384_phys_to_dma(dev, virt_to_phys(addr)); | ||
51 | } | ||
52 | |||
53 | dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) | ||
54 | { | ||
55 | return bcm3384_phys_to_dma(dev, page_to_phys(page)); | ||
56 | } | ||
57 | |||
58 | unsigned long plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr) | ||
59 | { | ||
60 | if (dev && dev_is_pci(dev) && | ||
61 | dma_addr >= BCM3384_MEM_HOLE_PA) | ||
62 | return dma_addr + BCM3384_MEM_HOLE_SIZE; | ||
63 | if ((dma_addr ^ bcm3384_dma_xor_mask) <= bcm3384_dma_xor_limit) | ||
64 | return dma_addr ^ bcm3384_dma_xor_mask; | ||
65 | return dma_addr; | ||
66 | } | ||
67 | |||
68 | static int __init bcm3384_init_dma_xor(void) | ||
69 | { | ||
70 | struct device_node *np = of_find_node_by_type(NULL, "memory"); | ||
71 | |||
72 | if (!np) | ||
73 | return 0; | ||
74 | |||
75 | of_property_read_u32(np, "dma-xor-mask", &bcm3384_dma_xor_mask); | ||
76 | of_property_read_u32(np, "dma-xor-limit", &bcm3384_dma_xor_limit); | ||
77 | |||
78 | of_node_put(np); | ||
79 | return 0; | ||
80 | } | ||
81 | arch_initcall(bcm3384_init_dma_xor); | ||
diff --git a/arch/mips/bcm3384/irq.c b/arch/mips/bcm3384/irq.c new file mode 100644 index 000000000000..0fb5134fb832 --- /dev/null +++ b/arch/mips/bcm3384/irq.c | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License version 2 as published | ||
4 | * by the Free Software Foundation. | ||
5 | * | ||
6 | * Partially based on arch/mips/ralink/irq.c | ||
7 | * | ||
8 | * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> | ||
9 | * Copyright (C) 2013 John Crispin <blogic@openwrt.org> | ||
10 | * Copyright (C) 2014 Kevin Cernekee <cernekee@gmail.com> | ||
11 | */ | ||
12 | |||
13 | #include <linux/io.h> | ||
14 | #include <linux/bitops.h> | ||
15 | #include <linux/of_platform.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/of_irq.h> | ||
18 | #include <linux/irqdomain.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | |||
23 | #include <asm/bmips.h> | ||
24 | #include <asm/irq_cpu.h> | ||
25 | #include <asm/mipsregs.h> | ||
26 | |||
27 | /* INTC register offsets */ | ||
28 | #define INTC_REG_ENABLE 0x00 | ||
29 | #define INTC_REG_STATUS 0x04 | ||
30 | |||
31 | #define MAX_WORDS 2 | ||
32 | #define IRQS_PER_WORD 32 | ||
33 | |||
34 | struct bcm3384_intc { | ||
35 | int n_words; | ||
36 | void __iomem *reg[MAX_WORDS]; | ||
37 | u32 enable[MAX_WORDS]; | ||
38 | spinlock_t lock; | ||
39 | }; | ||
40 | |||
41 | static void bcm3384_intc_irq_unmask(struct irq_data *d) | ||
42 | { | ||
43 | struct bcm3384_intc *priv = d->domain->host_data; | ||
44 | unsigned long flags; | ||
45 | int idx = d->hwirq / IRQS_PER_WORD; | ||
46 | int bit = d->hwirq % IRQS_PER_WORD; | ||
47 | |||
48 | spin_lock_irqsave(&priv->lock, flags); | ||
49 | priv->enable[idx] |= BIT(bit); | ||
50 | __raw_writel(priv->enable[idx], priv->reg[idx] + INTC_REG_ENABLE); | ||
51 | spin_unlock_irqrestore(&priv->lock, flags); | ||
52 | } | ||
53 | |||
54 | static void bcm3384_intc_irq_mask(struct irq_data *d) | ||
55 | { | ||
56 | struct bcm3384_intc *priv = d->domain->host_data; | ||
57 | unsigned long flags; | ||
58 | int idx = d->hwirq / IRQS_PER_WORD; | ||
59 | int bit = d->hwirq % IRQS_PER_WORD; | ||
60 | |||
61 | spin_lock_irqsave(&priv->lock, flags); | ||
62 | priv->enable[idx] &= ~BIT(bit); | ||
63 | __raw_writel(priv->enable[idx], priv->reg[idx] + INTC_REG_ENABLE); | ||
64 | spin_unlock_irqrestore(&priv->lock, flags); | ||
65 | } | ||
66 | |||
67 | static struct irq_chip bcm3384_intc_irq_chip = { | ||
68 | .name = "INTC", | ||
69 | .irq_unmask = bcm3384_intc_irq_unmask, | ||
70 | .irq_mask = bcm3384_intc_irq_mask, | ||
71 | .irq_mask_ack = bcm3384_intc_irq_mask, | ||
72 | }; | ||
73 | |||
74 | unsigned int get_c0_compare_int(void) | ||
75 | { | ||
76 | return CP0_LEGACY_COMPARE_IRQ; | ||
77 | } | ||
78 | |||
79 | static void bcm3384_intc_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
80 | { | ||
81 | struct irq_domain *domain = irq_get_handler_data(irq); | ||
82 | struct bcm3384_intc *priv = domain->host_data; | ||
83 | unsigned long flags; | ||
84 | unsigned int idx; | ||
85 | |||
86 | for (idx = 0; idx < priv->n_words; idx++) { | ||
87 | unsigned long pending; | ||
88 | int hwirq; | ||
89 | |||
90 | spin_lock_irqsave(&priv->lock, flags); | ||
91 | pending = __raw_readl(priv->reg[idx] + INTC_REG_STATUS) & | ||
92 | priv->enable[idx]; | ||
93 | spin_unlock_irqrestore(&priv->lock, flags); | ||
94 | |||
95 | for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) { | ||
96 | generic_handle_irq(irq_find_mapping(domain, | ||
97 | hwirq + idx * IRQS_PER_WORD)); | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | |||
102 | asmlinkage void plat_irq_dispatch(void) | ||
103 | { | ||
104 | unsigned long pending = | ||
105 | (read_c0_status() & read_c0_cause() & ST0_IM) >> STATUSB_IP0; | ||
106 | int bit; | ||
107 | |||
108 | for_each_set_bit(bit, &pending, 8) | ||
109 | do_IRQ(MIPS_CPU_IRQ_BASE + bit); | ||
110 | } | ||
111 | |||
112 | static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) | ||
113 | { | ||
114 | irq_set_chip_and_handler(irq, &bcm3384_intc_irq_chip, handle_level_irq); | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static const struct irq_domain_ops irq_domain_ops = { | ||
119 | .xlate = irq_domain_xlate_onecell, | ||
120 | .map = intc_map, | ||
121 | }; | ||
122 | |||
123 | static int __init ioremap_one_pair(struct bcm3384_intc *priv, | ||
124 | struct device_node *node, | ||
125 | int idx) | ||
126 | { | ||
127 | struct resource res; | ||
128 | |||
129 | if (of_address_to_resource(node, idx, &res)) | ||
130 | return 0; | ||
131 | |||
132 | if (request_mem_region(res.start, resource_size(&res), | ||
133 | res.name) < 0) | ||
134 | pr_err("Failed to request INTC register region\n"); | ||
135 | |||
136 | priv->reg[idx] = ioremap_nocache(res.start, resource_size(&res)); | ||
137 | if (!priv->reg[idx]) | ||
138 | panic("Failed to ioremap INTC register range"); | ||
139 | |||
140 | /* start up with everything masked before we hook the parent IRQ */ | ||
141 | __raw_writel(0, priv->reg[idx] + INTC_REG_ENABLE); | ||
142 | priv->enable[idx] = 0; | ||
143 | |||
144 | return IRQS_PER_WORD; | ||
145 | } | ||
146 | |||
147 | static int __init intc_of_init(struct device_node *node, | ||
148 | struct device_node *parent) | ||
149 | { | ||
150 | struct irq_domain *domain; | ||
151 | unsigned int parent_irq, n_irqs = 0; | ||
152 | struct bcm3384_intc *priv; | ||
153 | |||
154 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
155 | if (!priv) | ||
156 | panic("Failed to allocate bcm3384_intc struct"); | ||
157 | |||
158 | spin_lock_init(&priv->lock); | ||
159 | |||
160 | parent_irq = irq_of_parse_and_map(node, 0); | ||
161 | if (!parent_irq) | ||
162 | panic("Failed to get INTC IRQ"); | ||
163 | |||
164 | n_irqs += ioremap_one_pair(priv, node, 0); | ||
165 | n_irqs += ioremap_one_pair(priv, node, 1); | ||
166 | |||
167 | if (!n_irqs) | ||
168 | panic("Failed to map INTC registers"); | ||
169 | |||
170 | priv->n_words = n_irqs / IRQS_PER_WORD; | ||
171 | domain = irq_domain_add_linear(node, n_irqs, &irq_domain_ops, priv); | ||
172 | if (!domain) | ||
173 | panic("Failed to add irqdomain"); | ||
174 | |||
175 | irq_set_chained_handler(parent_irq, bcm3384_intc_irq_handler); | ||
176 | irq_set_handler_data(parent_irq, domain); | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static struct of_device_id of_irq_ids[] __initdata = { | ||
182 | { .compatible = "mti,cpu-interrupt-controller", | ||
183 | .data = mips_cpu_intc_init }, | ||
184 | { .compatible = "brcm,bcm3384-intc", | ||
185 | .data = intc_of_init }, | ||
186 | {}, | ||
187 | }; | ||
188 | |||
189 | void __init arch_init_irq(void) | ||
190 | { | ||
191 | bmips_tp1_irqs = 0; | ||
192 | of_irq_init(of_irq_ids); | ||
193 | } | ||
diff --git a/arch/mips/bcm3384/setup.c b/arch/mips/bcm3384/setup.c new file mode 100644 index 000000000000..d84b8400b874 --- /dev/null +++ b/arch/mips/bcm3384/setup.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> | ||
7 | * Copyright (C) 2014 Kevin Cernekee <cernekee@gmail.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/init.h> | ||
11 | #include <linux/bootmem.h> | ||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/ioport.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/of_fdt.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <linux/smp.h> | ||
18 | #include <asm/addrspace.h> | ||
19 | #include <asm/bmips.h> | ||
20 | #include <asm/bootinfo.h> | ||
21 | #include <asm/prom.h> | ||
22 | #include <asm/smp-ops.h> | ||
23 | #include <asm/time.h> | ||
24 | |||
25 | void __init prom_init(void) | ||
26 | { | ||
27 | register_bmips_smp_ops(); | ||
28 | } | ||
29 | |||
30 | void __init prom_free_prom_memory(void) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | const char *get_system_type(void) | ||
35 | { | ||
36 | return "BCM3384"; | ||
37 | } | ||
38 | |||
39 | void __init plat_time_init(void) | ||
40 | { | ||
41 | struct device_node *np; | ||
42 | u32 freq; | ||
43 | |||
44 | np = of_find_node_by_name(NULL, "cpus"); | ||
45 | if (!np) | ||
46 | panic("missing 'cpus' DT node"); | ||
47 | if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0) | ||
48 | panic("missing 'mips-hpt-frequency' property"); | ||
49 | of_node_put(np); | ||
50 | |||
51 | mips_hpt_frequency = freq; | ||
52 | } | ||
53 | |||
54 | void __init plat_mem_setup(void) | ||
55 | { | ||
56 | void *dtb = __dtb_start; | ||
57 | |||
58 | set_io_port_base(0); | ||
59 | ioport_resource.start = 0; | ||
60 | ioport_resource.end = ~0; | ||
61 | |||
62 | /* intended to somewhat resemble ARM; see Documentation/arm/Booting */ | ||
63 | if (fw_arg0 == 0 && fw_arg1 == 0xffffffff) | ||
64 | dtb = phys_to_virt(fw_arg2); | ||
65 | |||
66 | __dt_setup_arch(dtb); | ||
67 | |||
68 | strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); | ||
69 | } | ||
70 | |||
71 | void __init device_tree_init(void) | ||
72 | { | ||
73 | struct device_node *np; | ||
74 | |||
75 | unflatten_and_copy_device_tree(); | ||
76 | |||
77 | /* Disable SMP boot unless both CPUs are listed in DT and !disabled */ | ||
78 | np = of_find_node_by_name(NULL, "cpus"); | ||
79 | if (np && of_get_available_child_count(np) <= 1) | ||
80 | bmips_smp_enabled = 0; | ||
81 | of_node_put(np); | ||
82 | } | ||
83 | |||
84 | int __init plat_of_setup(void) | ||
85 | { | ||
86 | return __dt_register_buses("brcm,bcm3384", "simple-bus"); | ||
87 | } | ||
88 | |||
89 | arch_initcall(plat_of_setup); | ||
90 | |||
91 | static int __init plat_dev_init(void) | ||
92 | { | ||
93 | of_clk_init(NULL); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | device_initcall(plat_dev_init); | ||
diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h index f1cc9d0495d8..ea909a56a3ee 100644 --- a/arch/mips/bcm47xx/bcm47xx_private.h +++ b/arch/mips/bcm47xx/bcm47xx_private.h | |||
@@ -6,12 +6,18 @@ | |||
6 | /* prom.c */ | 6 | /* prom.c */ |
7 | void __init bcm47xx_prom_highmem_init(void); | 7 | void __init bcm47xx_prom_highmem_init(void); |
8 | 8 | ||
9 | /* sprom.c */ | ||
10 | void bcm47xx_sprom_register_fallbacks(void); | ||
11 | |||
9 | /* buttons.c */ | 12 | /* buttons.c */ |
10 | int __init bcm47xx_buttons_register(void); | 13 | int __init bcm47xx_buttons_register(void); |
11 | 14 | ||
12 | /* leds.c */ | 15 | /* leds.c */ |
13 | void __init bcm47xx_leds_register(void); | 16 | void __init bcm47xx_leds_register(void); |
14 | 17 | ||
18 | /* setup.c */ | ||
19 | void __init bcm47xx_bus_setup(void); | ||
20 | |||
15 | /* workarounds.c */ | 21 | /* workarounds.c */ |
16 | void __init bcm47xx_workarounds(void); | 22 | void __init bcm47xx_workarounds(void); |
17 | 23 | ||
diff --git a/arch/mips/bcm47xx/irq.c b/arch/mips/bcm47xx/irq.c index e0585b76ec19..21b4497f09be 100644 --- a/arch/mips/bcm47xx/irq.c +++ b/arch/mips/bcm47xx/irq.c | |||
@@ -22,6 +22,8 @@ | |||
22 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 22 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "bcm47xx_private.h" | ||
26 | |||
25 | #include <linux/types.h> | 27 | #include <linux/types.h> |
26 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
27 | #include <linux/irq.h> | 29 | #include <linux/irq.h> |
@@ -65,6 +67,12 @@ DEFINE_HWx_IRQDISPATCH(7) | |||
65 | 67 | ||
66 | void __init arch_init_irq(void) | 68 | void __init arch_init_irq(void) |
67 | { | 69 | { |
70 | /* | ||
71 | * This is the first arch callback after mm_init (we can use kmalloc), | ||
72 | * so let's finish bus initialization now. | ||
73 | */ | ||
74 | bcm47xx_bus_setup(); | ||
75 | |||
68 | #ifdef CONFIG_BCM47XX_BCMA | 76 | #ifdef CONFIG_BCM47XX_BCMA |
69 | if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) { | 77 | if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) { |
70 | bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core, | 78 | bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core, |
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index 2bed73a684ae..c5c381c43f17 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c | |||
@@ -13,24 +13,35 @@ | |||
13 | 13 | ||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/ssb/ssb.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/string.h> | 17 | #include <linux/string.h> |
19 | #include <asm/addrspace.h> | 18 | #include <linux/mtd/mtd.h> |
20 | #include <bcm47xx_nvram.h> | 19 | #include <bcm47xx_nvram.h> |
21 | #include <asm/mach-bcm47xx/bcm47xx.h> | 20 | |
21 | #define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ | ||
22 | #define NVRAM_SPACE 0x8000 | ||
23 | |||
24 | #define FLASH_MIN 0x00020000 /* Minimum flash size */ | ||
25 | |||
26 | struct nvram_header { | ||
27 | u32 magic; | ||
28 | u32 len; | ||
29 | u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ | ||
30 | u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ | ||
31 | u32 config_ncdl; /* ncdl values for memc */ | ||
32 | }; | ||
22 | 33 | ||
23 | static char nvram_buf[NVRAM_SPACE]; | 34 | static char nvram_buf[NVRAM_SPACE]; |
24 | static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; | 35 | static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; |
25 | 36 | ||
26 | static u32 find_nvram_size(u32 end) | 37 | static u32 find_nvram_size(void __iomem *end) |
27 | { | 38 | { |
28 | struct nvram_header *header; | 39 | struct nvram_header __iomem *header; |
29 | int i; | 40 | int i; |
30 | 41 | ||
31 | for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { | 42 | for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { |
32 | header = (struct nvram_header *)KSEG1ADDR(end - nvram_sizes[i]); | 43 | header = (struct nvram_header *)(end - nvram_sizes[i]); |
33 | if (header->magic == NVRAM_HEADER) | 44 | if (header->magic == NVRAM_MAGIC) |
34 | return nvram_sizes[i]; | 45 | return nvram_sizes[i]; |
35 | } | 46 | } |
36 | 47 | ||
@@ -38,36 +49,40 @@ static u32 find_nvram_size(u32 end) | |||
38 | } | 49 | } |
39 | 50 | ||
40 | /* Probe for NVRAM header */ | 51 | /* Probe for NVRAM header */ |
41 | static int nvram_find_and_copy(u32 base, u32 lim) | 52 | static int nvram_find_and_copy(void __iomem *iobase, u32 lim) |
42 | { | 53 | { |
43 | struct nvram_header *header; | 54 | struct nvram_header __iomem *header; |
44 | int i; | 55 | int i; |
45 | u32 off; | 56 | u32 off; |
46 | u32 *src, *dst; | 57 | u32 *src, *dst; |
47 | u32 size; | 58 | u32 size; |
48 | 59 | ||
60 | if (nvram_buf[0]) { | ||
61 | pr_warn("nvram already initialized\n"); | ||
62 | return -EEXIST; | ||
63 | } | ||
64 | |||
49 | /* TODO: when nvram is on nand flash check for bad blocks first. */ | 65 | /* TODO: when nvram is on nand flash check for bad blocks first. */ |
50 | off = FLASH_MIN; | 66 | off = FLASH_MIN; |
51 | while (off <= lim) { | 67 | while (off <= lim) { |
52 | /* Windowed flash access */ | 68 | /* Windowed flash access */ |
53 | size = find_nvram_size(base + off); | 69 | size = find_nvram_size(iobase + off); |
54 | if (size) { | 70 | if (size) { |
55 | header = (struct nvram_header *)KSEG1ADDR(base + off - | 71 | header = (struct nvram_header *)(iobase + off - size); |
56 | size); | ||
57 | goto found; | 72 | goto found; |
58 | } | 73 | } |
59 | off <<= 1; | 74 | off <<= 1; |
60 | } | 75 | } |
61 | 76 | ||
62 | /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ | 77 | /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ |
63 | header = (struct nvram_header *) KSEG1ADDR(base + 4096); | 78 | header = (struct nvram_header *)(iobase + 4096); |
64 | if (header->magic == NVRAM_HEADER) { | 79 | if (header->magic == NVRAM_MAGIC) { |
65 | size = NVRAM_SPACE; | 80 | size = NVRAM_SPACE; |
66 | goto found; | 81 | goto found; |
67 | } | 82 | } |
68 | 83 | ||
69 | header = (struct nvram_header *) KSEG1ADDR(base + 1024); | 84 | header = (struct nvram_header *)(iobase + 1024); |
70 | if (header->magic == NVRAM_HEADER) { | 85 | if (header->magic == NVRAM_MAGIC) { |
71 | size = NVRAM_SPACE; | 86 | size = NVRAM_SPACE; |
72 | goto found; | 87 | goto found; |
73 | } | 88 | } |
@@ -94,71 +109,73 @@ found: | |||
94 | return 0; | 109 | return 0; |
95 | } | 110 | } |
96 | 111 | ||
97 | #ifdef CONFIG_BCM47XX_SSB | 112 | /* |
98 | static int nvram_init_ssb(void) | 113 | * On bcm47xx we need access to the NVRAM very early, so we can't use mtd |
114 | * subsystem to access flash. We can't even use platform device / driver to | ||
115 | * store memory offset. | ||
116 | * To handle this we provide following symbol. It's supposed to be called as | ||
117 | * soon as we get info about flash device, before any NVRAM entry is needed. | ||
118 | */ | ||
119 | int bcm47xx_nvram_init_from_mem(u32 base, u32 lim) | ||
99 | { | 120 | { |
100 | struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore; | 121 | void __iomem *iobase; |
101 | u32 base; | 122 | int err; |
102 | u32 lim; | ||
103 | |||
104 | if (mcore->pflash.present) { | ||
105 | base = mcore->pflash.window; | ||
106 | lim = mcore->pflash.window_size; | ||
107 | } else { | ||
108 | pr_err("Couldn't find supported flash memory\n"); | ||
109 | return -ENXIO; | ||
110 | } | ||
111 | 123 | ||
112 | return nvram_find_and_copy(base, lim); | 124 | iobase = ioremap_nocache(base, lim); |
113 | } | 125 | if (!iobase) |
114 | #endif | 126 | return -ENOMEM; |
115 | 127 | ||
116 | #ifdef CONFIG_BCM47XX_BCMA | 128 | err = nvram_find_and_copy(iobase, lim); |
117 | static int nvram_init_bcma(void) | 129 | |
118 | { | 130 | iounmap(iobase); |
119 | struct bcma_drv_cc *cc = &bcm47xx_bus.bcma.bus.drv_cc; | ||
120 | u32 base; | ||
121 | u32 lim; | ||
122 | |||
123 | #ifdef CONFIG_BCMA_NFLASH | ||
124 | if (cc->nflash.boot) { | ||
125 | base = BCMA_SOC_FLASH1; | ||
126 | lim = BCMA_SOC_FLASH1_SZ; | ||
127 | } else | ||
128 | #endif | ||
129 | if (cc->pflash.present) { | ||
130 | base = cc->pflash.window; | ||
131 | lim = cc->pflash.window_size; | ||
132 | #ifdef CONFIG_BCMA_SFLASH | ||
133 | } else if (cc->sflash.present) { | ||
134 | base = cc->sflash.window; | ||
135 | lim = cc->sflash.size; | ||
136 | #endif | ||
137 | } else { | ||
138 | pr_err("Couldn't find supported flash memory\n"); | ||
139 | return -ENXIO; | ||
140 | } | ||
141 | 131 | ||
142 | return nvram_find_and_copy(base, lim); | 132 | return err; |
143 | } | 133 | } |
144 | #endif | ||
145 | 134 | ||
146 | static int nvram_init(void) | 135 | static int nvram_init(void) |
147 | { | 136 | { |
148 | switch (bcm47xx_bus_type) { | 137 | #ifdef CONFIG_MTD |
149 | #ifdef CONFIG_BCM47XX_SSB | 138 | struct mtd_info *mtd; |
150 | case BCM47XX_BUS_TYPE_SSB: | 139 | struct nvram_header header; |
151 | return nvram_init_ssb(); | 140 | size_t bytes_read; |
152 | #endif | 141 | int err, i; |
153 | #ifdef CONFIG_BCM47XX_BCMA | 142 | |
154 | case BCM47XX_BUS_TYPE_BCMA: | 143 | mtd = get_mtd_device_nm("nvram"); |
155 | return nvram_init_bcma(); | 144 | if (IS_ERR(mtd)) |
156 | #endif | 145 | return -ENODEV; |
146 | |||
147 | for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) { | ||
148 | loff_t from = mtd->size - nvram_sizes[i]; | ||
149 | |||
150 | if (from < 0) | ||
151 | continue; | ||
152 | |||
153 | err = mtd_read(mtd, from, sizeof(header), &bytes_read, | ||
154 | (uint8_t *)&header); | ||
155 | if (!err && header.magic == NVRAM_MAGIC) { | ||
156 | u8 *dst = (uint8_t *)nvram_buf; | ||
157 | size_t len = header.len; | ||
158 | |||
159 | if (header.len > NVRAM_SPACE) { | ||
160 | pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", | ||
161 | header.len, NVRAM_SPACE); | ||
162 | len = NVRAM_SPACE; | ||
163 | } | ||
164 | |||
165 | err = mtd_read(mtd, from, len, &bytes_read, dst); | ||
166 | if (err) | ||
167 | return err; | ||
168 | memset(dst + bytes_read, 0x0, NVRAM_SPACE - bytes_read); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
157 | } | 172 | } |
173 | #endif | ||
174 | |||
158 | return -ENXIO; | 175 | return -ENXIO; |
159 | } | 176 | } |
160 | 177 | ||
161 | int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len) | 178 | int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len) |
162 | { | 179 | { |
163 | char *var, *value, *end, *eq; | 180 | char *var, *value, *end, *eq; |
164 | int err; | 181 | int err; |
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index c00585d915bc..e43b5046cb30 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c | |||
@@ -102,23 +102,6 @@ static void bcm47xx_machine_halt(void) | |||
102 | } | 102 | } |
103 | 103 | ||
104 | #ifdef CONFIG_BCM47XX_SSB | 104 | #ifdef CONFIG_BCM47XX_SSB |
105 | static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out) | ||
106 | { | ||
107 | char prefix[10]; | ||
108 | |||
109 | if (bus->bustype == SSB_BUSTYPE_PCI) { | ||
110 | memset(out, 0, sizeof(struct ssb_sprom)); | ||
111 | snprintf(prefix, sizeof(prefix), "pci/%u/%u/", | ||
112 | bus->host_pci->bus->number + 1, | ||
113 | PCI_SLOT(bus->host_pci->devfn)); | ||
114 | bcm47xx_fill_sprom(out, prefix, false); | ||
115 | return 0; | ||
116 | } else { | ||
117 | printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n"); | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | static int bcm47xx_get_invariants(struct ssb_bus *bus, | 105 | static int bcm47xx_get_invariants(struct ssb_bus *bus, |
123 | struct ssb_init_invariants *iv) | 106 | struct ssb_init_invariants *iv) |
124 | { | 107 | { |
@@ -144,11 +127,6 @@ static void __init bcm47xx_register_ssb(void) | |||
144 | char buf[100]; | 127 | char buf[100]; |
145 | struct ssb_mipscore *mcore; | 128 | struct ssb_mipscore *mcore; |
146 | 129 | ||
147 | err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb); | ||
148 | if (err) | ||
149 | printk(KERN_WARNING "bcm47xx: someone else already registered" | ||
150 | " a ssb SPROM callback handler (err %d)\n", err); | ||
151 | |||
152 | err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE, | 130 | err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE, |
153 | bcm47xx_get_invariants); | 131 | bcm47xx_get_invariants); |
154 | if (err) | 132 | if (err) |
@@ -171,56 +149,21 @@ static void __init bcm47xx_register_ssb(void) | |||
171 | #endif | 149 | #endif |
172 | 150 | ||
173 | #ifdef CONFIG_BCM47XX_BCMA | 151 | #ifdef CONFIG_BCM47XX_BCMA |
174 | static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out) | ||
175 | { | ||
176 | char prefix[10]; | ||
177 | struct bcma_device *core; | ||
178 | |||
179 | switch (bus->hosttype) { | ||
180 | case BCMA_HOSTTYPE_PCI: | ||
181 | memset(out, 0, sizeof(struct ssb_sprom)); | ||
182 | snprintf(prefix, sizeof(prefix), "pci/%u/%u/", | ||
183 | bus->host_pci->bus->number + 1, | ||
184 | PCI_SLOT(bus->host_pci->devfn)); | ||
185 | bcm47xx_fill_sprom(out, prefix, false); | ||
186 | return 0; | ||
187 | case BCMA_HOSTTYPE_SOC: | ||
188 | memset(out, 0, sizeof(struct ssb_sprom)); | ||
189 | core = bcma_find_core(bus, BCMA_CORE_80211); | ||
190 | if (core) { | ||
191 | snprintf(prefix, sizeof(prefix), "sb/%u/", | ||
192 | core->core_index); | ||
193 | bcm47xx_fill_sprom(out, prefix, true); | ||
194 | } else { | ||
195 | bcm47xx_fill_sprom(out, NULL, false); | ||
196 | } | ||
197 | return 0; | ||
198 | default: | ||
199 | pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n"); | ||
200 | return -EINVAL; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | static void __init bcm47xx_register_bcma(void) | 152 | static void __init bcm47xx_register_bcma(void) |
205 | { | 153 | { |
206 | int err; | 154 | int err; |
207 | 155 | ||
208 | err = bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma); | ||
209 | if (err) | ||
210 | pr_warn("bcm47xx: someone else already registered a bcma SPROM callback handler (err %d)\n", err); | ||
211 | |||
212 | err = bcma_host_soc_register(&bcm47xx_bus.bcma); | 156 | err = bcma_host_soc_register(&bcm47xx_bus.bcma); |
213 | if (err) | 157 | if (err) |
214 | panic("Failed to register BCMA bus (err %d)", err); | 158 | panic("Failed to register BCMA bus (err %d)", err); |
215 | |||
216 | err = bcma_host_soc_init(&bcm47xx_bus.bcma); | ||
217 | if (err) | ||
218 | panic("Failed to initialize BCMA bus (err %d)", err); | ||
219 | |||
220 | bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo, NULL); | ||
221 | } | 159 | } |
222 | #endif | 160 | #endif |
223 | 161 | ||
162 | /* | ||
163 | * Memory setup is done in the early part of MIPS's arch_mem_init. It's supposed | ||
164 | * to detect memory and record it with add_memory_region. | ||
165 | * Any extra initializaion performed here must not use kmalloc or bootmem. | ||
166 | */ | ||
224 | void __init plat_mem_setup(void) | 167 | void __init plat_mem_setup(void) |
225 | { | 168 | { |
226 | struct cpuinfo_mips *c = ¤t_cpu_data; | 169 | struct cpuinfo_mips *c = ¤t_cpu_data; |
@@ -229,6 +172,7 @@ void __init plat_mem_setup(void) | |||
229 | printk(KERN_INFO "bcm47xx: using bcma bus\n"); | 172 | printk(KERN_INFO "bcm47xx: using bcma bus\n"); |
230 | #ifdef CONFIG_BCM47XX_BCMA | 173 | #ifdef CONFIG_BCM47XX_BCMA |
231 | bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA; | 174 | bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA; |
175 | bcm47xx_sprom_register_fallbacks(); | ||
232 | bcm47xx_register_bcma(); | 176 | bcm47xx_register_bcma(); |
233 | bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id); | 177 | bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id); |
234 | #ifdef CONFIG_HIGHMEM | 178 | #ifdef CONFIG_HIGHMEM |
@@ -239,6 +183,7 @@ void __init plat_mem_setup(void) | |||
239 | printk(KERN_INFO "bcm47xx: using ssb bus\n"); | 183 | printk(KERN_INFO "bcm47xx: using ssb bus\n"); |
240 | #ifdef CONFIG_BCM47XX_SSB | 184 | #ifdef CONFIG_BCM47XX_SSB |
241 | bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; | 185 | bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; |
186 | bcm47xx_sprom_register_fallbacks(); | ||
242 | bcm47xx_register_ssb(); | 187 | bcm47xx_register_ssb(); |
243 | bcm47xx_set_system_type(bcm47xx_bus.ssb.chip_id); | 188 | bcm47xx_set_system_type(bcm47xx_bus.ssb.chip_id); |
244 | #endif | 189 | #endif |
@@ -247,6 +192,28 @@ void __init plat_mem_setup(void) | |||
247 | _machine_restart = bcm47xx_machine_restart; | 192 | _machine_restart = bcm47xx_machine_restart; |
248 | _machine_halt = bcm47xx_machine_halt; | 193 | _machine_halt = bcm47xx_machine_halt; |
249 | pm_power_off = bcm47xx_machine_halt; | 194 | pm_power_off = bcm47xx_machine_halt; |
195 | } | ||
196 | |||
197 | /* | ||
198 | * This finishes bus initialization doing things that were not possible without | ||
199 | * kmalloc. Make sure to call it late enough (after mm_init). | ||
200 | */ | ||
201 | void __init bcm47xx_bus_setup(void) | ||
202 | { | ||
203 | #ifdef CONFIG_BCM47XX_BCMA | ||
204 | if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) { | ||
205 | int err; | ||
206 | |||
207 | err = bcma_host_soc_init(&bcm47xx_bus.bcma); | ||
208 | if (err) | ||
209 | panic("Failed to initialize BCMA bus (err %d)", err); | ||
210 | |||
211 | bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo, | ||
212 | NULL); | ||
213 | } | ||
214 | #endif | ||
215 | |||
216 | /* With bus initialized we can access NVRAM and detect the board */ | ||
250 | bcm47xx_board_detect(); | 217 | bcm47xx_board_detect(); |
251 | mips_set_machine_name(bcm47xx_board_get_name()); | 218 | mips_set_machine_name(bcm47xx_board_get_name()); |
252 | } | 219 | } |
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index 41226b68de3d..2eff7fe99c6b 100644 --- a/arch/mips/bcm47xx/sprom.c +++ b/arch/mips/bcm47xx/sprom.c | |||
@@ -136,6 +136,20 @@ static void nvram_read_leddc(const char *prefix, const char *name, | |||
136 | *leddc_off_time = (val >> 16) & 0xff; | 136 | *leddc_off_time = (val >> 16) & 0xff; |
137 | } | 137 | } |
138 | 138 | ||
139 | static void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6]) | ||
140 | { | ||
141 | if (strchr(buf, ':')) | ||
142 | sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], | ||
143 | &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], | ||
144 | &macaddr[5]); | ||
145 | else if (strchr(buf, '-')) | ||
146 | sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0], | ||
147 | &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], | ||
148 | &macaddr[5]); | ||
149 | else | ||
150 | pr_warn("Can not parse mac address: %s\n", buf); | ||
151 | } | ||
152 | |||
139 | static void nvram_read_macaddr(const char *prefix, const char *name, | 153 | static void nvram_read_macaddr(const char *prefix, const char *name, |
140 | u8 val[6], bool fallback) | 154 | u8 val[6], bool fallback) |
141 | { | 155 | { |
@@ -801,3 +815,71 @@ void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo, | |||
801 | nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true); | 815 | nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true); |
802 | } | 816 | } |
803 | #endif | 817 | #endif |
818 | |||
819 | #if defined(CONFIG_BCM47XX_SSB) | ||
820 | static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out) | ||
821 | { | ||
822 | char prefix[10]; | ||
823 | |||
824 | if (bus->bustype == SSB_BUSTYPE_PCI) { | ||
825 | memset(out, 0, sizeof(struct ssb_sprom)); | ||
826 | snprintf(prefix, sizeof(prefix), "pci/%u/%u/", | ||
827 | bus->host_pci->bus->number + 1, | ||
828 | PCI_SLOT(bus->host_pci->devfn)); | ||
829 | bcm47xx_fill_sprom(out, prefix, false); | ||
830 | return 0; | ||
831 | } else { | ||
832 | pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n"); | ||
833 | return -EINVAL; | ||
834 | } | ||
835 | } | ||
836 | #endif | ||
837 | |||
838 | #if defined(CONFIG_BCM47XX_BCMA) | ||
839 | static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out) | ||
840 | { | ||
841 | char prefix[10]; | ||
842 | struct bcma_device *core; | ||
843 | |||
844 | switch (bus->hosttype) { | ||
845 | case BCMA_HOSTTYPE_PCI: | ||
846 | memset(out, 0, sizeof(struct ssb_sprom)); | ||
847 | snprintf(prefix, sizeof(prefix), "pci/%u/%u/", | ||
848 | bus->host_pci->bus->number + 1, | ||
849 | PCI_SLOT(bus->host_pci->devfn)); | ||
850 | bcm47xx_fill_sprom(out, prefix, false); | ||
851 | return 0; | ||
852 | case BCMA_HOSTTYPE_SOC: | ||
853 | memset(out, 0, sizeof(struct ssb_sprom)); | ||
854 | core = bcma_find_core(bus, BCMA_CORE_80211); | ||
855 | if (core) { | ||
856 | snprintf(prefix, sizeof(prefix), "sb/%u/", | ||
857 | core->core_index); | ||
858 | bcm47xx_fill_sprom(out, prefix, true); | ||
859 | } else { | ||
860 | bcm47xx_fill_sprom(out, NULL, false); | ||
861 | } | ||
862 | return 0; | ||
863 | default: | ||
864 | pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n"); | ||
865 | return -EINVAL; | ||
866 | } | ||
867 | } | ||
868 | #endif | ||
869 | |||
870 | /* | ||
871 | * On bcm47xx we need to register SPROM fallback handler very early, so we can't | ||
872 | * use anything like platform device / driver for this. | ||
873 | */ | ||
874 | void bcm47xx_sprom_register_fallbacks(void) | ||
875 | { | ||
876 | #if defined(CONFIG_BCM47XX_SSB) | ||
877 | if (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb)) | ||
878 | pr_warn("Failed to registered ssb SPROM handler\n"); | ||
879 | #endif | ||
880 | |||
881 | #if defined(CONFIG_BCM47XX_BCMA) | ||
882 | if (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma)) | ||
883 | pr_warn("Failed to registered bcma SPROM handler\n"); | ||
884 | #endif | ||
885 | } | ||
diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index 536f64443031..307ec8b8e41c 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c | |||
@@ -263,7 +263,7 @@ static unsigned int detect_memory_size(void) | |||
263 | 263 | ||
264 | if (BCMCPU_IS_6345()) { | 264 | if (BCMCPU_IS_6345()) { |
265 | val = bcm_sdram_readl(SDRAM_MBASE_REG); | 265 | val = bcm_sdram_readl(SDRAM_MBASE_REG); |
266 | return (val * 8 * 1024 * 1024); | 266 | return val * 8 * 1024 * 1024; |
267 | } | 267 | } |
268 | 268 | ||
269 | if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { | 269 | if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { |
diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile index ca9c90e2cabf..4f49fa477f14 100644 --- a/arch/mips/boot/dts/Makefile +++ b/arch/mips/boot/dts/Makefile | |||
@@ -1,3 +1,4 @@ | |||
1 | dtb-$(CONFIG_BCM3384) += bcm93384wvg.dtb | ||
1 | dtb-$(CONFIG_CAVIUM_OCTEON_SOC) += octeon_3xxx.dtb octeon_68xx.dtb | 2 | dtb-$(CONFIG_CAVIUM_OCTEON_SOC) += octeon_3xxx.dtb octeon_68xx.dtb |
2 | dtb-$(CONFIG_DT_EASY50712) += easy50712.dtb | 3 | dtb-$(CONFIG_DT_EASY50712) += easy50712.dtb |
3 | dtb-$(CONFIG_DT_XLP_EVP) += xlp_evp.dtb | 4 | dtb-$(CONFIG_DT_XLP_EVP) += xlp_evp.dtb |
diff --git a/arch/mips/boot/dts/bcm3384.dtsi b/arch/mips/boot/dts/bcm3384.dtsi new file mode 100644 index 000000000000..21b074a99c94 --- /dev/null +++ b/arch/mips/boot/dts/bcm3384.dtsi | |||
@@ -0,0 +1,109 @@ | |||
1 | / { | ||
2 | #address-cells = <1>; | ||
3 | #size-cells = <1>; | ||
4 | compatible = "brcm,bcm3384", "brcm,bcm33843"; | ||
5 | |||
6 | cpus { | ||
7 | #address-cells = <1>; | ||
8 | #size-cells = <0>; | ||
9 | |||
10 | /* On BMIPS5000 this is 1/8th of the CPU core clock */ | ||
11 | mips-hpt-frequency = <100000000>; | ||
12 | |||
13 | cpu@0 { | ||
14 | compatible = "brcm,bmips5000"; | ||
15 | device_type = "cpu"; | ||
16 | reg = <0>; | ||
17 | }; | ||
18 | |||
19 | cpu@1 { | ||
20 | compatible = "brcm,bmips5000"; | ||
21 | device_type = "cpu"; | ||
22 | reg = <1>; | ||
23 | }; | ||
24 | }; | ||
25 | |||
26 | clocks { | ||
27 | #address-cells = <1>; | ||
28 | #size-cells = <0>; | ||
29 | |||
30 | periph_clk: periph_clk@0 { | ||
31 | compatible = "fixed-clock"; | ||
32 | #clock-cells = <0>; | ||
33 | clock-frequency = <54000000>; | ||
34 | }; | ||
35 | }; | ||
36 | |||
37 | aliases { | ||
38 | uart0 = &uart0; | ||
39 | }; | ||
40 | |||
41 | cpu_intc: cpu_intc@0 { | ||
42 | #address-cells = <0>; | ||
43 | compatible = "mti,cpu-interrupt-controller"; | ||
44 | |||
45 | interrupt-controller; | ||
46 | #interrupt-cells = <1>; | ||
47 | }; | ||
48 | |||
49 | periph_intc: periph_intc@14e00038 { | ||
50 | compatible = "brcm,bcm3384-intc"; | ||
51 | reg = <0x14e00038 0x8 0x14e00340 0x8>; | ||
52 | |||
53 | interrupt-controller; | ||
54 | #interrupt-cells = <1>; | ||
55 | |||
56 | interrupt-parent = <&cpu_intc>; | ||
57 | interrupts = <4>; | ||
58 | }; | ||
59 | |||
60 | zmips_intc: zmips_intc@104b0060 { | ||
61 | compatible = "brcm,bcm3384-intc"; | ||
62 | reg = <0x104b0060 0x8>; | ||
63 | |||
64 | interrupt-controller; | ||
65 | #interrupt-cells = <1>; | ||
66 | |||
67 | interrupt-parent = <&periph_intc>; | ||
68 | interrupts = <29>; | ||
69 | }; | ||
70 | |||
71 | iop_intc: iop_intc@14e00058 { | ||
72 | compatible = "brcm,bcm3384-intc"; | ||
73 | reg = <0x14e00058 0x8>; | ||
74 | |||
75 | interrupt-controller; | ||
76 | #interrupt-cells = <1>; | ||
77 | |||
78 | interrupt-parent = <&cpu_intc>; | ||
79 | interrupts = <6>; | ||
80 | }; | ||
81 | |||
82 | uart0: serial@14e00520 { | ||
83 | compatible = "brcm,bcm6345-uart"; | ||
84 | reg = <0x14e00520 0x18>; | ||
85 | interrupt-parent = <&periph_intc>; | ||
86 | interrupts = <2>; | ||
87 | clocks = <&periph_clk>; | ||
88 | status = "disabled"; | ||
89 | }; | ||
90 | |||
91 | ehci0: usb@15400300 { | ||
92 | compatible = "brcm,bcm3384-ehci", "generic-ehci"; | ||
93 | reg = <0x15400300 0x100>; | ||
94 | big-endian; | ||
95 | interrupt-parent = <&periph_intc>; | ||
96 | interrupts = <41>; | ||
97 | status = "disabled"; | ||
98 | }; | ||
99 | |||
100 | ohci0: usb@15400400 { | ||
101 | compatible = "brcm,bcm3384-ohci", "generic-ohci"; | ||
102 | reg = <0x15400400 0x100>; | ||
103 | big-endian; | ||
104 | no-big-frame-no; | ||
105 | interrupt-parent = <&periph_intc>; | ||
106 | interrupts = <40>; | ||
107 | status = "disabled"; | ||
108 | }; | ||
109 | }; | ||
diff --git a/arch/mips/boot/dts/bcm93384wvg.dts b/arch/mips/boot/dts/bcm93384wvg.dts new file mode 100644 index 000000000000..831741179212 --- /dev/null +++ b/arch/mips/boot/dts/bcm93384wvg.dts | |||
@@ -0,0 +1,32 @@ | |||
1 | /dts-v1/; | ||
2 | |||
3 | /include/ "bcm3384.dtsi" | ||
4 | |||
5 | / { | ||
6 | compatible = "brcm,bcm93384wvg", "brcm,bcm3384"; | ||
7 | model = "Broadcom BCM93384WVG"; | ||
8 | |||
9 | chosen { | ||
10 | bootargs = "console=ttyS0,115200"; | ||
11 | stdout-path = &uart0; | ||
12 | }; | ||
13 | |||
14 | memory@0 { | ||
15 | device_type = "memory"; | ||
16 | reg = <0x0 0x04000000>; | ||
17 | dma-xor-mask = <0x08000000>; | ||
18 | dma-xor-limit = <0x0fffffff>; | ||
19 | }; | ||
20 | }; | ||
21 | |||
22 | &uart0 { | ||
23 | status = "okay"; | ||
24 | }; | ||
25 | |||
26 | &ehci0 { | ||
27 | status = "okay"; | ||
28 | }; | ||
29 | |||
30 | &ohci0 { | ||
31 | status = "okay"; | ||
32 | }; | ||
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index 02f244475207..3778655c4a37 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c | |||
@@ -262,8 +262,8 @@ char *octeon_swiotlb; | |||
262 | void __init plat_swiotlb_setup(void) | 262 | void __init plat_swiotlb_setup(void) |
263 | { | 263 | { |
264 | int i; | 264 | int i; |
265 | phys_t max_addr; | 265 | phys_addr_t max_addr; |
266 | phys_t addr_size; | 266 | phys_addr_t addr_size; |
267 | size_t swiotlbsize; | 267 | size_t swiotlbsize; |
268 | unsigned long swiotlb_nslabs; | 268 | unsigned long swiotlb_nslabs; |
269 | 269 | ||
diff --git a/arch/mips/cavium-octeon/executive/octeon-model.c b/arch/mips/cavium-octeon/executive/octeon-model.c index f4c1b36fdf65..e15b049b3bd7 100644 --- a/arch/mips/cavium-octeon/executive/octeon-model.c +++ b/arch/mips/cavium-octeon/executive/octeon-model.c | |||
@@ -28,22 +28,23 @@ | |||
28 | #include <asm/octeon/octeon.h> | 28 | #include <asm/octeon/octeon.h> |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * Given the chip processor ID from COP0, this function returns a | 31 | * Read a byte of fuse data |
32 | * string representing the chip model number. The string is of the | 32 | * @byte_addr: address to read |
33 | * form CNXXXXpX.X-FREQ-SUFFIX. | ||
34 | * - XXXX = The chip model number | ||
35 | * - X.X = Chip pass number | ||
36 | * - FREQ = Current frequency in Mhz | ||
37 | * - SUFFIX = NSP, EXP, SCP, SSP, or CP | ||
38 | * | ||
39 | * @chip_id: Chip ID | ||
40 | * | 33 | * |
41 | * Returns Model string | 34 | * Returns fuse value: 0 or 1 |
42 | */ | 35 | */ |
43 | const char *octeon_model_get_string(uint32_t chip_id) | 36 | static uint8_t __init cvmx_fuse_read_byte(int byte_addr) |
44 | { | 37 | { |
45 | static char buffer[32]; | 38 | union cvmx_mio_fus_rcmd read_cmd; |
46 | return octeon_model_get_string_buffer(chip_id, buffer); | 39 | |
40 | read_cmd.u64 = 0; | ||
41 | read_cmd.s.addr = byte_addr; | ||
42 | read_cmd.s.pend = 1; | ||
43 | cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64); | ||
44 | while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD)) | ||
45 | && read_cmd.s.pend) | ||
46 | ; | ||
47 | return read_cmd.s.dat; | ||
47 | } | 48 | } |
48 | 49 | ||
49 | /* | 50 | /* |
@@ -51,7 +52,8 @@ const char *octeon_model_get_string(uint32_t chip_id) | |||
51 | * as running early in u-boot static/global variables don't work when | 52 | * as running early in u-boot static/global variables don't work when |
52 | * running from flash. | 53 | * running from flash. |
53 | */ | 54 | */ |
54 | const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer) | 55 | static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, |
56 | char *buffer) | ||
55 | { | 57 | { |
56 | const char *family; | 58 | const char *family; |
57 | const char *core_model; | 59 | const char *core_model; |
@@ -407,3 +409,22 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer) | |||
407 | sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix); | 409 | sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix); |
408 | return buffer; | 410 | return buffer; |
409 | } | 411 | } |
412 | |||
413 | /** | ||
414 | * Given the chip processor ID from COP0, this function returns a | ||
415 | * string representing the chip model number. The string is of the | ||
416 | * form CNXXXXpX.X-FREQ-SUFFIX. | ||
417 | * - XXXX = The chip model number | ||
418 | * - X.X = Chip pass number | ||
419 | * - FREQ = Current frequency in Mhz | ||
420 | * - SUFFIX = NSP, EXP, SCP, SSP, or CP | ||
421 | * | ||
422 | * @chip_id: Chip ID | ||
423 | * | ||
424 | * Returns Model string | ||
425 | */ | ||
426 | const char *__init octeon_model_get_string(uint32_t chip_id) | ||
427 | { | ||
428 | static char buffer[32]; | ||
429 | return octeon_model_get_string_buffer(chip_id, buffer); | ||
430 | } | ||
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 5ebdb32d9a2b..94f888d3384e 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c | |||
@@ -1092,7 +1092,7 @@ static int __init edac_devinit(void) | |||
1092 | name = edac_device_names[i]; | 1092 | name = edac_device_names[i]; |
1093 | dev = platform_device_register_simple(name, -1, NULL, 0); | 1093 | dev = platform_device_register_simple(name, -1, NULL, 0); |
1094 | if (IS_ERR(dev)) { | 1094 | if (IS_ERR(dev)) { |
1095 | pr_err("Registation of %s failed!\n", name); | 1095 | pr_err("Registration of %s failed!\n", name); |
1096 | err = PTR_ERR(dev); | 1096 | err = PTR_ERR(dev); |
1097 | } | 1097 | } |
1098 | } | 1098 | } |
@@ -1103,7 +1103,7 @@ static int __init edac_devinit(void) | |||
1103 | dev = platform_device_register_simple("octeon_lmc_edac", | 1103 | dev = platform_device_register_simple("octeon_lmc_edac", |
1104 | i, NULL, 0); | 1104 | i, NULL, 0); |
1105 | if (IS_ERR(dev)) { | 1105 | if (IS_ERR(dev)) { |
1106 | pr_err("Registation of octeon_lmc_edac %d failed!\n", i); | 1106 | pr_err("Registration of octeon_lmc_edac %d failed!\n", i); |
1107 | err = PTR_ERR(dev); | 1107 | err = PTR_ERR(dev); |
1108 | } | 1108 | } |
1109 | } | 1109 | } |
diff --git a/arch/mips/configs/bcm3384_defconfig b/arch/mips/configs/bcm3384_defconfig new file mode 100644 index 000000000000..88711c28ff32 --- /dev/null +++ b/arch/mips/configs/bcm3384_defconfig | |||
@@ -0,0 +1,78 @@ | |||
1 | CONFIG_BCM3384=y | ||
2 | CONFIG_HIGHMEM=y | ||
3 | CONFIG_SMP=y | ||
4 | CONFIG_NR_CPUS=4 | ||
5 | # CONFIG_SECCOMP is not set | ||
6 | CONFIG_MIPS_O32_FP64_SUPPORT=y | ||
7 | # CONFIG_LOCALVERSION_AUTO is not set | ||
8 | # CONFIG_SWAP is not set | ||
9 | CONFIG_NO_HZ=y | ||
10 | CONFIG_BLK_DEV_INITRD=y | ||
11 | # CONFIG_RD_GZIP is not set | ||
12 | CONFIG_EXPERT=y | ||
13 | # CONFIG_VM_EVENT_COUNTERS is not set | ||
14 | # CONFIG_SLUB_DEBUG is not set | ||
15 | # CONFIG_BLK_DEV_BSG is not set | ||
16 | # CONFIG_IOSCHED_DEADLINE is not set | ||
17 | # CONFIG_IOSCHED_CFQ is not set | ||
18 | CONFIG_NET=y | ||
19 | CONFIG_PACKET=y | ||
20 | CONFIG_PACKET_DIAG=y | ||
21 | CONFIG_UNIX=y | ||
22 | CONFIG_INET=y | ||
23 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | ||
24 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | ||
25 | # CONFIG_INET_XFRM_MODE_BEET is not set | ||
26 | # CONFIG_INET_LRO is not set | ||
27 | # CONFIG_INET_DIAG is not set | ||
28 | CONFIG_CFG80211=y | ||
29 | CONFIG_NL80211_TESTMODE=y | ||
30 | CONFIG_MAC80211=y | ||
31 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
32 | CONFIG_DEVTMPFS=y | ||
33 | CONFIG_DEVTMPFS_MOUNT=y | ||
34 | # CONFIG_STANDALONE is not set | ||
35 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set | ||
36 | CONFIG_MTD=y | ||
37 | CONFIG_MTD_CFI=y | ||
38 | CONFIG_MTD_CFI_INTELEXT=y | ||
39 | CONFIG_MTD_CFI_AMDSTD=y | ||
40 | CONFIG_MTD_PHYSMAP=y | ||
41 | # CONFIG_BLK_DEV is not set | ||
42 | CONFIG_SCSI=y | ||
43 | CONFIG_BLK_DEV_SD=y | ||
44 | # CONFIG_SCSI_LOWLEVEL is not set | ||
45 | CONFIG_NETDEVICES=y | ||
46 | CONFIG_USB_USBNET=y | ||
47 | # CONFIG_INPUT is not set | ||
48 | # CONFIG_SERIO is not set | ||
49 | # CONFIG_VT is not set | ||
50 | # CONFIG_DEVKMEM is not set | ||
51 | CONFIG_SERIAL_EARLYCON_FORCE=y | ||
52 | CONFIG_SERIAL_BCM63XX=y | ||
53 | CONFIG_SERIAL_BCM63XX_CONSOLE=y | ||
54 | # CONFIG_HW_RANDOM is not set | ||
55 | # CONFIG_HWMON is not set | ||
56 | CONFIG_USB=y | ||
57 | CONFIG_USB_EHCI_HCD=y | ||
58 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set | ||
59 | CONFIG_USB_EHCI_HCD_PLATFORM=y | ||
60 | CONFIG_USB_OHCI_HCD=y | ||
61 | CONFIG_USB_OHCI_HCD_PLATFORM=y | ||
62 | CONFIG_USB_STORAGE=y | ||
63 | CONFIG_EXT4_FS=y | ||
64 | CONFIG_EXT4_FS_POSIX_ACL=y | ||
65 | CONFIG_EXT4_FS_SECURITY=y | ||
66 | # CONFIG_DNOTIFY is not set | ||
67 | CONFIG_FUSE_FS=y | ||
68 | CONFIG_VFAT_FS=y | ||
69 | CONFIG_PROC_KCORE=y | ||
70 | CONFIG_TMPFS=y | ||
71 | CONFIG_NFS_FS=y | ||
72 | CONFIG_CIFS=y | ||
73 | CONFIG_NLS_CODEPAGE_437=y | ||
74 | CONFIG_NLS_ASCII=y | ||
75 | CONFIG_NLS_ISO8859_1=y | ||
76 | CONFIG_DEBUG_FS=y | ||
77 | CONFIG_MAGIC_SYSRQ=y | ||
78 | # CONFIG_CRYPTO_HW is not set | ||
diff --git a/arch/mips/fw/lib/cmdline.c b/arch/mips/fw/lib/cmdline.c index ffd0345780ae..6ecda64ad184 100644 --- a/arch/mips/fw/lib/cmdline.c +++ b/arch/mips/fw/lib/cmdline.c | |||
@@ -68,7 +68,7 @@ char *fw_getenv(char *envname) | |||
68 | result = fw_envp(index + 1); | 68 | result = fw_envp(index + 1); |
69 | break; | 69 | break; |
70 | } else if (fw_envp(index)[i] == '=') { | 70 | } else if (fw_envp(index)[i] == '=') { |
71 | result = (fw_envp(index + 1) + i); | 71 | result = fw_envp(index) + i + 1; |
72 | break; | 72 | break; |
73 | } | 73 | } |
74 | } | 74 | } |
@@ -88,13 +88,13 @@ unsigned long fw_getenvl(char *envname) | |||
88 | { | 88 | { |
89 | unsigned long envl = 0UL; | 89 | unsigned long envl = 0UL; |
90 | char *str; | 90 | char *str; |
91 | long val; | ||
92 | int tmp; | 91 | int tmp; |
93 | 92 | ||
94 | str = fw_getenv(envname); | 93 | str = fw_getenv(envname); |
95 | if (str) { | 94 | if (str) { |
96 | tmp = kstrtol(str, 0, &val); | 95 | tmp = kstrtoul(str, 0, &envl); |
97 | envl = (unsigned long)val; | 96 | if (tmp) |
97 | envl = 0; | ||
98 | } | 98 | } |
99 | 99 | ||
100 | return envl; | 100 | return envl; |
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index 6dd6bfc607e9..857da84cfc92 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/irqflags.h> | 17 | #include <linux/irqflags.h> |
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <asm/barrier.h> | 19 | #include <asm/barrier.h> |
20 | #include <asm/compiler.h> | ||
20 | #include <asm/cpu-features.h> | 21 | #include <asm/cpu-features.h> |
21 | #include <asm/cmpxchg.h> | 22 | #include <asm/cmpxchg.h> |
22 | #include <asm/war.h> | 23 | #include <asm/war.h> |
@@ -40,95 +41,97 @@ | |||
40 | */ | 41 | */ |
41 | #define atomic_set(v, i) ((v)->counter = (i)) | 42 | #define atomic_set(v, i) ((v)->counter = (i)) |
42 | 43 | ||
43 | #define ATOMIC_OP(op, c_op, asm_op) \ | 44 | #define ATOMIC_OP(op, c_op, asm_op) \ |
44 | static __inline__ void atomic_##op(int i, atomic_t * v) \ | 45 | static __inline__ void atomic_##op(int i, atomic_t * v) \ |
45 | { \ | 46 | { \ |
46 | if (kernel_uses_llsc && R10000_LLSC_WAR) { \ | 47 | if (kernel_uses_llsc && R10000_LLSC_WAR) { \ |
47 | int temp; \ | 48 | int temp; \ |
48 | \ | 49 | \ |
49 | __asm__ __volatile__( \ | 50 | __asm__ __volatile__( \ |
50 | " .set arch=r4000 \n" \ | 51 | " .set arch=r4000 \n" \ |
51 | "1: ll %0, %1 # atomic_" #op " \n" \ | 52 | "1: ll %0, %1 # atomic_" #op " \n" \ |
52 | " " #asm_op " %0, %2 \n" \ | 53 | " " #asm_op " %0, %2 \n" \ |
53 | " sc %0, %1 \n" \ | 54 | " sc %0, %1 \n" \ |
54 | " beqzl %0, 1b \n" \ | 55 | " beqzl %0, 1b \n" \ |
55 | " .set mips0 \n" \ | 56 | " .set mips0 \n" \ |
56 | : "=&r" (temp), "+m" (v->counter) \ | 57 | : "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \ |
57 | : "Ir" (i)); \ | 58 | : "Ir" (i)); \ |
58 | } else if (kernel_uses_llsc) { \ | 59 | } else if (kernel_uses_llsc) { \ |
59 | int temp; \ | 60 | int temp; \ |
60 | \ | 61 | \ |
61 | do { \ | 62 | do { \ |
62 | __asm__ __volatile__( \ | 63 | __asm__ __volatile__( \ |
63 | " .set arch=r4000 \n" \ | 64 | " .set arch=r4000 \n" \ |
64 | " ll %0, %1 # atomic_" #op "\n" \ | 65 | " ll %0, %1 # atomic_" #op "\n" \ |
65 | " " #asm_op " %0, %2 \n" \ | 66 | " " #asm_op " %0, %2 \n" \ |
66 | " sc %0, %1 \n" \ | 67 | " sc %0, %1 \n" \ |
67 | " .set mips0 \n" \ | 68 | " .set mips0 \n" \ |
68 | : "=&r" (temp), "+m" (v->counter) \ | 69 | : "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \ |
69 | : "Ir" (i)); \ | 70 | : "Ir" (i)); \ |
70 | } while (unlikely(!temp)); \ | 71 | } while (unlikely(!temp)); \ |
71 | } else { \ | 72 | } else { \ |
72 | unsigned long flags; \ | 73 | unsigned long flags; \ |
73 | \ | 74 | \ |
74 | raw_local_irq_save(flags); \ | 75 | raw_local_irq_save(flags); \ |
75 | v->counter c_op i; \ | 76 | v->counter c_op i; \ |
76 | raw_local_irq_restore(flags); \ | 77 | raw_local_irq_restore(flags); \ |
77 | } \ | 78 | } \ |
78 | } \ | ||
79 | |||
80 | #define ATOMIC_OP_RETURN(op, c_op, asm_op) \ | ||
81 | static __inline__ int atomic_##op##_return(int i, atomic_t * v) \ | ||
82 | { \ | ||
83 | int result; \ | ||
84 | \ | ||
85 | smp_mb__before_llsc(); \ | ||
86 | \ | ||
87 | if (kernel_uses_llsc && R10000_LLSC_WAR) { \ | ||
88 | int temp; \ | ||
89 | \ | ||
90 | __asm__ __volatile__( \ | ||
91 | " .set arch=r4000 \n" \ | ||
92 | "1: ll %1, %2 # atomic_" #op "_return \n" \ | ||
93 | " " #asm_op " %0, %1, %3 \n" \ | ||
94 | " sc %0, %2 \n" \ | ||
95 | " beqzl %0, 1b \n" \ | ||
96 | " " #asm_op " %0, %1, %3 \n" \ | ||
97 | " .set mips0 \n" \ | ||
98 | : "=&r" (result), "=&r" (temp), "+m" (v->counter) \ | ||
99 | : "Ir" (i)); \ | ||
100 | } else if (kernel_uses_llsc) { \ | ||
101 | int temp; \ | ||
102 | \ | ||
103 | do { \ | ||
104 | __asm__ __volatile__( \ | ||
105 | " .set arch=r4000 \n" \ | ||
106 | " ll %1, %2 # atomic_" #op "_return \n" \ | ||
107 | " " #asm_op " %0, %1, %3 \n" \ | ||
108 | " sc %0, %2 \n" \ | ||
109 | " .set mips0 \n" \ | ||
110 | : "=&r" (result), "=&r" (temp), "+m" (v->counter) \ | ||
111 | : "Ir" (i)); \ | ||
112 | } while (unlikely(!result)); \ | ||
113 | \ | ||
114 | result = temp; result c_op i; \ | ||
115 | } else { \ | ||
116 | unsigned long flags; \ | ||
117 | \ | ||
118 | raw_local_irq_save(flags); \ | ||
119 | result = v->counter; \ | ||
120 | result c_op i; \ | ||
121 | v->counter = result; \ | ||
122 | raw_local_irq_restore(flags); \ | ||
123 | } \ | ||
124 | \ | ||
125 | smp_llsc_mb(); \ | ||
126 | \ | ||
127 | return result; \ | ||
128 | } | 79 | } |
129 | 80 | ||
130 | #define ATOMIC_OPS(op, c_op, asm_op) \ | 81 | #define ATOMIC_OP_RETURN(op, c_op, asm_op) \ |
131 | ATOMIC_OP(op, c_op, asm_op) \ | 82 | static __inline__ int atomic_##op##_return(int i, atomic_t * v) \ |
83 | { \ | ||
84 | int result; \ | ||
85 | \ | ||
86 | smp_mb__before_llsc(); \ | ||
87 | \ | ||
88 | if (kernel_uses_llsc && R10000_LLSC_WAR) { \ | ||
89 | int temp; \ | ||
90 | \ | ||
91 | __asm__ __volatile__( \ | ||
92 | " .set arch=r4000 \n" \ | ||
93 | "1: ll %1, %2 # atomic_" #op "_return \n" \ | ||
94 | " " #asm_op " %0, %1, %3 \n" \ | ||
95 | " sc %0, %2 \n" \ | ||
96 | " beqzl %0, 1b \n" \ | ||
97 | " " #asm_op " %0, %1, %3 \n" \ | ||
98 | " .set mips0 \n" \ | ||
99 | : "=&r" (result), "=&r" (temp), \ | ||
100 | "+" GCC_OFF12_ASM() (v->counter) \ | ||
101 | : "Ir" (i)); \ | ||
102 | } else if (kernel_uses_llsc) { \ | ||
103 | int temp; \ | ||
104 | \ | ||
105 | do { \ | ||
106 | __asm__ __volatile__( \ | ||
107 | " .set arch=r4000 \n" \ | ||
108 | " ll %1, %2 # atomic_" #op "_return \n" \ | ||
109 | " " #asm_op " %0, %1, %3 \n" \ | ||
110 | " sc %0, %2 \n" \ | ||
111 | " .set mips0 \n" \ | ||
112 | : "=&r" (result), "=&r" (temp), \ | ||
113 | "+" GCC_OFF12_ASM() (v->counter) \ | ||
114 | : "Ir" (i)); \ | ||
115 | } while (unlikely(!result)); \ | ||
116 | \ | ||
117 | result = temp; result c_op i; \ | ||
118 | } else { \ | ||
119 | unsigned long flags; \ | ||
120 | \ | ||
121 | raw_local_irq_save(flags); \ | ||
122 | result = v->counter; \ | ||
123 | result c_op i; \ | ||
124 | v->counter = result; \ | ||
125 | raw_local_irq_restore(flags); \ | ||
126 | } \ | ||
127 | \ | ||
128 | smp_llsc_mb(); \ | ||
129 | \ | ||
130 | return result; \ | ||
131 | } | ||
132 | |||
133 | #define ATOMIC_OPS(op, c_op, asm_op) \ | ||
134 | ATOMIC_OP(op, c_op, asm_op) \ | ||
132 | ATOMIC_OP_RETURN(op, c_op, asm_op) | 135 | ATOMIC_OP_RETURN(op, c_op, asm_op) |
133 | 136 | ||
134 | ATOMIC_OPS(add, +=, addu) | 137 | ATOMIC_OPS(add, +=, addu) |
@@ -167,8 +170,9 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) | |||
167 | " .set reorder \n" | 170 | " .set reorder \n" |
168 | "1: \n" | 171 | "1: \n" |
169 | " .set mips0 \n" | 172 | " .set mips0 \n" |
170 | : "=&r" (result), "=&r" (temp), "+m" (v->counter) | 173 | : "=&r" (result), "=&r" (temp), |
171 | : "Ir" (i), "m" (v->counter) | 174 | "+" GCC_OFF12_ASM() (v->counter) |
175 | : "Ir" (i), GCC_OFF12_ASM() (v->counter) | ||
172 | : "memory"); | 176 | : "memory"); |
173 | } else if (kernel_uses_llsc) { | 177 | } else if (kernel_uses_llsc) { |
174 | int temp; | 178 | int temp; |
@@ -185,7 +189,8 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) | |||
185 | " .set reorder \n" | 189 | " .set reorder \n" |
186 | "1: \n" | 190 | "1: \n" |
187 | " .set mips0 \n" | 191 | " .set mips0 \n" |
188 | : "=&r" (result), "=&r" (temp), "+m" (v->counter) | 192 | : "=&r" (result), "=&r" (temp), |
193 | "+" GCC_OFF12_ASM() (v->counter) | ||
189 | : "Ir" (i)); | 194 | : "Ir" (i)); |
190 | } else { | 195 | } else { |
191 | unsigned long flags; | 196 | unsigned long flags; |
@@ -315,96 +320,98 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) | |||
315 | */ | 320 | */ |
316 | #define atomic64_set(v, i) ((v)->counter = (i)) | 321 | #define atomic64_set(v, i) ((v)->counter = (i)) |
317 | 322 | ||
318 | #define ATOMIC64_OP(op, c_op, asm_op) \ | 323 | #define ATOMIC64_OP(op, c_op, asm_op) \ |
319 | static __inline__ void atomic64_##op(long i, atomic64_t * v) \ | 324 | static __inline__ void atomic64_##op(long i, atomic64_t * v) \ |
320 | { \ | 325 | { \ |
321 | if (kernel_uses_llsc && R10000_LLSC_WAR) { \ | 326 | if (kernel_uses_llsc && R10000_LLSC_WAR) { \ |
322 | long temp; \ | 327 | long temp; \ |
323 | \ | 328 | \ |
324 | __asm__ __volatile__( \ | 329 | __asm__ __volatile__( \ |
325 | " .set arch=r4000 \n" \ | 330 | " .set arch=r4000 \n" \ |
326 | "1: lld %0, %1 # atomic64_" #op " \n" \ | 331 | "1: lld %0, %1 # atomic64_" #op " \n" \ |
327 | " " #asm_op " %0, %2 \n" \ | 332 | " " #asm_op " %0, %2 \n" \ |
328 | " scd %0, %1 \n" \ | 333 | " scd %0, %1 \n" \ |
329 | " beqzl %0, 1b \n" \ | 334 | " beqzl %0, 1b \n" \ |
330 | " .set mips0 \n" \ | 335 | " .set mips0 \n" \ |
331 | : "=&r" (temp), "+m" (v->counter) \ | 336 | : "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \ |
332 | : "Ir" (i)); \ | 337 | : "Ir" (i)); \ |
333 | } else if (kernel_uses_llsc) { \ | 338 | } else if (kernel_uses_llsc) { \ |
334 | long temp; \ | 339 | long temp; \ |
335 | \ | 340 | \ |
336 | do { \ | 341 | do { \ |
337 | __asm__ __volatile__( \ | 342 | __asm__ __volatile__( \ |
338 | " .set arch=r4000 \n" \ | 343 | " .set arch=r4000 \n" \ |
339 | " lld %0, %1 # atomic64_" #op "\n" \ | 344 | " lld %0, %1 # atomic64_" #op "\n" \ |
340 | " " #asm_op " %0, %2 \n" \ | 345 | " " #asm_op " %0, %2 \n" \ |
341 | " scd %0, %1 \n" \ | 346 | " scd %0, %1 \n" \ |
342 | " .set mips0 \n" \ | 347 | " .set mips0 \n" \ |
343 | : "=&r" (temp), "+m" (v->counter) \ | 348 | : "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \ |
344 | : "Ir" (i)); \ | 349 | : "Ir" (i)); \ |
345 | } while (unlikely(!temp)); \ | 350 | } while (unlikely(!temp)); \ |
346 | } else { \ | 351 | } else { \ |
347 | unsigned long flags; \ | 352 | unsigned long flags; \ |
348 | \ | 353 | \ |
349 | raw_local_irq_save(flags); \ | 354 | raw_local_irq_save(flags); \ |
350 | v->counter c_op i; \ | 355 | v->counter c_op i; \ |
351 | raw_local_irq_restore(flags); \ | 356 | raw_local_irq_restore(flags); \ |
352 | } \ | 357 | } \ |
353 | } \ | 358 | } |
354 | 359 | ||
355 | #define ATOMIC64_OP_RETURN(op, c_op, asm_op) \ | 360 | #define ATOMIC64_OP_RETURN(op, c_op, asm_op) \ |
356 | static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \ | 361 | static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \ |
357 | { \ | 362 | { \ |
358 | long result; \ | 363 | long result; \ |
359 | \ | 364 | \ |
360 | smp_mb__before_llsc(); \ | 365 | smp_mb__before_llsc(); \ |
361 | \ | 366 | \ |
362 | if (kernel_uses_llsc && R10000_LLSC_WAR) { \ | 367 | if (kernel_uses_llsc && R10000_LLSC_WAR) { \ |
363 | long temp; \ | 368 | long temp; \ |
364 | \ | 369 | \ |
365 | __asm__ __volatile__( \ | 370 | __asm__ __volatile__( \ |
366 | " .set arch=r4000 \n" \ | 371 | " .set arch=r4000 \n" \ |
367 | "1: lld %1, %2 # atomic64_" #op "_return\n" \ | 372 | "1: lld %1, %2 # atomic64_" #op "_return\n" \ |
368 | " " #asm_op " %0, %1, %3 \n" \ | 373 | " " #asm_op " %0, %1, %3 \n" \ |
369 | " scd %0, %2 \n" \ | 374 | " scd %0, %2 \n" \ |
370 | " beqzl %0, 1b \n" \ | 375 | " beqzl %0, 1b \n" \ |
371 | " " #asm_op " %0, %1, %3 \n" \ | 376 | " " #asm_op " %0, %1, %3 \n" \ |
372 | " .set mips0 \n" \ | 377 | " .set mips0 \n" \ |
373 | : "=&r" (result), "=&r" (temp), "+m" (v->counter) \ | 378 | : "=&r" (result), "=&r" (temp), \ |
374 | : "Ir" (i)); \ | 379 | "+" GCC_OFF12_ASM() (v->counter) \ |
375 | } else if (kernel_uses_llsc) { \ | 380 | : "Ir" (i)); \ |
376 | long temp; \ | 381 | } else if (kernel_uses_llsc) { \ |
377 | \ | 382 | long temp; \ |
378 | do { \ | 383 | \ |
379 | __asm__ __volatile__( \ | 384 | do { \ |
380 | " .set arch=r4000 \n" \ | 385 | __asm__ __volatile__( \ |
381 | " lld %1, %2 # atomic64_" #op "_return\n" \ | 386 | " .set arch=r4000 \n" \ |
382 | " " #asm_op " %0, %1, %3 \n" \ | 387 | " lld %1, %2 # atomic64_" #op "_return\n" \ |
383 | " scd %0, %2 \n" \ | 388 | " " #asm_op " %0, %1, %3 \n" \ |
384 | " .set mips0 \n" \ | 389 | " scd %0, %2 \n" \ |
385 | : "=&r" (result), "=&r" (temp), "=m" (v->counter) \ | 390 | " .set mips0 \n" \ |
386 | : "Ir" (i), "m" (v->counter) \ | 391 | : "=&r" (result), "=&r" (temp), \ |
387 | : "memory"); \ | 392 | "=" GCC_OFF12_ASM() (v->counter) \ |
388 | } while (unlikely(!result)); \ | 393 | : "Ir" (i), GCC_OFF12_ASM() (v->counter) \ |
389 | \ | 394 | : "memory"); \ |
390 | result = temp; result c_op i; \ | 395 | } while (unlikely(!result)); \ |
391 | } else { \ | 396 | \ |
392 | unsigned long flags; \ | 397 | result = temp; result c_op i; \ |
393 | \ | 398 | } else { \ |
394 | raw_local_irq_save(flags); \ | 399 | unsigned long flags; \ |
395 | result = v->counter; \ | 400 | \ |
396 | result c_op i; \ | 401 | raw_local_irq_save(flags); \ |
397 | v->counter = result; \ | 402 | result = v->counter; \ |
398 | raw_local_irq_restore(flags); \ | 403 | result c_op i; \ |
399 | } \ | 404 | v->counter = result; \ |
400 | \ | 405 | raw_local_irq_restore(flags); \ |
401 | smp_llsc_mb(); \ | 406 | } \ |
402 | \ | 407 | \ |
403 | return result; \ | 408 | smp_llsc_mb(); \ |
409 | \ | ||
410 | return result; \ | ||
404 | } | 411 | } |
405 | 412 | ||
406 | #define ATOMIC64_OPS(op, c_op, asm_op) \ | 413 | #define ATOMIC64_OPS(op, c_op, asm_op) \ |
407 | ATOMIC64_OP(op, c_op, asm_op) \ | 414 | ATOMIC64_OP(op, c_op, asm_op) \ |
408 | ATOMIC64_OP_RETURN(op, c_op, asm_op) | 415 | ATOMIC64_OP_RETURN(op, c_op, asm_op) |
409 | 416 | ||
410 | ATOMIC64_OPS(add, +=, daddu) | 417 | ATOMIC64_OPS(add, +=, daddu) |
@@ -415,7 +422,8 @@ ATOMIC64_OPS(sub, -=, dsubu) | |||
415 | #undef ATOMIC64_OP | 422 | #undef ATOMIC64_OP |
416 | 423 | ||
417 | /* | 424 | /* |
418 | * atomic64_sub_if_positive - conditionally subtract integer from atomic variable | 425 | * atomic64_sub_if_positive - conditionally subtract integer from atomic |
426 | * variable | ||
419 | * @i: integer value to subtract | 427 | * @i: integer value to subtract |
420 | * @v: pointer of type atomic64_t | 428 | * @v: pointer of type atomic64_t |
421 | * | 429 | * |
@@ -443,8 +451,9 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) | |||
443 | " .set reorder \n" | 451 | " .set reorder \n" |
444 | "1: \n" | 452 | "1: \n" |
445 | " .set mips0 \n" | 453 | " .set mips0 \n" |
446 | : "=&r" (result), "=&r" (temp), "=m" (v->counter) | 454 | : "=&r" (result), "=&r" (temp), |
447 | : "Ir" (i), "m" (v->counter) | 455 | "=" GCC_OFF12_ASM() (v->counter) |
456 | : "Ir" (i), GCC_OFF12_ASM() (v->counter) | ||
448 | : "memory"); | 457 | : "memory"); |
449 | } else if (kernel_uses_llsc) { | 458 | } else if (kernel_uses_llsc) { |
450 | long temp; | 459 | long temp; |
@@ -461,7 +470,8 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) | |||
461 | " .set reorder \n" | 470 | " .set reorder \n" |
462 | "1: \n" | 471 | "1: \n" |
463 | " .set mips0 \n" | 472 | " .set mips0 \n" |
464 | : "=&r" (result), "=&r" (temp), "+m" (v->counter) | 473 | : "=&r" (result), "=&r" (temp), |
474 | "+" GCC_OFF12_ASM() (v->counter) | ||
465 | : "Ir" (i)); | 475 | : "Ir" (i)); |
466 | } else { | 476 | } else { |
467 | unsigned long flags; | 477 | unsigned long flags; |
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index bae6b0fa8ab5..6663bcca9d0c 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <asm/barrier.h> | 18 | #include <asm/barrier.h> |
19 | #include <asm/byteorder.h> /* sigh ... */ | 19 | #include <asm/byteorder.h> /* sigh ... */ |
20 | #include <asm/compiler.h> | ||
20 | #include <asm/cpu-features.h> | 21 | #include <asm/cpu-features.h> |
21 | #include <asm/sgidefs.h> | 22 | #include <asm/sgidefs.h> |
22 | #include <asm/war.h> | 23 | #include <asm/war.h> |
@@ -78,8 +79,8 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) | |||
78 | " " __SC "%0, %1 \n" | 79 | " " __SC "%0, %1 \n" |
79 | " beqzl %0, 1b \n" | 80 | " beqzl %0, 1b \n" |
80 | " .set mips0 \n" | 81 | " .set mips0 \n" |
81 | : "=&r" (temp), "=m" (*m) | 82 | : "=&r" (temp), "=" GCC_OFF12_ASM() (*m) |
82 | : "ir" (1UL << bit), "m" (*m)); | 83 | : "ir" (1UL << bit), GCC_OFF12_ASM() (*m)); |
83 | #ifdef CONFIG_CPU_MIPSR2 | 84 | #ifdef CONFIG_CPU_MIPSR2 |
84 | } else if (kernel_uses_llsc && __builtin_constant_p(bit)) { | 85 | } else if (kernel_uses_llsc && __builtin_constant_p(bit)) { |
85 | do { | 86 | do { |
@@ -87,7 +88,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) | |||
87 | " " __LL "%0, %1 # set_bit \n" | 88 | " " __LL "%0, %1 # set_bit \n" |
88 | " " __INS "%0, %3, %2, 1 \n" | 89 | " " __INS "%0, %3, %2, 1 \n" |
89 | " " __SC "%0, %1 \n" | 90 | " " __SC "%0, %1 \n" |
90 | : "=&r" (temp), "+m" (*m) | 91 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m) |
91 | : "ir" (bit), "r" (~0)); | 92 | : "ir" (bit), "r" (~0)); |
92 | } while (unlikely(!temp)); | 93 | } while (unlikely(!temp)); |
93 | #endif /* CONFIG_CPU_MIPSR2 */ | 94 | #endif /* CONFIG_CPU_MIPSR2 */ |
@@ -99,7 +100,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) | |||
99 | " or %0, %2 \n" | 100 | " or %0, %2 \n" |
100 | " " __SC "%0, %1 \n" | 101 | " " __SC "%0, %1 \n" |
101 | " .set mips0 \n" | 102 | " .set mips0 \n" |
102 | : "=&r" (temp), "+m" (*m) | 103 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m) |
103 | : "ir" (1UL << bit)); | 104 | : "ir" (1UL << bit)); |
104 | } while (unlikely(!temp)); | 105 | } while (unlikely(!temp)); |
105 | } else | 106 | } else |
@@ -130,7 +131,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) | |||
130 | " " __SC "%0, %1 \n" | 131 | " " __SC "%0, %1 \n" |
131 | " beqzl %0, 1b \n" | 132 | " beqzl %0, 1b \n" |
132 | " .set mips0 \n" | 133 | " .set mips0 \n" |
133 | : "=&r" (temp), "+m" (*m) | 134 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m) |
134 | : "ir" (~(1UL << bit))); | 135 | : "ir" (~(1UL << bit))); |
135 | #ifdef CONFIG_CPU_MIPSR2 | 136 | #ifdef CONFIG_CPU_MIPSR2 |
136 | } else if (kernel_uses_llsc && __builtin_constant_p(bit)) { | 137 | } else if (kernel_uses_llsc && __builtin_constant_p(bit)) { |
@@ -139,7 +140,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) | |||
139 | " " __LL "%0, %1 # clear_bit \n" | 140 | " " __LL "%0, %1 # clear_bit \n" |
140 | " " __INS "%0, $0, %2, 1 \n" | 141 | " " __INS "%0, $0, %2, 1 \n" |
141 | " " __SC "%0, %1 \n" | 142 | " " __SC "%0, %1 \n" |
142 | : "=&r" (temp), "+m" (*m) | 143 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m) |
143 | : "ir" (bit)); | 144 | : "ir" (bit)); |
144 | } while (unlikely(!temp)); | 145 | } while (unlikely(!temp)); |
145 | #endif /* CONFIG_CPU_MIPSR2 */ | 146 | #endif /* CONFIG_CPU_MIPSR2 */ |
@@ -151,7 +152,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) | |||
151 | " and %0, %2 \n" | 152 | " and %0, %2 \n" |
152 | " " __SC "%0, %1 \n" | 153 | " " __SC "%0, %1 \n" |
153 | " .set mips0 \n" | 154 | " .set mips0 \n" |
154 | : "=&r" (temp), "+m" (*m) | 155 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m) |
155 | : "ir" (~(1UL << bit))); | 156 | : "ir" (~(1UL << bit))); |
156 | } while (unlikely(!temp)); | 157 | } while (unlikely(!temp)); |
157 | } else | 158 | } else |
@@ -196,7 +197,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) | |||
196 | " " __SC "%0, %1 \n" | 197 | " " __SC "%0, %1 \n" |
197 | " beqzl %0, 1b \n" | 198 | " beqzl %0, 1b \n" |
198 | " .set mips0 \n" | 199 | " .set mips0 \n" |
199 | : "=&r" (temp), "+m" (*m) | 200 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m) |
200 | : "ir" (1UL << bit)); | 201 | : "ir" (1UL << bit)); |
201 | } else if (kernel_uses_llsc) { | 202 | } else if (kernel_uses_llsc) { |
202 | unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); | 203 | unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); |
@@ -209,7 +210,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) | |||
209 | " xor %0, %2 \n" | 210 | " xor %0, %2 \n" |
210 | " " __SC "%0, %1 \n" | 211 | " " __SC "%0, %1 \n" |
211 | " .set mips0 \n" | 212 | " .set mips0 \n" |
212 | : "=&r" (temp), "+m" (*m) | 213 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m) |
213 | : "ir" (1UL << bit)); | 214 | : "ir" (1UL << bit)); |
214 | } while (unlikely(!temp)); | 215 | } while (unlikely(!temp)); |
215 | } else | 216 | } else |
@@ -244,7 +245,7 @@ static inline int test_and_set_bit(unsigned long nr, | |||
244 | " beqzl %2, 1b \n" | 245 | " beqzl %2, 1b \n" |
245 | " and %2, %0, %3 \n" | 246 | " and %2, %0, %3 \n" |
246 | " .set mips0 \n" | 247 | " .set mips0 \n" |
247 | : "=&r" (temp), "+m" (*m), "=&r" (res) | 248 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res) |
248 | : "r" (1UL << bit) | 249 | : "r" (1UL << bit) |
249 | : "memory"); | 250 | : "memory"); |
250 | } else if (kernel_uses_llsc) { | 251 | } else if (kernel_uses_llsc) { |
@@ -258,7 +259,7 @@ static inline int test_and_set_bit(unsigned long nr, | |||
258 | " or %2, %0, %3 \n" | 259 | " or %2, %0, %3 \n" |
259 | " " __SC "%2, %1 \n" | 260 | " " __SC "%2, %1 \n" |
260 | " .set mips0 \n" | 261 | " .set mips0 \n" |
261 | : "=&r" (temp), "+m" (*m), "=&r" (res) | 262 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res) |
262 | : "r" (1UL << bit) | 263 | : "r" (1UL << bit) |
263 | : "memory"); | 264 | : "memory"); |
264 | } while (unlikely(!res)); | 265 | } while (unlikely(!res)); |
@@ -312,7 +313,7 @@ static inline int test_and_set_bit_lock(unsigned long nr, | |||
312 | " or %2, %0, %3 \n" | 313 | " or %2, %0, %3 \n" |
313 | " " __SC "%2, %1 \n" | 314 | " " __SC "%2, %1 \n" |
314 | " .set mips0 \n" | 315 | " .set mips0 \n" |
315 | : "=&r" (temp), "+m" (*m), "=&r" (res) | 316 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res) |
316 | : "r" (1UL << bit) | 317 | : "r" (1UL << bit) |
317 | : "memory"); | 318 | : "memory"); |
318 | } while (unlikely(!res)); | 319 | } while (unlikely(!res)); |
@@ -354,7 +355,7 @@ static inline int test_and_clear_bit(unsigned long nr, | |||
354 | " beqzl %2, 1b \n" | 355 | " beqzl %2, 1b \n" |
355 | " and %2, %0, %3 \n" | 356 | " and %2, %0, %3 \n" |
356 | " .set mips0 \n" | 357 | " .set mips0 \n" |
357 | : "=&r" (temp), "+m" (*m), "=&r" (res) | 358 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res) |
358 | : "r" (1UL << bit) | 359 | : "r" (1UL << bit) |
359 | : "memory"); | 360 | : "memory"); |
360 | #ifdef CONFIG_CPU_MIPSR2 | 361 | #ifdef CONFIG_CPU_MIPSR2 |
@@ -368,7 +369,7 @@ static inline int test_and_clear_bit(unsigned long nr, | |||
368 | " " __EXT "%2, %0, %3, 1 \n" | 369 | " " __EXT "%2, %0, %3, 1 \n" |
369 | " " __INS "%0, $0, %3, 1 \n" | 370 | " " __INS "%0, $0, %3, 1 \n" |
370 | " " __SC "%0, %1 \n" | 371 | " " __SC "%0, %1 \n" |
371 | : "=&r" (temp), "+m" (*m), "=&r" (res) | 372 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res) |
372 | : "ir" (bit) | 373 | : "ir" (bit) |
373 | : "memory"); | 374 | : "memory"); |
374 | } while (unlikely(!temp)); | 375 | } while (unlikely(!temp)); |
@@ -385,7 +386,7 @@ static inline int test_and_clear_bit(unsigned long nr, | |||
385 | " xor %2, %3 \n" | 386 | " xor %2, %3 \n" |
386 | " " __SC "%2, %1 \n" | 387 | " " __SC "%2, %1 \n" |
387 | " .set mips0 \n" | 388 | " .set mips0 \n" |
388 | : "=&r" (temp), "+m" (*m), "=&r" (res) | 389 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res) |
389 | : "r" (1UL << bit) | 390 | : "r" (1UL << bit) |
390 | : "memory"); | 391 | : "memory"); |
391 | } while (unlikely(!res)); | 392 | } while (unlikely(!res)); |
@@ -427,7 +428,7 @@ static inline int test_and_change_bit(unsigned long nr, | |||
427 | " beqzl %2, 1b \n" | 428 | " beqzl %2, 1b \n" |
428 | " and %2, %0, %3 \n" | 429 | " and %2, %0, %3 \n" |
429 | " .set mips0 \n" | 430 | " .set mips0 \n" |
430 | : "=&r" (temp), "+m" (*m), "=&r" (res) | 431 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res) |
431 | : "r" (1UL << bit) | 432 | : "r" (1UL << bit) |
432 | : "memory"); | 433 | : "memory"); |
433 | } else if (kernel_uses_llsc) { | 434 | } else if (kernel_uses_llsc) { |
@@ -441,7 +442,7 @@ static inline int test_and_change_bit(unsigned long nr, | |||
441 | " xor %2, %0, %3 \n" | 442 | " xor %2, %0, %3 \n" |
442 | " " __SC "\t%2, %1 \n" | 443 | " " __SC "\t%2, %1 \n" |
443 | " .set mips0 \n" | 444 | " .set mips0 \n" |
444 | : "=&r" (temp), "+m" (*m), "=&r" (res) | 445 | : "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res) |
445 | : "r" (1UL << bit) | 446 | : "r" (1UL << bit) |
446 | : "memory"); | 447 | : "memory"); |
447 | } while (unlikely(!res)); | 448 | } while (unlikely(!res)); |
diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h index cbaccebf5065..30939b02e3ff 100644 --- a/arch/mips/include/asm/bmips.h +++ b/arch/mips/include/asm/bmips.h | |||
@@ -84,6 +84,7 @@ extern char bmips_smp_int_vec_end; | |||
84 | extern int bmips_smp_enabled; | 84 | extern int bmips_smp_enabled; |
85 | extern int bmips_cpu_offset; | 85 | extern int bmips_cpu_offset; |
86 | extern cpumask_t bmips_booted_mask; | 86 | extern cpumask_t bmips_booted_mask; |
87 | extern unsigned long bmips_tp1_irqs; | ||
87 | 88 | ||
88 | extern void bmips_ebase_setup(void); | 89 | extern void bmips_ebase_setup(void); |
89 | extern asmlinkage void plat_wired_tlb_setup(void); | 90 | extern asmlinkage void plat_wired_tlb_setup(void); |
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h index 1f7ca8b00404..b603804caac5 100644 --- a/arch/mips/include/asm/bootinfo.h +++ b/arch/mips/include/asm/bootinfo.h | |||
@@ -70,10 +70,7 @@ enum loongson_machine_type { | |||
70 | MACH_DEXXON_GDIUM2F10, | 70 | MACH_DEXXON_GDIUM2F10, |
71 | MACH_LEMOTE_NAS, | 71 | MACH_LEMOTE_NAS, |
72 | MACH_LEMOTE_LL2F, | 72 | MACH_LEMOTE_LL2F, |
73 | MACH_LEMOTE_A1004, | 73 | MACH_LOONGSON_GENERIC, |
74 | MACH_LEMOTE_A1101, | ||
75 | MACH_LEMOTE_A1201, | ||
76 | MACH_LEMOTE_A1205, | ||
77 | MACH_LOONGSON_END | 74 | MACH_LOONGSON_END |
78 | }; | 75 | }; |
79 | 76 | ||
@@ -101,16 +98,16 @@ extern unsigned long mips_machtype; | |||
101 | struct boot_mem_map { | 98 | struct boot_mem_map { |
102 | int nr_map; | 99 | int nr_map; |
103 | struct boot_mem_map_entry { | 100 | struct boot_mem_map_entry { |
104 | phys_t addr; /* start of memory segment */ | 101 | phys_addr_t addr; /* start of memory segment */ |
105 | phys_t size; /* size of memory segment */ | 102 | phys_addr_t size; /* size of memory segment */ |
106 | long type; /* type of memory segment */ | 103 | long type; /* type of memory segment */ |
107 | } map[BOOT_MEM_MAP_MAX]; | 104 | } map[BOOT_MEM_MAP_MAX]; |
108 | }; | 105 | }; |
109 | 106 | ||
110 | extern struct boot_mem_map boot_mem_map; | 107 | extern struct boot_mem_map boot_mem_map; |
111 | 108 | ||
112 | extern void add_memory_region(phys_t start, phys_t size, long type); | 109 | extern void add_memory_region(phys_addr_t start, phys_addr_t size, long type); |
113 | extern void detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max); | 110 | extern void detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_addr_t sz_max); |
114 | 111 | ||
115 | extern void prom_init(void); | 112 | extern void prom_init(void); |
116 | extern void prom_free_prom_memory(void); | 113 | extern void prom_free_prom_memory(void); |
diff --git a/arch/mips/include/asm/clock.h b/arch/mips/include/asm/clock.h index 778e32d817bc..4809c29a4890 100644 --- a/arch/mips/include/asm/clock.h +++ b/arch/mips/include/asm/clock.h | |||
@@ -35,9 +35,6 @@ struct clk { | |||
35 | #define CLK_ALWAYS_ENABLED (1 << 0) | 35 | #define CLK_ALWAYS_ENABLED (1 << 0) |
36 | #define CLK_RATE_PROPAGATES (1 << 1) | 36 | #define CLK_RATE_PROPAGATES (1 << 1) |
37 | 37 | ||
38 | /* Should be defined by processor-specific code */ | ||
39 | void arch_init_clk_ops(struct clk_ops **, int type); | ||
40 | |||
41 | int clk_init(void); | 38 | int clk_init(void); |
42 | 39 | ||
43 | int __clk_enable(struct clk *); | 40 | int __clk_enable(struct clk *); |
diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h index eefcaa363a87..28b1edf19501 100644 --- a/arch/mips/include/asm/cmpxchg.h +++ b/arch/mips/include/asm/cmpxchg.h | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/bug.h> | 11 | #include <linux/bug.h> |
12 | #include <linux/irqflags.h> | 12 | #include <linux/irqflags.h> |
13 | #include <asm/compiler.h> | ||
13 | #include <asm/war.h> | 14 | #include <asm/war.h> |
14 | 15 | ||
15 | static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) | 16 | static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) |
@@ -30,8 +31,8 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) | |||
30 | " sc %2, %1 \n" | 31 | " sc %2, %1 \n" |
31 | " beqzl %2, 1b \n" | 32 | " beqzl %2, 1b \n" |
32 | " .set mips0 \n" | 33 | " .set mips0 \n" |
33 | : "=&r" (retval), "=m" (*m), "=&r" (dummy) | 34 | : "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy) |
34 | : "R" (*m), "Jr" (val) | 35 | : GCC_OFF12_ASM() (*m), "Jr" (val) |
35 | : "memory"); | 36 | : "memory"); |
36 | } else if (kernel_uses_llsc) { | 37 | } else if (kernel_uses_llsc) { |
37 | unsigned long dummy; | 38 | unsigned long dummy; |
@@ -45,8 +46,9 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) | |||
45 | " .set arch=r4000 \n" | 46 | " .set arch=r4000 \n" |
46 | " sc %2, %1 \n" | 47 | " sc %2, %1 \n" |
47 | " .set mips0 \n" | 48 | " .set mips0 \n" |
48 | : "=&r" (retval), "=m" (*m), "=&r" (dummy) | 49 | : "=&r" (retval), "=" GCC_OFF12_ASM() (*m), |
49 | : "R" (*m), "Jr" (val) | 50 | "=&r" (dummy) |
51 | : GCC_OFF12_ASM() (*m), "Jr" (val) | ||
50 | : "memory"); | 52 | : "memory"); |
51 | } while (unlikely(!dummy)); | 53 | } while (unlikely(!dummy)); |
52 | } else { | 54 | } else { |
@@ -80,8 +82,8 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val) | |||
80 | " scd %2, %1 \n" | 82 | " scd %2, %1 \n" |
81 | " beqzl %2, 1b \n" | 83 | " beqzl %2, 1b \n" |
82 | " .set mips0 \n" | 84 | " .set mips0 \n" |
83 | : "=&r" (retval), "=m" (*m), "=&r" (dummy) | 85 | : "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy) |
84 | : "R" (*m), "Jr" (val) | 86 | : GCC_OFF12_ASM() (*m), "Jr" (val) |
85 | : "memory"); | 87 | : "memory"); |
86 | } else if (kernel_uses_llsc) { | 88 | } else if (kernel_uses_llsc) { |
87 | unsigned long dummy; | 89 | unsigned long dummy; |
@@ -93,8 +95,9 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val) | |||
93 | " move %2, %z4 \n" | 95 | " move %2, %z4 \n" |
94 | " scd %2, %1 \n" | 96 | " scd %2, %1 \n" |
95 | " .set mips0 \n" | 97 | " .set mips0 \n" |
96 | : "=&r" (retval), "=m" (*m), "=&r" (dummy) | 98 | : "=&r" (retval), "=" GCC_OFF12_ASM() (*m), |
97 | : "R" (*m), "Jr" (val) | 99 | "=&r" (dummy) |
100 | : GCC_OFF12_ASM() (*m), "Jr" (val) | ||
98 | : "memory"); | 101 | : "memory"); |
99 | } while (unlikely(!dummy)); | 102 | } while (unlikely(!dummy)); |
100 | } else { | 103 | } else { |
@@ -155,8 +158,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz | |||
155 | " beqzl $1, 1b \n" \ | 158 | " beqzl $1, 1b \n" \ |
156 | "2: \n" \ | 159 | "2: \n" \ |
157 | " .set pop \n" \ | 160 | " .set pop \n" \ |
158 | : "=&r" (__ret), "=R" (*m) \ | 161 | : "=&r" (__ret), "=" GCC_OFF12_ASM() (*m) \ |
159 | : "R" (*m), "Jr" (old), "Jr" (new) \ | 162 | : GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new) \ |
160 | : "memory"); \ | 163 | : "memory"); \ |
161 | } else if (kernel_uses_llsc) { \ | 164 | } else if (kernel_uses_llsc) { \ |
162 | __asm__ __volatile__( \ | 165 | __asm__ __volatile__( \ |
@@ -172,8 +175,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz | |||
172 | " beqz $1, 1b \n" \ | 175 | " beqz $1, 1b \n" \ |
173 | " .set pop \n" \ | 176 | " .set pop \n" \ |
174 | "2: \n" \ | 177 | "2: \n" \ |
175 | : "=&r" (__ret), "=R" (*m) \ | 178 | : "=&r" (__ret), "=" GCC_OFF12_ASM() (*m) \ |
176 | : "R" (*m), "Jr" (old), "Jr" (new) \ | 179 | : GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new) \ |
177 | : "memory"); \ | 180 | : "memory"); \ |
178 | } else { \ | 181 | } else { \ |
179 | unsigned long __flags; \ | 182 | unsigned long __flags; \ |
diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h index 71f5c5cfc58a..c73815e0123a 100644 --- a/arch/mips/include/asm/compiler.h +++ b/arch/mips/include/asm/compiler.h | |||
@@ -16,4 +16,12 @@ | |||
16 | #define GCC_REG_ACCUM "accum" | 16 | #define GCC_REG_ACCUM "accum" |
17 | #endif | 17 | #endif |
18 | 18 | ||
19 | #ifndef CONFIG_CPU_MICROMIPS | ||
20 | #define GCC_OFF12_ASM() "R" | ||
21 | #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) | ||
22 | #define GCC_OFF12_ASM() "ZC" | ||
23 | #else | ||
24 | #error "microMIPS compilation unsupported with GCC older than 4.9" | ||
25 | #endif | ||
26 | |||
19 | #endif /* _ASM_COMPILER_H */ | 27 | #endif /* _ASM_COMPILER_H */ |
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 3325f3eb248c..2897cfafcaf0 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h | |||
@@ -344,4 +344,8 @@ | |||
344 | # define cpu_has_msa 0 | 344 | # define cpu_has_msa 0 |
345 | #endif | 345 | #endif |
346 | 346 | ||
347 | #ifndef cpu_has_fre | ||
348 | # define cpu_has_fre (cpu_data[0].options & MIPS_CPU_FRE) | ||
349 | #endif | ||
350 | |||
347 | #endif /* __ASM_CPU_FEATURES_H */ | 351 | #endif /* __ASM_CPU_FEATURES_H */ |
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index dfdc77ed1839..33866fce4d63 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h | |||
@@ -142,6 +142,7 @@ | |||
142 | #define PRID_IMP_BMIPS3300_BUG 0x0000 | 142 | #define PRID_IMP_BMIPS3300_BUG 0x0000 |
143 | #define PRID_IMP_BMIPS43XX 0xa000 | 143 | #define PRID_IMP_BMIPS43XX 0xa000 |
144 | #define PRID_IMP_BMIPS5000 0x5a00 | 144 | #define PRID_IMP_BMIPS5000 0x5a00 |
145 | #define PRID_IMP_BMIPS5200 0x5b00 | ||
145 | 146 | ||
146 | #define PRID_REV_BMIPS4380_LO 0x0040 | 147 | #define PRID_REV_BMIPS4380_LO 0x0040 |
147 | #define PRID_REV_BMIPS4380_HI 0x006f | 148 | #define PRID_REV_BMIPS4380_HI 0x006f |
@@ -368,6 +369,7 @@ enum cpu_type_enum { | |||
368 | #define MIPS_CPU_HTW 0x100000000ull /* CPU support Hardware Page Table Walker */ | 369 | #define MIPS_CPU_HTW 0x100000000ull /* CPU support Hardware Page Table Walker */ |
369 | #define MIPS_CPU_RIXIEX 0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ | 370 | #define MIPS_CPU_RIXIEX 0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */ |
370 | #define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */ | 371 | #define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */ |
372 | #define MIPS_CPU_FRE 0x800000000ull /* FRE & UFE bits implemented */ | ||
371 | 373 | ||
372 | /* | 374 | /* |
373 | * CPU ASE encodings | 375 | * CPU ASE encodings |
diff --git a/arch/mips/include/asm/edac.h b/arch/mips/include/asm/edac.h index 4da0c1fe30d9..ae6fedcb0060 100644 --- a/arch/mips/include/asm/edac.h +++ b/arch/mips/include/asm/edac.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef ASM_EDAC_H | 1 | #ifndef ASM_EDAC_H |
2 | #define ASM_EDAC_H | 2 | #define ASM_EDAC_H |
3 | 3 | ||
4 | #include <asm/compiler.h> | ||
5 | |||
4 | /* ECC atomic, DMA, SMP and interrupt safe scrub function */ | 6 | /* ECC atomic, DMA, SMP and interrupt safe scrub function */ |
5 | 7 | ||
6 | static inline void atomic_scrub(void *va, u32 size) | 8 | static inline void atomic_scrub(void *va, u32 size) |
@@ -24,8 +26,8 @@ static inline void atomic_scrub(void *va, u32 size) | |||
24 | " sc %0, %1 \n" | 26 | " sc %0, %1 \n" |
25 | " beqz %0, 1b \n" | 27 | " beqz %0, 1b \n" |
26 | " .set mips0 \n" | 28 | " .set mips0 \n" |
27 | : "=&r" (temp), "=m" (*virt_addr) | 29 | : "=&r" (temp), "=" GCC_OFF12_ASM() (*virt_addr) |
28 | : "m" (*virt_addr)); | 30 | : GCC_OFF12_ASM() (*virt_addr)); |
29 | 31 | ||
30 | virt_addr++; | 32 | virt_addr++; |
31 | } | 33 | } |
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index 1d38fe0edd2d..eb4d95de619c 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h | |||
@@ -8,6 +8,8 @@ | |||
8 | #ifndef _ASM_ELF_H | 8 | #ifndef _ASM_ELF_H |
9 | #define _ASM_ELF_H | 9 | #define _ASM_ELF_H |
10 | 10 | ||
11 | #include <linux/fs.h> | ||
12 | #include <uapi/linux/elf.h> | ||
11 | 13 | ||
12 | /* ELF header e_flags defines. */ | 14 | /* ELF header e_flags defines. */ |
13 | /* MIPS architecture level. */ | 15 | /* MIPS architecture level. */ |
@@ -28,6 +30,7 @@ | |||
28 | #define PT_MIPS_REGINFO 0x70000000 | 30 | #define PT_MIPS_REGINFO 0x70000000 |
29 | #define PT_MIPS_RTPROC 0x70000001 | 31 | #define PT_MIPS_RTPROC 0x70000001 |
30 | #define PT_MIPS_OPTIONS 0x70000002 | 32 | #define PT_MIPS_OPTIONS 0x70000002 |
33 | #define PT_MIPS_ABIFLAGS 0x70000003 | ||
31 | 34 | ||
32 | /* Flags in the e_flags field of the header */ | 35 | /* Flags in the e_flags field of the header */ |
33 | #define EF_MIPS_NOREORDER 0x00000001 | 36 | #define EF_MIPS_NOREORDER 0x00000001 |
@@ -174,6 +177,30 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; | |||
174 | typedef double elf_fpreg_t; | 177 | typedef double elf_fpreg_t; |
175 | typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; | 178 | typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; |
176 | 179 | ||
180 | struct mips_elf_abiflags_v0 { | ||
181 | uint16_t version; /* Version of flags structure */ | ||
182 | uint8_t isa_level; /* The level of the ISA: 1-5, 32, 64 */ | ||
183 | uint8_t isa_rev; /* The revision of ISA: 0 for MIPS V and below, | ||
184 | 1-n otherwise */ | ||
185 | uint8_t gpr_size; /* The size of general purpose registers */ | ||
186 | uint8_t cpr1_size; /* The size of co-processor 1 registers */ | ||
187 | uint8_t cpr2_size; /* The size of co-processor 2 registers */ | ||
188 | uint8_t fp_abi; /* The floating-point ABI */ | ||
189 | uint32_t isa_ext; /* Mask of processor-specific extensions */ | ||
190 | uint32_t ases; /* Mask of ASEs used */ | ||
191 | uint32_t flags1; /* Mask of general flags */ | ||
192 | uint32_t flags2; | ||
193 | }; | ||
194 | |||
195 | #define MIPS_ABI_FP_ANY 0 /* FP ABI doesn't matter */ | ||
196 | #define MIPS_ABI_FP_DOUBLE 1 /* -mdouble-float */ | ||
197 | #define MIPS_ABI_FP_SINGLE 2 /* -msingle-float */ | ||
198 | #define MIPS_ABI_FP_SOFT 3 /* -msoft-float */ | ||
199 | #define MIPS_ABI_FP_OLD_64 4 /* -mips32r2 -mfp64 */ | ||
200 | #define MIPS_ABI_FP_XX 5 /* -mfpxx */ | ||
201 | #define MIPS_ABI_FP_64 6 /* -mips32r2 -mfp64 */ | ||
202 | #define MIPS_ABI_FP_64A 7 /* -mips32r2 -mfp64 -mno-odd-spreg */ | ||
203 | |||
177 | #ifdef CONFIG_32BIT | 204 | #ifdef CONFIG_32BIT |
178 | 205 | ||
179 | /* | 206 | /* |
@@ -262,16 +289,13 @@ extern struct mips_abi mips_abi_n32; | |||
262 | 289 | ||
263 | #ifdef CONFIG_32BIT | 290 | #ifdef CONFIG_32BIT |
264 | 291 | ||
265 | #define SET_PERSONALITY(ex) \ | 292 | #define SET_PERSONALITY2(ex, state) \ |
266 | do { \ | 293 | do { \ |
267 | if ((ex).e_flags & EF_MIPS_FP64) \ | ||
268 | clear_thread_flag(TIF_32BIT_FPREGS); \ | ||
269 | else \ | ||
270 | set_thread_flag(TIF_32BIT_FPREGS); \ | ||
271 | \ | ||
272 | if (personality(current->personality) != PER_LINUX) \ | 294 | if (personality(current->personality) != PER_LINUX) \ |
273 | set_personality(PER_LINUX); \ | 295 | set_personality(PER_LINUX); \ |
274 | \ | 296 | \ |
297 | mips_set_personality_fp(state); \ | ||
298 | \ | ||
275 | current->thread.abi = &mips_abi; \ | 299 | current->thread.abi = &mips_abi; \ |
276 | } while (0) | 300 | } while (0) |
277 | 301 | ||
@@ -291,44 +315,44 @@ do { \ | |||
291 | #endif | 315 | #endif |
292 | 316 | ||
293 | #ifdef CONFIG_MIPS32_O32 | 317 | #ifdef CONFIG_MIPS32_O32 |
294 | #define __SET_PERSONALITY32_O32(ex) \ | 318 | #define __SET_PERSONALITY32_O32(ex, state) \ |
295 | do { \ | 319 | do { \ |
296 | set_thread_flag(TIF_32BIT_REGS); \ | 320 | set_thread_flag(TIF_32BIT_REGS); \ |
297 | set_thread_flag(TIF_32BIT_ADDR); \ | 321 | set_thread_flag(TIF_32BIT_ADDR); \ |
298 | \ | 322 | \ |
299 | if (!((ex).e_flags & EF_MIPS_FP64)) \ | 323 | mips_set_personality_fp(state); \ |
300 | set_thread_flag(TIF_32BIT_FPREGS); \ | ||
301 | \ | 324 | \ |
302 | current->thread.abi = &mips_abi_32; \ | 325 | current->thread.abi = &mips_abi_32; \ |
303 | } while (0) | 326 | } while (0) |
304 | #else | 327 | #else |
305 | #define __SET_PERSONALITY32_O32(ex) \ | 328 | #define __SET_PERSONALITY32_O32(ex, state) \ |
306 | do { } while (0) | 329 | do { } while (0) |
307 | #endif | 330 | #endif |
308 | 331 | ||
309 | #ifdef CONFIG_MIPS32_COMPAT | 332 | #ifdef CONFIG_MIPS32_COMPAT |
310 | #define __SET_PERSONALITY32(ex) \ | 333 | #define __SET_PERSONALITY32(ex, state) \ |
311 | do { \ | 334 | do { \ |
312 | if ((((ex).e_flags & EF_MIPS_ABI2) != 0) && \ | 335 | if ((((ex).e_flags & EF_MIPS_ABI2) != 0) && \ |
313 | ((ex).e_flags & EF_MIPS_ABI) == 0) \ | 336 | ((ex).e_flags & EF_MIPS_ABI) == 0) \ |
314 | __SET_PERSONALITY32_N32(); \ | 337 | __SET_PERSONALITY32_N32(); \ |
315 | else \ | 338 | else \ |
316 | __SET_PERSONALITY32_O32(ex); \ | 339 | __SET_PERSONALITY32_O32(ex, state); \ |
317 | } while (0) | 340 | } while (0) |
318 | #else | 341 | #else |
319 | #define __SET_PERSONALITY32(ex) do { } while (0) | 342 | #define __SET_PERSONALITY32(ex, state) do { } while (0) |
320 | #endif | 343 | #endif |
321 | 344 | ||
322 | #define SET_PERSONALITY(ex) \ | 345 | #define SET_PERSONALITY2(ex, state) \ |
323 | do { \ | 346 | do { \ |
324 | unsigned int p; \ | 347 | unsigned int p; \ |
325 | \ | 348 | \ |
326 | clear_thread_flag(TIF_32BIT_REGS); \ | 349 | clear_thread_flag(TIF_32BIT_REGS); \ |
327 | clear_thread_flag(TIF_32BIT_FPREGS); \ | 350 | clear_thread_flag(TIF_32BIT_FPREGS); \ |
351 | clear_thread_flag(TIF_HYBRID_FPREGS); \ | ||
328 | clear_thread_flag(TIF_32BIT_ADDR); \ | 352 | clear_thread_flag(TIF_32BIT_ADDR); \ |
329 | \ | 353 | \ |
330 | if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ | 354 | if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ |
331 | __SET_PERSONALITY32(ex); \ | 355 | __SET_PERSONALITY32(ex, state); \ |
332 | else \ | 356 | else \ |
333 | current->thread.abi = &mips_abi; \ | 357 | current->thread.abi = &mips_abi; \ |
334 | \ | 358 | \ |
@@ -390,4 +414,24 @@ struct mm_struct; | |||
390 | extern unsigned long arch_randomize_brk(struct mm_struct *mm); | 414 | extern unsigned long arch_randomize_brk(struct mm_struct *mm); |
391 | #define arch_randomize_brk arch_randomize_brk | 415 | #define arch_randomize_brk arch_randomize_brk |
392 | 416 | ||
417 | struct arch_elf_state { | ||
418 | int fp_abi; | ||
419 | int interp_fp_abi; | ||
420 | int overall_abi; | ||
421 | }; | ||
422 | |||
423 | #define INIT_ARCH_ELF_STATE { \ | ||
424 | .fp_abi = -1, \ | ||
425 | .interp_fp_abi = -1, \ | ||
426 | .overall_abi = -1, \ | ||
427 | } | ||
428 | |||
429 | extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf, | ||
430 | bool is_interp, struct arch_elf_state *state); | ||
431 | |||
432 | extern int arch_check_elf(void *ehdr, bool has_interpreter, | ||
433 | struct arch_elf_state *state); | ||
434 | |||
435 | extern void mips_set_personality_fp(struct arch_elf_state *state); | ||
436 | |||
393 | #endif /* _ASM_ELF_H */ | 437 | #endif /* _ASM_ELF_H */ |
diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h index dd562414cd5e..994d21939676 100644 --- a/arch/mips/include/asm/fpu.h +++ b/arch/mips/include/asm/fpu.h | |||
@@ -36,14 +36,16 @@ extern void _restore_fp(struct task_struct *); | |||
36 | 36 | ||
37 | /* | 37 | /* |
38 | * This enum specifies a mode in which we want the FPU to operate, for cores | 38 | * This enum specifies a mode in which we want the FPU to operate, for cores |
39 | * which implement the Status.FR bit. Note that FPU_32BIT & FPU_64BIT | 39 | * which implement the Status.FR bit. Note that the bottom bit of the value |
40 | * purposefully have the values 0 & 1 respectively, so that an integer value | 40 | * purposefully matches the desired value of the Status.FR bit. |
41 | * of Status.FR can be trivially casted to the corresponding enum fpu_mode. | ||
42 | */ | 41 | */ |
43 | enum fpu_mode { | 42 | enum fpu_mode { |
44 | FPU_32BIT = 0, /* FR = 0 */ | 43 | FPU_32BIT = 0, /* FR = 0 */ |
45 | FPU_64BIT, /* FR = 1 */ | 44 | FPU_64BIT, /* FR = 1, FRE = 0 */ |
46 | FPU_AS_IS, | 45 | FPU_AS_IS, |
46 | FPU_HYBRID, /* FR = 1, FRE = 1 */ | ||
47 | |||
48 | #define FPU_FR_MASK 0x1 | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | static inline int __enable_fpu(enum fpu_mode mode) | 51 | static inline int __enable_fpu(enum fpu_mode mode) |
@@ -57,6 +59,14 @@ static inline int __enable_fpu(enum fpu_mode mode) | |||
57 | enable_fpu_hazard(); | 59 | enable_fpu_hazard(); |
58 | return 0; | 60 | return 0; |
59 | 61 | ||
62 | case FPU_HYBRID: | ||
63 | if (!cpu_has_fre) | ||
64 | return SIGFPE; | ||
65 | |||
66 | /* set FRE */ | ||
67 | write_c0_config5(read_c0_config5() | MIPS_CONF5_FRE); | ||
68 | goto fr_common; | ||
69 | |||
60 | case FPU_64BIT: | 70 | case FPU_64BIT: |
61 | #if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT)) | 71 | #if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT)) |
62 | /* we only have a 32-bit FPU */ | 72 | /* we only have a 32-bit FPU */ |
@@ -64,8 +74,11 @@ static inline int __enable_fpu(enum fpu_mode mode) | |||
64 | #endif | 74 | #endif |
65 | /* fall through */ | 75 | /* fall through */ |
66 | case FPU_32BIT: | 76 | case FPU_32BIT: |
77 | /* clear FRE */ | ||
78 | write_c0_config5(read_c0_config5() & ~MIPS_CONF5_FRE); | ||
79 | fr_common: | ||
67 | /* set CU1 & change FR appropriately */ | 80 | /* set CU1 & change FR appropriately */ |
68 | fr = (int)mode; | 81 | fr = (int)mode & FPU_FR_MASK; |
69 | change_c0_status(ST0_CU1 | ST0_FR, ST0_CU1 | (fr ? ST0_FR : 0)); | 82 | change_c0_status(ST0_CU1 | ST0_FR, ST0_CU1 | (fr ? ST0_FR : 0)); |
70 | enable_fpu_hazard(); | 83 | enable_fpu_hazard(); |
71 | 84 | ||
@@ -102,13 +115,17 @@ static inline int __own_fpu(void) | |||
102 | enum fpu_mode mode; | 115 | enum fpu_mode mode; |
103 | int ret; | 116 | int ret; |
104 | 117 | ||
105 | mode = !test_thread_flag(TIF_32BIT_FPREGS); | 118 | if (test_thread_flag(TIF_HYBRID_FPREGS)) |
119 | mode = FPU_HYBRID; | ||
120 | else | ||
121 | mode = !test_thread_flag(TIF_32BIT_FPREGS); | ||
122 | |||
106 | ret = __enable_fpu(mode); | 123 | ret = __enable_fpu(mode); |
107 | if (ret) | 124 | if (ret) |
108 | return ret; | 125 | return ret; |
109 | 126 | ||
110 | KSTK_STATUS(current) |= ST0_CU1; | 127 | KSTK_STATUS(current) |= ST0_CU1; |
111 | if (mode == FPU_64BIT) | 128 | if (mode == FPU_64BIT || mode == FPU_HYBRID) |
112 | KSTK_STATUS(current) |= ST0_FR; | 129 | KSTK_STATUS(current) |= ST0_FR; |
113 | else /* mode == FPU_32BIT */ | 130 | else /* mode == FPU_32BIT */ |
114 | KSTK_STATUS(current) &= ~ST0_FR; | 131 | KSTK_STATUS(current) &= ~ST0_FR; |
@@ -166,8 +183,24 @@ static inline int init_fpu(void) | |||
166 | 183 | ||
167 | if (cpu_has_fpu) { | 184 | if (cpu_has_fpu) { |
168 | ret = __own_fpu(); | 185 | ret = __own_fpu(); |
169 | if (!ret) | 186 | if (!ret) { |
187 | unsigned int config5 = read_c0_config5(); | ||
188 | |||
189 | /* | ||
190 | * Ensure FRE is clear whilst running _init_fpu, since | ||
191 | * single precision FP instructions are used. If FRE | ||
192 | * was set then we'll just end up initialising all 32 | ||
193 | * 64b registers. | ||
194 | */ | ||
195 | write_c0_config5(config5 & ~MIPS_CONF5_FRE); | ||
196 | enable_fpu_hazard(); | ||
197 | |||
170 | _init_fpu(); | 198 | _init_fpu(); |
199 | |||
200 | /* Restore FRE */ | ||
201 | write_c0_config5(config5); | ||
202 | enable_fpu_hazard(); | ||
203 | } | ||
171 | } else | 204 | } else |
172 | fpu_emulator_init_fpu(); | 205 | fpu_emulator_init_fpu(); |
173 | 206 | ||
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h index 194cda0396a3..ef9987a61d88 100644 --- a/arch/mips/include/asm/futex.h +++ b/arch/mips/include/asm/futex.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
15 | #include <asm/asm-eva.h> | 15 | #include <asm/asm-eva.h> |
16 | #include <asm/barrier.h> | 16 | #include <asm/barrier.h> |
17 | #include <asm/compiler.h> | ||
17 | #include <asm/errno.h> | 18 | #include <asm/errno.h> |
18 | #include <asm/war.h> | 19 | #include <asm/war.h> |
19 | 20 | ||
@@ -32,6 +33,7 @@ | |||
32 | " beqzl $1, 1b \n" \ | 33 | " beqzl $1, 1b \n" \ |
33 | __WEAK_LLSC_MB \ | 34 | __WEAK_LLSC_MB \ |
34 | "3: \n" \ | 35 | "3: \n" \ |
36 | " .insn \n" \ | ||
35 | " .set pop \n" \ | 37 | " .set pop \n" \ |
36 | " .set mips0 \n" \ | 38 | " .set mips0 \n" \ |
37 | " .section .fixup,\"ax\" \n" \ | 39 | " .section .fixup,\"ax\" \n" \ |
@@ -42,8 +44,10 @@ | |||
42 | " "__UA_ADDR "\t1b, 4b \n" \ | 44 | " "__UA_ADDR "\t1b, 4b \n" \ |
43 | " "__UA_ADDR "\t2b, 4b \n" \ | 45 | " "__UA_ADDR "\t2b, 4b \n" \ |
44 | " .previous \n" \ | 46 | " .previous \n" \ |
45 | : "=r" (ret), "=&r" (oldval), "=R" (*uaddr) \ | 47 | : "=r" (ret), "=&r" (oldval), \ |
46 | : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT) \ | 48 | "=" GCC_OFF12_ASM() (*uaddr) \ |
49 | : "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg), \ | ||
50 | "i" (-EFAULT) \ | ||
47 | : "memory"); \ | 51 | : "memory"); \ |
48 | } else if (cpu_has_llsc) { \ | 52 | } else if (cpu_has_llsc) { \ |
49 | __asm__ __volatile__( \ | 53 | __asm__ __volatile__( \ |
@@ -58,6 +62,7 @@ | |||
58 | " beqz $1, 1b \n" \ | 62 | " beqz $1, 1b \n" \ |
59 | __WEAK_LLSC_MB \ | 63 | __WEAK_LLSC_MB \ |
60 | "3: \n" \ | 64 | "3: \n" \ |
65 | " .insn \n" \ | ||
61 | " .set pop \n" \ | 66 | " .set pop \n" \ |
62 | " .set mips0 \n" \ | 67 | " .set mips0 \n" \ |
63 | " .section .fixup,\"ax\" \n" \ | 68 | " .section .fixup,\"ax\" \n" \ |
@@ -68,8 +73,10 @@ | |||
68 | " "__UA_ADDR "\t1b, 4b \n" \ | 73 | " "__UA_ADDR "\t1b, 4b \n" \ |
69 | " "__UA_ADDR "\t2b, 4b \n" \ | 74 | " "__UA_ADDR "\t2b, 4b \n" \ |
70 | " .previous \n" \ | 75 | " .previous \n" \ |
71 | : "=r" (ret), "=&r" (oldval), "=R" (*uaddr) \ | 76 | : "=r" (ret), "=&r" (oldval), \ |
72 | : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT) \ | 77 | "=" GCC_OFF12_ASM() (*uaddr) \ |
78 | : "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg), \ | ||
79 | "i" (-EFAULT) \ | ||
73 | : "memory"); \ | 80 | : "memory"); \ |
74 | } else \ | 81 | } else \ |
75 | ret = -ENOSYS; \ | 82 | ret = -ENOSYS; \ |
@@ -157,6 +164,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | |||
157 | " beqzl $1, 1b \n" | 164 | " beqzl $1, 1b \n" |
158 | __WEAK_LLSC_MB | 165 | __WEAK_LLSC_MB |
159 | "3: \n" | 166 | "3: \n" |
167 | " .insn \n" | ||
160 | " .set pop \n" | 168 | " .set pop \n" |
161 | " .section .fixup,\"ax\" \n" | 169 | " .section .fixup,\"ax\" \n" |
162 | "4: li %0, %6 \n" | 170 | "4: li %0, %6 \n" |
@@ -166,8 +174,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | |||
166 | " "__UA_ADDR "\t1b, 4b \n" | 174 | " "__UA_ADDR "\t1b, 4b \n" |
167 | " "__UA_ADDR "\t2b, 4b \n" | 175 | " "__UA_ADDR "\t2b, 4b \n" |
168 | " .previous \n" | 176 | " .previous \n" |
169 | : "+r" (ret), "=&r" (val), "=R" (*uaddr) | 177 | : "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr) |
170 | : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) | 178 | : GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval), |
179 | "i" (-EFAULT) | ||
171 | : "memory"); | 180 | : "memory"); |
172 | } else if (cpu_has_llsc) { | 181 | } else if (cpu_has_llsc) { |
173 | __asm__ __volatile__( | 182 | __asm__ __volatile__( |
@@ -184,6 +193,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | |||
184 | " beqz $1, 1b \n" | 193 | " beqz $1, 1b \n" |
185 | __WEAK_LLSC_MB | 194 | __WEAK_LLSC_MB |
186 | "3: \n" | 195 | "3: \n" |
196 | " .insn \n" | ||
187 | " .set pop \n" | 197 | " .set pop \n" |
188 | " .section .fixup,\"ax\" \n" | 198 | " .section .fixup,\"ax\" \n" |
189 | "4: li %0, %6 \n" | 199 | "4: li %0, %6 \n" |
@@ -193,8 +203,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | |||
193 | " "__UA_ADDR "\t1b, 4b \n" | 203 | " "__UA_ADDR "\t1b, 4b \n" |
194 | " "__UA_ADDR "\t2b, 4b \n" | 204 | " "__UA_ADDR "\t2b, 4b \n" |
195 | " .previous \n" | 205 | " .previous \n" |
196 | : "+r" (ret), "=&r" (val), "=R" (*uaddr) | 206 | : "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr) |
197 | : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) | 207 | : GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval), |
208 | "i" (-EFAULT) | ||
198 | : "memory"); | 209 | : "memory"); |
199 | } else | 210 | } else |
200 | return -ENOSYS; | 211 | return -ENOSYS; |
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h deleted file mode 100644 index d7699cf7e135..000000000000 --- a/arch/mips/include/asm/gic.h +++ /dev/null | |||
@@ -1,384 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2000, 07 MIPS Technologies, Inc. | ||
7 | * | ||
8 | * GIC Register Definitions | ||
9 | * | ||
10 | */ | ||
11 | #ifndef _ASM_GICREGS_H | ||
12 | #define _ASM_GICREGS_H | ||
13 | |||
14 | #include <linux/bitmap.h> | ||
15 | #include <linux/threads.h> | ||
16 | |||
17 | #include <irq.h> | ||
18 | |||
19 | #undef GICISBYTELITTLEENDIAN | ||
20 | |||
21 | /* Constants */ | ||
22 | #define GIC_POL_POS 1 | ||
23 | #define GIC_POL_NEG 0 | ||
24 | #define GIC_TRIG_EDGE 1 | ||
25 | #define GIC_TRIG_LEVEL 0 | ||
26 | |||
27 | #define MSK(n) ((1 << (n)) - 1) | ||
28 | #define REG32(addr) (*(volatile unsigned int *) (addr)) | ||
29 | #define REG(base, offs) REG32((unsigned long)(base) + offs##_##OFS) | ||
30 | #define REGP(base, phys) REG32((unsigned long)(base) + (phys)) | ||
31 | |||
32 | /* Accessors */ | ||
33 | #define GIC_REG(segment, offset) \ | ||
34 | REG32(_gic_base + segment##_##SECTION_OFS + offset##_##OFS) | ||
35 | #define GIC_REG_ADDR(segment, offset) \ | ||
36 | REG32(_gic_base + segment##_##SECTION_OFS + offset) | ||
37 | |||
38 | #define GIC_ABS_REG(segment, offset) \ | ||
39 | (_gic_base + segment##_##SECTION_OFS + offset##_##OFS) | ||
40 | #define GIC_REG_ABS_ADDR(segment, offset) \ | ||
41 | (_gic_base + segment##_##SECTION_OFS + offset) | ||
42 | |||
43 | #ifdef GICISBYTELITTLEENDIAN | ||
44 | #define GICREAD(reg, data) ((data) = (reg), (data) = le32_to_cpu(data)) | ||
45 | #define GICWRITE(reg, data) ((reg) = cpu_to_le32(data)) | ||
46 | #else | ||
47 | #define GICREAD(reg, data) ((data) = (reg)) | ||
48 | #define GICWRITE(reg, data) ((reg) = (data)) | ||
49 | #endif | ||
50 | #define GICBIS(reg, mask, bits) \ | ||
51 | do { u32 data; \ | ||
52 | GICREAD(reg, data); \ | ||
53 | data &= ~(mask); \ | ||
54 | data |= ((bits) & (mask)); \ | ||
55 | GICWRITE((reg), data); \ | ||
56 | } while (0) | ||
57 | |||
58 | |||
59 | /* GIC Address Space */ | ||
60 | #define SHARED_SECTION_OFS 0x0000 | ||
61 | #define SHARED_SECTION_SIZE 0x8000 | ||
62 | #define VPE_LOCAL_SECTION_OFS 0x8000 | ||
63 | #define VPE_LOCAL_SECTION_SIZE 0x4000 | ||
64 | #define VPE_OTHER_SECTION_OFS 0xc000 | ||
65 | #define VPE_OTHER_SECTION_SIZE 0x4000 | ||
66 | #define USM_VISIBLE_SECTION_OFS 0x10000 | ||
67 | #define USM_VISIBLE_SECTION_SIZE 0x10000 | ||
68 | |||
69 | /* Register Map for Shared Section */ | ||
70 | |||
71 | #define GIC_SH_CONFIG_OFS 0x0000 | ||
72 | |||
73 | /* Shared Global Counter */ | ||
74 | #define GIC_SH_COUNTER_31_00_OFS 0x0010 | ||
75 | #define GIC_SH_COUNTER_63_32_OFS 0x0014 | ||
76 | #define GIC_SH_REVISIONID_OFS 0x0020 | ||
77 | |||
78 | /* Interrupt Polarity */ | ||
79 | #define GIC_SH_POL_31_0_OFS 0x0100 | ||
80 | #define GIC_SH_POL_63_32_OFS 0x0104 | ||
81 | #define GIC_SH_POL_95_64_OFS 0x0108 | ||
82 | #define GIC_SH_POL_127_96_OFS 0x010c | ||
83 | #define GIC_SH_POL_159_128_OFS 0x0110 | ||
84 | #define GIC_SH_POL_191_160_OFS 0x0114 | ||
85 | #define GIC_SH_POL_223_192_OFS 0x0118 | ||
86 | #define GIC_SH_POL_255_224_OFS 0x011c | ||
87 | |||
88 | /* Edge/Level Triggering */ | ||
89 | #define GIC_SH_TRIG_31_0_OFS 0x0180 | ||
90 | #define GIC_SH_TRIG_63_32_OFS 0x0184 | ||
91 | #define GIC_SH_TRIG_95_64_OFS 0x0188 | ||
92 | #define GIC_SH_TRIG_127_96_OFS 0x018c | ||
93 | #define GIC_SH_TRIG_159_128_OFS 0x0190 | ||
94 | #define GIC_SH_TRIG_191_160_OFS 0x0194 | ||
95 | #define GIC_SH_TRIG_223_192_OFS 0x0198 | ||
96 | #define GIC_SH_TRIG_255_224_OFS 0x019c | ||
97 | |||
98 | /* Dual Edge Triggering */ | ||
99 | #define GIC_SH_DUAL_31_0_OFS 0x0200 | ||
100 | #define GIC_SH_DUAL_63_32_OFS 0x0204 | ||
101 | #define GIC_SH_DUAL_95_64_OFS 0x0208 | ||
102 | #define GIC_SH_DUAL_127_96_OFS 0x020c | ||
103 | #define GIC_SH_DUAL_159_128_OFS 0x0210 | ||
104 | #define GIC_SH_DUAL_191_160_OFS 0x0214 | ||
105 | #define GIC_SH_DUAL_223_192_OFS 0x0218 | ||
106 | #define GIC_SH_DUAL_255_224_OFS 0x021c | ||
107 | |||
108 | /* Set/Clear corresponding bit in Edge Detect Register */ | ||
109 | #define GIC_SH_WEDGE_OFS 0x0280 | ||
110 | |||
111 | /* Reset Mask - Disables Interrupt */ | ||
112 | #define GIC_SH_RMASK_31_0_OFS 0x0300 | ||
113 | #define GIC_SH_RMASK_63_32_OFS 0x0304 | ||
114 | #define GIC_SH_RMASK_95_64_OFS 0x0308 | ||
115 | #define GIC_SH_RMASK_127_96_OFS 0x030c | ||
116 | #define GIC_SH_RMASK_159_128_OFS 0x0310 | ||
117 | #define GIC_SH_RMASK_191_160_OFS 0x0314 | ||
118 | #define GIC_SH_RMASK_223_192_OFS 0x0318 | ||
119 | #define GIC_SH_RMASK_255_224_OFS 0x031c | ||
120 | |||
121 | /* Set Mask (WO) - Enables Interrupt */ | ||
122 | #define GIC_SH_SMASK_31_0_OFS 0x0380 | ||
123 | #define GIC_SH_SMASK_63_32_OFS 0x0384 | ||
124 | #define GIC_SH_SMASK_95_64_OFS 0x0388 | ||
125 | #define GIC_SH_SMASK_127_96_OFS 0x038c | ||
126 | #define GIC_SH_SMASK_159_128_OFS 0x0390 | ||
127 | #define GIC_SH_SMASK_191_160_OFS 0x0394 | ||
128 | #define GIC_SH_SMASK_223_192_OFS 0x0398 | ||
129 | #define GIC_SH_SMASK_255_224_OFS 0x039c | ||
130 | |||
131 | /* Global Interrupt Mask Register (RO) - Bit Set == Interrupt enabled */ | ||
132 | #define GIC_SH_MASK_31_0_OFS 0x0400 | ||
133 | #define GIC_SH_MASK_63_32_OFS 0x0404 | ||
134 | #define GIC_SH_MASK_95_64_OFS 0x0408 | ||
135 | #define GIC_SH_MASK_127_96_OFS 0x040c | ||
136 | #define GIC_SH_MASK_159_128_OFS 0x0410 | ||
137 | #define GIC_SH_MASK_191_160_OFS 0x0414 | ||
138 | #define GIC_SH_MASK_223_192_OFS 0x0418 | ||
139 | #define GIC_SH_MASK_255_224_OFS 0x041c | ||
140 | |||
141 | /* Pending Global Interrupts (RO) */ | ||
142 | #define GIC_SH_PEND_31_0_OFS 0x0480 | ||
143 | #define GIC_SH_PEND_63_32_OFS 0x0484 | ||
144 | #define GIC_SH_PEND_95_64_OFS 0x0488 | ||
145 | #define GIC_SH_PEND_127_96_OFS 0x048c | ||
146 | #define GIC_SH_PEND_159_128_OFS 0x0490 | ||
147 | #define GIC_SH_PEND_191_160_OFS 0x0494 | ||
148 | #define GIC_SH_PEND_223_192_OFS 0x0498 | ||
149 | #define GIC_SH_PEND_255_224_OFS 0x049c | ||
150 | |||
151 | #define GIC_SH_INTR_MAP_TO_PIN_BASE_OFS 0x0500 | ||
152 | |||
153 | /* Maps Interrupt X to a Pin */ | ||
154 | #define GIC_SH_MAP_TO_PIN(intr) \ | ||
155 | (GIC_SH_INTR_MAP_TO_PIN_BASE_OFS + (4 * intr)) | ||
156 | |||
157 | #define GIC_SH_INTR_MAP_TO_VPE_BASE_OFS 0x2000 | ||
158 | |||
159 | /* Maps Interrupt X to a VPE */ | ||
160 | #define GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe) \ | ||
161 | (GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + (((vpe) / 32) * 4)) | ||
162 | #define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32)) | ||
163 | |||
164 | /* Convert an interrupt number to a byte offset/bit for multi-word registers */ | ||
165 | #define GIC_INTR_OFS(intr) (((intr) / 32)*4) | ||
166 | #define GIC_INTR_BIT(intr) ((intr) % 32) | ||
167 | |||
168 | /* Polarity : Reset Value is always 0 */ | ||
169 | #define GIC_SH_SET_POLARITY_OFS 0x0100 | ||
170 | #define GIC_SET_POLARITY(intr, pol) \ | ||
171 | GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \ | ||
172 | GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \ | ||
173 | (pol) << GIC_INTR_BIT(intr)) | ||
174 | |||
175 | /* Triggering : Reset Value is always 0 */ | ||
176 | #define GIC_SH_SET_TRIGGER_OFS 0x0180 | ||
177 | #define GIC_SET_TRIGGER(intr, trig) \ | ||
178 | GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \ | ||
179 | GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \ | ||
180 | (trig) << GIC_INTR_BIT(intr)) | ||
181 | |||
182 | /* Mask manipulation */ | ||
183 | #define GIC_SH_SMASK_OFS 0x0380 | ||
184 | #define GIC_SET_INTR_MASK(intr) \ | ||
185 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + \ | ||
186 | GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr)) | ||
187 | #define GIC_SH_RMASK_OFS 0x0300 | ||
188 | #define GIC_CLR_INTR_MASK(intr) \ | ||
189 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + \ | ||
190 | GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr)) | ||
191 | |||
192 | /* Register Map for Local Section */ | ||
193 | #define GIC_VPE_CTL_OFS 0x0000 | ||
194 | #define GIC_VPE_PEND_OFS 0x0004 | ||
195 | #define GIC_VPE_MASK_OFS 0x0008 | ||
196 | #define GIC_VPE_RMASK_OFS 0x000c | ||
197 | #define GIC_VPE_SMASK_OFS 0x0010 | ||
198 | #define GIC_VPE_WD_MAP_OFS 0x0040 | ||
199 | #define GIC_VPE_COMPARE_MAP_OFS 0x0044 | ||
200 | #define GIC_VPE_TIMER_MAP_OFS 0x0048 | ||
201 | #define GIC_VPE_PERFCTR_MAP_OFS 0x0050 | ||
202 | #define GIC_VPE_SWINT0_MAP_OFS 0x0054 | ||
203 | #define GIC_VPE_SWINT1_MAP_OFS 0x0058 | ||
204 | #define GIC_VPE_OTHER_ADDR_OFS 0x0080 | ||
205 | #define GIC_VPE_WD_CONFIG0_OFS 0x0090 | ||
206 | #define GIC_VPE_WD_COUNT0_OFS 0x0094 | ||
207 | #define GIC_VPE_WD_INITIAL0_OFS 0x0098 | ||
208 | #define GIC_VPE_COMPARE_LO_OFS 0x00a0 | ||
209 | #define GIC_VPE_COMPARE_HI_OFS 0x00a4 | ||
210 | |||
211 | #define GIC_VPE_EIC_SHADOW_SET_BASE 0x0100 | ||
212 | #define GIC_VPE_EIC_SS(intr) \ | ||
213 | (GIC_VPE_EIC_SHADOW_SET_BASE + (4 * intr)) | ||
214 | |||
215 | #define GIC_VPE_EIC_VEC_BASE 0x0800 | ||
216 | #define GIC_VPE_EIC_VEC(intr) \ | ||
217 | (GIC_VPE_EIC_VEC_BASE + (4 * intr)) | ||
218 | |||
219 | #define GIC_VPE_TENABLE_NMI_OFS 0x1000 | ||
220 | #define GIC_VPE_TENABLE_YQ_OFS 0x1004 | ||
221 | #define GIC_VPE_TENABLE_INT_31_0_OFS 0x1080 | ||
222 | #define GIC_VPE_TENABLE_INT_63_32_OFS 0x1084 | ||
223 | |||
224 | /* User Mode Visible Section Register Map */ | ||
225 | #define GIC_UMV_SH_COUNTER_31_00_OFS 0x0000 | ||
226 | #define GIC_UMV_SH_COUNTER_63_32_OFS 0x0004 | ||
227 | |||
228 | /* Masks */ | ||
229 | #define GIC_SH_CONFIG_COUNTSTOP_SHF 28 | ||
230 | #define GIC_SH_CONFIG_COUNTSTOP_MSK (MSK(1) << GIC_SH_CONFIG_COUNTSTOP_SHF) | ||
231 | |||
232 | #define GIC_SH_CONFIG_COUNTBITS_SHF 24 | ||
233 | #define GIC_SH_CONFIG_COUNTBITS_MSK (MSK(4) << GIC_SH_CONFIG_COUNTBITS_SHF) | ||
234 | |||
235 | #define GIC_SH_CONFIG_NUMINTRS_SHF 16 | ||
236 | #define GIC_SH_CONFIG_NUMINTRS_MSK (MSK(8) << GIC_SH_CONFIG_NUMINTRS_SHF) | ||
237 | |||
238 | #define GIC_SH_CONFIG_NUMVPES_SHF 0 | ||
239 | #define GIC_SH_CONFIG_NUMVPES_MSK (MSK(8) << GIC_SH_CONFIG_NUMVPES_SHF) | ||
240 | |||
241 | #define GIC_SH_WEDGE_SET(intr) (intr | (0x1 << 31)) | ||
242 | #define GIC_SH_WEDGE_CLR(intr) (intr & ~(0x1 << 31)) | ||
243 | |||
244 | #define GIC_MAP_TO_PIN_SHF 31 | ||
245 | #define GIC_MAP_TO_PIN_MSK (MSK(1) << GIC_MAP_TO_PIN_SHF) | ||
246 | #define GIC_MAP_TO_NMI_SHF 30 | ||
247 | #define GIC_MAP_TO_NMI_MSK (MSK(1) << GIC_MAP_TO_NMI_SHF) | ||
248 | #define GIC_MAP_TO_YQ_SHF 29 | ||
249 | #define GIC_MAP_TO_YQ_MSK (MSK(1) << GIC_MAP_TO_YQ_SHF) | ||
250 | #define GIC_MAP_SHF 0 | ||
251 | #define GIC_MAP_MSK (MSK(6) << GIC_MAP_SHF) | ||
252 | |||
253 | /* GIC_VPE_CTL Masks */ | ||
254 | #define GIC_VPE_CTL_PERFCNT_RTBL_SHF 2 | ||
255 | #define GIC_VPE_CTL_PERFCNT_RTBL_MSK (MSK(1) << GIC_VPE_CTL_PERFCNT_RTBL_SHF) | ||
256 | #define GIC_VPE_CTL_TIMER_RTBL_SHF 1 | ||
257 | #define GIC_VPE_CTL_TIMER_RTBL_MSK (MSK(1) << GIC_VPE_CTL_TIMER_RTBL_SHF) | ||
258 | #define GIC_VPE_CTL_EIC_MODE_SHF 0 | ||
259 | #define GIC_VPE_CTL_EIC_MODE_MSK (MSK(1) << GIC_VPE_CTL_EIC_MODE_SHF) | ||
260 | |||
261 | /* GIC_VPE_PEND Masks */ | ||
262 | #define GIC_VPE_PEND_WD_SHF 0 | ||
263 | #define GIC_VPE_PEND_WD_MSK (MSK(1) << GIC_VPE_PEND_WD_SHF) | ||
264 | #define GIC_VPE_PEND_CMP_SHF 1 | ||
265 | #define GIC_VPE_PEND_CMP_MSK (MSK(1) << GIC_VPE_PEND_CMP_SHF) | ||
266 | #define GIC_VPE_PEND_TIMER_SHF 2 | ||
267 | #define GIC_VPE_PEND_TIMER_MSK (MSK(1) << GIC_VPE_PEND_TIMER_SHF) | ||
268 | #define GIC_VPE_PEND_PERFCOUNT_SHF 3 | ||
269 | #define GIC_VPE_PEND_PERFCOUNT_MSK (MSK(1) << GIC_VPE_PEND_PERFCOUNT_SHF) | ||
270 | #define GIC_VPE_PEND_SWINT0_SHF 4 | ||
271 | #define GIC_VPE_PEND_SWINT0_MSK (MSK(1) << GIC_VPE_PEND_SWINT0_SHF) | ||
272 | #define GIC_VPE_PEND_SWINT1_SHF 5 | ||
273 | #define GIC_VPE_PEND_SWINT1_MSK (MSK(1) << GIC_VPE_PEND_SWINT1_SHF) | ||
274 | |||
275 | /* GIC_VPE_RMASK Masks */ | ||
276 | #define GIC_VPE_RMASK_WD_SHF 0 | ||
277 | #define GIC_VPE_RMASK_WD_MSK (MSK(1) << GIC_VPE_RMASK_WD_SHF) | ||
278 | #define GIC_VPE_RMASK_CMP_SHF 1 | ||
279 | #define GIC_VPE_RMASK_CMP_MSK (MSK(1) << GIC_VPE_RMASK_CMP_SHF) | ||
280 | #define GIC_VPE_RMASK_TIMER_SHF 2 | ||
281 | #define GIC_VPE_RMASK_TIMER_MSK (MSK(1) << GIC_VPE_RMASK_TIMER_SHF) | ||
282 | #define GIC_VPE_RMASK_PERFCNT_SHF 3 | ||
283 | #define GIC_VPE_RMASK_PERFCNT_MSK (MSK(1) << GIC_VPE_RMASK_PERFCNT_SHF) | ||
284 | #define GIC_VPE_RMASK_SWINT0_SHF 4 | ||
285 | #define GIC_VPE_RMASK_SWINT0_MSK (MSK(1) << GIC_VPE_RMASK_SWINT0_SHF) | ||
286 | #define GIC_VPE_RMASK_SWINT1_SHF 5 | ||
287 | #define GIC_VPE_RMASK_SWINT1_MSK (MSK(1) << GIC_VPE_RMASK_SWINT1_SHF) | ||
288 | |||
289 | /* GIC_VPE_SMASK Masks */ | ||
290 | #define GIC_VPE_SMASK_WD_SHF 0 | ||
291 | #define GIC_VPE_SMASK_WD_MSK (MSK(1) << GIC_VPE_SMASK_WD_SHF) | ||
292 | #define GIC_VPE_SMASK_CMP_SHF 1 | ||
293 | #define GIC_VPE_SMASK_CMP_MSK (MSK(1) << GIC_VPE_SMASK_CMP_SHF) | ||
294 | #define GIC_VPE_SMASK_TIMER_SHF 2 | ||
295 | #define GIC_VPE_SMASK_TIMER_MSK (MSK(1) << GIC_VPE_SMASK_TIMER_SHF) | ||
296 | #define GIC_VPE_SMASK_PERFCNT_SHF 3 | ||
297 | #define GIC_VPE_SMASK_PERFCNT_MSK (MSK(1) << GIC_VPE_SMASK_PERFCNT_SHF) | ||
298 | #define GIC_VPE_SMASK_SWINT0_SHF 4 | ||
299 | #define GIC_VPE_SMASK_SWINT0_MSK (MSK(1) << GIC_VPE_SMASK_SWINT0_SHF) | ||
300 | #define GIC_VPE_SMASK_SWINT1_SHF 5 | ||
301 | #define GIC_VPE_SMASK_SWINT1_MSK (MSK(1) << GIC_VPE_SMASK_SWINT1_SHF) | ||
302 | |||
303 | /* | ||
304 | * Set the Mapping of Interrupt X to a VPE. | ||
305 | */ | ||
306 | #define GIC_SH_MAP_TO_VPE_SMASK(intr, vpe) \ | ||
307 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \ | ||
308 | GIC_SH_MAP_TO_VPE_REG_BIT(vpe)) | ||
309 | |||
310 | /* | ||
311 | * Interrupt Meta-data specification. The ipiflag helps | ||
312 | * in building ipi_map. | ||
313 | */ | ||
314 | struct gic_intr_map { | ||
315 | unsigned int cpunum; /* Directed to this CPU */ | ||
316 | #define GIC_UNUSED 0xdead /* Dummy data */ | ||
317 | unsigned int pin; /* Directed to this Pin */ | ||
318 | unsigned int polarity; /* Polarity : +/- */ | ||
319 | unsigned int trigtype; /* Trigger : Edge/Levl */ | ||
320 | unsigned int flags; /* Misc flags */ | ||
321 | #define GIC_FLAG_TRANSPARENT 0x01 | ||
322 | }; | ||
323 | |||
324 | /* | ||
325 | * This is only used in EIC mode. This helps to figure out which | ||
326 | * shared interrupts we need to process when we get a vector interrupt. | ||
327 | */ | ||
328 | #define GIC_MAX_SHARED_INTR 0x5 | ||
329 | struct gic_shared_intr_map { | ||
330 | unsigned int num_shared_intr; | ||
331 | unsigned int intr_list[GIC_MAX_SHARED_INTR]; | ||
332 | unsigned int local_intr_mask; | ||
333 | }; | ||
334 | |||
335 | /* GIC nomenclature for Core Interrupt Pins. */ | ||
336 | #define GIC_CPU_INT0 0 /* Core Interrupt 2 */ | ||
337 | #define GIC_CPU_INT1 1 /* . */ | ||
338 | #define GIC_CPU_INT2 2 /* . */ | ||
339 | #define GIC_CPU_INT3 3 /* . */ | ||
340 | #define GIC_CPU_INT4 4 /* . */ | ||
341 | #define GIC_CPU_INT5 5 /* Core Interrupt 7 */ | ||
342 | |||
343 | /* Local GIC interrupts. */ | ||
344 | #define GIC_INT_TMR (GIC_CPU_INT5) | ||
345 | #define GIC_INT_PERFCTR (GIC_CPU_INT5) | ||
346 | |||
347 | /* Add 2 to convert non-EIC hardware interrupt to EIC vector number. */ | ||
348 | #define GIC_CPU_TO_VEC_OFFSET (2) | ||
349 | |||
350 | /* Mapped interrupt to pin X, then GIC will generate the vector (X+1). */ | ||
351 | #define GIC_PIN_TO_VEC_OFFSET (1) | ||
352 | |||
353 | #include <linux/clocksource.h> | ||
354 | #include <linux/irq.h> | ||
355 | |||
356 | extern unsigned int gic_present; | ||
357 | extern unsigned int gic_frequency; | ||
358 | extern unsigned long _gic_base; | ||
359 | extern unsigned int gic_irq_base; | ||
360 | extern unsigned int gic_irq_flags[]; | ||
361 | extern struct gic_shared_intr_map gic_shared_intr_map[]; | ||
362 | |||
363 | extern void gic_init(unsigned long gic_base_addr, | ||
364 | unsigned long gic_addrspace_size, struct gic_intr_map *intrmap, | ||
365 | unsigned int intrmap_size, unsigned int irqbase); | ||
366 | extern void gic_clocksource_init(unsigned int); | ||
367 | extern unsigned int gic_compare_int (void); | ||
368 | extern cycle_t gic_read_count(void); | ||
369 | extern cycle_t gic_read_compare(void); | ||
370 | extern void gic_write_compare(cycle_t cnt); | ||
371 | extern void gic_write_cpu_compare(cycle_t cnt, int cpu); | ||
372 | extern void gic_send_ipi(unsigned int intr); | ||
373 | extern unsigned int plat_ipi_call_int_xlate(unsigned int); | ||
374 | extern unsigned int plat_ipi_resched_int_xlate(unsigned int); | ||
375 | extern void gic_bind_eic_interrupt(int irq, int set); | ||
376 | extern unsigned int gic_get_timer_pending(void); | ||
377 | extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src); | ||
378 | extern unsigned int gic_get_int(void); | ||
379 | extern void gic_enable_interrupt(int irq_vec); | ||
380 | extern void gic_disable_interrupt(int irq_vec); | ||
381 | extern void gic_irq_ack(struct irq_data *d); | ||
382 | extern void gic_finish_irq(struct irq_data *d); | ||
383 | extern void gic_platform_init(int irqs, struct irq_chip *irq_controller); | ||
384 | #endif /* _ASM_GICREGS_H */ | ||
diff --git a/arch/mips/include/asm/hpet.h b/arch/mips/include/asm/hpet.h new file mode 100644 index 000000000000..18a8f778bfaa --- /dev/null +++ b/arch/mips/include/asm/hpet.h | |||
@@ -0,0 +1,73 @@ | |||
1 | #ifndef _ASM_HPET_H | ||
2 | #define _ASM_HPET_H | ||
3 | |||
4 | #ifdef CONFIG_RS780_HPET | ||
5 | |||
6 | #define HPET_MMAP_SIZE 1024 | ||
7 | |||
8 | #define HPET_ID 0x000 | ||
9 | #define HPET_PERIOD 0x004 | ||
10 | #define HPET_CFG 0x010 | ||
11 | #define HPET_STATUS 0x020 | ||
12 | #define HPET_COUNTER 0x0f0 | ||
13 | |||
14 | #define HPET_Tn_CFG(n) (0x100 + 0x20 * n) | ||
15 | #define HPET_Tn_CMP(n) (0x108 + 0x20 * n) | ||
16 | #define HPET_Tn_ROUTE(n) (0x110 + 0x20 * n) | ||
17 | |||
18 | #define HPET_T0_IRS 0x001 | ||
19 | #define HPET_T1_IRS 0x002 | ||
20 | #define HPET_T3_IRS 0x004 | ||
21 | |||
22 | #define HPET_T0_CFG 0x100 | ||
23 | #define HPET_T0_CMP 0x108 | ||
24 | #define HPET_T0_ROUTE 0x110 | ||
25 | #define HPET_T1_CFG 0x120 | ||
26 | #define HPET_T1_CMP 0x128 | ||
27 | #define HPET_T1_ROUTE 0x130 | ||
28 | #define HPET_T2_CFG 0x140 | ||
29 | #define HPET_T2_CMP 0x148 | ||
30 | #define HPET_T2_ROUTE 0x150 | ||
31 | |||
32 | #define HPET_ID_REV 0x000000ff | ||
33 | #define HPET_ID_NUMBER 0x00001f00 | ||
34 | #define HPET_ID_64BIT 0x00002000 | ||
35 | #define HPET_ID_LEGSUP 0x00008000 | ||
36 | #define HPET_ID_VENDOR 0xffff0000 | ||
37 | #define HPET_ID_NUMBER_SHIFT 8 | ||
38 | #define HPET_ID_VENDOR_SHIFT 16 | ||
39 | |||
40 | #define HPET_CFG_ENABLE 0x001 | ||
41 | #define HPET_CFG_LEGACY 0x002 | ||
42 | #define HPET_LEGACY_8254 2 | ||
43 | #define HPET_LEGACY_RTC 8 | ||
44 | |||
45 | #define HPET_TN_LEVEL 0x0002 | ||
46 | #define HPET_TN_ENABLE 0x0004 | ||
47 | #define HPET_TN_PERIODIC 0x0008 | ||
48 | #define HPET_TN_PERIODIC_CAP 0x0010 | ||
49 | #define HPET_TN_64BIT_CAP 0x0020 | ||
50 | #define HPET_TN_SETVAL 0x0040 | ||
51 | #define HPET_TN_32BIT 0x0100 | ||
52 | #define HPET_TN_ROUTE 0x3e00 | ||
53 | #define HPET_TN_FSB 0x4000 | ||
54 | #define HPET_TN_FSB_CAP 0x8000 | ||
55 | #define HPET_TN_ROUTE_SHIFT 9 | ||
56 | |||
57 | /* Max HPET Period is 10^8 femto sec as in HPET spec */ | ||
58 | #define HPET_MAX_PERIOD 100000000UL | ||
59 | /* | ||
60 | * Min HPET period is 10^5 femto sec just for safety. If it is less than this, | ||
61 | * then 32 bit HPET counter wrapsaround in less than 0.5 sec. | ||
62 | */ | ||
63 | #define HPET_MIN_PERIOD 100000UL | ||
64 | |||
65 | #define HPET_ADDR 0x20000 | ||
66 | #define HPET_MMIO_ADDR 0x90000e0000020000 | ||
67 | #define HPET_FREQ 14318780 | ||
68 | #define HPET_COMPARE_VAL ((HPET_FREQ + HZ / 2) / HZ) | ||
69 | #define HPET_T0_IRQ 0 | ||
70 | |||
71 | extern void __init setup_hpet_timer(void); | ||
72 | #endif /* CONFIG_RS780_HPET */ | ||
73 | #endif /* _ASM_HPET_H */ | ||
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 933b50e125a0..9e777cd42b67 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h | |||
@@ -167,7 +167,7 @@ static inline void * isa_bus_to_virt(unsigned long address) | |||
167 | */ | 167 | */ |
168 | #define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) | 168 | #define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) |
169 | 169 | ||
170 | extern void __iomem * __ioremap(phys_t offset, phys_t size, unsigned long flags); | 170 | extern void __iomem * __ioremap(phys_addr_t offset, phys_addr_t size, unsigned long flags); |
171 | extern void __iounmap(const volatile void __iomem *addr); | 171 | extern void __iounmap(const volatile void __iomem *addr); |
172 | 172 | ||
173 | #ifndef CONFIG_PCI | 173 | #ifndef CONFIG_PCI |
@@ -175,7 +175,7 @@ struct pci_dev; | |||
175 | static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} | 175 | static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} |
176 | #endif | 176 | #endif |
177 | 177 | ||
178 | static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size, | 178 | static inline void __iomem * __ioremap_mode(phys_addr_t offset, unsigned long size, |
179 | unsigned long flags) | 179 | unsigned long flags) |
180 | { | 180 | { |
181 | void __iomem *addr = plat_ioremap(offset, size, flags); | 181 | void __iomem *addr = plat_ioremap(offset, size, flags); |
@@ -183,7 +183,7 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size, | |||
183 | if (addr) | 183 | if (addr) |
184 | return addr; | 184 | return addr; |
185 | 185 | ||
186 | #define __IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL)) | 186 | #define __IS_LOW512(addr) (!((phys_addr_t)(addr) & (phys_addr_t) ~0x1fffffffULL)) |
187 | 187 | ||
188 | if (cpu_has_64bit_addresses) { | 188 | if (cpu_has_64bit_addresses) { |
189 | u64 base = UNCAC_BASE; | 189 | u64 base = UNCAC_BASE; |
@@ -197,7 +197,7 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size, | |||
197 | return (void __iomem *) (unsigned long) (base + offset); | 197 | return (void __iomem *) (unsigned long) (base + offset); |
198 | } else if (__builtin_constant_p(offset) && | 198 | } else if (__builtin_constant_p(offset) && |
199 | __builtin_constant_p(size) && __builtin_constant_p(flags)) { | 199 | __builtin_constant_p(size) && __builtin_constant_p(flags)) { |
200 | phys_t phys_addr, last_addr; | 200 | phys_addr_t phys_addr, last_addr; |
201 | 201 | ||
202 | phys_addr = fixup_bigphys_addr(offset, size); | 202 | phys_addr = fixup_bigphys_addr(offset, size); |
203 | 203 | ||
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index 39f07aec640c..5a4e1bb8fb1b 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h | |||
@@ -48,4 +48,7 @@ extern int cp0_compare_irq; | |||
48 | extern int cp0_compare_irq_shift; | 48 | extern int cp0_compare_irq_shift; |
49 | extern int cp0_perfcount_irq; | 49 | extern int cp0_perfcount_irq; |
50 | 50 | ||
51 | void arch_trigger_all_cpu_backtrace(bool); | ||
52 | #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace | ||
53 | |||
51 | #endif /* _ASM_IRQ_H */ | 54 | #endif /* _ASM_IRQ_H */ |
diff --git a/arch/mips/include/asm/irq_cpu.h b/arch/mips/include/asm/irq_cpu.h index 3f11fdb3ed8c..39a160bb41dc 100644 --- a/arch/mips/include/asm/irq_cpu.h +++ b/arch/mips/include/asm/irq_cpu.h | |||
@@ -19,8 +19,8 @@ extern void rm9k_cpu_irq_init(void); | |||
19 | 19 | ||
20 | #ifdef CONFIG_IRQ_DOMAIN | 20 | #ifdef CONFIG_IRQ_DOMAIN |
21 | struct device_node; | 21 | struct device_node; |
22 | extern int mips_cpu_intc_init(struct device_node *of_node, | 22 | extern int mips_cpu_irq_of_init(struct device_node *of_node, |
23 | struct device_node *parent); | 23 | struct device_node *parent); |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | #endif /* _ASM_IRQ_CPU_H */ | 26 | #endif /* _ASM_IRQ_CPU_H */ |
diff --git a/arch/mips/include/asm/mach-ath25/ath25_platform.h b/arch/mips/include/asm/mach-ath25/ath25_platform.h new file mode 100644 index 000000000000..4f4ee4f9e5ec --- /dev/null +++ b/arch/mips/include/asm/mach-ath25/ath25_platform.h | |||
@@ -0,0 +1,73 @@ | |||
1 | #ifndef __ASM_MACH_ATH25_PLATFORM_H | ||
2 | #define __ASM_MACH_ATH25_PLATFORM_H | ||
3 | |||
4 | #include <linux/etherdevice.h> | ||
5 | |||
6 | /* | ||
7 | * This is board-specific data that is stored in a "fixed" location in flash. | ||
8 | * It is shared across operating systems, so it should not be changed lightly. | ||
9 | * The main reason we need it is in order to extract the ethernet MAC | ||
10 | * address(es). | ||
11 | */ | ||
12 | struct ath25_boarddata { | ||
13 | u32 magic; /* board data is valid */ | ||
14 | #define ATH25_BD_MAGIC 0x35333131 /* "5311", for all 531x/231x platforms */ | ||
15 | u16 cksum; /* checksum (starting with BD_REV 2) */ | ||
16 | u16 rev; /* revision of this struct */ | ||
17 | #define BD_REV 4 | ||
18 | char board_name[64]; /* Name of board */ | ||
19 | u16 major; /* Board major number */ | ||
20 | u16 minor; /* Board minor number */ | ||
21 | u32 flags; /* Board configuration */ | ||
22 | #define BD_ENET0 0x00000001 /* ENET0 is stuffed */ | ||
23 | #define BD_ENET1 0x00000002 /* ENET1 is stuffed */ | ||
24 | #define BD_UART1 0x00000004 /* UART1 is stuffed */ | ||
25 | #define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */ | ||
26 | #define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */ | ||
27 | #define BD_SYSLED 0x00000020 /* System LED stuffed */ | ||
28 | #define BD_EXTUARTCLK 0x00000040 /* External UART clock */ | ||
29 | #define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */ | ||
30 | #define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */ | ||
31 | #define BD_WLAN0 0x00000200 /* Enable WLAN0 */ | ||
32 | #define BD_MEMCAP 0x00000400 /* CAP SDRAM @ mem_cap for testing */ | ||
33 | #define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */ | ||
34 | #define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */ | ||
35 | #define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */ | ||
36 | #define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */ | ||
37 | #define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */ | ||
38 | #define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */ | ||
39 | #define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */ | ||
40 | u16 reset_config_gpio; /* Reset factory GPIO pin */ | ||
41 | u16 sys_led_gpio; /* System LED GPIO pin */ | ||
42 | |||
43 | u32 cpu_freq; /* CPU core frequency in Hz */ | ||
44 | u32 sys_freq; /* System frequency in Hz */ | ||
45 | u32 cnt_freq; /* Calculated C0_COUNT frequency */ | ||
46 | |||
47 | u8 wlan0_mac[ETH_ALEN]; | ||
48 | u8 enet0_mac[ETH_ALEN]; | ||
49 | u8 enet1_mac[ETH_ALEN]; | ||
50 | |||
51 | u16 pci_id; /* Pseudo PCIID for common code */ | ||
52 | u16 mem_cap; /* cap bank1 in MB */ | ||
53 | |||
54 | /* version 3 */ | ||
55 | u8 wlan1_mac[ETH_ALEN]; /* (ar5212) */ | ||
56 | }; | ||
57 | |||
58 | #define BOARD_CONFIG_BUFSZ 0x1000 | ||
59 | |||
60 | /* | ||
61 | * Platform device information for the Wireless MAC | ||
62 | */ | ||
63 | struct ar231x_board_config { | ||
64 | u16 devid; | ||
65 | |||
66 | /* board config data */ | ||
67 | struct ath25_boarddata *config; | ||
68 | |||
69 | /* radio calibration data */ | ||
70 | const char *radio; | ||
71 | }; | ||
72 | |||
73 | #endif /* __ASM_MACH_ATH25_PLATFORM_H */ | ||
diff --git a/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h new file mode 100644 index 000000000000..ade0356df257 --- /dev/null +++ b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Atheros AR231x/AR531x SoC specific CPU feature overrides | ||
3 | * | ||
4 | * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> | ||
5 | * | ||
6 | * This file was derived from: include/asm-mips/cpu-features.h | ||
7 | * Copyright (C) 2003, 2004 Ralf Baechle | ||
8 | * Copyright (C) 2004 Maciej W. Rozycki | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | #ifndef __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H | ||
16 | #define __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H | ||
17 | |||
18 | /* | ||
19 | * The Atheros AR531x/AR231x SoCs have MIPS 4Kc/4KEc core. | ||
20 | */ | ||
21 | #define cpu_has_tlb 1 | ||
22 | #define cpu_has_4kex 1 | ||
23 | #define cpu_has_3k_cache 0 | ||
24 | #define cpu_has_4k_cache 1 | ||
25 | #define cpu_has_tx39_cache 0 | ||
26 | #define cpu_has_sb1_cache 0 | ||
27 | #define cpu_has_fpu 0 | ||
28 | #define cpu_has_32fpr 0 | ||
29 | #define cpu_has_counter 1 | ||
30 | #define cpu_has_ejtag 1 | ||
31 | |||
32 | #if !defined(CONFIG_SOC_AR5312) | ||
33 | # define cpu_has_llsc 1 | ||
34 | #else | ||
35 | /* | ||
36 | * The MIPS 4Kc V0.9 core in the AR5312/AR2312 have problems with the | ||
37 | * ll/sc instructions. | ||
38 | */ | ||
39 | # define cpu_has_llsc 0 | ||
40 | #endif | ||
41 | |||
42 | #define cpu_has_mips16 0 | ||
43 | #define cpu_has_mdmx 0 | ||
44 | #define cpu_has_mips3d 0 | ||
45 | #define cpu_has_smartmips 0 | ||
46 | |||
47 | #define cpu_has_mips32r1 1 | ||
48 | |||
49 | #if !defined(CONFIG_SOC_AR5312) | ||
50 | # define cpu_has_mips32r2 1 | ||
51 | #endif | ||
52 | |||
53 | #define cpu_has_mips64r1 0 | ||
54 | #define cpu_has_mips64r2 0 | ||
55 | |||
56 | #define cpu_has_dsp 0 | ||
57 | #define cpu_has_mipsmt 0 | ||
58 | |||
59 | #define cpu_has_64bits 0 | ||
60 | #define cpu_has_64bit_zero_reg 0 | ||
61 | #define cpu_has_64bit_gp_regs 0 | ||
62 | #define cpu_has_64bit_addresses 0 | ||
63 | |||
64 | #endif /* __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H */ | ||
diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h b/arch/mips/include/asm/mach-ath25/dma-coherence.h new file mode 100644 index 000000000000..d8009c93a465 --- /dev/null +++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org> | ||
7 | * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> | ||
8 | * | ||
9 | */ | ||
10 | #ifndef __ASM_MACH_ATH25_DMA_COHERENCE_H | ||
11 | #define __ASM_MACH_ATH25_DMA_COHERENCE_H | ||
12 | |||
13 | #include <linux/device.h> | ||
14 | |||
15 | /* | ||
16 | * We need some arbitrary non-zero value to be programmed to the BAR1 register | ||
17 | * of PCI host controller to enable DMA. The same value should be used as the | ||
18 | * offset to calculate the physical address of DMA buffer for PCI devices. | ||
19 | */ | ||
20 | #define AR2315_PCI_HOST_SDRAM_BASEADDR 0x20000000 | ||
21 | |||
22 | static inline dma_addr_t ath25_dev_offset(struct device *dev) | ||
23 | { | ||
24 | #ifdef CONFIG_PCI | ||
25 | extern struct bus_type pci_bus_type; | ||
26 | |||
27 | if (dev && dev->bus == &pci_bus_type) | ||
28 | return AR2315_PCI_HOST_SDRAM_BASEADDR; | ||
29 | #endif | ||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | static inline dma_addr_t | ||
34 | plat_map_dma_mem(struct device *dev, void *addr, size_t size) | ||
35 | { | ||
36 | return virt_to_phys(addr) + ath25_dev_offset(dev); | ||
37 | } | ||
38 | |||
39 | static inline dma_addr_t | ||
40 | plat_map_dma_mem_page(struct device *dev, struct page *page) | ||
41 | { | ||
42 | return page_to_phys(page) + ath25_dev_offset(dev); | ||
43 | } | ||
44 | |||
45 | static inline unsigned long | ||
46 | plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr) | ||
47 | { | ||
48 | return dma_addr - ath25_dev_offset(dev); | ||
49 | } | ||
50 | |||
51 | static inline void | ||
52 | plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
53 | enum dma_data_direction direction) | ||
54 | { | ||
55 | } | ||
56 | |||
57 | static inline int plat_dma_supported(struct device *dev, u64 mask) | ||
58 | { | ||
59 | return 1; | ||
60 | } | ||
61 | |||
62 | static inline void plat_extra_sync_for_device(struct device *dev) | ||
63 | { | ||
64 | } | ||
65 | |||
66 | static inline int plat_dma_mapping_error(struct device *dev, | ||
67 | dma_addr_t dma_addr) | ||
68 | { | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static inline int plat_device_is_coherent(struct device *dev) | ||
73 | { | ||
74 | #ifdef CONFIG_DMA_COHERENT | ||
75 | return 1; | ||
76 | #endif | ||
77 | #ifdef CONFIG_DMA_NONCOHERENT | ||
78 | return 0; | ||
79 | #endif | ||
80 | } | ||
81 | |||
82 | #endif /* __ASM_MACH_ATH25_DMA_COHERENCE_H */ | ||
diff --git a/arch/mips/include/asm/mach-ath25/gpio.h b/arch/mips/include/asm/mach-ath25/gpio.h new file mode 100644 index 000000000000..713564b8e8ef --- /dev/null +++ b/arch/mips/include/asm/mach-ath25/gpio.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef __ASM_MACH_ATH25_GPIO_H | ||
2 | #define __ASM_MACH_ATH25_GPIO_H | ||
3 | |||
4 | #include <asm-generic/gpio.h> | ||
5 | |||
6 | #define gpio_get_value __gpio_get_value | ||
7 | #define gpio_set_value __gpio_set_value | ||
8 | #define gpio_cansleep __gpio_cansleep | ||
9 | #define gpio_to_irq __gpio_to_irq | ||
10 | |||
11 | static inline int irq_to_gpio(unsigned irq) | ||
12 | { | ||
13 | return -EINVAL; | ||
14 | } | ||
15 | |||
16 | #endif /* __ASM_MACH_ATH25_GPIO_H */ | ||
diff --git a/arch/mips/include/asm/mach-ath25/war.h b/arch/mips/include/asm/mach-ath25/war.h new file mode 100644 index 000000000000..e3a5250ebd67 --- /dev/null +++ b/arch/mips/include/asm/mach-ath25/war.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> | ||
7 | */ | ||
8 | #ifndef __ASM_MACH_ATH25_WAR_H | ||
9 | #define __ASM_MACH_ATH25_WAR_H | ||
10 | |||
11 | #define R4600_V1_INDEX_ICACHEOP_WAR 0 | ||
12 | #define R4600_V1_HIT_CACHEOP_WAR 0 | ||
13 | #define R4600_V2_HIT_CACHEOP_WAR 0 | ||
14 | #define R5432_CP0_INTERRUPT_WAR 0 | ||
15 | #define BCM1250_M3_WAR 0 | ||
16 | #define SIBYTE_1956_WAR 0 | ||
17 | #define MIPS4K_ICACHE_REFILL_WAR 0 | ||
18 | #define MIPS_CACHE_SYNC_WAR 0 | ||
19 | #define TX49XX_ICACHE_INDEX_INV_WAR 0 | ||
20 | #define RM9000_CDEX_SMP_WAR 0 | ||
21 | #define ICACHE_REFILLS_WORKAROUND_WAR 0 | ||
22 | #define R10000_LLSC_WAR 0 | ||
23 | #define MIPS34K_MISSED_ITLB_WAR 0 | ||
24 | |||
25 | #endif /* __ASM_MACH_ATH25_WAR_H */ | ||
diff --git a/arch/mips/include/asm/mach-au1x00/ioremap.h b/arch/mips/include/asm/mach-au1x00/ioremap.h index 75a94ad3ac91..99fea1fbb4f5 100644 --- a/arch/mips/include/asm/mach-au1x00/ioremap.h +++ b/arch/mips/include/asm/mach-au1x00/ioremap.h | |||
@@ -11,10 +11,10 @@ | |||
11 | 11 | ||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | 13 | ||
14 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_PCI) | 14 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_PCI) |
15 | extern phys_t __fixup_bigphys_addr(phys_t, phys_t); | 15 | extern phys_addr_t __fixup_bigphys_addr(phys_addr_t, phys_addr_t); |
16 | #else | 16 | #else |
17 | static inline phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size) | 17 | static inline phys_addr_t __fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) |
18 | { | 18 | { |
19 | return phys_addr; | 19 | return phys_addr; |
20 | } | 20 | } |
@@ -23,12 +23,12 @@ static inline phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size) | |||
23 | /* | 23 | /* |
24 | * Allow physical addresses to be fixed up to help 36-bit peripherals. | 24 | * Allow physical addresses to be fixed up to help 36-bit peripherals. |
25 | */ | 25 | */ |
26 | static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) | 26 | static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) |
27 | { | 27 | { |
28 | return __fixup_bigphys_addr(phys_addr, size); | 28 | return __fixup_bigphys_addr(phys_addr, size); |
29 | } | 29 | } |
30 | 30 | ||
31 | static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, | 31 | static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size, |
32 | unsigned long flags) | 32 | unsigned long flags) |
33 | { | 33 | { |
34 | return NULL; | 34 | return NULL; |
diff --git a/arch/mips/include/asm/mach-bcm3384/dma-coherence.h b/arch/mips/include/asm/mach-bcm3384/dma-coherence.h new file mode 100644 index 000000000000..a3be8e50e1f0 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm3384/dma-coherence.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org> | ||
3 | * Copyright (C) 2009 Broadcom Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef __ASM_MACH_BCM3384_DMA_COHERENCE_H | ||
16 | #define __ASM_MACH_BCM3384_DMA_COHERENCE_H | ||
17 | |||
18 | struct device; | ||
19 | |||
20 | extern dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size); | ||
21 | extern dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page); | ||
22 | extern unsigned long plat_dma_addr_to_phys(struct device *dev, | ||
23 | dma_addr_t dma_addr); | ||
24 | |||
25 | static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, | ||
26 | size_t size, enum dma_data_direction direction) | ||
27 | { | ||
28 | } | ||
29 | |||
30 | static inline int plat_dma_supported(struct device *dev, u64 mask) | ||
31 | { | ||
32 | /* | ||
33 | * we fall back to GFP_DMA when the mask isn't all 1s, | ||
34 | * so we can't guarantee allocations that must be | ||
35 | * within a tighter range than GFP_DMA.. | ||
36 | */ | ||
37 | if (mask < DMA_BIT_MASK(24)) | ||
38 | return 0; | ||
39 | |||
40 | return 1; | ||
41 | } | ||
42 | |||
43 | static inline int plat_device_is_coherent(struct device *dev) | ||
44 | { | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | #endif /* __ASM_MACH_BCM3384_DMA_COHERENCE_H */ | ||
diff --git a/arch/mips/include/asm/mach-bcm3384/war.h b/arch/mips/include/asm/mach-bcm3384/war.h new file mode 100644 index 000000000000..59d7599059b0 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm3384/war.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> | ||
7 | */ | ||
8 | #ifndef __ASM_MIPS_MACH_BCM3384_WAR_H | ||
9 | #define __ASM_MIPS_MACH_BCM3384_WAR_H | ||
10 | |||
11 | #define R4600_V1_INDEX_ICACHEOP_WAR 0 | ||
12 | #define R4600_V1_HIT_CACHEOP_WAR 0 | ||
13 | #define R4600_V2_HIT_CACHEOP_WAR 0 | ||
14 | #define R5432_CP0_INTERRUPT_WAR 0 | ||
15 | #define BCM1250_M3_WAR 0 | ||
16 | #define SIBYTE_1956_WAR 0 | ||
17 | #define MIPS4K_ICACHE_REFILL_WAR 0 | ||
18 | #define MIPS_CACHE_SYNC_WAR 0 | ||
19 | #define TX49XX_ICACHE_INDEX_INV_WAR 0 | ||
20 | #define ICACHE_REFILLS_WORKAROUND_WAR 0 | ||
21 | #define R10000_LLSC_WAR 0 | ||
22 | #define MIPS34K_MISSED_ITLB_WAR 0 | ||
23 | |||
24 | #endif /* __ASM_MIPS_MACH_BCM3384_WAR_H */ | ||
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h index 36a3fc1aa3ae..ee59ffe99922 100644 --- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h +++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h | |||
@@ -14,40 +14,8 @@ | |||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | 16 | ||
17 | struct nvram_header { | 17 | int bcm47xx_nvram_init_from_mem(u32 base, u32 lim); |
18 | u32 magic; | 18 | int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len); |
19 | u32 len; | ||
20 | u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ | ||
21 | u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ | ||
22 | u32 config_ncdl; /* ncdl values for memc */ | ||
23 | }; | ||
24 | |||
25 | #define NVRAM_HEADER 0x48534C46 /* 'FLSH' */ | ||
26 | #define NVRAM_VERSION 1 | ||
27 | #define NVRAM_HEADER_SIZE 20 | ||
28 | #define NVRAM_SPACE 0x8000 | ||
29 | |||
30 | #define FLASH_MIN 0x00020000 /* Minimum flash size */ | ||
31 | |||
32 | #define NVRAM_MAX_VALUE_LEN 255 | ||
33 | #define NVRAM_MAX_PARAM_LEN 64 | ||
34 | |||
35 | extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len); | ||
36 | |||
37 | static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6]) | ||
38 | { | ||
39 | if (strchr(buf, ':')) | ||
40 | sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], | ||
41 | &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], | ||
42 | &macaddr[5]); | ||
43 | else if (strchr(buf, '-')) | ||
44 | sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0], | ||
45 | &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4], | ||
46 | &macaddr[5]); | ||
47 | else | ||
48 | printk(KERN_WARNING "Can not parse mac address: %s\n", buf); | ||
49 | } | ||
50 | |||
51 | int bcm47xx_nvram_gpio_pin(const char *name); | 19 | int bcm47xx_nvram_gpio_pin(const char *name); |
52 | 20 | ||
53 | #endif /* __BCM47XX_NVRAM_H */ | 21 | #endif /* __BCM47XX_NVRAM_H */ |
diff --git a/arch/mips/include/asm/mach-bcm63xx/ioremap.h b/arch/mips/include/asm/mach-bcm63xx/ioremap.h index ff15e3b14e7a..aea6e64b828f 100644 --- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h +++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h | |||
@@ -3,12 +3,12 @@ | |||
3 | 3 | ||
4 | #include <bcm63xx_cpu.h> | 4 | #include <bcm63xx_cpu.h> |
5 | 5 | ||
6 | static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) | 6 | static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) |
7 | { | 7 | { |
8 | return phys_addr; | 8 | return phys_addr; |
9 | } | 9 | } |
10 | 10 | ||
11 | static inline int is_bcm63xx_internal_registers(phys_t offset) | 11 | static inline int is_bcm63xx_internal_registers(phys_addr_t offset) |
12 | { | 12 | { |
13 | switch (bcm63xx_get_cpu_id()) { | 13 | switch (bcm63xx_get_cpu_id()) { |
14 | case BCM3368_CPU_ID: | 14 | case BCM3368_CPU_ID: |
@@ -32,7 +32,7 @@ static inline int is_bcm63xx_internal_registers(phys_t offset) | |||
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, | 35 | static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size, |
36 | unsigned long flags) | 36 | unsigned long flags) |
37 | { | 37 | { |
38 | if (is_bcm63xx_internal_registers(offset)) | 38 | if (is_bcm63xx_internal_registers(offset)) |
diff --git a/arch/mips/include/asm/mach-generic/ioremap.h b/arch/mips/include/asm/mach-generic/ioremap.h index b379938d47f0..513371f7c39c 100644 --- a/arch/mips/include/asm/mach-generic/ioremap.h +++ b/arch/mips/include/asm/mach-generic/ioremap.h | |||
@@ -15,12 +15,12 @@ | |||
15 | * Allow physical addresses to be fixed up to help peripherals located | 15 | * Allow physical addresses to be fixed up to help peripherals located |
16 | * outside the low 32-bit range -- generic pass-through version. | 16 | * outside the low 32-bit range -- generic pass-through version. |
17 | */ | 17 | */ |
18 | static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) | 18 | static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) |
19 | { | 19 | { |
20 | return phys_addr; | 20 | return phys_addr; |
21 | } | 21 | } |
22 | 22 | ||
23 | static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, | 23 | static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size, |
24 | unsigned long flags) | 24 | unsigned long flags) |
25 | { | 25 | { |
26 | return NULL; | 26 | return NULL; |
diff --git a/arch/mips/include/asm/mach-generic/irq.h b/arch/mips/include/asm/mach-generic/irq.h index 139cd200e79d..050e18bb1a04 100644 --- a/arch/mips/include/asm/mach-generic/irq.h +++ b/arch/mips/include/asm/mach-generic/irq.h | |||
@@ -36,4 +36,10 @@ | |||
36 | 36 | ||
37 | #endif /* CONFIG_IRQ_CPU */ | 37 | #endif /* CONFIG_IRQ_CPU */ |
38 | 38 | ||
39 | #ifdef CONFIG_MIPS_GIC | ||
40 | #ifndef MIPS_GIC_IRQ_BASE | ||
41 | #define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) | ||
42 | #endif | ||
43 | #endif /* CONFIG_MIPS_GIC */ | ||
44 | |||
39 | #endif /* __ASM_MACH_GENERIC_IRQ_H */ | 45 | #endif /* __ASM_MACH_GENERIC_IRQ_H */ |
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h index f196cceb7322..4e5ae6523cb4 100644 --- a/arch/mips/include/asm/mach-lantiq/lantiq.h +++ b/arch/mips/include/asm/mach-lantiq/lantiq.h | |||
@@ -48,6 +48,8 @@ extern struct clk *clk_get_ppe(void); | |||
48 | extern unsigned char ltq_boot_select(void); | 48 | extern unsigned char ltq_boot_select(void); |
49 | /* find out what caused the last cpu reset */ | 49 | /* find out what caused the last cpu reset */ |
50 | extern int ltq_reset_cause(void); | 50 | extern int ltq_reset_cause(void); |
51 | /* find out the soc type */ | ||
52 | extern int ltq_soc_type(void); | ||
51 | 53 | ||
52 | #define IOPORT_RESOURCE_START 0x10000000 | 54 | #define IOPORT_RESOURCE_START 0x10000000 |
53 | #define IOPORT_RESOURCE_END 0xffffffff | 55 | #define IOPORT_RESOURCE_END 0xffffffff |
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h index 3388fc53599e..fa802926523f 100644 --- a/arch/mips/include/asm/mach-loongson/boot_param.h +++ b/arch/mips/include/asm/mach-loongson/boot_param.h | |||
@@ -10,7 +10,8 @@ | |||
10 | #define VIDEO_ROM 7 | 10 | #define VIDEO_ROM 7 |
11 | #define ADAPTER_ROM 8 | 11 | #define ADAPTER_ROM 8 |
12 | #define ACPI_TABLE 9 | 12 | #define ACPI_TABLE 9 |
13 | #define MAX_MEMORY_TYPE 10 | 13 | #define SMBIOS_TABLE 10 |
14 | #define MAX_MEMORY_TYPE 11 | ||
14 | 15 | ||
15 | #define LOONGSON3_BOOT_MEM_MAP_MAX 128 | 16 | #define LOONGSON3_BOOT_MEM_MAP_MAX 128 |
16 | struct efi_memory_map_loongson { | 17 | struct efi_memory_map_loongson { |
@@ -42,15 +43,49 @@ struct efi_cpuinfo_loongson { | |||
42 | u32 processor_id; /* PRID, e.g. 6305, 6306 */ | 43 | u32 processor_id; /* PRID, e.g. 6305, 6306 */ |
43 | u32 cputype; /* Loongson_3A/3B, etc. */ | 44 | u32 cputype; /* Loongson_3A/3B, etc. */ |
44 | u32 total_node; /* num of total numa nodes */ | 45 | u32 total_node; /* num of total numa nodes */ |
45 | u32 cpu_startup_core_id; /* Core id */ | 46 | u16 cpu_startup_core_id; /* Boot core id */ |
47 | u16 reserved_cores_mask; | ||
46 | u32 cpu_clock_freq; /* cpu_clock */ | 48 | u32 cpu_clock_freq; /* cpu_clock */ |
47 | u32 nr_cpus; | 49 | u32 nr_cpus; |
48 | } __packed; | 50 | } __packed; |
49 | 51 | ||
52 | #define MAX_UARTS 64 | ||
53 | struct uart_device { | ||
54 | u32 iotype; /* see include/linux/serial_core.h */ | ||
55 | u32 uartclk; | ||
56 | u32 int_offset; | ||
57 | u64 uart_base; | ||
58 | } __packed; | ||
59 | |||
60 | #define MAX_SENSORS 64 | ||
61 | #define SENSOR_TEMPER 0x00000001 | ||
62 | #define SENSOR_VOLTAGE 0x00000002 | ||
63 | #define SENSOR_FAN 0x00000004 | ||
64 | struct sensor_device { | ||
65 | char name[32]; /* a formal name */ | ||
66 | char label[64]; /* a flexible description */ | ||
67 | u32 type; /* SENSOR_* */ | ||
68 | u32 id; /* instance id of a sensor-class */ | ||
69 | u32 fan_policy; /* see loongson_hwmon.h */ | ||
70 | u32 fan_percent;/* only for constant speed policy */ | ||
71 | u64 base_addr; /* base address of device registers */ | ||
72 | } __packed; | ||
73 | |||
50 | struct system_loongson { | 74 | struct system_loongson { |
51 | u16 vers; /* version of system_loongson */ | 75 | u16 vers; /* version of system_loongson */ |
52 | u32 ccnuma_smp; /* 0: no numa; 1: has numa */ | 76 | u32 ccnuma_smp; /* 0: no numa; 1: has numa */ |
53 | u32 sing_double_channel; /* 1:single; 2:double */ | 77 | u32 sing_double_channel; /* 1:single; 2:double */ |
78 | u32 nr_uarts; | ||
79 | struct uart_device uarts[MAX_UARTS]; | ||
80 | u32 nr_sensors; | ||
81 | struct sensor_device sensors[MAX_SENSORS]; | ||
82 | char has_ec; | ||
83 | char ec_name[32]; | ||
84 | u64 ec_base_addr; | ||
85 | char has_tcm; | ||
86 | char tcm_name[32]; | ||
87 | u64 tcm_base_addr; | ||
88 | u64 workarounds; /* see workarounds.h */ | ||
54 | } __packed; | 89 | } __packed; |
55 | 90 | ||
56 | struct irq_source_routing_table { | 91 | struct irq_source_routing_table { |
@@ -149,6 +184,8 @@ struct loongson_system_configuration { | |||
149 | u32 nr_nodes; | 184 | u32 nr_nodes; |
150 | int cores_per_node; | 185 | int cores_per_node; |
151 | int cores_per_package; | 186 | int cores_per_package; |
187 | u16 boot_cpu_id; | ||
188 | u16 reserved_cpus_mask; | ||
152 | enum loongson_cpu_type cputype; | 189 | enum loongson_cpu_type cputype; |
153 | u64 ht_control_base; | 190 | u64 ht_control_base; |
154 | u64 pci_mem_start_addr; | 191 | u64 pci_mem_start_addr; |
@@ -159,9 +196,15 @@ struct loongson_system_configuration { | |||
159 | u64 suspend_addr; | 196 | u64 suspend_addr; |
160 | u64 vgabios_addr; | 197 | u64 vgabios_addr; |
161 | u32 dma_mask_bits; | 198 | u32 dma_mask_bits; |
199 | char ecname[32]; | ||
200 | u32 nr_uarts; | ||
201 | struct uart_device uarts[MAX_UARTS]; | ||
202 | u32 nr_sensors; | ||
203 | struct sensor_device sensors[MAX_SENSORS]; | ||
204 | u64 workarounds; | ||
162 | }; | 205 | }; |
163 | 206 | ||
164 | extern struct efi_memory_map_loongson *loongson_memmap; | 207 | extern struct efi_memory_map_loongson *loongson_memmap; |
165 | extern struct loongson_system_configuration loongson_sysconf; | 208 | extern struct loongson_system_configuration loongson_sysconf; |
166 | extern int cpuhotplug_workaround; | 209 | |
167 | #endif | 210 | #endif |
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h index 6a902751cc7f..a90534161bd2 100644 --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h | |||
@@ -23,7 +23,7 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, | |||
23 | size_t size) | 23 | size_t size) |
24 | { | 24 | { |
25 | #ifdef CONFIG_CPU_LOONGSON3 | 25 | #ifdef CONFIG_CPU_LOONGSON3 |
26 | return virt_to_phys(addr); | 26 | return phys_to_dma(dev, virt_to_phys(addr)); |
27 | #else | 27 | #else |
28 | return virt_to_phys(addr) | 0x80000000; | 28 | return virt_to_phys(addr) | 0x80000000; |
29 | #endif | 29 | #endif |
@@ -33,7 +33,7 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, | |||
33 | struct page *page) | 33 | struct page *page) |
34 | { | 34 | { |
35 | #ifdef CONFIG_CPU_LOONGSON3 | 35 | #ifdef CONFIG_CPU_LOONGSON3 |
36 | return page_to_phys(page); | 36 | return phys_to_dma(dev, page_to_phys(page)); |
37 | #else | 37 | #else |
38 | return page_to_phys(page) | 0x80000000; | 38 | return page_to_phys(page) | 0x80000000; |
39 | #endif | 39 | #endif |
@@ -43,7 +43,7 @@ static inline unsigned long plat_dma_addr_to_phys(struct device *dev, | |||
43 | dma_addr_t dma_addr) | 43 | dma_addr_t dma_addr) |
44 | { | 44 | { |
45 | #if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT) | 45 | #if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT) |
46 | return dma_addr; | 46 | return dma_to_phys(dev, dma_addr); |
47 | #elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) | 47 | #elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) |
48 | return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff); | 48 | return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff); |
49 | #else | 49 | #else |
diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h index 34560bda6626..a281cca5f2fb 100644 --- a/arch/mips/include/asm/mach-loongson/irq.h +++ b/arch/mips/include/asm/mach-loongson/irq.h | |||
@@ -32,8 +32,7 @@ | |||
32 | #define LOONGSON_INT_ROUTER_LPC LOONGSON_INT_ROUTER_ENTRY(0x0a) | 32 | #define LOONGSON_INT_ROUTER_LPC LOONGSON_INT_ROUTER_ENTRY(0x0a) |
33 | #define LOONGSON_INT_ROUTER_HT1(n) LOONGSON_INT_ROUTER_ENTRY(n + 0x18) | 33 | #define LOONGSON_INT_ROUTER_HT1(n) LOONGSON_INT_ROUTER_ENTRY(n + 0x18) |
34 | 34 | ||
35 | #define LOONGSON_INT_CORE0_INT0 0x11 /* route to int 0 of core 0 */ | 35 | #define LOONGSON_INT_COREx_INTy(x, y) (1<<(x) | 1<<(y+4)) /* route to int y of core x */ |
36 | #define LOONGSON_INT_CORE0_INT1 0x21 /* route to int 1 of core 0 */ | ||
37 | 36 | ||
38 | #endif | 37 | #endif |
39 | 38 | ||
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h index 92bf76c21441..5459ac09679f 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson/loongson.h | |||
@@ -35,7 +35,7 @@ extern void __init prom_init_cmdline(void); | |||
35 | extern void __init prom_init_machtype(void); | 35 | extern void __init prom_init_machtype(void); |
36 | extern void __init prom_init_env(void); | 36 | extern void __init prom_init_env(void); |
37 | #ifdef CONFIG_LOONGSON_UART_BASE | 37 | #ifdef CONFIG_LOONGSON_UART_BASE |
38 | extern unsigned long _loongson_uart_base, loongson_uart_base; | 38 | extern unsigned long _loongson_uart_base[], loongson_uart_base[]; |
39 | extern void prom_init_loongson_uart_base(void); | 39 | extern void prom_init_loongson_uart_base(void); |
40 | #endif | 40 | #endif |
41 | 41 | ||
diff --git a/arch/mips/include/asm/mach-loongson/loongson_hwmon.h b/arch/mips/include/asm/mach-loongson/loongson_hwmon.h new file mode 100644 index 000000000000..4431fc54a36c --- /dev/null +++ b/arch/mips/include/asm/mach-loongson/loongson_hwmon.h | |||
@@ -0,0 +1,55 @@ | |||
1 | #ifndef __LOONGSON_HWMON_H_ | ||
2 | #define __LOONGSON_HWMON_H_ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | #define MIN_TEMP 0 | ||
7 | #define MAX_TEMP 255 | ||
8 | #define NOT_VALID_TEMP 999 | ||
9 | |||
10 | typedef int (*get_temp_fun)(int); | ||
11 | extern int loongson3_cpu_temp(int); | ||
12 | |||
13 | /* 0:Max speed, 1:Manual, 2:Auto */ | ||
14 | enum fan_control_mode { | ||
15 | FAN_FULL_MODE = 0, | ||
16 | FAN_MANUAL_MODE = 1, | ||
17 | FAN_AUTO_MODE = 2, | ||
18 | FAN_MODE_END | ||
19 | }; | ||
20 | |||
21 | struct temp_range { | ||
22 | u8 low; | ||
23 | u8 high; | ||
24 | u8 level; | ||
25 | }; | ||
26 | |||
27 | #define CONSTANT_SPEED_POLICY 0 /* at constent speed */ | ||
28 | #define STEP_SPEED_POLICY 1 /* use up/down arrays to describe policy */ | ||
29 | #define KERNEL_HELPER_POLICY 2 /* kernel as a helper to fan control */ | ||
30 | |||
31 | #define MAX_STEP_NUM 16 | ||
32 | #define MAX_FAN_LEVEL 255 | ||
33 | |||
34 | /* loongson_fan_policy works when fan work at FAN_AUTO_MODE */ | ||
35 | struct loongson_fan_policy { | ||
36 | u8 type; | ||
37 | |||
38 | /* percent only used when type is CONSTANT_SPEED_POLICY */ | ||
39 | u8 percent; | ||
40 | |||
41 | /* period between two check. (Unit: S) */ | ||
42 | u8 adjust_period; | ||
43 | |||
44 | /* fan adjust usually depend on a temprature input */ | ||
45 | get_temp_fun depend_temp; | ||
46 | |||
47 | /* up_step/down_step used when type is STEP_SPEED_POLICY */ | ||
48 | u8 up_step_num; | ||
49 | u8 down_step_num; | ||
50 | struct temp_range up_step[MAX_STEP_NUM]; | ||
51 | struct temp_range down_step[MAX_STEP_NUM]; | ||
52 | struct delayed_work work; | ||
53 | }; | ||
54 | |||
55 | #endif /* __LOONGSON_HWMON_H_*/ | ||
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h index 228e37847a36..cb2b60249cd2 100644 --- a/arch/mips/include/asm/mach-loongson/machine.h +++ b/arch/mips/include/asm/mach-loongson/machine.h | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #ifdef CONFIG_LOONGSON_MACH3X | 27 | #ifdef CONFIG_LOONGSON_MACH3X |
28 | 28 | ||
29 | #define LOONGSON_MACHTYPE MACH_LEMOTE_A1101 | 29 | #define LOONGSON_MACHTYPE MACH_LOONGSON_GENERIC |
30 | 30 | ||
31 | #endif /* CONFIG_LOONGSON_MACH3X */ | 31 | #endif /* CONFIG_LOONGSON_MACH3X */ |
32 | 32 | ||
diff --git a/arch/mips/include/asm/mach-loongson/topology.h b/arch/mips/include/asm/mach-loongson/topology.h index 5598ba77d2ef..0d8f3b55bdbc 100644 --- a/arch/mips/include/asm/mach-loongson/topology.h +++ b/arch/mips/include/asm/mach-loongson/topology.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | #ifdef CONFIG_NUMA | 4 | #ifdef CONFIG_NUMA |
5 | 5 | ||
6 | #define cpu_to_node(cpu) ((cpu) >> 2) | 6 | #define cpu_to_node(cpu) (cpu_logical_map(cpu) >> 2) |
7 | #define parent_node(node) (node) | 7 | #define parent_node(node) (node) |
8 | #define cpumask_of_node(node) (&__node_data[(node)]->cpumask) | 8 | #define cpumask_of_node(node) (&__node_data[(node)]->cpumask) |
9 | 9 | ||
diff --git a/arch/mips/include/asm/mach-loongson/workarounds.h b/arch/mips/include/asm/mach-loongson/workarounds.h new file mode 100644 index 000000000000..e180c1422eae --- /dev/null +++ b/arch/mips/include/asm/mach-loongson/workarounds.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __ASM_MACH_LOONGSON_WORKAROUNDS_H_ | ||
2 | #define __ASM_MACH_LOONGSON_WORKAROUNDS_H_ | ||
3 | |||
4 | #define WORKAROUND_CPUFREQ 0x00000001 | ||
5 | #define WORKAROUND_CPUHOTPLUG 0x00000002 | ||
6 | |||
7 | #endif | ||
diff --git a/arch/mips/include/asm/mach-loongson1/cpufreq.h b/arch/mips/include/asm/mach-loongson1/cpufreq.h new file mode 100644 index 000000000000..e7765ce30bcf --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/cpufreq.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * Loongson 1 CPUFreq platform support. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | |||
13 | #ifndef __ASM_MACH_LOONGSON1_CPUFREQ_H | ||
14 | #define __ASM_MACH_LOONGSON1_CPUFREQ_H | ||
15 | |||
16 | struct plat_ls1x_cpufreq { | ||
17 | const char *clk_name; /* CPU clk */ | ||
18 | const char *osc_clk_name; /* OSC clk */ | ||
19 | unsigned int max_freq; /* in kHz */ | ||
20 | unsigned int min_freq; /* in kHz */ | ||
21 | }; | ||
22 | |||
23 | #endif /* __ASM_MACH_LOONGSON1_CPUFREQ_H */ | ||
diff --git a/arch/mips/include/asm/mach-loongson1/loongson1.h b/arch/mips/include/asm/mach-loongson1/loongson1.h index 5c437c2ba6b3..20e0c2b155dd 100644 --- a/arch/mips/include/asm/mach-loongson1/loongson1.h +++ b/arch/mips/include/asm/mach-loongson1/loongson1.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define DEFAULT_MEMSIZE 256 /* If no memsize provided */ | 16 | #define DEFAULT_MEMSIZE 256 /* If no memsize provided */ |
17 | 17 | ||
18 | /* Loongson 1 Register Bases */ | 18 | /* Loongson 1 Register Bases */ |
19 | #define LS1X_MUX_BASE 0x1fd00420 | ||
19 | #define LS1X_INTC_BASE 0x1fd01040 | 20 | #define LS1X_INTC_BASE 0x1fd01040 |
20 | #define LS1X_EHCI_BASE 0x1fe00000 | 21 | #define LS1X_EHCI_BASE 0x1fe00000 |
21 | #define LS1X_OHCI_BASE 0x1fe08000 | 22 | #define LS1X_OHCI_BASE 0x1fe08000 |
@@ -31,7 +32,10 @@ | |||
31 | #define LS1X_I2C0_BASE 0x1fe58000 | 32 | #define LS1X_I2C0_BASE 0x1fe58000 |
32 | #define LS1X_I2C1_BASE 0x1fe68000 | 33 | #define LS1X_I2C1_BASE 0x1fe68000 |
33 | #define LS1X_I2C2_BASE 0x1fe70000 | 34 | #define LS1X_I2C2_BASE 0x1fe70000 |
34 | #define LS1X_PWM_BASE 0x1fe5c000 | 35 | #define LS1X_PWM0_BASE 0x1fe5c000 |
36 | #define LS1X_PWM1_BASE 0x1fe5c010 | ||
37 | #define LS1X_PWM2_BASE 0x1fe5c020 | ||
38 | #define LS1X_PWM3_BASE 0x1fe5c030 | ||
35 | #define LS1X_WDT_BASE 0x1fe5c060 | 39 | #define LS1X_WDT_BASE 0x1fe5c060 |
36 | #define LS1X_RTC_BASE 0x1fe64000 | 40 | #define LS1X_RTC_BASE 0x1fe64000 |
37 | #define LS1X_AC97_BASE 0x1fe74000 | 41 | #define LS1X_AC97_BASE 0x1fe74000 |
@@ -39,6 +43,8 @@ | |||
39 | #define LS1X_CLK_BASE 0x1fe78030 | 43 | #define LS1X_CLK_BASE 0x1fe78030 |
40 | 44 | ||
41 | #include <regs-clk.h> | 45 | #include <regs-clk.h> |
46 | #include <regs-mux.h> | ||
47 | #include <regs-pwm.h> | ||
42 | #include <regs-wdt.h> | 48 | #include <regs-wdt.h> |
43 | 49 | ||
44 | #endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */ | 50 | #endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */ |
diff --git a/arch/mips/include/asm/mach-loongson1/platform.h b/arch/mips/include/asm/mach-loongson1/platform.h index 30c13e508fff..47de55e0c835 100644 --- a/arch/mips/include/asm/mach-loongson1/platform.h +++ b/arch/mips/include/asm/mach-loongson1/platform.h | |||
@@ -13,10 +13,12 @@ | |||
13 | 13 | ||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | 15 | ||
16 | extern struct platform_device ls1x_uart_device; | 16 | extern struct platform_device ls1x_uart_pdev; |
17 | extern struct platform_device ls1x_eth0_device; | 17 | extern struct platform_device ls1x_cpufreq_pdev; |
18 | extern struct platform_device ls1x_ehci_device; | 18 | extern struct platform_device ls1x_eth0_pdev; |
19 | extern struct platform_device ls1x_rtc_device; | 19 | extern struct platform_device ls1x_eth1_pdev; |
20 | extern struct platform_device ls1x_ehci_pdev; | ||
21 | extern struct platform_device ls1x_rtc_pdev; | ||
20 | 22 | ||
21 | extern void __init ls1x_clk_init(void); | 23 | extern void __init ls1x_clk_init(void); |
22 | extern void __init ls1x_serial_setup(struct platform_device *pdev); | 24 | extern void __init ls1x_serial_setup(struct platform_device *pdev); |
diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson1/regs-clk.h index fb6a3ff9318f..ee2445b10fc3 100644 --- a/arch/mips/include/asm/mach-loongson1/regs-clk.h +++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h | |||
@@ -20,15 +20,32 @@ | |||
20 | 20 | ||
21 | /* Clock PLL Divisor Register Bits */ | 21 | /* Clock PLL Divisor Register Bits */ |
22 | #define DIV_DC_EN (0x1 << 31) | 22 | #define DIV_DC_EN (0x1 << 31) |
23 | #define DIV_DC_RST (0x1 << 30) | ||
23 | #define DIV_CPU_EN (0x1 << 25) | 24 | #define DIV_CPU_EN (0x1 << 25) |
25 | #define DIV_CPU_RST (0x1 << 24) | ||
24 | #define DIV_DDR_EN (0x1 << 19) | 26 | #define DIV_DDR_EN (0x1 << 19) |
27 | #define DIV_DDR_RST (0x1 << 18) | ||
28 | #define RST_DC_EN (0x1 << 5) | ||
29 | #define RST_DC (0x1 << 4) | ||
30 | #define RST_DDR_EN (0x1 << 3) | ||
31 | #define RST_DDR (0x1 << 2) | ||
32 | #define RST_CPU_EN (0x1 << 1) | ||
33 | #define RST_CPU 0x1 | ||
25 | 34 | ||
26 | #define DIV_DC_SHIFT 26 | 35 | #define DIV_DC_SHIFT 26 |
27 | #define DIV_CPU_SHIFT 20 | 36 | #define DIV_CPU_SHIFT 20 |
28 | #define DIV_DDR_SHIFT 14 | 37 | #define DIV_DDR_SHIFT 14 |
29 | 38 | ||
30 | #define DIV_DC_WIDTH 5 | 39 | #define DIV_DC_WIDTH 4 |
31 | #define DIV_CPU_WIDTH 5 | 40 | #define DIV_CPU_WIDTH 4 |
32 | #define DIV_DDR_WIDTH 5 | 41 | #define DIV_DDR_WIDTH 4 |
42 | |||
43 | #define BYPASS_DC_SHIFT 12 | ||
44 | #define BYPASS_DDR_SHIFT 10 | ||
45 | #define BYPASS_CPU_SHIFT 8 | ||
46 | |||
47 | #define BYPASS_DC_WIDTH 1 | ||
48 | #define BYPASS_DDR_WIDTH 1 | ||
49 | #define BYPASS_CPU_WIDTH 1 | ||
33 | 50 | ||
34 | #endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */ | 51 | #endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */ |
diff --git a/arch/mips/include/asm/mach-loongson1/regs-mux.h b/arch/mips/include/asm/mach-loongson1/regs-mux.h new file mode 100644 index 000000000000..fb1e36efaa19 --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/regs-mux.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * Loongson 1 MUX Register Definitions. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef __ASM_MACH_LOONGSON1_REGS_MUX_H | ||
13 | #define __ASM_MACH_LOONGSON1_REGS_MUX_H | ||
14 | |||
15 | #define LS1X_MUX_REG(x) \ | ||
16 | ((void __iomem *)KSEG1ADDR(LS1X_MUX_BASE + (x))) | ||
17 | |||
18 | #define LS1X_MUX_CTRL0 LS1X_MUX_REG(0x0) | ||
19 | #define LS1X_MUX_CTRL1 LS1X_MUX_REG(0x4) | ||
20 | |||
21 | /* MUX CTRL0 Register Bits */ | ||
22 | #define UART0_USE_PWM23 (0x1 << 28) | ||
23 | #define UART0_USE_PWM01 (0x1 << 27) | ||
24 | #define UART1_USE_LCD0_5_6_11 (0x1 << 26) | ||
25 | #define I2C2_USE_CAN1 (0x1 << 25) | ||
26 | #define I2C1_USE_CAN0 (0x1 << 24) | ||
27 | #define NAND3_USE_UART5 (0x1 << 23) | ||
28 | #define NAND3_USE_UART4 (0x1 << 22) | ||
29 | #define NAND3_USE_UART1_DAT (0x1 << 21) | ||
30 | #define NAND3_USE_UART1_CTS (0x1 << 20) | ||
31 | #define NAND3_USE_PWM23 (0x1 << 19) | ||
32 | #define NAND3_USE_PWM01 (0x1 << 18) | ||
33 | #define NAND2_USE_UART5 (0x1 << 17) | ||
34 | #define NAND2_USE_UART4 (0x1 << 16) | ||
35 | #define NAND2_USE_UART1_DAT (0x1 << 15) | ||
36 | #define NAND2_USE_UART1_CTS (0x1 << 14) | ||
37 | #define NAND2_USE_PWM23 (0x1 << 13) | ||
38 | #define NAND2_USE_PWM01 (0x1 << 12) | ||
39 | #define NAND1_USE_UART5 (0x1 << 11) | ||
40 | #define NAND1_USE_UART4 (0x1 << 10) | ||
41 | #define NAND1_USE_UART1_DAT (0x1 << 9) | ||
42 | #define NAND1_USE_UART1_CTS (0x1 << 8) | ||
43 | #define NAND1_USE_PWM23 (0x1 << 7) | ||
44 | #define NAND1_USE_PWM01 (0x1 << 6) | ||
45 | #define GMAC1_USE_UART1 (0x1 << 4) | ||
46 | #define GMAC1_USE_UART0 (0x1 << 3) | ||
47 | #define LCD_USE_UART0_DAT (0x1 << 2) | ||
48 | #define LCD_USE_UART15 (0x1 << 1) | ||
49 | #define LCD_USE_UART0 0x1 | ||
50 | |||
51 | /* MUX CTRL1 Register Bits */ | ||
52 | #define USB_RESET (0x1 << 31) | ||
53 | #define SPI1_CS_USE_PWM01 (0x1 << 24) | ||
54 | #define SPI1_USE_CAN (0x1 << 23) | ||
55 | #define DISABLE_DDR_CONFSPACE (0x1 << 20) | ||
56 | #define DDR32TO16EN (0x1 << 16) | ||
57 | #define GMAC1_SHUT (0x1 << 13) | ||
58 | #define GMAC0_SHUT (0x1 << 12) | ||
59 | #define USB_SHUT (0x1 << 11) | ||
60 | #define UART1_3_USE_CAN1 (0x1 << 5) | ||
61 | #define UART1_2_USE_CAN0 (0x1 << 4) | ||
62 | #define GMAC1_USE_TXCLK (0x1 << 3) | ||
63 | #define GMAC0_USE_TXCLK (0x1 << 2) | ||
64 | #define GMAC1_USE_PWM23 (0x1 << 1) | ||
65 | #define GMAC0_USE_PWM01 0x1 | ||
66 | |||
67 | #endif /* __ASM_MACH_LOONGSON1_REGS_MUX_H */ | ||
diff --git a/arch/mips/include/asm/mach-loongson1/regs-pwm.h b/arch/mips/include/asm/mach-loongson1/regs-pwm.h new file mode 100644 index 000000000000..99f2bcc586f0 --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/regs-pwm.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * Loongson 1 PWM Register Definitions. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef __ASM_MACH_LOONGSON1_REGS_PWM_H | ||
13 | #define __ASM_MACH_LOONGSON1_REGS_PWM_H | ||
14 | |||
15 | /* Loongson 1 PWM Timer Register Definitions */ | ||
16 | #define PWM_CNT 0x0 | ||
17 | #define PWM_HRC 0x4 | ||
18 | #define PWM_LRC 0x8 | ||
19 | #define PWM_CTRL 0xc | ||
20 | |||
21 | /* PWM Control Register Bits */ | ||
22 | #define CNT_RST (0x1 << 7) | ||
23 | #define INT_SR (0x1 << 6) | ||
24 | #define INT_EN (0x1 << 5) | ||
25 | #define PWM_SINGLE (0x1 << 4) | ||
26 | #define PWM_OE (0x1 << 3) | ||
27 | #define CNT_EN 0x1 | ||
28 | |||
29 | #endif /* __ASM_MACH_LOONGSON1_REGS_PWM_H */ | ||
diff --git a/arch/mips/include/asm/mach-loongson1/regs-wdt.h b/arch/mips/include/asm/mach-loongson1/regs-wdt.h index 6574568c2084..c39ee982ad3b 100644 --- a/arch/mips/include/asm/mach-loongson1/regs-wdt.h +++ b/arch/mips/include/asm/mach-loongson1/regs-wdt.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> | 2 | * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> |
3 | * | 3 | * |
4 | * Loongson 1 watchdog register definitions. | 4 | * Loongson 1 Watchdog Register Definitions. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
@@ -12,11 +12,8 @@ | |||
12 | #ifndef __ASM_MACH_LOONGSON1_REGS_WDT_H | 12 | #ifndef __ASM_MACH_LOONGSON1_REGS_WDT_H |
13 | #define __ASM_MACH_LOONGSON1_REGS_WDT_H | 13 | #define __ASM_MACH_LOONGSON1_REGS_WDT_H |
14 | 14 | ||
15 | #define LS1X_WDT_REG(x) \ | 15 | #define WDT_EN 0x0 |
16 | ((void __iomem *)KSEG1ADDR(LS1X_WDT_BASE + (x))) | 16 | #define WDT_TIMER 0x4 |
17 | 17 | #define WDT_SET 0x8 | |
18 | #define LS1X_WDT_EN LS1X_WDT_REG(0x0) | ||
19 | #define LS1X_WDT_SET LS1X_WDT_REG(0x4) | ||
20 | #define LS1X_WDT_TIMER LS1X_WDT_REG(0x8) | ||
21 | 18 | ||
22 | #endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */ | 19 | #endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */ |
diff --git a/arch/mips/include/asm/mach-malta/irq.h b/arch/mips/include/asm/mach-malta/irq.h index f2c13d211abb..47cfe64efbb0 100644 --- a/arch/mips/include/asm/mach-malta/irq.h +++ b/arch/mips/include/asm/mach-malta/irq.h | |||
@@ -2,7 +2,6 @@ | |||
2 | #define __ASM_MACH_MIPS_IRQ_H | 2 | #define __ASM_MACH_MIPS_IRQ_H |
3 | 3 | ||
4 | 4 | ||
5 | #define GIC_NUM_INTRS (24 + NR_CPUS * 2) | ||
6 | #define NR_IRQS 256 | 5 | #define NR_IRQS 256 |
7 | 6 | ||
8 | #include_next <irq.h> | 7 | #include_next <irq.h> |
diff --git a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h index fc946c835995..2e54b4bff5cf 100644 --- a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h +++ b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h | |||
@@ -49,6 +49,7 @@ | |||
49 | 49 | ||
50 | #include <linux/types.h> | 50 | #include <linux/types.h> |
51 | 51 | ||
52 | #include <asm/compiler.h> | ||
52 | #include <asm/war.h> | 53 | #include <asm/war.h> |
53 | 54 | ||
54 | #ifndef R10000_LLSC_WAR | 55 | #ifndef R10000_LLSC_WAR |
@@ -84,8 +85,8 @@ static inline void set_value_reg32(volatile u32 *const addr, | |||
84 | " "__beqz"%0, 1b \n" | 85 | " "__beqz"%0, 1b \n" |
85 | " nop \n" | 86 | " nop \n" |
86 | " .set pop \n" | 87 | " .set pop \n" |
87 | : "=&r" (temp), "=m" (*addr) | 88 | : "=&r" (temp), "=" GCC_OFF12_ASM() (*addr) |
88 | : "ir" (~mask), "ir" (value), "m" (*addr)); | 89 | : "ir" (~mask), "ir" (value), GCC_OFF12_ASM() (*addr)); |
89 | } | 90 | } |
90 | 91 | ||
91 | /* | 92 | /* |
@@ -105,8 +106,8 @@ static inline void set_reg32(volatile u32 *const addr, | |||
105 | " "__beqz"%0, 1b \n" | 106 | " "__beqz"%0, 1b \n" |
106 | " nop \n" | 107 | " nop \n" |
107 | " .set pop \n" | 108 | " .set pop \n" |
108 | : "=&r" (temp), "=m" (*addr) | 109 | : "=&r" (temp), "=" GCC_OFF12_ASM() (*addr) |
109 | : "ir" (mask), "m" (*addr)); | 110 | : "ir" (mask), GCC_OFF12_ASM() (*addr)); |
110 | } | 111 | } |
111 | 112 | ||
112 | /* | 113 | /* |
@@ -126,8 +127,8 @@ static inline void clear_reg32(volatile u32 *const addr, | |||
126 | " "__beqz"%0, 1b \n" | 127 | " "__beqz"%0, 1b \n" |
127 | " nop \n" | 128 | " nop \n" |
128 | " .set pop \n" | 129 | " .set pop \n" |
129 | : "=&r" (temp), "=m" (*addr) | 130 | : "=&r" (temp), "=" GCC_OFF12_ASM() (*addr) |
130 | : "ir" (~mask), "m" (*addr)); | 131 | : "ir" (~mask), GCC_OFF12_ASM() (*addr)); |
131 | } | 132 | } |
132 | 133 | ||
133 | /* | 134 | /* |
@@ -147,8 +148,8 @@ static inline void toggle_reg32(volatile u32 *const addr, | |||
147 | " "__beqz"%0, 1b \n" | 148 | " "__beqz"%0, 1b \n" |
148 | " nop \n" | 149 | " nop \n" |
149 | " .set pop \n" | 150 | " .set pop \n" |
150 | : "=&r" (temp), "=m" (*addr) | 151 | : "=&r" (temp), "=" GCC_OFF12_ASM() (*addr) |
151 | : "ir" (mask), "m" (*addr)); | 152 | : "ir" (mask), GCC_OFF12_ASM() (*addr)); |
152 | } | 153 | } |
153 | 154 | ||
154 | /* | 155 | /* |
@@ -219,8 +220,8 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr) | |||
219 | " .set arch=r4000 \n" \ | 220 | " .set arch=r4000 \n" \ |
220 | "1: ll %0, %1 #custom_read_reg32 \n" \ | 221 | "1: ll %0, %1 #custom_read_reg32 \n" \ |
221 | " .set pop \n" \ | 222 | " .set pop \n" \ |
222 | : "=r" (tmp), "=m" (*address) \ | 223 | : "=r" (tmp), "=" GCC_OFF12_ASM() (*address) \ |
223 | : "m" (*address)) | 224 | : GCC_OFF12_ASM() (*address)) |
224 | 225 | ||
225 | #define custom_write_reg32(address, tmp) \ | 226 | #define custom_write_reg32(address, tmp) \ |
226 | __asm__ __volatile__( \ | 227 | __asm__ __volatile__( \ |
@@ -230,7 +231,7 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr) | |||
230 | " "__beqz"%0, 1b \n" \ | 231 | " "__beqz"%0, 1b \n" \ |
231 | " nop \n" \ | 232 | " nop \n" \ |
232 | " .set pop \n" \ | 233 | " .set pop \n" \ |
233 | : "=&r" (tmp), "=m" (*address) \ | 234 | : "=&r" (tmp), "=" GCC_OFF12_ASM() (*address) \ |
234 | : "0" (tmp), "m" (*address)) | 235 | : "0" (tmp), GCC_OFF12_ASM() (*address)) |
235 | 236 | ||
236 | #endif /* __ASM_REGOPS_H__ */ | 237 | #endif /* __ASM_REGOPS_H__ */ |
diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h index 6f9b24f51157..1976fb815fd1 100644 --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h | |||
@@ -13,6 +13,13 @@ | |||
13 | #ifndef _MT7620_REGS_H_ | 13 | #ifndef _MT7620_REGS_H_ |
14 | #define _MT7620_REGS_H_ | 14 | #define _MT7620_REGS_H_ |
15 | 15 | ||
16 | enum mt762x_soc_type { | ||
17 | MT762X_SOC_UNKNOWN = 0, | ||
18 | MT762X_SOC_MT7620A, | ||
19 | MT762X_SOC_MT7620N, | ||
20 | MT762X_SOC_MT7628AN, | ||
21 | }; | ||
22 | |||
16 | #define MT7620_SYSC_BASE 0x10000000 | 23 | #define MT7620_SYSC_BASE 0x10000000 |
17 | 24 | ||
18 | #define SYSC_REG_CHIP_NAME0 0x00 | 25 | #define SYSC_REG_CHIP_NAME0 0x00 |
@@ -25,11 +32,9 @@ | |||
25 | #define SYSC_REG_CPLL_CONFIG0 0x54 | 32 | #define SYSC_REG_CPLL_CONFIG0 0x54 |
26 | #define SYSC_REG_CPLL_CONFIG1 0x58 | 33 | #define SYSC_REG_CPLL_CONFIG1 0x58 |
27 | 34 | ||
28 | #define MT7620N_CHIP_NAME0 0x33365452 | 35 | #define MT7620_CHIP_NAME0 0x3637544d |
29 | #define MT7620N_CHIP_NAME1 0x20203235 | 36 | #define MT7620_CHIP_NAME1 0x20203032 |
30 | 37 | #define MT7628_CHIP_NAME1 0x20203832 | |
31 | #define MT7620A_CHIP_NAME0 0x3637544d | ||
32 | #define MT7620A_CHIP_NAME1 0x20203032 | ||
33 | 38 | ||
34 | #define SYSCFG0_XTAL_FREQ_SEL BIT(6) | 39 | #define SYSCFG0_XTAL_FREQ_SEL BIT(6) |
35 | 40 | ||
@@ -74,6 +79,9 @@ | |||
74 | #define SYSCFG0_DRAM_TYPE_DDR1 1 | 79 | #define SYSCFG0_DRAM_TYPE_DDR1 1 |
75 | #define SYSCFG0_DRAM_TYPE_DDR2 2 | 80 | #define SYSCFG0_DRAM_TYPE_DDR2 2 |
76 | 81 | ||
82 | #define SYSCFG0_DRAM_TYPE_DDR2_MT7628 0 | ||
83 | #define SYSCFG0_DRAM_TYPE_DDR1_MT7628 1 | ||
84 | |||
77 | #define MT7620_DRAM_BASE 0x0 | 85 | #define MT7620_DRAM_BASE 0x0 |
78 | #define MT7620_SDRAM_SIZE_MIN 2 | 86 | #define MT7620_SDRAM_SIZE_MIN 2 |
79 | #define MT7620_SDRAM_SIZE_MAX 64 | 87 | #define MT7620_SDRAM_SIZE_MAX 64 |
@@ -82,7 +90,6 @@ | |||
82 | #define MT7620_DDR2_SIZE_MIN 32 | 90 | #define MT7620_DDR2_SIZE_MIN 32 |
83 | #define MT7620_DDR2_SIZE_MAX 256 | 91 | #define MT7620_DDR2_SIZE_MAX 256 |
84 | 92 | ||
85 | #define MT7620_GPIO_MODE_I2C BIT(0) | ||
86 | #define MT7620_GPIO_MODE_UART0_SHIFT 2 | 93 | #define MT7620_GPIO_MODE_UART0_SHIFT 2 |
87 | #define MT7620_GPIO_MODE_UART0_MASK 0x7 | 94 | #define MT7620_GPIO_MODE_UART0_MASK 0x7 |
88 | #define MT7620_GPIO_MODE_UART0(x) ((x) << MT7620_GPIO_MODE_UART0_SHIFT) | 95 | #define MT7620_GPIO_MODE_UART0(x) ((x) << MT7620_GPIO_MODE_UART0_SHIFT) |
@@ -94,15 +101,40 @@ | |||
94 | #define MT7620_GPIO_MODE_GPIO_UARTF 0x5 | 101 | #define MT7620_GPIO_MODE_GPIO_UARTF 0x5 |
95 | #define MT7620_GPIO_MODE_GPIO_I2S 0x6 | 102 | #define MT7620_GPIO_MODE_GPIO_I2S 0x6 |
96 | #define MT7620_GPIO_MODE_GPIO 0x7 | 103 | #define MT7620_GPIO_MODE_GPIO 0x7 |
97 | #define MT7620_GPIO_MODE_UART1 BIT(5) | 104 | |
98 | #define MT7620_GPIO_MODE_MDIO BIT(8) | 105 | #define MT7620_GPIO_MODE_NAND 0 |
99 | #define MT7620_GPIO_MODE_RGMII1 BIT(9) | 106 | #define MT7620_GPIO_MODE_SD 1 |
100 | #define MT7620_GPIO_MODE_RGMII2 BIT(10) | 107 | #define MT7620_GPIO_MODE_ND_SD_GPIO 2 |
101 | #define MT7620_GPIO_MODE_SPI BIT(11) | 108 | #define MT7620_GPIO_MODE_ND_SD_MASK 0x3 |
102 | #define MT7620_GPIO_MODE_SPI_REF_CLK BIT(12) | 109 | #define MT7620_GPIO_MODE_ND_SD_SHIFT 18 |
103 | #define MT7620_GPIO_MODE_WLED BIT(13) | 110 | |
104 | #define MT7620_GPIO_MODE_JTAG BIT(15) | 111 | #define MT7620_GPIO_MODE_PCIE_RST 0 |
105 | #define MT7620_GPIO_MODE_EPHY BIT(15) | 112 | #define MT7620_GPIO_MODE_PCIE_REF 1 |
106 | #define MT7620_GPIO_MODE_WDT BIT(22) | 113 | #define MT7620_GPIO_MODE_PCIE_GPIO 2 |
114 | #define MT7620_GPIO_MODE_PCIE_MASK 0x3 | ||
115 | #define MT7620_GPIO_MODE_PCIE_SHIFT 16 | ||
116 | |||
117 | #define MT7620_GPIO_MODE_WDT_RST 0 | ||
118 | #define MT7620_GPIO_MODE_WDT_REF 1 | ||
119 | #define MT7620_GPIO_MODE_WDT_GPIO 2 | ||
120 | #define MT7620_GPIO_MODE_WDT_MASK 0x3 | ||
121 | #define MT7620_GPIO_MODE_WDT_SHIFT 21 | ||
122 | |||
123 | #define MT7620_GPIO_MODE_I2C 0 | ||
124 | #define MT7620_GPIO_MODE_UART1 5 | ||
125 | #define MT7620_GPIO_MODE_MDIO 8 | ||
126 | #define MT7620_GPIO_MODE_RGMII1 9 | ||
127 | #define MT7620_GPIO_MODE_RGMII2 10 | ||
128 | #define MT7620_GPIO_MODE_SPI 11 | ||
129 | #define MT7620_GPIO_MODE_SPI_REF_CLK 12 | ||
130 | #define MT7620_GPIO_MODE_WLED 13 | ||
131 | #define MT7620_GPIO_MODE_JTAG 15 | ||
132 | #define MT7620_GPIO_MODE_EPHY 15 | ||
133 | #define MT7620_GPIO_MODE_PA 20 | ||
134 | |||
135 | static inline int mt7620_get_eco(void) | ||
136 | { | ||
137 | return rt_sysc_r32(SYSC_REG_CHIP_REV) & CHIP_REV_ECO_MASK; | ||
138 | } | ||
107 | 139 | ||
108 | #endif | 140 | #endif |
diff --git a/arch/mips/include/asm/mach-ralink/pinmux.h b/arch/mips/include/asm/mach-ralink/pinmux.h new file mode 100644 index 000000000000..be106cb2e26d --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/pinmux.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License version 2 as | ||
4 | * publishhed by the Free Software Foundation. | ||
5 | * | ||
6 | * Copyright (C) 2012 John Crispin <blogic@openwrt.org> | ||
7 | */ | ||
8 | |||
9 | #ifndef _RT288X_PINMUX_H__ | ||
10 | #define _RT288X_PINMUX_H__ | ||
11 | |||
12 | #define FUNC(name, value, pin_first, pin_count) \ | ||
13 | { name, value, pin_first, pin_count } | ||
14 | |||
15 | #define GRP(_name, _func, _mask, _shift) \ | ||
16 | { .name = _name, .mask = _mask, .shift = _shift, \ | ||
17 | .func = _func, .gpio = _mask, \ | ||
18 | .func_count = ARRAY_SIZE(_func) } | ||
19 | |||
20 | #define GRP_G(_name, _func, _mask, _gpio, _shift) \ | ||
21 | { .name = _name, .mask = _mask, .shift = _shift, \ | ||
22 | .func = _func, .gpio = _gpio, \ | ||
23 | .func_count = ARRAY_SIZE(_func) } | ||
24 | |||
25 | struct rt2880_pmx_group; | ||
26 | |||
27 | struct rt2880_pmx_func { | ||
28 | const char *name; | ||
29 | const char value; | ||
30 | |||
31 | int pin_first; | ||
32 | int pin_count; | ||
33 | int *pins; | ||
34 | |||
35 | int *groups; | ||
36 | int group_count; | ||
37 | |||
38 | int enabled; | ||
39 | }; | ||
40 | |||
41 | struct rt2880_pmx_group { | ||
42 | const char *name; | ||
43 | int enabled; | ||
44 | |||
45 | const u32 shift; | ||
46 | const char mask; | ||
47 | const char gpio; | ||
48 | |||
49 | struct rt2880_pmx_func *func; | ||
50 | int func_count; | ||
51 | }; | ||
52 | |||
53 | extern struct rt2880_pmx_group *rt2880_pinmux_data; | ||
54 | |||
55 | #endif | ||
diff --git a/arch/mips/include/asm/mach-ralink/ralink_regs.h b/arch/mips/include/asm/mach-ralink/ralink_regs.h index 5a508f9f9432..bd93014490df 100644 --- a/arch/mips/include/asm/mach-ralink/ralink_regs.h +++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h | |||
@@ -26,6 +26,13 @@ static inline u32 rt_sysc_r32(unsigned reg) | |||
26 | return __raw_readl(rt_sysc_membase + reg); | 26 | return __raw_readl(rt_sysc_membase + reg); |
27 | } | 27 | } |
28 | 28 | ||
29 | static inline void rt_sysc_m32(u32 clr, u32 set, unsigned reg) | ||
30 | { | ||
31 | u32 val = rt_sysc_r32(reg) & ~clr; | ||
32 | |||
33 | __raw_writel(val | set, rt_sysc_membase + reg); | ||
34 | } | ||
35 | |||
29 | static inline void rt_memc_w32(u32 val, unsigned reg) | 36 | static inline void rt_memc_w32(u32 val, unsigned reg) |
30 | { | 37 | { |
31 | __raw_writel(val, rt_memc_membase + reg); | 38 | __raw_writel(val, rt_memc_membase + reg); |
diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h index 069bf37a6010..96f731bac79a 100644 --- a/arch/mips/include/asm/mach-ralink/rt305x.h +++ b/arch/mips/include/asm/mach-ralink/rt305x.h | |||
@@ -125,24 +125,29 @@ static inline int soc_is_rt5350(void) | |||
125 | #define RT305X_GPIO_GE0_TXD0 40 | 125 | #define RT305X_GPIO_GE0_TXD0 40 |
126 | #define RT305X_GPIO_GE0_RXCLK 51 | 126 | #define RT305X_GPIO_GE0_RXCLK 51 |
127 | 127 | ||
128 | #define RT305X_GPIO_MODE_I2C BIT(0) | ||
129 | #define RT305X_GPIO_MODE_SPI BIT(1) | ||
130 | #define RT305X_GPIO_MODE_UART0_SHIFT 2 | 128 | #define RT305X_GPIO_MODE_UART0_SHIFT 2 |
131 | #define RT305X_GPIO_MODE_UART0_MASK 0x7 | 129 | #define RT305X_GPIO_MODE_UART0_MASK 0x7 |
132 | #define RT305X_GPIO_MODE_UART0(x) ((x) << RT305X_GPIO_MODE_UART0_SHIFT) | 130 | #define RT305X_GPIO_MODE_UART0(x) ((x) << RT305X_GPIO_MODE_UART0_SHIFT) |
133 | #define RT305X_GPIO_MODE_UARTF 0x0 | 131 | #define RT305X_GPIO_MODE_UARTF 0 |
134 | #define RT305X_GPIO_MODE_PCM_UARTF 0x1 | 132 | #define RT305X_GPIO_MODE_PCM_UARTF 1 |
135 | #define RT305X_GPIO_MODE_PCM_I2S 0x2 | 133 | #define RT305X_GPIO_MODE_PCM_I2S 2 |
136 | #define RT305X_GPIO_MODE_I2S_UARTF 0x3 | 134 | #define RT305X_GPIO_MODE_I2S_UARTF 3 |
137 | #define RT305X_GPIO_MODE_PCM_GPIO 0x4 | 135 | #define RT305X_GPIO_MODE_PCM_GPIO 4 |
138 | #define RT305X_GPIO_MODE_GPIO_UARTF 0x5 | 136 | #define RT305X_GPIO_MODE_GPIO_UARTF 5 |
139 | #define RT305X_GPIO_MODE_GPIO_I2S 0x6 | 137 | #define RT305X_GPIO_MODE_GPIO_I2S 6 |
140 | #define RT305X_GPIO_MODE_GPIO 0x7 | 138 | #define RT305X_GPIO_MODE_GPIO 7 |
141 | #define RT305X_GPIO_MODE_UART1 BIT(5) | 139 | |
142 | #define RT305X_GPIO_MODE_JTAG BIT(6) | 140 | #define RT305X_GPIO_MODE_I2C 0 |
143 | #define RT305X_GPIO_MODE_MDIO BIT(7) | 141 | #define RT305X_GPIO_MODE_SPI 1 |
144 | #define RT305X_GPIO_MODE_SDRAM BIT(8) | 142 | #define RT305X_GPIO_MODE_UART1 5 |
145 | #define RT305X_GPIO_MODE_RGMII BIT(9) | 143 | #define RT305X_GPIO_MODE_JTAG 6 |
144 | #define RT305X_GPIO_MODE_MDIO 7 | ||
145 | #define RT305X_GPIO_MODE_SDRAM 8 | ||
146 | #define RT305X_GPIO_MODE_RGMII 9 | ||
147 | #define RT5350_GPIO_MODE_PHY_LED 14 | ||
148 | #define RT5350_GPIO_MODE_SPI_CS1 21 | ||
149 | #define RT3352_GPIO_MODE_LNA 18 | ||
150 | #define RT3352_GPIO_MODE_PA 20 | ||
146 | 151 | ||
147 | #define RT3352_SYSC_REG_SYSCFG0 0x010 | 152 | #define RT3352_SYSC_REG_SYSCFG0 0x010 |
148 | #define RT3352_SYSC_REG_SYSCFG1 0x014 | 153 | #define RT3352_SYSC_REG_SYSCFG1 0x014 |
diff --git a/arch/mips/include/asm/mach-ralink/rt3883.h b/arch/mips/include/asm/mach-ralink/rt3883.h index 058382f37f92..0fbe6f9257cd 100644 --- a/arch/mips/include/asm/mach-ralink/rt3883.h +++ b/arch/mips/include/asm/mach-ralink/rt3883.h | |||
@@ -112,8 +112,6 @@ | |||
112 | #define RT3883_CLKCFG1_PCI_CLK_EN BIT(19) | 112 | #define RT3883_CLKCFG1_PCI_CLK_EN BIT(19) |
113 | #define RT3883_CLKCFG1_UPHY0_CLK_EN BIT(18) | 113 | #define RT3883_CLKCFG1_UPHY0_CLK_EN BIT(18) |
114 | 114 | ||
115 | #define RT3883_GPIO_MODE_I2C BIT(0) | ||
116 | #define RT3883_GPIO_MODE_SPI BIT(1) | ||
117 | #define RT3883_GPIO_MODE_UART0_SHIFT 2 | 115 | #define RT3883_GPIO_MODE_UART0_SHIFT 2 |
118 | #define RT3883_GPIO_MODE_UART0_MASK 0x7 | 116 | #define RT3883_GPIO_MODE_UART0_MASK 0x7 |
119 | #define RT3883_GPIO_MODE_UART0(x) ((x) << RT3883_GPIO_MODE_UART0_SHIFT) | 117 | #define RT3883_GPIO_MODE_UART0(x) ((x) << RT3883_GPIO_MODE_UART0_SHIFT) |
@@ -125,11 +123,15 @@ | |||
125 | #define RT3883_GPIO_MODE_GPIO_UARTF 0x5 | 123 | #define RT3883_GPIO_MODE_GPIO_UARTF 0x5 |
126 | #define RT3883_GPIO_MODE_GPIO_I2S 0x6 | 124 | #define RT3883_GPIO_MODE_GPIO_I2S 0x6 |
127 | #define RT3883_GPIO_MODE_GPIO 0x7 | 125 | #define RT3883_GPIO_MODE_GPIO 0x7 |
128 | #define RT3883_GPIO_MODE_UART1 BIT(5) | 126 | |
129 | #define RT3883_GPIO_MODE_JTAG BIT(6) | 127 | #define RT3883_GPIO_MODE_I2C 0 |
130 | #define RT3883_GPIO_MODE_MDIO BIT(7) | 128 | #define RT3883_GPIO_MODE_SPI 1 |
131 | #define RT3883_GPIO_MODE_GE1 BIT(9) | 129 | #define RT3883_GPIO_MODE_UART1 5 |
132 | #define RT3883_GPIO_MODE_GE2 BIT(10) | 130 | #define RT3883_GPIO_MODE_JTAG 6 |
131 | #define RT3883_GPIO_MODE_MDIO 7 | ||
132 | #define RT3883_GPIO_MODE_GE1 9 | ||
133 | #define RT3883_GPIO_MODE_GE2 10 | ||
134 | |||
133 | #define RT3883_GPIO_MODE_PCI_SHIFT 11 | 135 | #define RT3883_GPIO_MODE_PCI_SHIFT 11 |
134 | #define RT3883_GPIO_MODE_PCI_MASK 0x7 | 136 | #define RT3883_GPIO_MODE_PCI_MASK 0x7 |
135 | #define RT3883_GPIO_MODE_PCI (RT3883_GPIO_MODE_PCI_MASK << RT3883_GPIO_MODE_PCI_SHIFT) | 137 | #define RT3883_GPIO_MODE_PCI (RT3883_GPIO_MODE_PCI_MASK << RT3883_GPIO_MODE_PCI_SHIFT) |
diff --git a/arch/mips/include/asm/mach-sead3/irq.h b/arch/mips/include/asm/mach-sead3/irq.h index d8106f75b9af..5d154cfbcf4c 100644 --- a/arch/mips/include/asm/mach-sead3/irq.h +++ b/arch/mips/include/asm/mach-sead3/irq.h | |||
@@ -1,7 +1,6 @@ | |||
1 | #ifndef __ASM_MACH_MIPS_IRQ_H | 1 | #ifndef __ASM_MACH_MIPS_IRQ_H |
2 | #define __ASM_MACH_MIPS_IRQ_H | 2 | #define __ASM_MACH_MIPS_IRQ_H |
3 | 3 | ||
4 | #define GIC_NUM_INTRS (24 + NR_CPUS * 2) | ||
5 | #define NR_IRQS 256 | 4 | #define NR_IRQS 256 |
6 | 5 | ||
7 | 6 | ||
diff --git a/arch/mips/include/asm/mach-tx39xx/ioremap.h b/arch/mips/include/asm/mach-tx39xx/ioremap.h index 93c6c04ffda3..0874cd2b06d7 100644 --- a/arch/mips/include/asm/mach-tx39xx/ioremap.h +++ b/arch/mips/include/asm/mach-tx39xx/ioremap.h | |||
@@ -15,12 +15,12 @@ | |||
15 | * Allow physical addresses to be fixed up to help peripherals located | 15 | * Allow physical addresses to be fixed up to help peripherals located |
16 | * outside the low 32-bit range -- generic pass-through version. | 16 | * outside the low 32-bit range -- generic pass-through version. |
17 | */ | 17 | */ |
18 | static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) | 18 | static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) |
19 | { | 19 | { |
20 | return phys_addr; | 20 | return phys_addr; |
21 | } | 21 | } |
22 | 22 | ||
23 | static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, | 23 | static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size, |
24 | unsigned long flags) | 24 | unsigned long flags) |
25 | { | 25 | { |
26 | #define TXX9_DIRECTMAP_BASE 0xff000000ul | 26 | #define TXX9_DIRECTMAP_BASE 0xff000000ul |
diff --git a/arch/mips/include/asm/mach-tx49xx/ioremap.h b/arch/mips/include/asm/mach-tx49xx/ioremap.h index 1e7beae72229..4b6a8441b25f 100644 --- a/arch/mips/include/asm/mach-tx49xx/ioremap.h +++ b/arch/mips/include/asm/mach-tx49xx/ioremap.h | |||
@@ -15,12 +15,12 @@ | |||
15 | * Allow physical addresses to be fixed up to help peripherals located | 15 | * Allow physical addresses to be fixed up to help peripherals located |
16 | * outside the low 32-bit range -- generic pass-through version. | 16 | * outside the low 32-bit range -- generic pass-through version. |
17 | */ | 17 | */ |
18 | static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) | 18 | static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size) |
19 | { | 19 | { |
20 | return phys_addr; | 20 | return phys_addr; |
21 | } | 21 | } |
22 | 22 | ||
23 | static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size, | 23 | static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size, |
24 | unsigned long flags) | 24 | unsigned long flags) |
25 | { | 25 | { |
26 | #ifdef CONFIG_64BIT | 26 | #ifdef CONFIG_64BIT |
diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h index e330732ddf98..987ff580466b 100644 --- a/arch/mips/include/asm/mips-boards/maltaint.h +++ b/arch/mips/include/asm/mips-boards/maltaint.h | |||
@@ -10,7 +10,7 @@ | |||
10 | #ifndef _MIPS_MALTAINT_H | 10 | #ifndef _MIPS_MALTAINT_H |
11 | #define _MIPS_MALTAINT_H | 11 | #define _MIPS_MALTAINT_H |
12 | 12 | ||
13 | #define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) | 13 | #include <linux/irqchip/mips-gic.h> |
14 | 14 | ||
15 | /* | 15 | /* |
16 | * Interrupts 0..15 are used for Malta ISA compatible interrupts | 16 | * Interrupts 0..15 are used for Malta ISA compatible interrupts |
@@ -22,29 +22,28 @@ | |||
22 | #define MIPSCPU_INT_SW1 1 | 22 | #define MIPSCPU_INT_SW1 1 |
23 | #define MIPSCPU_INT_MB0 2 | 23 | #define MIPSCPU_INT_MB0 2 |
24 | #define MIPSCPU_INT_I8259A MIPSCPU_INT_MB0 | 24 | #define MIPSCPU_INT_I8259A MIPSCPU_INT_MB0 |
25 | #define MIPSCPU_INT_GIC MIPSCPU_INT_MB0 /* GIC chained interrupt */ | ||
25 | #define MIPSCPU_INT_MB1 3 | 26 | #define MIPSCPU_INT_MB1 3 |
26 | #define MIPSCPU_INT_SMI MIPSCPU_INT_MB1 | 27 | #define MIPSCPU_INT_SMI MIPSCPU_INT_MB1 |
27 | #define MIPSCPU_INT_IPI0 MIPSCPU_INT_MB1 /* GIC IPI */ | ||
28 | #define MIPSCPU_INT_MB2 4 | 28 | #define MIPSCPU_INT_MB2 4 |
29 | #define MIPSCPU_INT_IPI1 MIPSCPU_INT_MB2 /* GIC IPI */ | ||
30 | #define MIPSCPU_INT_MB3 5 | 29 | #define MIPSCPU_INT_MB3 5 |
31 | #define MIPSCPU_INT_COREHI MIPSCPU_INT_MB3 | 30 | #define MIPSCPU_INT_COREHI MIPSCPU_INT_MB3 |
32 | #define MIPSCPU_INT_MB4 6 | 31 | #define MIPSCPU_INT_MB4 6 |
33 | #define MIPSCPU_INT_CORELO MIPSCPU_INT_MB4 | 32 | #define MIPSCPU_INT_CORELO MIPSCPU_INT_MB4 |
34 | 33 | ||
35 | /* | 34 | /* |
36 | * Interrupts 64..127 are used for Soc-it Classic interrupts | 35 | * Interrupts 96..127 are used for Soc-it Classic interrupts |
37 | */ | 36 | */ |
38 | #define MSC01C_INT_BASE 64 | 37 | #define MSC01C_INT_BASE 96 |
39 | 38 | ||
40 | /* SOC-it Classic interrupt offsets */ | 39 | /* SOC-it Classic interrupt offsets */ |
41 | #define MSC01C_INT_TMR 0 | 40 | #define MSC01C_INT_TMR 0 |
42 | #define MSC01C_INT_PCI 1 | 41 | #define MSC01C_INT_PCI 1 |
43 | 42 | ||
44 | /* | 43 | /* |
45 | * Interrupts 64..127 are used for Soc-it EIC interrupts | 44 | * Interrupts 96..127 are used for Soc-it EIC interrupts |
46 | */ | 45 | */ |
47 | #define MSC01E_INT_BASE 64 | 46 | #define MSC01E_INT_BASE 96 |
48 | 47 | ||
49 | /* SOC-it EIC interrupt offsets */ | 48 | /* SOC-it EIC interrupt offsets */ |
50 | #define MSC01E_INT_SW0 1 | 49 | #define MSC01E_INT_SW0 1 |
@@ -63,14 +62,7 @@ | |||
63 | #define MSC01E_INT_PERFCTR 10 | 62 | #define MSC01E_INT_PERFCTR 10 |
64 | #define MSC01E_INT_CPUCTR 11 | 63 | #define MSC01E_INT_CPUCTR 11 |
65 | 64 | ||
66 | /* External Interrupts used for IPI */ | 65 | /* GIC external interrupts */ |
67 | #define GIC_IPI_EXT_INTR_RESCHED_VPE0 16 | 66 | #define GIC_INT_I8259A GIC_SHARED_TO_HWIRQ(3) |
68 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17 | ||
69 | #define GIC_IPI_EXT_INTR_RESCHED_VPE1 18 | ||
70 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE1 19 | ||
71 | #define GIC_IPI_EXT_INTR_RESCHED_VPE2 20 | ||
72 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE2 21 | ||
73 | #define GIC_IPI_EXT_INTR_RESCHED_VPE3 22 | ||
74 | #define GIC_IPI_EXT_INTR_CALLFNC_VPE3 23 | ||
75 | 67 | ||
76 | #endif /* !(_MIPS_MALTAINT_H) */ | 68 | #endif /* !(_MIPS_MALTAINT_H) */ |
diff --git a/arch/mips/include/asm/mips-boards/sead3int.h b/arch/mips/include/asm/mips-boards/sead3int.h index 6b17aaf7d901..8932c7de0419 100644 --- a/arch/mips/include/asm/mips-boards/sead3int.h +++ b/arch/mips/include/asm/mips-boards/sead3int.h | |||
@@ -10,10 +10,23 @@ | |||
10 | #ifndef _MIPS_SEAD3INT_H | 10 | #ifndef _MIPS_SEAD3INT_H |
11 | #define _MIPS_SEAD3INT_H | 11 | #define _MIPS_SEAD3INT_H |
12 | 12 | ||
13 | #include <linux/irqchip/mips-gic.h> | ||
14 | |||
13 | /* SEAD-3 GIC address space definitions. */ | 15 | /* SEAD-3 GIC address space definitions. */ |
14 | #define GIC_BASE_ADDR 0x1b1c0000 | 16 | #define GIC_BASE_ADDR 0x1b1c0000 |
15 | #define GIC_ADDRSPACE_SZ (128 * 1024) | 17 | #define GIC_ADDRSPACE_SZ (128 * 1024) |
16 | 18 | ||
17 | #define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 0) | 19 | /* CPU interrupt offsets */ |
20 | #define CPU_INT_GIC 2 | ||
21 | #define CPU_INT_EHCI 2 | ||
22 | #define CPU_INT_UART0 4 | ||
23 | #define CPU_INT_UART1 4 | ||
24 | #define CPU_INT_NET 6 | ||
25 | |||
26 | /* GIC interrupt offsets */ | ||
27 | #define GIC_INT_NET GIC_SHARED_TO_HWIRQ(0) | ||
28 | #define GIC_INT_UART1 GIC_SHARED_TO_HWIRQ(2) | ||
29 | #define GIC_INT_UART0 GIC_SHARED_TO_HWIRQ(3) | ||
30 | #define GIC_INT_EHCI GIC_SHARED_TO_HWIRQ(5) | ||
18 | 31 | ||
19 | #endif /* !(_MIPS_SEAD3INT_H) */ | 32 | #endif /* !(_MIPS_SEAD3INT_H) */ |
diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 6a9d2dd005ca..b95a827d763e 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h | |||
@@ -30,7 +30,7 @@ extern void __iomem *mips_cm_l2sync_base; | |||
30 | * different way by defining a function with the same prototype except for the | 30 | * different way by defining a function with the same prototype except for the |
31 | * name mips_cm_phys_base (without underscores). | 31 | * name mips_cm_phys_base (without underscores). |
32 | */ | 32 | */ |
33 | extern phys_t __mips_cm_phys_base(void); | 33 | extern phys_addr_t __mips_cm_phys_base(void); |
34 | 34 | ||
35 | /** | 35 | /** |
36 | * mips_cm_probe - probe for a Coherence Manager | 36 | * mips_cm_probe - probe for a Coherence Manager |
diff --git a/arch/mips/include/asm/mips-cpc.h b/arch/mips/include/asm/mips-cpc.h index e139a534e0fd..1cebe8c79051 100644 --- a/arch/mips/include/asm/mips-cpc.h +++ b/arch/mips/include/asm/mips-cpc.h | |||
@@ -25,7 +25,7 @@ extern void __iomem *mips_cpc_base; | |||
25 | * memory mapped registers. This is platform dependant & must therefore be | 25 | * memory mapped registers. This is platform dependant & must therefore be |
26 | * implemented per-platform. | 26 | * implemented per-platform. |
27 | */ | 27 | */ |
28 | extern phys_t mips_cpc_default_phys_base(void); | 28 | extern phys_addr_t mips_cpc_default_phys_base(void); |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * mips_cpc_phys_base - retrieve the physical base address of the CPC | 31 | * mips_cpc_phys_base - retrieve the physical base address of the CPC |
@@ -35,7 +35,7 @@ extern phys_t mips_cpc_default_phys_base(void); | |||
35 | * is present. It may be overriden by individual platforms which determine | 35 | * is present. It may be overriden by individual platforms which determine |
36 | * this address in a different way. | 36 | * this address in a different way. |
37 | */ | 37 | */ |
38 | extern phys_t __weak mips_cpc_phys_base(void); | 38 | extern phys_addr_t __weak mips_cpc_phys_base(void); |
39 | 39 | ||
40 | /** | 40 | /** |
41 | * mips_cpc_probe - probe for a Cluster Power Controller | 41 | * mips_cpc_probe - probe for a Cluster Power Controller |
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 22a135ac91de..5e4aef304b02 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h | |||
@@ -653,6 +653,9 @@ | |||
653 | #define MIPS_CONF5_NF (_ULCAST_(1) << 0) | 653 | #define MIPS_CONF5_NF (_ULCAST_(1) << 0) |
654 | #define MIPS_CONF5_UFR (_ULCAST_(1) << 2) | 654 | #define MIPS_CONF5_UFR (_ULCAST_(1) << 2) |
655 | #define MIPS_CONF5_MRP (_ULCAST_(1) << 3) | 655 | #define MIPS_CONF5_MRP (_ULCAST_(1) << 3) |
656 | #define MIPS_CONF5_MVH (_ULCAST_(1) << 5) | ||
657 | #define MIPS_CONF5_FRE (_ULCAST_(1) << 8) | ||
658 | #define MIPS_CONF5_UFE (_ULCAST_(1) << 9) | ||
656 | #define MIPS_CONF5_MSAEN (_ULCAST_(1) << 27) | 659 | #define MIPS_CONF5_MSAEN (_ULCAST_(1) << 27) |
657 | #define MIPS_CONF5_EVA (_ULCAST_(1) << 28) | 660 | #define MIPS_CONF5_EVA (_ULCAST_(1) << 28) |
658 | #define MIPS_CONF5_CV (_ULCAST_(1) << 29) | 661 | #define MIPS_CONF5_CV (_ULCAST_(1) << 29) |
@@ -694,6 +697,7 @@ | |||
694 | #define MIPS_FPIR_W (_ULCAST_(1) << 20) | 697 | #define MIPS_FPIR_W (_ULCAST_(1) << 20) |
695 | #define MIPS_FPIR_L (_ULCAST_(1) << 21) | 698 | #define MIPS_FPIR_L (_ULCAST_(1) << 21) |
696 | #define MIPS_FPIR_F64 (_ULCAST_(1) << 22) | 699 | #define MIPS_FPIR_F64 (_ULCAST_(1) << 22) |
700 | #define MIPS_FPIR_FREP (_ULCAST_(1) << 29) | ||
697 | 701 | ||
698 | /* | 702 | /* |
699 | * Bits in the MIPS32 Memory Segmentation registers. | 703 | * Bits in the MIPS32 Memory Segmentation registers. |
@@ -994,6 +998,39 @@ do { \ | |||
994 | local_irq_restore(__flags); \ | 998 | local_irq_restore(__flags); \ |
995 | } while (0) | 999 | } while (0) |
996 | 1000 | ||
1001 | #define __readx_32bit_c0_register(source) \ | ||
1002 | ({ \ | ||
1003 | unsigned int __res; \ | ||
1004 | \ | ||
1005 | __asm__ __volatile__( \ | ||
1006 | " .set push \n" \ | ||
1007 | " .set noat \n" \ | ||
1008 | " .set mips32r2 \n" \ | ||
1009 | " .insn \n" \ | ||
1010 | " # mfhc0 $1, %1 \n" \ | ||
1011 | " .word (0x40410000 | ((%1 & 0x1f) << 11)) \n" \ | ||
1012 | " move %0, $1 \n" \ | ||
1013 | " .set pop \n" \ | ||
1014 | : "=r" (__res) \ | ||
1015 | : "i" (source)); \ | ||
1016 | __res; \ | ||
1017 | }) | ||
1018 | |||
1019 | #define __writex_32bit_c0_register(register, value) \ | ||
1020 | do { \ | ||
1021 | __asm__ __volatile__( \ | ||
1022 | " .set push \n" \ | ||
1023 | " .set noat \n" \ | ||
1024 | " .set mips32r2 \n" \ | ||
1025 | " move $1, %0 \n" \ | ||
1026 | " # mthc0 $1, %1 \n" \ | ||
1027 | " .insn \n" \ | ||
1028 | " .word (0x40c10000 | ((%1 & 0x1f) << 11)) \n" \ | ||
1029 | " .set pop \n" \ | ||
1030 | : \ | ||
1031 | : "r" (value), "i" (register)); \ | ||
1032 | } while (0) | ||
1033 | |||
997 | #define read_c0_index() __read_32bit_c0_register($0, 0) | 1034 | #define read_c0_index() __read_32bit_c0_register($0, 0) |
998 | #define write_c0_index(val) __write_32bit_c0_register($0, 0, val) | 1035 | #define write_c0_index(val) __write_32bit_c0_register($0, 0, val) |
999 | 1036 | ||
@@ -1003,9 +1040,15 @@ do { \ | |||
1003 | #define read_c0_entrylo0() __read_ulong_c0_register($2, 0) | 1040 | #define read_c0_entrylo0() __read_ulong_c0_register($2, 0) |
1004 | #define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val) | 1041 | #define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val) |
1005 | 1042 | ||
1043 | #define readx_c0_entrylo0() __readx_32bit_c0_register(2) | ||
1044 | #define writex_c0_entrylo0(val) __writex_32bit_c0_register(2, val) | ||
1045 | |||
1006 | #define read_c0_entrylo1() __read_ulong_c0_register($3, 0) | 1046 | #define read_c0_entrylo1() __read_ulong_c0_register($3, 0) |
1007 | #define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val) | 1047 | #define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val) |
1008 | 1048 | ||
1049 | #define readx_c0_entrylo1() __readx_32bit_c0_register(3) | ||
1050 | #define writex_c0_entrylo1(val) __writex_32bit_c0_register(3, val) | ||
1051 | |||
1009 | #define read_c0_conf() __read_32bit_c0_register($3, 0) | 1052 | #define read_c0_conf() __read_32bit_c0_register($3, 0) |
1010 | #define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) | 1053 | #define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) |
1011 | 1054 | ||
diff --git a/arch/mips/include/asm/octeon/cvmx-cmd-queue.h b/arch/mips/include/asm/octeon/cvmx-cmd-queue.h index 024a71b2bff9..75739c83f07e 100644 --- a/arch/mips/include/asm/octeon/cvmx-cmd-queue.h +++ b/arch/mips/include/asm/octeon/cvmx-cmd-queue.h | |||
@@ -76,6 +76,8 @@ | |||
76 | 76 | ||
77 | #include <linux/prefetch.h> | 77 | #include <linux/prefetch.h> |
78 | 78 | ||
79 | #include <asm/compiler.h> | ||
80 | |||
79 | #include <asm/octeon/cvmx-fpa.h> | 81 | #include <asm/octeon/cvmx-fpa.h> |
80 | /** | 82 | /** |
81 | * By default we disable the max depth support. Most programs | 83 | * By default we disable the max depth support. Most programs |
@@ -273,7 +275,7 @@ static inline void __cvmx_cmd_queue_lock(cvmx_cmd_queue_id_t queue_id, | |||
273 | " lbu %[ticket], %[now_serving]\n" | 275 | " lbu %[ticket], %[now_serving]\n" |
274 | "4:\n" | 276 | "4:\n" |
275 | ".set pop\n" : | 277 | ".set pop\n" : |
276 | [ticket_ptr] "=m"(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]), | 278 | [ticket_ptr] "=" GCC_OFF12_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]), |
277 | [now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp), | 279 | [now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp), |
278 | [my_ticket] "=r"(my_ticket) | 280 | [my_ticket] "=r"(my_ticket) |
279 | ); | 281 | ); |
diff --git a/arch/mips/include/asm/octeon/cvmx-pow.h b/arch/mips/include/asm/octeon/cvmx-pow.h index 4b4d0ecfd9eb..2188e65afb86 100644 --- a/arch/mips/include/asm/octeon/cvmx-pow.h +++ b/arch/mips/include/asm/octeon/cvmx-pow.h | |||
@@ -1066,7 +1066,7 @@ static inline void __cvmx_pow_warn_if_pending_switch(const char *function) | |||
1066 | uint64_t switch_complete; | 1066 | uint64_t switch_complete; |
1067 | CVMX_MF_CHORD(switch_complete); | 1067 | CVMX_MF_CHORD(switch_complete); |
1068 | if (!switch_complete) | 1068 | if (!switch_complete) |
1069 | pr_warning("%s called with tag switch in progress\n", function); | 1069 | pr_warn("%s called with tag switch in progress\n", function); |
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | /** | 1072 | /** |
@@ -1084,8 +1084,7 @@ static inline void cvmx_pow_tag_sw_wait(void) | |||
1084 | if (unlikely(switch_complete)) | 1084 | if (unlikely(switch_complete)) |
1085 | break; | 1085 | break; |
1086 | if (unlikely(cvmx_get_cycle() > start_cycle + MAX_CYCLES)) { | 1086 | if (unlikely(cvmx_get_cycle() > start_cycle + MAX_CYCLES)) { |
1087 | pr_warning("Tag switch is taking a long time, " | 1087 | pr_warn("Tag switch is taking a long time, possible deadlock\n"); |
1088 | "possible deadlock\n"); | ||
1089 | start_cycle = -MAX_CYCLES - 1; | 1088 | start_cycle = -MAX_CYCLES - 1; |
1090 | } | 1089 | } |
1091 | } | 1090 | } |
@@ -1296,19 +1295,16 @@ static inline void cvmx_pow_tag_sw_nocheck(uint32_t tag, | |||
1296 | __cvmx_pow_warn_if_pending_switch(__func__); | 1295 | __cvmx_pow_warn_if_pending_switch(__func__); |
1297 | current_tag = cvmx_pow_get_current_tag(); | 1296 | current_tag = cvmx_pow_get_current_tag(); |
1298 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) | 1297 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) |
1299 | pr_warning("%s called with NULL_NULL tag\n", | 1298 | pr_warn("%s called with NULL_NULL tag\n", __func__); |
1300 | __func__); | ||
1301 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) | 1299 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) |
1302 | pr_warning("%s called with NULL tag\n", __func__); | 1300 | pr_warn("%s called with NULL tag\n", __func__); |
1303 | if ((current_tag.s.type == tag_type) | 1301 | if ((current_tag.s.type == tag_type) |
1304 | && (current_tag.s.tag == tag)) | 1302 | && (current_tag.s.tag == tag)) |
1305 | pr_warning("%s called to perform a tag switch to the " | 1303 | pr_warn("%s called to perform a tag switch to the same tag\n", |
1306 | "same tag\n", | 1304 | __func__); |
1307 | __func__); | ||
1308 | if (tag_type == CVMX_POW_TAG_TYPE_NULL) | 1305 | if (tag_type == CVMX_POW_TAG_TYPE_NULL) |
1309 | pr_warning("%s called to perform a tag switch to " | 1306 | pr_warn("%s called to perform a tag switch to NULL. Use cvmx_pow_tag_sw_null() instead\n", |
1310 | "NULL. Use cvmx_pow_tag_sw_null() instead\n", | 1307 | __func__); |
1311 | __func__); | ||
1312 | } | 1308 | } |
1313 | 1309 | ||
1314 | /* | 1310 | /* |
@@ -1407,23 +1403,19 @@ static inline void cvmx_pow_tag_sw_full_nocheck(cvmx_wqe_t *wqp, uint32_t tag, | |||
1407 | __cvmx_pow_warn_if_pending_switch(__func__); | 1403 | __cvmx_pow_warn_if_pending_switch(__func__); |
1408 | current_tag = cvmx_pow_get_current_tag(); | 1404 | current_tag = cvmx_pow_get_current_tag(); |
1409 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) | 1405 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) |
1410 | pr_warning("%s called with NULL_NULL tag\n", | 1406 | pr_warn("%s called with NULL_NULL tag\n", __func__); |
1411 | __func__); | ||
1412 | if ((current_tag.s.type == tag_type) | 1407 | if ((current_tag.s.type == tag_type) |
1413 | && (current_tag.s.tag == tag)) | 1408 | && (current_tag.s.tag == tag)) |
1414 | pr_warning("%s called to perform a tag switch to " | 1409 | pr_warn("%s called to perform a tag switch to the same tag\n", |
1415 | "the same tag\n", | 1410 | __func__); |
1416 | __func__); | ||
1417 | if (tag_type == CVMX_POW_TAG_TYPE_NULL) | 1411 | if (tag_type == CVMX_POW_TAG_TYPE_NULL) |
1418 | pr_warning("%s called to perform a tag switch to " | 1412 | pr_warn("%s called to perform a tag switch to NULL. Use cvmx_pow_tag_sw_null() instead\n", |
1419 | "NULL. Use cvmx_pow_tag_sw_null() instead\n", | 1413 | __func__); |
1420 | __func__); | ||
1421 | if (wqp != cvmx_phys_to_ptr(0x80)) | 1414 | if (wqp != cvmx_phys_to_ptr(0x80)) |
1422 | if (wqp != cvmx_pow_get_current_wqp()) | 1415 | if (wqp != cvmx_pow_get_current_wqp()) |
1423 | pr_warning("%s passed WQE(%p) doesn't match " | 1416 | pr_warn("%s passed WQE(%p) doesn't match the address in the POW(%p)\n", |
1424 | "the address in the POW(%p)\n", | 1417 | __func__, wqp, |
1425 | __func__, wqp, | 1418 | cvmx_pow_get_current_wqp()); |
1426 | cvmx_pow_get_current_wqp()); | ||
1427 | } | 1419 | } |
1428 | 1420 | ||
1429 | /* | 1421 | /* |
@@ -1507,12 +1499,10 @@ static inline void cvmx_pow_tag_sw_null_nocheck(void) | |||
1507 | __cvmx_pow_warn_if_pending_switch(__func__); | 1499 | __cvmx_pow_warn_if_pending_switch(__func__); |
1508 | current_tag = cvmx_pow_get_current_tag(); | 1500 | current_tag = cvmx_pow_get_current_tag(); |
1509 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) | 1501 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) |
1510 | pr_warning("%s called with NULL_NULL tag\n", | 1502 | pr_warn("%s called with NULL_NULL tag\n", __func__); |
1511 | __func__); | ||
1512 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) | 1503 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) |
1513 | pr_warning("%s called when we already have a " | 1504 | pr_warn("%s called when we already have a NULL tag\n", |
1514 | "NULL tag\n", | 1505 | __func__); |
1515 | __func__); | ||
1516 | } | 1506 | } |
1517 | 1507 | ||
1518 | tag_req.u64 = 0; | 1508 | tag_req.u64 = 0; |
@@ -1725,17 +1715,14 @@ static inline void cvmx_pow_tag_sw_desched_nocheck( | |||
1725 | __cvmx_pow_warn_if_pending_switch(__func__); | 1715 | __cvmx_pow_warn_if_pending_switch(__func__); |
1726 | current_tag = cvmx_pow_get_current_tag(); | 1716 | current_tag = cvmx_pow_get_current_tag(); |
1727 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) | 1717 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) |
1728 | pr_warning("%s called with NULL_NULL tag\n", | 1718 | pr_warn("%s called with NULL_NULL tag\n", __func__); |
1729 | __func__); | ||
1730 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) | 1719 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) |
1731 | pr_warning("%s called with NULL tag. Deschedule not " | 1720 | pr_warn("%s called with NULL tag. Deschedule not allowed from NULL state\n", |
1732 | "allowed from NULL state\n", | 1721 | __func__); |
1733 | __func__); | ||
1734 | if ((current_tag.s.type != CVMX_POW_TAG_TYPE_ATOMIC) | 1722 | if ((current_tag.s.type != CVMX_POW_TAG_TYPE_ATOMIC) |
1735 | && (tag_type != CVMX_POW_TAG_TYPE_ATOMIC)) | 1723 | && (tag_type != CVMX_POW_TAG_TYPE_ATOMIC)) |
1736 | pr_warning("%s called where neither the before or " | 1724 | pr_warn("%s called where neither the before or after tag is ATOMIC\n", |
1737 | "after tag is ATOMIC\n", | 1725 | __func__); |
1738 | __func__); | ||
1739 | } | 1726 | } |
1740 | 1727 | ||
1741 | tag_req.u64 = 0; | 1728 | tag_req.u64 = 0; |
@@ -1832,12 +1819,10 @@ static inline void cvmx_pow_desched(uint64_t no_sched) | |||
1832 | __cvmx_pow_warn_if_pending_switch(__func__); | 1819 | __cvmx_pow_warn_if_pending_switch(__func__); |
1833 | current_tag = cvmx_pow_get_current_tag(); | 1820 | current_tag = cvmx_pow_get_current_tag(); |
1834 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) | 1821 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL) |
1835 | pr_warning("%s called with NULL_NULL tag\n", | 1822 | pr_warn("%s called with NULL_NULL tag\n", __func__); |
1836 | __func__); | ||
1837 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) | 1823 | if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL) |
1838 | pr_warning("%s called with NULL tag. Deschedule not " | 1824 | pr_warn("%s called with NULL tag. Deschedule not expected from NULL state\n", |
1839 | "expected from NULL state\n", | 1825 | __func__); |
1840 | __func__); | ||
1841 | } | 1826 | } |
1842 | 1827 | ||
1843 | /* Need to make sure any writes to the work queue entry are complete */ | 1828 | /* Need to make sure any writes to the work queue entry are complete */ |
diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h index f991e7701d3d..33db1c806b01 100644 --- a/arch/mips/include/asm/octeon/cvmx.h +++ b/arch/mips/include/asm/octeon/cvmx.h | |||
@@ -451,67 +451,4 @@ static inline uint32_t cvmx_octeon_num_cores(void) | |||
451 | return cvmx_pop(ciu_fuse); | 451 | return cvmx_pop(ciu_fuse); |
452 | } | 452 | } |
453 | 453 | ||
454 | /** | ||
455 | * Read a byte of fuse data | ||
456 | * @byte_addr: address to read | ||
457 | * | ||
458 | * Returns fuse value: 0 or 1 | ||
459 | */ | ||
460 | static uint8_t cvmx_fuse_read_byte(int byte_addr) | ||
461 | { | ||
462 | union cvmx_mio_fus_rcmd read_cmd; | ||
463 | |||
464 | read_cmd.u64 = 0; | ||
465 | read_cmd.s.addr = byte_addr; | ||
466 | read_cmd.s.pend = 1; | ||
467 | cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64); | ||
468 | while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD)) | ||
469 | && read_cmd.s.pend) | ||
470 | ; | ||
471 | return read_cmd.s.dat; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * Read a single fuse bit | ||
476 | * | ||
477 | * @fuse: Fuse number (0-1024) | ||
478 | * | ||
479 | * Returns fuse value: 0 or 1 | ||
480 | */ | ||
481 | static inline int cvmx_fuse_read(int fuse) | ||
482 | { | ||
483 | return (cvmx_fuse_read_byte(fuse >> 3) >> (fuse & 0x7)) & 1; | ||
484 | } | ||
485 | |||
486 | static inline int cvmx_octeon_model_CN36XX(void) | ||
487 | { | ||
488 | return OCTEON_IS_MODEL(OCTEON_CN38XX) | ||
489 | && !cvmx_octeon_is_pass1() | ||
490 | && cvmx_fuse_read(264); | ||
491 | } | ||
492 | |||
493 | static inline int cvmx_octeon_zip_present(void) | ||
494 | { | ||
495 | return octeon_has_feature(OCTEON_FEATURE_ZIP); | ||
496 | } | ||
497 | |||
498 | static inline int cvmx_octeon_dfa_present(void) | ||
499 | { | ||
500 | if (!OCTEON_IS_MODEL(OCTEON_CN38XX) | ||
501 | && !OCTEON_IS_MODEL(OCTEON_CN31XX) | ||
502 | && !OCTEON_IS_MODEL(OCTEON_CN58XX)) | ||
503 | return 0; | ||
504 | else if (OCTEON_IS_MODEL(OCTEON_CN3020)) | ||
505 | return 0; | ||
506 | else if (cvmx_octeon_is_pass1()) | ||
507 | return 1; | ||
508 | else | ||
509 | return !cvmx_fuse_read(120); | ||
510 | } | ||
511 | |||
512 | static inline int cvmx_octeon_crypto_present(void) | ||
513 | { | ||
514 | return octeon_has_feature(OCTEON_FEATURE_CRYPTO); | ||
515 | } | ||
516 | |||
517 | #endif /* __CVMX_H__ */ | 454 | #endif /* __CVMX_H__ */ |
diff --git a/arch/mips/include/asm/octeon/octeon-feature.h b/arch/mips/include/asm/octeon/octeon-feature.h index 90e05a8d4b15..c4fe81f47f53 100644 --- a/arch/mips/include/asm/octeon/octeon-feature.h +++ b/arch/mips/include/asm/octeon/octeon-feature.h | |||
@@ -86,8 +86,6 @@ enum octeon_feature { | |||
86 | OCTEON_MAX_FEATURE | 86 | OCTEON_MAX_FEATURE |
87 | }; | 87 | }; |
88 | 88 | ||
89 | static inline int cvmx_fuse_read(int fuse); | ||
90 | |||
91 | /** | 89 | /** |
92 | * Determine if the current Octeon supports a specific feature. These | 90 | * Determine if the current Octeon supports a specific feature. These |
93 | * checks have been optimized to be fairly quick, but they should still | 91 | * checks have been optimized to be fairly quick, but they should still |
@@ -105,33 +103,6 @@ static inline int octeon_has_feature(enum octeon_feature feature) | |||
105 | case OCTEON_FEATURE_SAAD: | 103 | case OCTEON_FEATURE_SAAD: |
106 | return !OCTEON_IS_MODEL(OCTEON_CN3XXX); | 104 | return !OCTEON_IS_MODEL(OCTEON_CN3XXX); |
107 | 105 | ||
108 | case OCTEON_FEATURE_ZIP: | ||
109 | if (OCTEON_IS_MODEL(OCTEON_CN30XX) | ||
110 | || OCTEON_IS_MODEL(OCTEON_CN50XX) | ||
111 | || OCTEON_IS_MODEL(OCTEON_CN52XX)) | ||
112 | return 0; | ||
113 | else if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1)) | ||
114 | return 1; | ||
115 | else | ||
116 | return !cvmx_fuse_read(121); | ||
117 | |||
118 | case OCTEON_FEATURE_CRYPTO: | ||
119 | if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) { | ||
120 | union cvmx_mio_fus_dat2 fus_2; | ||
121 | fus_2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); | ||
122 | if (fus_2.s.nocrypto || fus_2.s.nomul) { | ||
123 | return 0; | ||
124 | } else if (!fus_2.s.dorm_crypto) { | ||
125 | return 1; | ||
126 | } else { | ||
127 | union cvmx_rnm_ctl_status st; | ||
128 | st.u64 = cvmx_read_csr(CVMX_RNM_CTL_STATUS); | ||
129 | return st.s.eer_val; | ||
130 | } | ||
131 | } else { | ||
132 | return !cvmx_fuse_read(90); | ||
133 | } | ||
134 | |||
135 | case OCTEON_FEATURE_DORM_CRYPTO: | 106 | case OCTEON_FEATURE_DORM_CRYPTO: |
136 | if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) { | 107 | if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) { |
137 | union cvmx_mio_fus_dat2 fus_2; | 108 | union cvmx_mio_fus_dat2 fus_2; |
@@ -188,29 +159,6 @@ static inline int octeon_has_feature(enum octeon_feature feature) | |||
188 | && !OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) | 159 | && !OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) |
189 | && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X); | 160 | && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X); |
190 | 161 | ||
191 | case OCTEON_FEATURE_DFA: | ||
192 | if (!OCTEON_IS_MODEL(OCTEON_CN38XX) | ||
193 | && !OCTEON_IS_MODEL(OCTEON_CN31XX) | ||
194 | && !OCTEON_IS_MODEL(OCTEON_CN58XX)) | ||
195 | return 0; | ||
196 | else if (OCTEON_IS_MODEL(OCTEON_CN3020)) | ||
197 | return 0; | ||
198 | else | ||
199 | return !cvmx_fuse_read(120); | ||
200 | |||
201 | case OCTEON_FEATURE_HFA: | ||
202 | if (!OCTEON_IS_MODEL(OCTEON_CN6XXX)) | ||
203 | return 0; | ||
204 | else | ||
205 | return !cvmx_fuse_read(90); | ||
206 | |||
207 | case OCTEON_FEATURE_DFM: | ||
208 | if (!(OCTEON_IS_MODEL(OCTEON_CN63XX) | ||
209 | || OCTEON_IS_MODEL(OCTEON_CN66XX))) | ||
210 | return 0; | ||
211 | else | ||
212 | return !cvmx_fuse_read(90); | ||
213 | |||
214 | case OCTEON_FEATURE_MDIO_CLAUSE_45: | 162 | case OCTEON_FEATURE_MDIO_CLAUSE_45: |
215 | return !(OCTEON_IS_MODEL(OCTEON_CN3XXX) | 163 | return !(OCTEON_IS_MODEL(OCTEON_CN3XXX) |
216 | || OCTEON_IS_MODEL(OCTEON_CN58XX) | 164 | || OCTEON_IS_MODEL(OCTEON_CN58XX) |
diff --git a/arch/mips/include/asm/octeon/octeon-model.h b/arch/mips/include/asm/octeon/octeon-model.h index e2c122c6a657..e8a1c2fd52cd 100644 --- a/arch/mips/include/asm/octeon/octeon-model.h +++ b/arch/mips/include/asm/octeon/octeon-model.h | |||
@@ -326,8 +326,7 @@ static inline int __octeon_is_model_runtime__(uint32_t model) | |||
326 | #define OCTEON_IS_COMMON_BINARY() 1 | 326 | #define OCTEON_IS_COMMON_BINARY() 1 |
327 | #undef OCTEON_MODEL | 327 | #undef OCTEON_MODEL |
328 | 328 | ||
329 | const char *octeon_model_get_string(uint32_t chip_id); | 329 | const char *__init octeon_model_get_string(uint32_t chip_id); |
330 | const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer); | ||
331 | 330 | ||
332 | /* | 331 | /* |
333 | * Return the octeon family, i.e., ProcessorID of the PrID register. | 332 | * Return the octeon family, i.e., ProcessorID of the PrID register. |
diff --git a/arch/mips/include/asm/paccess.h b/arch/mips/include/asm/paccess.h index 2474fc5d1751..af81ab0da55f 100644 --- a/arch/mips/include/asm/paccess.h +++ b/arch/mips/include/asm/paccess.h | |||
@@ -56,6 +56,7 @@ struct __large_pstruct { unsigned long buf[100]; }; | |||
56 | "1:\t" insn "\t%1,%2\n\t" \ | 56 | "1:\t" insn "\t%1,%2\n\t" \ |
57 | "move\t%0,$0\n" \ | 57 | "move\t%0,$0\n" \ |
58 | "2:\n\t" \ | 58 | "2:\n\t" \ |
59 | ".insn\n\t" \ | ||
59 | ".section\t.fixup,\"ax\"\n" \ | 60 | ".section\t.fixup,\"ax\"\n" \ |
60 | "3:\tli\t%0,%3\n\t" \ | 61 | "3:\tli\t%0,%3\n\t" \ |
61 | "move\t%1,$0\n\t" \ | 62 | "move\t%1,$0\n\t" \ |
@@ -94,6 +95,7 @@ extern void __get_dbe_unknown(void); | |||
94 | "1:\t" insn "\t%1,%2\n\t" \ | 95 | "1:\t" insn "\t%1,%2\n\t" \ |
95 | "move\t%0,$0\n" \ | 96 | "move\t%0,$0\n" \ |
96 | "2:\n\t" \ | 97 | "2:\n\t" \ |
98 | ".insn\n\t" \ | ||
97 | ".section\t.fixup,\"ax\"\n" \ | 99 | ".section\t.fixup,\"ax\"\n" \ |
98 | "3:\tli\t%0,%3\n\t" \ | 100 | "3:\tli\t%0,%3\n\t" \ |
99 | "j\t2b\n\t" \ | 101 | "j\t2b\n\t" \ |
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index 3be81803595d..154b70a10483 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h | |||
@@ -116,7 +116,7 @@ extern void copy_user_highpage(struct page *to, struct page *from, | |||
116 | /* | 116 | /* |
117 | * These are used to make use of C type-checking.. | 117 | * These are used to make use of C type-checking.. |
118 | */ | 118 | */ |
119 | #ifdef CONFIG_64BIT_PHYS_ADDR | 119 | #ifdef CONFIG_PHYS_ADDR_T_64BIT |
120 | #ifdef CONFIG_CPU_MIPS32 | 120 | #ifdef CONFIG_CPU_MIPS32 |
121 | typedef struct { unsigned long pte_low, pte_high; } pte_t; | 121 | typedef struct { unsigned long pte_low, pte_high; } pte_t; |
122 | #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32)) | 122 | #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32)) |
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 974b0e308963..69529624a005 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h | |||
@@ -84,7 +84,7 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar, | |||
84 | const struct resource *rsrc, resource_size_t *start, | 84 | const struct resource *rsrc, resource_size_t *start, |
85 | resource_size_t *end) | 85 | resource_size_t *end) |
86 | { | 86 | { |
87 | phys_t size = resource_size(rsrc); | 87 | phys_addr_t size = resource_size(rsrc); |
88 | 88 | ||
89 | *start = fixup_bigphys_addr(rsrc->start, size); | 89 | *start = fixup_bigphys_addr(rsrc->start, size); |
90 | *end = rsrc->start + size; | 90 | *end = rsrc->start + size; |
diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index cd7d6064bcbe..68984b612f9d 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h | |||
@@ -69,7 +69,7 @@ extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, | |||
69 | # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) | 69 | # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | #ifdef CONFIG_64BIT_PHYS_ADDR | 72 | #ifdef CONFIG_PHYS_ADDR_T_64BIT |
73 | #define pte_ERROR(e) \ | 73 | #define pte_ERROR(e) \ |
74 | printk("%s:%d: bad pte %016Lx.\n", __FILE__, __LINE__, pte_val(e)) | 74 | printk("%s:%d: bad pte %016Lx.\n", __FILE__, __LINE__, pte_val(e)) |
75 | #else | 75 | #else |
@@ -103,7 +103,7 @@ static inline void pmd_clear(pmd_t *pmdp) | |||
103 | pmd_val(*pmdp) = ((unsigned long) invalid_pte_table); | 103 | pmd_val(*pmdp) = ((unsigned long) invalid_pte_table); |
104 | } | 104 | } |
105 | 105 | ||
106 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 106 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
107 | #define pte_page(x) pfn_to_page(pte_pfn(x)) | 107 | #define pte_page(x) pfn_to_page(pte_pfn(x)) |
108 | #define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) | 108 | #define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) |
109 | static inline pte_t | 109 | static inline pte_t |
@@ -126,7 +126,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot) | |||
126 | #define pte_pfn(x) ((unsigned long)((x).pte >> _PFN_SHIFT)) | 126 | #define pte_pfn(x) ((unsigned long)((x).pte >> _PFN_SHIFT)) |
127 | #define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << _PFN_SHIFT) | pgprot_val(prot)) | 127 | #define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << _PFN_SHIFT) | pgprot_val(prot)) |
128 | #endif | 128 | #endif |
129 | #endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) */ | 129 | #endif /* defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) */ |
130 | 130 | ||
131 | #define __pgd_offset(address) pgd_index(address) | 131 | #define __pgd_offset(address) pgd_index(address) |
132 | #define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) | 132 | #define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) |
@@ -155,73 +155,75 @@ pfn_pte(unsigned long pfn, pgprot_t prot) | |||
155 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | 155 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) |
156 | 156 | ||
157 | /* Swap entries must have VALID bit cleared. */ | 157 | /* Swap entries must have VALID bit cleared. */ |
158 | #define __swp_type(x) (((x).val >> 10) & 0x1f) | 158 | #define __swp_type(x) (((x).val >> 10) & 0x1f) |
159 | #define __swp_offset(x) ((x).val >> 15) | 159 | #define __swp_offset(x) ((x).val >> 15) |
160 | #define __swp_entry(type,offset) \ | 160 | #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 10) | ((offset) << 15) }) |
161 | ((swp_entry_t) { ((type) << 10) | ((offset) << 15) }) | 161 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) |
162 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) | ||
162 | 163 | ||
163 | /* | 164 | /* |
164 | * Bits 0, 4, 8, and 9 are taken, split up 28 bits of offset into this range: | 165 | * Encode and decode a nonlinear file mapping entry |
165 | */ | 166 | */ |
166 | #define PTE_FILE_MAX_BITS 28 | 167 | #define pte_to_pgoff(_pte) ((((_pte).pte >> 1 ) & 0x07) | \ |
167 | 168 | (((_pte).pte >> 2 ) & 0x38) | \ | |
168 | #define pte_to_pgoff(_pte) ((((_pte).pte >> 1 ) & 0x07) | \ | 169 | (((_pte).pte >> 10) << 6 )) |
169 | (((_pte).pte >> 2 ) & 0x38) | \ | ||
170 | (((_pte).pte >> 10) << 6 )) | ||
171 | 170 | ||
172 | #define pgoff_to_pte(off) ((pte_t) { (((off) & 0x07) << 1 ) | \ | 171 | #define pgoff_to_pte(off) ((pte_t) { (((off) & 0x07) << 1 ) | \ |
173 | (((off) & 0x38) << 2 ) | \ | 172 | (((off) & 0x38) << 2 ) | \ |
174 | (((off) >> 6 ) << 10) | \ | 173 | (((off) >> 6 ) << 10) | \ |
175 | _PAGE_FILE }) | 174 | _PAGE_FILE }) |
176 | 175 | ||
176 | /* | ||
177 | * Bits 0, 4, 8, and 9 are taken, split up 28 bits of offset into this range: | ||
178 | */ | ||
179 | #define PTE_FILE_MAX_BITS 28 | ||
177 | #else | 180 | #else |
178 | 181 | ||
182 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) | ||
183 | |||
179 | /* Swap entries must have VALID and GLOBAL bits cleared. */ | 184 | /* Swap entries must have VALID and GLOBAL bits cleared. */ |
180 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 185 | #define __swp_type(x) (((x).val >> 2) & 0x1f) |
181 | #define __swp_type(x) (((x).val >> 2) & 0x1f) | 186 | #define __swp_offset(x) ((x).val >> 7) |
182 | #define __swp_offset(x) ((x).val >> 7) | 187 | #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 7) }) |
183 | #define __swp_entry(type,offset) \ | 188 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) |
184 | ((swp_entry_t) { ((type) << 2) | ((offset) << 7) }) | 189 | #define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) |
185 | #else | ||
186 | #define __swp_type(x) (((x).val >> 8) & 0x1f) | ||
187 | #define __swp_offset(x) ((x).val >> 13) | ||
188 | #define __swp_entry(type,offset) \ | ||
189 | ((swp_entry_t) { ((type) << 8) | ((offset) << 13) }) | ||
190 | #endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) */ | ||
191 | 190 | ||
192 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | ||
193 | /* | 191 | /* |
194 | * Bits 0 and 1 of pte_high are taken, use the rest for the page offset... | 192 | * Bits 0 and 1 of pte_high are taken, use the rest for the page offset... |
195 | */ | 193 | */ |
196 | #define PTE_FILE_MAX_BITS 30 | 194 | #define pte_to_pgoff(_pte) ((_pte).pte_high >> 2) |
197 | 195 | #define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) << 2 }) | |
198 | #define pte_to_pgoff(_pte) ((_pte).pte_high >> 2) | ||
199 | #define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) << 2 }) | ||
200 | 196 | ||
197 | #define PTE_FILE_MAX_BITS 30 | ||
201 | #else | 198 | #else |
202 | /* | 199 | /* |
203 | * Bits 0, 4, 6, and 7 are taken, split up 28 bits of offset into this range: | 200 | * Constraints: |
201 | * _PAGE_PRESENT at bit 0 | ||
202 | * _PAGE_MODIFIED at bit 4 | ||
203 | * _PAGE_GLOBAL at bit 6 | ||
204 | * _PAGE_VALID at bit 7 | ||
204 | */ | 205 | */ |
205 | #define PTE_FILE_MAX_BITS 28 | 206 | #define __swp_type(x) (((x).val >> 8) & 0x1f) |
207 | #define __swp_offset(x) ((x).val >> 13) | ||
208 | #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 8) | ((offset) << 13) }) | ||
209 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) | ||
210 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) | ||
206 | 211 | ||
207 | #define pte_to_pgoff(_pte) ((((_pte).pte >> 1) & 0x7) | \ | 212 | /* |
208 | (((_pte).pte >> 2) & 0x8) | \ | 213 | * Encode and decode a nonlinear file mapping entry |
209 | (((_pte).pte >> 8) << 4)) | 214 | */ |
215 | #define pte_to_pgoff(_pte) ((((_pte).pte >> 1) & 0x7) | \ | ||
216 | (((_pte).pte >> 2) & 0x8) | \ | ||
217 | (((_pte).pte >> 8) << 4)) | ||
210 | 218 | ||
211 | #define pgoff_to_pte(off) ((pte_t) { (((off) & 0x7) << 1) | \ | 219 | #define pgoff_to_pte(off) ((pte_t) { (((off) & 0x7) << 1) | \ |
212 | (((off) & 0x8) << 2) | \ | 220 | (((off) & 0x8) << 2) | \ |
213 | (((off) >> 4) << 8) | \ | 221 | (((off) >> 4) << 8) | \ |
214 | _PAGE_FILE }) | 222 | _PAGE_FILE }) |
215 | #endif | ||
216 | 223 | ||
217 | #endif | 224 | #define PTE_FILE_MAX_BITS 28 |
225 | #endif /* defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) */ | ||
218 | 226 | ||
219 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 227 | #endif /* defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) */ |
220 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) | ||
221 | #define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) | ||
222 | #else | ||
223 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) | ||
224 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) | ||
225 | #endif | ||
226 | 228 | ||
227 | #endif /* _ASM_PGTABLE_32_H */ | 229 | #endif /* _ASM_PGTABLE_32_H */ |
diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index e747bfa0be7e..ca11f14f40a3 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h | |||
@@ -32,39 +32,41 @@ | |||
32 | * unpredictable things. The code (when it is written) to deal with | 32 | * unpredictable things. The code (when it is written) to deal with |
33 | * this problem will be in the update_mmu_cache() code for the r4k. | 33 | * this problem will be in the update_mmu_cache() code for the r4k. |
34 | */ | 34 | */ |
35 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 35 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * The following bits are directly used by the TLB hardware | 38 | * The following bits are directly used by the TLB hardware |
39 | */ | 39 | */ |
40 | #define _PAGE_R4KBUG (1 << 0) /* workaround for r4k bug */ | 40 | #define _PAGE_GLOBAL_SHIFT 0 |
41 | #define _PAGE_GLOBAL (1 << 0) | 41 | #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) |
42 | #define _PAGE_VALID_SHIFT 1 | 42 | #define _PAGE_VALID_SHIFT (_PAGE_GLOBAL_SHIFT + 1) |
43 | #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) | 43 | #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) |
44 | #define _PAGE_SILENT_READ (1 << 1) /* synonym */ | 44 | #define _PAGE_DIRTY_SHIFT (_PAGE_VALID_SHIFT + 1) |
45 | #define _PAGE_DIRTY_SHIFT 2 | 45 | #define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) |
46 | #define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) /* The MIPS dirty bit */ | 46 | #define _CACHE_SHIFT (_PAGE_DIRTY_SHIFT + 1) |
47 | #define _PAGE_SILENT_WRITE (1 << 2) | 47 | #define _CACHE_MASK (7 << _CACHE_SHIFT) |
48 | #define _CACHE_SHIFT 3 | ||
49 | #define _CACHE_MASK (7 << 3) | ||
50 | 48 | ||
51 | /* | 49 | /* |
52 | * The following bits are implemented in software | 50 | * The following bits are implemented in software |
53 | * | 51 | * |
54 | * _PAGE_FILE semantics: set:pagecache unset:swap | 52 | * _PAGE_FILE semantics: set:pagecache unset:swap |
55 | */ | 53 | */ |
56 | #define _PAGE_PRESENT_SHIFT 6 | 54 | #define _PAGE_PRESENT_SHIFT (_CACHE_SHIFT + 3) |
57 | #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) | 55 | #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) |
58 | #define _PAGE_READ_SHIFT 7 | 56 | #define _PAGE_READ_SHIFT (_PAGE_PRESENT_SHIFT + 1) |
59 | #define _PAGE_READ (1 << _PAGE_READ_SHIFT) | 57 | #define _PAGE_READ (1 << _PAGE_READ_SHIFT) |
60 | #define _PAGE_WRITE_SHIFT 8 | 58 | #define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) |
61 | #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) | 59 | #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) |
62 | #define _PAGE_ACCESSED_SHIFT 9 | 60 | #define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) |
63 | #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) | 61 | #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) |
64 | #define _PAGE_MODIFIED_SHIFT 10 | 62 | #define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) |
65 | #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) | 63 | #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) |
66 | 64 | ||
67 | #define _PAGE_FILE (1 << 10) | 65 | #define _PAGE_SILENT_READ _PAGE_VALID |
66 | #define _PAGE_SILENT_WRITE _PAGE_DIRTY | ||
67 | #define _PAGE_FILE _PAGE_MODIFIED | ||
68 | |||
69 | #define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) | ||
68 | 70 | ||
69 | #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | 71 | #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) |
70 | 72 | ||
@@ -172,7 +174,7 @@ | |||
172 | 174 | ||
173 | #define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) | 175 | #define _PFN_SHIFT (PAGE_SHIFT - 12 + _CACHE_SHIFT + 3) |
174 | 176 | ||
175 | #endif /* defined(CONFIG_64BIT_PHYS_ADDR && defined(CONFIG_CPU_MIPS32) */ | 177 | #endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */ |
176 | 178 | ||
177 | #ifndef _PFN_SHIFT | 179 | #ifndef _PFN_SHIFT |
178 | #define _PFN_SHIFT PAGE_SHIFT | 180 | #define _PFN_SHIFT PAGE_SHIFT |
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index d6d1928539b1..62a6ba383d4f 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h | |||
@@ -125,7 +125,7 @@ do { \ | |||
125 | extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | 125 | extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, |
126 | pte_t pteval); | 126 | pte_t pteval); |
127 | 127 | ||
128 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 128 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
129 | 129 | ||
130 | #define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL)) | 130 | #define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL)) |
131 | #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) | 131 | #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) |
@@ -227,7 +227,7 @@ extern pgd_t swapper_pg_dir[]; | |||
227 | * The following only work if pte_present() is true. | 227 | * The following only work if pte_present() is true. |
228 | * Undefined behaviour if not.. | 228 | * Undefined behaviour if not.. |
229 | */ | 229 | */ |
230 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 230 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
231 | static inline int pte_write(pte_t pte) { return pte.pte_low & _PAGE_WRITE; } | 231 | static inline int pte_write(pte_t pte) { return pte.pte_low & _PAGE_WRITE; } |
232 | static inline int pte_dirty(pte_t pte) { return pte.pte_low & _PAGE_MODIFIED; } | 232 | static inline int pte_dirty(pte_t pte) { return pte.pte_low & _PAGE_MODIFIED; } |
233 | static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; } | 233 | static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; } |
@@ -297,13 +297,13 @@ static inline pte_t pte_wrprotect(pte_t pte) | |||
297 | 297 | ||
298 | static inline pte_t pte_mkclean(pte_t pte) | 298 | static inline pte_t pte_mkclean(pte_t pte) |
299 | { | 299 | { |
300 | pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); | 300 | pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); |
301 | return pte; | 301 | return pte; |
302 | } | 302 | } |
303 | 303 | ||
304 | static inline pte_t pte_mkold(pte_t pte) | 304 | static inline pte_t pte_mkold(pte_t pte) |
305 | { | 305 | { |
306 | pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ); | 306 | pte_val(pte) &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ); |
307 | return pte; | 307 | return pte; |
308 | } | 308 | } |
309 | 309 | ||
@@ -382,13 +382,13 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot) | |||
382 | */ | 382 | */ |
383 | #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) | 383 | #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) |
384 | 384 | ||
385 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 385 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
386 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 386 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
387 | { | 387 | { |
388 | pte.pte_low &= _PAGE_CHG_MASK; | 388 | pte.pte_low &= _PAGE_CHG_MASK; |
389 | pte.pte_high &= ~0x3f; | 389 | pte.pte_high &= (_PFN_MASK | _CACHE_MASK); |
390 | pte.pte_low |= pgprot_val(newprot); | 390 | pte.pte_low |= pgprot_val(newprot); |
391 | pte.pte_high |= pgprot_val(newprot) & 0x3f; | 391 | pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK); |
392 | return pte; | 392 | return pte; |
393 | } | 393 | } |
394 | #else | 394 | #else |
@@ -419,7 +419,7 @@ static inline void update_mmu_cache_pmd(struct vm_area_struct *vma, | |||
419 | 419 | ||
420 | #define kern_addr_valid(addr) (1) | 420 | #define kern_addr_valid(addr) (1) |
421 | 421 | ||
422 | #ifdef CONFIG_64BIT_PHYS_ADDR | 422 | #ifdef CONFIG_PHYS_ADDR_T_64BIT |
423 | extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot); | 423 | extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot); |
424 | 424 | ||
425 | static inline int io_remap_pfn_range(struct vm_area_struct *vma, | 425 | static inline int io_remap_pfn_range(struct vm_area_struct *vma, |
@@ -428,7 +428,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma, | |||
428 | unsigned long size, | 428 | unsigned long size, |
429 | pgprot_t prot) | 429 | pgprot_t prot) |
430 | { | 430 | { |
431 | phys_t phys_addr_high = fixup_bigphys_addr(pfn << PAGE_SHIFT, size); | 431 | phys_addr_t phys_addr_high = fixup_bigphys_addr(pfn << PAGE_SHIFT, size); |
432 | return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot); | 432 | return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot); |
433 | } | 433 | } |
434 | #define io_remap_pfn_range io_remap_pfn_range | 434 | #define io_remap_pfn_range io_remap_pfn_range |
diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h index a9494c0141fb..eaa26270a5e5 100644 --- a/arch/mips/include/asm/prom.h +++ b/arch/mips/include/asm/prom.h | |||
@@ -22,6 +22,7 @@ extern void device_tree_init(void); | |||
22 | struct boot_param_header; | 22 | struct boot_param_header; |
23 | 23 | ||
24 | extern void __dt_setup_arch(void *bph); | 24 | extern void __dt_setup_arch(void *bph); |
25 | extern int __dt_register_buses(const char *bus0, const char *bus1); | ||
25 | 26 | ||
26 | #define dt_setup_arch(sym) \ | 27 | #define dt_setup_arch(sym) \ |
27 | ({ \ | 28 | ({ \ |
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h index cd6e0afc6833..e293a8d89a6d 100644 --- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h | |||
@@ -47,79 +47,20 @@ extern void (*r4k_blast_icache)(void); | |||
47 | 47 | ||
48 | #ifdef CONFIG_MIPS_MT | 48 | #ifdef CONFIG_MIPS_MT |
49 | 49 | ||
50 | /* | ||
51 | * Optionally force single-threaded execution during I-cache flushes. | ||
52 | */ | ||
53 | #define PROTECT_CACHE_FLUSHES 1 | ||
54 | |||
55 | #ifdef PROTECT_CACHE_FLUSHES | ||
56 | |||
57 | extern int mt_protiflush; | ||
58 | extern int mt_protdflush; | ||
59 | extern void mt_cflush_lockdown(void); | ||
60 | extern void mt_cflush_release(void); | ||
61 | |||
62 | #define BEGIN_MT_IPROT \ | ||
63 | unsigned long flags = 0; \ | ||
64 | unsigned long mtflags = 0; \ | ||
65 | if(mt_protiflush) { \ | ||
66 | local_irq_save(flags); \ | ||
67 | ehb(); \ | ||
68 | mtflags = dvpe(); \ | ||
69 | mt_cflush_lockdown(); \ | ||
70 | } | ||
71 | |||
72 | #define END_MT_IPROT \ | ||
73 | if(mt_protiflush) { \ | ||
74 | mt_cflush_release(); \ | ||
75 | evpe(mtflags); \ | ||
76 | local_irq_restore(flags); \ | ||
77 | } | ||
78 | |||
79 | #define BEGIN_MT_DPROT \ | ||
80 | unsigned long flags = 0; \ | ||
81 | unsigned long mtflags = 0; \ | ||
82 | if(mt_protdflush) { \ | ||
83 | local_irq_save(flags); \ | ||
84 | ehb(); \ | ||
85 | mtflags = dvpe(); \ | ||
86 | mt_cflush_lockdown(); \ | ||
87 | } | ||
88 | |||
89 | #define END_MT_DPROT \ | ||
90 | if(mt_protdflush) { \ | ||
91 | mt_cflush_release(); \ | ||
92 | evpe(mtflags); \ | ||
93 | local_irq_restore(flags); \ | ||
94 | } | ||
95 | |||
96 | #else | ||
97 | |||
98 | #define BEGIN_MT_IPROT | ||
99 | #define BEGIN_MT_DPROT | ||
100 | #define END_MT_IPROT | ||
101 | #define END_MT_DPROT | ||
102 | |||
103 | #endif /* PROTECT_CACHE_FLUSHES */ | ||
104 | |||
105 | #define __iflush_prologue \ | 50 | #define __iflush_prologue \ |
106 | unsigned long redundance; \ | 51 | unsigned long redundance; \ |
107 | extern int mt_n_iflushes; \ | 52 | extern int mt_n_iflushes; \ |
108 | BEGIN_MT_IPROT \ | ||
109 | for (redundance = 0; redundance < mt_n_iflushes; redundance++) { | 53 | for (redundance = 0; redundance < mt_n_iflushes; redundance++) { |
110 | 54 | ||
111 | #define __iflush_epilogue \ | 55 | #define __iflush_epilogue \ |
112 | END_MT_IPROT \ | ||
113 | } | 56 | } |
114 | 57 | ||
115 | #define __dflush_prologue \ | 58 | #define __dflush_prologue \ |
116 | unsigned long redundance; \ | 59 | unsigned long redundance; \ |
117 | extern int mt_n_dflushes; \ | 60 | extern int mt_n_dflushes; \ |
118 | BEGIN_MT_DPROT \ | ||
119 | for (redundance = 0; redundance < mt_n_dflushes; redundance++) { | 61 | for (redundance = 0; redundance < mt_n_dflushes; redundance++) { |
120 | 62 | ||
121 | #define __dflush_epilogue \ | 63 | #define __dflush_epilogue \ |
122 | END_MT_DPROT \ | ||
123 | } | 64 | } |
124 | 65 | ||
125 | #define __inv_dflush_prologue __dflush_prologue | 66 | #define __inv_dflush_prologue __dflush_prologue |
diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h index 78d201fb6c87..c6d06d383ef9 100644 --- a/arch/mips/include/asm/spinlock.h +++ b/arch/mips/include/asm/spinlock.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/compiler.h> | 12 | #include <linux/compiler.h> |
13 | 13 | ||
14 | #include <asm/barrier.h> | 14 | #include <asm/barrier.h> |
15 | #include <asm/compiler.h> | ||
15 | #include <asm/war.h> | 16 | #include <asm/war.h> |
16 | 17 | ||
17 | /* | 18 | /* |
@@ -88,7 +89,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) | |||
88 | " subu %[ticket], %[ticket], 1 \n" | 89 | " subu %[ticket], %[ticket], 1 \n" |
89 | " .previous \n" | 90 | " .previous \n" |
90 | " .set pop \n" | 91 | " .set pop \n" |
91 | : [ticket_ptr] "+m" (lock->lock), | 92 | : [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock), |
92 | [serving_now_ptr] "+m" (lock->h.serving_now), | 93 | [serving_now_ptr] "+m" (lock->h.serving_now), |
93 | [ticket] "=&r" (tmp), | 94 | [ticket] "=&r" (tmp), |
94 | [my_ticket] "=&r" (my_ticket) | 95 | [my_ticket] "=&r" (my_ticket) |
@@ -121,7 +122,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) | |||
121 | " subu %[ticket], %[ticket], 1 \n" | 122 | " subu %[ticket], %[ticket], 1 \n" |
122 | " .previous \n" | 123 | " .previous \n" |
123 | " .set pop \n" | 124 | " .set pop \n" |
124 | : [ticket_ptr] "+m" (lock->lock), | 125 | : [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock), |
125 | [serving_now_ptr] "+m" (lock->h.serving_now), | 126 | [serving_now_ptr] "+m" (lock->h.serving_now), |
126 | [ticket] "=&r" (tmp), | 127 | [ticket] "=&r" (tmp), |
127 | [my_ticket] "=&r" (my_ticket) | 128 | [my_ticket] "=&r" (my_ticket) |
@@ -163,7 +164,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock) | |||
163 | " li %[ticket], 0 \n" | 164 | " li %[ticket], 0 \n" |
164 | " .previous \n" | 165 | " .previous \n" |
165 | " .set pop \n" | 166 | " .set pop \n" |
166 | : [ticket_ptr] "+m" (lock->lock), | 167 | : [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock), |
167 | [ticket] "=&r" (tmp), | 168 | [ticket] "=&r" (tmp), |
168 | [my_ticket] "=&r" (tmp2), | 169 | [my_ticket] "=&r" (tmp2), |
169 | [now_serving] "=&r" (tmp3) | 170 | [now_serving] "=&r" (tmp3) |
@@ -187,7 +188,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock) | |||
187 | " li %[ticket], 0 \n" | 188 | " li %[ticket], 0 \n" |
188 | " .previous \n" | 189 | " .previous \n" |
189 | " .set pop \n" | 190 | " .set pop \n" |
190 | : [ticket_ptr] "+m" (lock->lock), | 191 | : [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock), |
191 | [ticket] "=&r" (tmp), | 192 | [ticket] "=&r" (tmp), |
192 | [my_ticket] "=&r" (tmp2), | 193 | [my_ticket] "=&r" (tmp2), |
193 | [now_serving] "=&r" (tmp3) | 194 | [now_serving] "=&r" (tmp3) |
@@ -234,8 +235,8 @@ static inline void arch_read_lock(arch_rwlock_t *rw) | |||
234 | " beqzl %1, 1b \n" | 235 | " beqzl %1, 1b \n" |
235 | " nop \n" | 236 | " nop \n" |
236 | " .set reorder \n" | 237 | " .set reorder \n" |
237 | : "=m" (rw->lock), "=&r" (tmp) | 238 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp) |
238 | : "m" (rw->lock) | 239 | : GCC_OFF12_ASM() (rw->lock) |
239 | : "memory"); | 240 | : "memory"); |
240 | } else { | 241 | } else { |
241 | do { | 242 | do { |
@@ -244,8 +245,8 @@ static inline void arch_read_lock(arch_rwlock_t *rw) | |||
244 | " bltz %1, 1b \n" | 245 | " bltz %1, 1b \n" |
245 | " addu %1, 1 \n" | 246 | " addu %1, 1 \n" |
246 | "2: sc %1, %0 \n" | 247 | "2: sc %1, %0 \n" |
247 | : "=m" (rw->lock), "=&r" (tmp) | 248 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp) |
248 | : "m" (rw->lock) | 249 | : GCC_OFF12_ASM() (rw->lock) |
249 | : "memory"); | 250 | : "memory"); |
250 | } while (unlikely(!tmp)); | 251 | } while (unlikely(!tmp)); |
251 | } | 252 | } |
@@ -268,8 +269,8 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) | |||
268 | " sub %1, 1 \n" | 269 | " sub %1, 1 \n" |
269 | " sc %1, %0 \n" | 270 | " sc %1, %0 \n" |
270 | " beqzl %1, 1b \n" | 271 | " beqzl %1, 1b \n" |
271 | : "=m" (rw->lock), "=&r" (tmp) | 272 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp) |
272 | : "m" (rw->lock) | 273 | : GCC_OFF12_ASM() (rw->lock) |
273 | : "memory"); | 274 | : "memory"); |
274 | } else { | 275 | } else { |
275 | do { | 276 | do { |
@@ -277,8 +278,8 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) | |||
277 | "1: ll %1, %2 # arch_read_unlock \n" | 278 | "1: ll %1, %2 # arch_read_unlock \n" |
278 | " sub %1, 1 \n" | 279 | " sub %1, 1 \n" |
279 | " sc %1, %0 \n" | 280 | " sc %1, %0 \n" |
280 | : "=m" (rw->lock), "=&r" (tmp) | 281 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp) |
281 | : "m" (rw->lock) | 282 | : GCC_OFF12_ASM() (rw->lock) |
282 | : "memory"); | 283 | : "memory"); |
283 | } while (unlikely(!tmp)); | 284 | } while (unlikely(!tmp)); |
284 | } | 285 | } |
@@ -298,8 +299,8 @@ static inline void arch_write_lock(arch_rwlock_t *rw) | |||
298 | " beqzl %1, 1b \n" | 299 | " beqzl %1, 1b \n" |
299 | " nop \n" | 300 | " nop \n" |
300 | " .set reorder \n" | 301 | " .set reorder \n" |
301 | : "=m" (rw->lock), "=&r" (tmp) | 302 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp) |
302 | : "m" (rw->lock) | 303 | : GCC_OFF12_ASM() (rw->lock) |
303 | : "memory"); | 304 | : "memory"); |
304 | } else { | 305 | } else { |
305 | do { | 306 | do { |
@@ -308,8 +309,8 @@ static inline void arch_write_lock(arch_rwlock_t *rw) | |||
308 | " bnez %1, 1b \n" | 309 | " bnez %1, 1b \n" |
309 | " lui %1, 0x8000 \n" | 310 | " lui %1, 0x8000 \n" |
310 | "2: sc %1, %0 \n" | 311 | "2: sc %1, %0 \n" |
311 | : "=m" (rw->lock), "=&r" (tmp) | 312 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp) |
312 | : "m" (rw->lock) | 313 | : GCC_OFF12_ASM() (rw->lock) |
313 | : "memory"); | 314 | : "memory"); |
314 | } while (unlikely(!tmp)); | 315 | } while (unlikely(!tmp)); |
315 | } | 316 | } |
@@ -348,8 +349,8 @@ static inline int arch_read_trylock(arch_rwlock_t *rw) | |||
348 | __WEAK_LLSC_MB | 349 | __WEAK_LLSC_MB |
349 | " li %2, 1 \n" | 350 | " li %2, 1 \n" |
350 | "2: \n" | 351 | "2: \n" |
351 | : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) | 352 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret) |
352 | : "m" (rw->lock) | 353 | : GCC_OFF12_ASM() (rw->lock) |
353 | : "memory"); | 354 | : "memory"); |
354 | } else { | 355 | } else { |
355 | __asm__ __volatile__( | 356 | __asm__ __volatile__( |
@@ -365,8 +366,8 @@ static inline int arch_read_trylock(arch_rwlock_t *rw) | |||
365 | __WEAK_LLSC_MB | 366 | __WEAK_LLSC_MB |
366 | " li %2, 1 \n" | 367 | " li %2, 1 \n" |
367 | "2: \n" | 368 | "2: \n" |
368 | : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) | 369 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret) |
369 | : "m" (rw->lock) | 370 | : GCC_OFF12_ASM() (rw->lock) |
370 | : "memory"); | 371 | : "memory"); |
371 | } | 372 | } |
372 | 373 | ||
@@ -392,8 +393,8 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) | |||
392 | " li %2, 1 \n" | 393 | " li %2, 1 \n" |
393 | " .set reorder \n" | 394 | " .set reorder \n" |
394 | "2: \n" | 395 | "2: \n" |
395 | : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) | 396 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret) |
396 | : "m" (rw->lock) | 397 | : GCC_OFF12_ASM() (rw->lock) |
397 | : "memory"); | 398 | : "memory"); |
398 | } else { | 399 | } else { |
399 | do { | 400 | do { |
@@ -405,8 +406,9 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) | |||
405 | " sc %1, %0 \n" | 406 | " sc %1, %0 \n" |
406 | " li %2, 1 \n" | 407 | " li %2, 1 \n" |
407 | "2: \n" | 408 | "2: \n" |
408 | : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) | 409 | : "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), |
409 | : "m" (rw->lock) | 410 | "=&r" (ret) |
411 | : GCC_OFF12_ASM() (rw->lock) | ||
410 | : "memory"); | 412 | : "memory"); |
411 | } while (unlikely(!tmp)); | 413 | } while (unlikely(!tmp)); |
412 | 414 | ||
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 7de865805deb..99eea59604e9 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h | |||
@@ -116,6 +116,7 @@ static inline struct thread_info *current_thread_info(void) | |||
116 | #define TIF_LOAD_WATCH 25 /* If set, load watch registers */ | 116 | #define TIF_LOAD_WATCH 25 /* If set, load watch registers */ |
117 | #define TIF_SYSCALL_TRACEPOINT 26 /* syscall tracepoint instrumentation */ | 117 | #define TIF_SYSCALL_TRACEPOINT 26 /* syscall tracepoint instrumentation */ |
118 | #define TIF_32BIT_FPREGS 27 /* 32-bit floating point registers */ | 118 | #define TIF_32BIT_FPREGS 27 /* 32-bit floating point registers */ |
119 | #define TIF_HYBRID_FPREGS 28 /* 64b FP registers, odd singles in bits 63:32 of even doubles */ | ||
119 | #define TIF_USEDMSA 29 /* MSA has been used this quantum */ | 120 | #define TIF_USEDMSA 29 /* MSA has been used this quantum */ |
120 | #define TIF_MSA_CTX_LIVE 30 /* MSA context must be preserved */ | 121 | #define TIF_MSA_CTX_LIVE 30 /* MSA context must be preserved */ |
121 | #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ | 122 | #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ |
@@ -135,6 +136,7 @@ static inline struct thread_info *current_thread_info(void) | |||
135 | #define _TIF_FPUBOUND (1<<TIF_FPUBOUND) | 136 | #define _TIF_FPUBOUND (1<<TIF_FPUBOUND) |
136 | #define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH) | 137 | #define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH) |
137 | #define _TIF_32BIT_FPREGS (1<<TIF_32BIT_FPREGS) | 138 | #define _TIF_32BIT_FPREGS (1<<TIF_32BIT_FPREGS) |
139 | #define _TIF_HYBRID_FPREGS (1<<TIF_HYBRID_FPREGS) | ||
138 | #define _TIF_USEDMSA (1<<TIF_USEDMSA) | 140 | #define _TIF_USEDMSA (1<<TIF_USEDMSA) |
139 | #define _TIF_MSA_CTX_LIVE (1<<TIF_MSA_CTX_LIVE) | 141 | #define _TIF_MSA_CTX_LIVE (1<<TIF_MSA_CTX_LIVE) |
140 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) | 142 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) |
diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h index 8f3047d611ee..8ab2874225c4 100644 --- a/arch/mips/include/asm/time.h +++ b/arch/mips/include/asm/time.h | |||
@@ -46,19 +46,17 @@ extern unsigned int mips_hpt_frequency; | |||
46 | * so it lives here. | 46 | * so it lives here. |
47 | */ | 47 | */ |
48 | extern int (*perf_irq)(void); | 48 | extern int (*perf_irq)(void); |
49 | extern int __weak get_c0_perfcount_int(void); | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * Initialize the calling CPU's compare interrupt as clockevent device | 52 | * Initialize the calling CPU's compare interrupt as clockevent device |
52 | */ | 53 | */ |
53 | extern unsigned int __weak get_c0_compare_int(void); | 54 | extern unsigned int __weak get_c0_compare_int(void); |
54 | extern int r4k_clockevent_init(void); | 55 | extern int r4k_clockevent_init(void); |
55 | extern int gic_clockevent_init(void); | ||
56 | 56 | ||
57 | static inline int mips_clockevent_init(void) | 57 | static inline int mips_clockevent_init(void) |
58 | { | 58 | { |
59 | #if defined(CONFIG_CEVT_GIC) | 59 | #ifdef CONFIG_CEVT_R4K |
60 | return (gic_clockevent_init() | r4k_clockevent_init()); | ||
61 | #elif defined(CONFIG_CEVT_R4K) | ||
62 | return r4k_clockevent_init(); | 60 | return r4k_clockevent_init(); |
63 | #else | 61 | #else |
64 | return -ENXIO; | 62 | return -ENXIO; |
diff --git a/arch/mips/include/asm/types.h b/arch/mips/include/asm/types.h index a845aafedee4..148d42a17f30 100644 --- a/arch/mips/include/asm/types.h +++ b/arch/mips/include/asm/types.h | |||
@@ -11,23 +11,7 @@ | |||
11 | #ifndef _ASM_TYPES_H | 11 | #ifndef _ASM_TYPES_H |
12 | #define _ASM_TYPES_H | 12 | #define _ASM_TYPES_H |
13 | 13 | ||
14 | # include <asm-generic/int-ll64.h> | 14 | #include <asm-generic/int-ll64.h> |
15 | #include <uapi/asm/types.h> | 15 | #include <uapi/asm/types.h> |
16 | 16 | ||
17 | /* | ||
18 | * These aren't exported outside the kernel to avoid name space clashes | ||
19 | */ | ||
20 | #ifndef __ASSEMBLY__ | ||
21 | |||
22 | /* | ||
23 | * Don't use phys_t. You've been warned. | ||
24 | */ | ||
25 | #ifdef CONFIG_64BIT_PHYS_ADDR | ||
26 | typedef unsigned long long phys_t; | ||
27 | #else | ||
28 | typedef unsigned long phys_t; | ||
29 | #endif | ||
30 | |||
31 | #endif /* __ASSEMBLY__ */ | ||
32 | |||
33 | #endif /* _ASM_TYPES_H */ | 17 | #endif /* _ASM_TYPES_H */ |
diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h index 22a5624e2fd2..bf8b32450ef6 100644 --- a/arch/mips/include/asm/uaccess.h +++ b/arch/mips/include/asm/uaccess.h | |||
@@ -1325,33 +1325,6 @@ strncpy_from_user(char *__to, const char __user *__from, long __len) | |||
1325 | return res; | 1325 | return res; |
1326 | } | 1326 | } |
1327 | 1327 | ||
1328 | /* Returns: 0 if bad, string length+1 (memory size) of string if ok */ | ||
1329 | static inline long __strlen_user(const char __user *s) | ||
1330 | { | ||
1331 | long res; | ||
1332 | |||
1333 | if (segment_eq(get_fs(), get_ds())) { | ||
1334 | __asm__ __volatile__( | ||
1335 | "move\t$4, %1\n\t" | ||
1336 | __MODULE_JAL(__strlen_kernel_nocheck_asm) | ||
1337 | "move\t%0, $2" | ||
1338 | : "=r" (res) | ||
1339 | : "r" (s) | ||
1340 | : "$2", "$4", __UA_t0, "$31"); | ||
1341 | } else { | ||
1342 | might_fault(); | ||
1343 | __asm__ __volatile__( | ||
1344 | "move\t$4, %1\n\t" | ||
1345 | __MODULE_JAL(__strlen_user_nocheck_asm) | ||
1346 | "move\t%0, $2" | ||
1347 | : "=r" (res) | ||
1348 | : "r" (s) | ||
1349 | : "$2", "$4", __UA_t0, "$31"); | ||
1350 | } | ||
1351 | |||
1352 | return res; | ||
1353 | } | ||
1354 | |||
1355 | /* | 1328 | /* |
1356 | * strlen_user: - Get the size of a string in user space. | 1329 | * strlen_user: - Get the size of a string in user space. |
1357 | * @str: The string to measure. | 1330 | * @str: The string to measure. |
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 708c5d414905..fc1cdd25fcda 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h | |||
@@ -136,9 +136,11 @@ Ip_u1s2(_lui); | |||
136 | Ip_u2s3u1(_lw); | 136 | Ip_u2s3u1(_lw); |
137 | Ip_u3u1u2(_lwx); | 137 | Ip_u3u1u2(_lwx); |
138 | Ip_u1u2u3(_mfc0); | 138 | Ip_u1u2u3(_mfc0); |
139 | Ip_u1u2u3(_mfhc0); | ||
139 | Ip_u1(_mfhi); | 140 | Ip_u1(_mfhi); |
140 | Ip_u1(_mflo); | 141 | Ip_u1(_mflo); |
141 | Ip_u1u2u3(_mtc0); | 142 | Ip_u1u2u3(_mtc0); |
143 | Ip_u1u2u3(_mthc0); | ||
142 | Ip_u3u1u2(_mul); | 144 | Ip_u3u1u2(_mul); |
143 | Ip_u3u1u2(_or); | 145 | Ip_u3u1u2(_or); |
144 | Ip_u2u1u3(_ori); | 146 | Ip_u2u1u3(_ori); |
diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 4bfdb9d4c186..89c22433b1c6 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h | |||
@@ -108,9 +108,10 @@ enum rt_op { | |||
108 | */ | 108 | */ |
109 | enum cop_op { | 109 | enum cop_op { |
110 | mfc_op = 0x00, dmfc_op = 0x01, | 110 | mfc_op = 0x00, dmfc_op = 0x01, |
111 | cfc_op = 0x02, mfhc_op = 0x03, | 111 | cfc_op = 0x02, mfhc0_op = 0x02, |
112 | mtc_op = 0x04, dmtc_op = 0x05, | 112 | mfhc_op = 0x03, mtc_op = 0x04, |
113 | ctc_op = 0x06, mthc_op = 0x07, | 113 | dmtc_op = 0x05, ctc_op = 0x06, |
114 | mthc0_op = 0x06, mthc_op = 0x07, | ||
114 | bc_op = 0x08, cop_op = 0x10, | 115 | bc_op = 0x08, cop_op = 0x10, |
115 | copm_op = 0x18 | 116 | copm_op = 0x18 |
116 | }; | 117 | }; |
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c index 76eafcb79c89..ef796f97b996 100644 --- a/arch/mips/jz4740/setup.c +++ b/arch/mips/jz4740/setup.c | |||
@@ -32,7 +32,7 @@ static void __init jz4740_detect_mem(void) | |||
32 | { | 32 | { |
33 | void __iomem *jz_emc_base; | 33 | void __iomem *jz_emc_base; |
34 | u32 ctrl, bus, bank, rows, cols; | 34 | u32 ctrl, bus, bank, rows, cols; |
35 | phys_t size; | 35 | phys_addr_t size; |
36 | 36 | ||
37 | jz_emc_base = ioremap(JZ4740_EMC_BASE_ADDR, 0x100); | 37 | jz_emc_base = ioremap(JZ4740_EMC_BASE_ADDR, 0x100); |
38 | ctrl = readl(jz_emc_base + JZ4740_EMC_SDRAM_CTRL); | 38 | ctrl = readl(jz_emc_base + JZ4740_EMC_SDRAM_CTRL); |
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 008a2fed0584..92987d1bbe5f 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -4,9 +4,10 @@ | |||
4 | 4 | ||
5 | extra-y := head.o vmlinux.lds | 5 | extra-y := head.o vmlinux.lds |
6 | 6 | ||
7 | obj-y += cpu-probe.o branch.o entry.o genex.o idle.o irq.o process.o \ | 7 | obj-y += cpu-probe.o branch.o elf.o entry.o genex.o idle.o irq.o \ |
8 | prom.o ptrace.o reset.o setup.o signal.o syscall.o \ | 8 | process.o prom.o ptrace.o reset.o setup.o signal.o \ |
9 | time.o topology.o traps.o unaligned.o watch.o vdso.o | 9 | syscall.o time.o topology.o traps.o unaligned.o watch.o \ |
10 | vdso.o | ||
10 | 11 | ||
11 | ifdef CONFIG_FUNCTION_TRACER | 12 | ifdef CONFIG_FUNCTION_TRACER |
12 | CFLAGS_REMOVE_ftrace.o = -pg | 13 | CFLAGS_REMOVE_ftrace.o = -pg |
@@ -18,12 +19,10 @@ endif | |||
18 | obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o | 19 | obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o |
19 | obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o | 20 | obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o |
20 | obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o | 21 | obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o |
21 | obj-$(CONFIG_CEVT_GIC) += cevt-gic.o | ||
22 | obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o | 22 | obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o |
23 | obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o | 23 | obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o |
24 | obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o | 24 | obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o |
25 | obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o | 25 | obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o |
26 | obj-$(CONFIG_CSRC_GIC) += csrc-gic.o | ||
27 | obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o | 26 | obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o |
28 | obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o | 27 | obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o |
29 | obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o | 28 | obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o |
@@ -68,7 +67,6 @@ obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o | |||
68 | obj-$(CONFIG_MIPS_MSC) += irq-msc01.o | 67 | obj-$(CONFIG_MIPS_MSC) += irq-msc01.o |
69 | obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o | 68 | obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o |
70 | obj-$(CONFIG_IRQ_GT641XX) += irq-gt641xx.o | 69 | obj-$(CONFIG_IRQ_GT641XX) += irq-gt641xx.o |
71 | obj-$(CONFIG_IRQ_GIC) += irq-gic.o | ||
72 | 70 | ||
73 | obj-$(CONFIG_KPROBES) += kprobes.o | 71 | obj-$(CONFIG_KPROBES) += kprobes.o |
74 | obj-$(CONFIG_32BIT) += scall32-o32.o | 72 | obj-$(CONFIG_32BIT) += scall32-o32.o |
diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c deleted file mode 100644 index 6093716980b9..000000000000 --- a/arch/mips/kernel/cevt-gic.c +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2013 Imagination Technologies Ltd. | ||
7 | */ | ||
8 | #include <linux/clockchips.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/percpu.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <linux/irq.h> | ||
13 | |||
14 | #include <asm/time.h> | ||
15 | #include <asm/gic.h> | ||
16 | #include <asm/mips-boards/maltaint.h> | ||
17 | |||
18 | DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); | ||
19 | int gic_timer_irq_installed; | ||
20 | |||
21 | |||
22 | static int gic_next_event(unsigned long delta, struct clock_event_device *evt) | ||
23 | { | ||
24 | u64 cnt; | ||
25 | int res; | ||
26 | |||
27 | cnt = gic_read_count(); | ||
28 | cnt += (u64)delta; | ||
29 | gic_write_cpu_compare(cnt, cpumask_first(evt->cpumask)); | ||
30 | res = ((int)(gic_read_count() - cnt) >= 0) ? -ETIME : 0; | ||
31 | return res; | ||
32 | } | ||
33 | |||
34 | void gic_set_clock_mode(enum clock_event_mode mode, | ||
35 | struct clock_event_device *evt) | ||
36 | { | ||
37 | /* Nothing to do ... */ | ||
38 | } | ||
39 | |||
40 | irqreturn_t gic_compare_interrupt(int irq, void *dev_id) | ||
41 | { | ||
42 | struct clock_event_device *cd; | ||
43 | int cpu = smp_processor_id(); | ||
44 | |||
45 | gic_write_compare(gic_read_compare()); | ||
46 | cd = &per_cpu(gic_clockevent_device, cpu); | ||
47 | cd->event_handler(cd); | ||
48 | return IRQ_HANDLED; | ||
49 | } | ||
50 | |||
51 | struct irqaction gic_compare_irqaction = { | ||
52 | .handler = gic_compare_interrupt, | ||
53 | .flags = IRQF_PERCPU | IRQF_TIMER, | ||
54 | .name = "timer", | ||
55 | }; | ||
56 | |||
57 | |||
58 | void gic_event_handler(struct clock_event_device *dev) | ||
59 | { | ||
60 | } | ||
61 | |||
62 | int gic_clockevent_init(void) | ||
63 | { | ||
64 | unsigned int cpu = smp_processor_id(); | ||
65 | struct clock_event_device *cd; | ||
66 | unsigned int irq; | ||
67 | |||
68 | if (!cpu_has_counter || !gic_frequency) | ||
69 | return -ENXIO; | ||
70 | |||
71 | irq = MIPS_GIC_IRQ_BASE; | ||
72 | |||
73 | cd = &per_cpu(gic_clockevent_device, cpu); | ||
74 | |||
75 | cd->name = "MIPS GIC"; | ||
76 | cd->features = CLOCK_EVT_FEAT_ONESHOT | | ||
77 | CLOCK_EVT_FEAT_C3STOP; | ||
78 | |||
79 | clockevent_set_clock(cd, gic_frequency); | ||
80 | |||
81 | /* Calculate the min / max delta */ | ||
82 | cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); | ||
83 | cd->min_delta_ns = clockevent_delta2ns(0x300, cd); | ||
84 | |||
85 | cd->rating = 300; | ||
86 | cd->irq = irq; | ||
87 | cd->cpumask = cpumask_of(cpu); | ||
88 | cd->set_next_event = gic_next_event; | ||
89 | cd->set_mode = gic_set_clock_mode; | ||
90 | cd->event_handler = gic_event_handler; | ||
91 | |||
92 | clockevents_register_device(cd); | ||
93 | |||
94 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_MAP), 0x80000002); | ||
95 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), GIC_VPE_SMASK_CMP_MSK); | ||
96 | |||
97 | if (gic_timer_irq_installed) | ||
98 | return 0; | ||
99 | |||
100 | gic_timer_irq_installed = 1; | ||
101 | |||
102 | setup_irq(irq, &gic_compare_irqaction); | ||
103 | irq_set_handler(irq, handle_percpu_irq); | ||
104 | return 0; | ||
105 | } | ||
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index bc127e22fdab..6acaad0480af 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c | |||
@@ -11,10 +11,10 @@ | |||
11 | #include <linux/percpu.h> | 11 | #include <linux/percpu.h> |
12 | #include <linux/smp.h> | 12 | #include <linux/smp.h> |
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/irqchip/mips-gic.h> | ||
14 | 15 | ||
15 | #include <asm/time.h> | 16 | #include <asm/time.h> |
16 | #include <asm/cevt-r4k.h> | 17 | #include <asm/cevt-r4k.h> |
17 | #include <asm/gic.h> | ||
18 | 18 | ||
19 | static int mips_next_event(unsigned long delta, | 19 | static int mips_next_event(unsigned long delta, |
20 | struct clock_event_device *evt) | 20 | struct clock_event_device *evt) |
@@ -85,8 +85,8 @@ void mips_event_handler(struct clock_event_device *dev) | |||
85 | */ | 85 | */ |
86 | static int c0_compare_int_pending(void) | 86 | static int c0_compare_int_pending(void) |
87 | { | 87 | { |
88 | #ifdef CONFIG_IRQ_GIC | 88 | #ifdef CONFIG_MIPS_GIC |
89 | if (cpu_has_veic) | 89 | if (gic_present) |
90 | return gic_get_timer_pending(); | 90 | return gic_get_timer_pending(); |
91 | #endif | 91 | #endif |
92 | return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP); | 92 | return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP); |
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index dc49cf30c2db..5342674842f5 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
@@ -69,6 +69,63 @@ static int __init htw_disable(char *s) | |||
69 | 69 | ||
70 | __setup("nohtw", htw_disable); | 70 | __setup("nohtw", htw_disable); |
71 | 71 | ||
72 | static int mips_ftlb_disabled; | ||
73 | static int mips_has_ftlb_configured; | ||
74 | |||
75 | static void set_ftlb_enable(struct cpuinfo_mips *c, int enable); | ||
76 | |||
77 | static int __init ftlb_disable(char *s) | ||
78 | { | ||
79 | unsigned int config4, mmuextdef; | ||
80 | |||
81 | /* | ||
82 | * If the core hasn't done any FTLB configuration, there is nothing | ||
83 | * for us to do here. | ||
84 | */ | ||
85 | if (!mips_has_ftlb_configured) | ||
86 | return 1; | ||
87 | |||
88 | /* Disable it in the boot cpu */ | ||
89 | set_ftlb_enable(&cpu_data[0], 0); | ||
90 | |||
91 | back_to_back_c0_hazard(); | ||
92 | |||
93 | config4 = read_c0_config4(); | ||
94 | |||
95 | /* Check that FTLB has been disabled */ | ||
96 | mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF; | ||
97 | /* MMUSIZEEXT == VTLB ON, FTLB OFF */ | ||
98 | if (mmuextdef == MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT) { | ||
99 | /* This should never happen */ | ||
100 | pr_warn("FTLB could not be disabled!\n"); | ||
101 | return 1; | ||
102 | } | ||
103 | |||
104 | mips_ftlb_disabled = 1; | ||
105 | mips_has_ftlb_configured = 0; | ||
106 | |||
107 | /* | ||
108 | * noftlb is mainly used for debug purposes so print | ||
109 | * an informative message instead of using pr_debug() | ||
110 | */ | ||
111 | pr_info("FTLB has been disabled\n"); | ||
112 | |||
113 | /* | ||
114 | * Some of these bits are duplicated in the decode_config4. | ||
115 | * MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT is the only possible case | ||
116 | * once FTLB has been disabled so undo what decode_config4 did. | ||
117 | */ | ||
118 | cpu_data[0].tlbsize -= cpu_data[0].tlbsizeftlbways * | ||
119 | cpu_data[0].tlbsizeftlbsets; | ||
120 | cpu_data[0].tlbsizeftlbsets = 0; | ||
121 | cpu_data[0].tlbsizeftlbways = 0; | ||
122 | |||
123 | return 1; | ||
124 | } | ||
125 | |||
126 | __setup("noftlb", ftlb_disable); | ||
127 | |||
128 | |||
72 | static inline void check_errata(void) | 129 | static inline void check_errata(void) |
73 | { | 130 | { |
74 | struct cpuinfo_mips *c = ¤t_cpu_data; | 131 | struct cpuinfo_mips *c = ¤t_cpu_data; |
@@ -140,7 +197,7 @@ static inline unsigned long cpu_get_fpu_id(void) | |||
140 | */ | 197 | */ |
141 | static inline int __cpu_has_fpu(void) | 198 | static inline int __cpu_has_fpu(void) |
142 | { | 199 | { |
143 | return ((cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE); | 200 | return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE; |
144 | } | 201 | } |
145 | 202 | ||
146 | static inline unsigned long cpu_get_msa_id(void) | 203 | static inline unsigned long cpu_get_msa_id(void) |
@@ -399,6 +456,8 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) | |||
399 | ftlb_page = MIPS_CONF4_VFTLBPAGESIZE; | 456 | ftlb_page = MIPS_CONF4_VFTLBPAGESIZE; |
400 | /* fall through */ | 457 | /* fall through */ |
401 | case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT: | 458 | case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT: |
459 | if (mips_ftlb_disabled) | ||
460 | break; | ||
402 | newcf4 = (config4 & ~ftlb_page) | | 461 | newcf4 = (config4 & ~ftlb_page) | |
403 | (page_size_ftlb(mmuextdef) << | 462 | (page_size_ftlb(mmuextdef) << |
404 | MIPS_CONF4_FTLBPAGESIZE_SHIFT); | 463 | MIPS_CONF4_FTLBPAGESIZE_SHIFT); |
@@ -418,6 +477,7 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) | |||
418 | c->tlbsizeftlbways = ((config4 & MIPS_CONF4_FTLBWAYS) >> | 477 | c->tlbsizeftlbways = ((config4 & MIPS_CONF4_FTLBWAYS) >> |
419 | MIPS_CONF4_FTLBWAYS_SHIFT) + 2; | 478 | MIPS_CONF4_FTLBWAYS_SHIFT) + 2; |
420 | c->tlbsize += c->tlbsizeftlbways * c->tlbsizeftlbsets; | 479 | c->tlbsize += c->tlbsizeftlbways * c->tlbsizeftlbsets; |
480 | mips_has_ftlb_configured = 1; | ||
421 | break; | 481 | break; |
422 | } | 482 | } |
423 | } | 483 | } |
@@ -432,7 +492,7 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c) | |||
432 | unsigned int config5; | 492 | unsigned int config5; |
433 | 493 | ||
434 | config5 = read_c0_config5(); | 494 | config5 = read_c0_config5(); |
435 | config5 &= ~MIPS_CONF5_UFR; | 495 | config5 &= ~(MIPS_CONF5_UFR | MIPS_CONF5_UFE); |
436 | write_c0_config5(config5); | 496 | write_c0_config5(config5); |
437 | 497 | ||
438 | if (config5 & MIPS_CONF5_EVA) | 498 | if (config5 & MIPS_CONF5_EVA) |
@@ -453,8 +513,8 @@ static void decode_configs(struct cpuinfo_mips *c) | |||
453 | 513 | ||
454 | c->scache.flags = MIPS_CACHE_NOT_PRESENT; | 514 | c->scache.flags = MIPS_CACHE_NOT_PRESENT; |
455 | 515 | ||
456 | /* Enable FTLB if present */ | 516 | /* Enable FTLB if present and not disabled */ |
457 | set_ftlb_enable(c, 1); | 517 | set_ftlb_enable(c, !mips_ftlb_disabled); |
458 | 518 | ||
459 | ok = decode_config0(c); /* Read Config registers. */ | 519 | ok = decode_config0(c); /* Read Config registers. */ |
460 | BUG_ON(!ok); /* Arch spec violation! */ | 520 | BUG_ON(!ok); /* Arch spec violation! */ |
@@ -1058,6 +1118,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) | |||
1058 | break; | 1118 | break; |
1059 | } | 1119 | } |
1060 | case PRID_IMP_BMIPS5000: | 1120 | case PRID_IMP_BMIPS5000: |
1121 | case PRID_IMP_BMIPS5200: | ||
1061 | c->cputype = CPU_BMIPS5000; | 1122 | c->cputype = CPU_BMIPS5000; |
1062 | __cpu_name[cpu] = "Broadcom BMIPS5000"; | 1123 | __cpu_name[cpu] = "Broadcom BMIPS5000"; |
1063 | set_elf_platform(cpu, "bmips5000"); | 1124 | set_elf_platform(cpu, "bmips5000"); |
@@ -1288,6 +1349,8 @@ void cpu_probe(void) | |||
1288 | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) { | 1349 | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) { |
1289 | if (c->fpu_id & MIPS_FPIR_3D) | 1350 | if (c->fpu_id & MIPS_FPIR_3D) |
1290 | c->ases |= MIPS_ASE_MIPS3D; | 1351 | c->ases |= MIPS_ASE_MIPS3D; |
1352 | if (c->fpu_id & MIPS_FPIR_FREP) | ||
1353 | c->options |= MIPS_CPU_FRE; | ||
1291 | } | 1354 | } |
1292 | } | 1355 | } |
1293 | 1356 | ||
diff --git a/arch/mips/kernel/crash_dump.c b/arch/mips/kernel/crash_dump.c index f291cf99b03a..6fe7790e5868 100644 --- a/arch/mips/kernel/crash_dump.c +++ b/arch/mips/kernel/crash_dump.c | |||
@@ -38,7 +38,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, | |||
38 | kunmap_atomic(vaddr); | 38 | kunmap_atomic(vaddr); |
39 | } else { | 39 | } else { |
40 | if (!kdump_buf_page) { | 40 | if (!kdump_buf_page) { |
41 | pr_warning("Kdump: Kdump buffer page not allocated\n"); | 41 | pr_warn("Kdump: Kdump buffer page not allocated\n"); |
42 | 42 | ||
43 | return -EFAULT; | 43 | return -EFAULT; |
44 | } | 44 | } |
@@ -57,7 +57,7 @@ static int __init kdump_buf_page_init(void) | |||
57 | 57 | ||
58 | kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL); | 58 | kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL); |
59 | if (!kdump_buf_page) { | 59 | if (!kdump_buf_page) { |
60 | pr_warning("Kdump: Failed to allocate kdump buffer page\n"); | 60 | pr_warn("Kdump: Failed to allocate kdump buffer page\n"); |
61 | ret = -ENOMEM; | 61 | ret = -ENOMEM; |
62 | } | 62 | } |
63 | 63 | ||
diff --git a/arch/mips/kernel/csrc-gic.c b/arch/mips/kernel/csrc-gic.c deleted file mode 100644 index e02620901117..000000000000 --- a/arch/mips/kernel/csrc-gic.c +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
7 | */ | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/time.h> | ||
10 | |||
11 | #include <asm/gic.h> | ||
12 | |||
13 | static cycle_t gic_hpt_read(struct clocksource *cs) | ||
14 | { | ||
15 | return gic_read_count(); | ||
16 | } | ||
17 | |||
18 | static struct clocksource gic_clocksource = { | ||
19 | .name = "GIC", | ||
20 | .read = gic_hpt_read, | ||
21 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
22 | }; | ||
23 | |||
24 | void __init gic_clocksource_init(unsigned int frequency) | ||
25 | { | ||
26 | unsigned int config, bits; | ||
27 | |||
28 | /* Calculate the clocksource mask. */ | ||
29 | GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), config); | ||
30 | bits = 32 + ((config & GIC_SH_CONFIG_COUNTBITS_MSK) >> | ||
31 | (GIC_SH_CONFIG_COUNTBITS_SHF - 2)); | ||
32 | |||
33 | /* Set clocksource mask. */ | ||
34 | gic_clocksource.mask = CLOCKSOURCE_MASK(bits); | ||
35 | |||
36 | /* Calculate a somewhat reasonable rating value. */ | ||
37 | gic_clocksource.rating = 200 + frequency / 10000000; | ||
38 | |||
39 | clocksource_register_hz(&gic_clocksource, frequency); | ||
40 | } | ||
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c new file mode 100644 index 000000000000..c92b15df6893 --- /dev/null +++ b/arch/mips/kernel/elf.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Imagination Technologies | ||
3 | * Author: Paul Burton <paul.burton@imgtec.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <linux/elf.h> | ||
12 | #include <linux/sched.h> | ||
13 | |||
14 | enum { | ||
15 | FP_ERROR = -1, | ||
16 | FP_DOUBLE_64A = -2, | ||
17 | }; | ||
18 | |||
19 | int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf, | ||
20 | bool is_interp, struct arch_elf_state *state) | ||
21 | { | ||
22 | struct elfhdr *ehdr = _ehdr; | ||
23 | struct elf_phdr *phdr = _phdr; | ||
24 | struct mips_elf_abiflags_v0 abiflags; | ||
25 | int ret; | ||
26 | |||
27 | if (config_enabled(CONFIG_64BIT) && | ||
28 | (ehdr->e_ident[EI_CLASS] != ELFCLASS32)) | ||
29 | return 0; | ||
30 | if (phdr->p_type != PT_MIPS_ABIFLAGS) | ||
31 | return 0; | ||
32 | if (phdr->p_filesz < sizeof(abiflags)) | ||
33 | return -EINVAL; | ||
34 | |||
35 | ret = kernel_read(elf, phdr->p_offset, (char *)&abiflags, | ||
36 | sizeof(abiflags)); | ||
37 | if (ret < 0) | ||
38 | return ret; | ||
39 | if (ret != sizeof(abiflags)) | ||
40 | return -EIO; | ||
41 | |||
42 | /* Record the required FP ABIs for use by mips_check_elf */ | ||
43 | if (is_interp) | ||
44 | state->interp_fp_abi = abiflags.fp_abi; | ||
45 | else | ||
46 | state->fp_abi = abiflags.fp_abi; | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static inline unsigned get_fp_abi(struct elfhdr *ehdr, int in_abi) | ||
52 | { | ||
53 | /* If the ABI requirement is provided, simply return that */ | ||
54 | if (in_abi != -1) | ||
55 | return in_abi; | ||
56 | |||
57 | /* If the EF_MIPS_FP64 flag was set, return MIPS_ABI_FP_64 */ | ||
58 | if (ehdr->e_flags & EF_MIPS_FP64) | ||
59 | return MIPS_ABI_FP_64; | ||
60 | |||
61 | /* Default to MIPS_ABI_FP_DOUBLE */ | ||
62 | return MIPS_ABI_FP_DOUBLE; | ||
63 | } | ||
64 | |||
65 | int arch_check_elf(void *_ehdr, bool has_interpreter, | ||
66 | struct arch_elf_state *state) | ||
67 | { | ||
68 | struct elfhdr *ehdr = _ehdr; | ||
69 | unsigned fp_abi, interp_fp_abi, abi0, abi1; | ||
70 | |||
71 | /* Ignore non-O32 binaries */ | ||
72 | if (config_enabled(CONFIG_64BIT) && | ||
73 | (ehdr->e_ident[EI_CLASS] != ELFCLASS32)) | ||
74 | return 0; | ||
75 | |||
76 | fp_abi = get_fp_abi(ehdr, state->fp_abi); | ||
77 | |||
78 | if (has_interpreter) { | ||
79 | interp_fp_abi = get_fp_abi(ehdr, state->interp_fp_abi); | ||
80 | |||
81 | abi0 = min(fp_abi, interp_fp_abi); | ||
82 | abi1 = max(fp_abi, interp_fp_abi); | ||
83 | } else { | ||
84 | abi0 = abi1 = fp_abi; | ||
85 | } | ||
86 | |||
87 | state->overall_abi = FP_ERROR; | ||
88 | |||
89 | if (abi0 == abi1) { | ||
90 | state->overall_abi = abi0; | ||
91 | } else if (abi0 == MIPS_ABI_FP_ANY) { | ||
92 | state->overall_abi = abi1; | ||
93 | } else if (abi0 == MIPS_ABI_FP_DOUBLE) { | ||
94 | switch (abi1) { | ||
95 | case MIPS_ABI_FP_XX: | ||
96 | state->overall_abi = MIPS_ABI_FP_DOUBLE; | ||
97 | break; | ||
98 | |||
99 | case MIPS_ABI_FP_64A: | ||
100 | state->overall_abi = FP_DOUBLE_64A; | ||
101 | break; | ||
102 | } | ||
103 | } else if (abi0 == MIPS_ABI_FP_SINGLE || | ||
104 | abi0 == MIPS_ABI_FP_SOFT) { | ||
105 | /* Cannot link with other ABIs */ | ||
106 | } else if (abi0 == MIPS_ABI_FP_OLD_64) { | ||
107 | switch (abi1) { | ||
108 | case MIPS_ABI_FP_XX: | ||
109 | case MIPS_ABI_FP_64: | ||
110 | case MIPS_ABI_FP_64A: | ||
111 | state->overall_abi = MIPS_ABI_FP_64; | ||
112 | break; | ||
113 | } | ||
114 | } else if (abi0 == MIPS_ABI_FP_XX || | ||
115 | abi0 == MIPS_ABI_FP_64 || | ||
116 | abi0 == MIPS_ABI_FP_64A) { | ||
117 | state->overall_abi = MIPS_ABI_FP_64; | ||
118 | } | ||
119 | |||
120 | switch (state->overall_abi) { | ||
121 | case MIPS_ABI_FP_64: | ||
122 | case MIPS_ABI_FP_64A: | ||
123 | case FP_DOUBLE_64A: | ||
124 | if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) | ||
125 | return -ELIBBAD; | ||
126 | break; | ||
127 | |||
128 | case FP_ERROR: | ||
129 | return -ELIBBAD; | ||
130 | } | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | void mips_set_personality_fp(struct arch_elf_state *state) | ||
136 | { | ||
137 | if (config_enabled(CONFIG_FP32XX_HYBRID_FPRS)) { | ||
138 | /* | ||
139 | * Use hybrid FPRs for all code which can correctly execute | ||
140 | * with that mode. | ||
141 | */ | ||
142 | switch (state->overall_abi) { | ||
143 | case MIPS_ABI_FP_DOUBLE: | ||
144 | case MIPS_ABI_FP_SINGLE: | ||
145 | case MIPS_ABI_FP_SOFT: | ||
146 | case MIPS_ABI_FP_XX: | ||
147 | case MIPS_ABI_FP_ANY: | ||
148 | /* FR=1, FRE=1 */ | ||
149 | clear_thread_flag(TIF_32BIT_FPREGS); | ||
150 | set_thread_flag(TIF_HYBRID_FPREGS); | ||
151 | return; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | switch (state->overall_abi) { | ||
156 | case MIPS_ABI_FP_DOUBLE: | ||
157 | case MIPS_ABI_FP_SINGLE: | ||
158 | case MIPS_ABI_FP_SOFT: | ||
159 | /* FR=0 */ | ||
160 | set_thread_flag(TIF_32BIT_FPREGS); | ||
161 | clear_thread_flag(TIF_HYBRID_FPREGS); | ||
162 | break; | ||
163 | |||
164 | case FP_DOUBLE_64A: | ||
165 | /* FR=1, FRE=1 */ | ||
166 | clear_thread_flag(TIF_32BIT_FPREGS); | ||
167 | set_thread_flag(TIF_HYBRID_FPREGS); | ||
168 | break; | ||
169 | |||
170 | case MIPS_ABI_FP_64: | ||
171 | case MIPS_ABI_FP_64A: | ||
172 | /* FR=1, FRE=0 */ | ||
173 | clear_thread_flag(TIF_32BIT_FPREGS); | ||
174 | clear_thread_flag(TIF_HYBRID_FPREGS); | ||
175 | break; | ||
176 | |||
177 | case MIPS_ABI_FP_XX: | ||
178 | case MIPS_ABI_FP_ANY: | ||
179 | if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) | ||
180 | set_thread_flag(TIF_32BIT_FPREGS); | ||
181 | else | ||
182 | clear_thread_flag(TIF_32BIT_FPREGS); | ||
183 | |||
184 | clear_thread_flag(TIF_HYBRID_FPREGS); | ||
185 | break; | ||
186 | |||
187 | default: | ||
188 | case FP_ERROR: | ||
189 | BUG(); | ||
190 | } | ||
191 | } | ||
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index 50b364897dda..a74ec3ae557c 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/ioport.h> | 13 | #include <linux/ioport.h> |
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/irqdomain.h> | ||
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
17 | #include <linux/syscore_ops.h> | 18 | #include <linux/syscore_ops.h> |
@@ -308,6 +309,19 @@ static struct resource pic2_io_resource = { | |||
308 | .flags = IORESOURCE_BUSY | 309 | .flags = IORESOURCE_BUSY |
309 | }; | 310 | }; |
310 | 311 | ||
312 | static int i8259A_irq_domain_map(struct irq_domain *d, unsigned int virq, | ||
313 | irq_hw_number_t hw) | ||
314 | { | ||
315 | irq_set_chip_and_handler(virq, &i8259A_chip, handle_level_irq); | ||
316 | irq_set_probe(virq); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static struct irq_domain_ops i8259A_ops = { | ||
321 | .map = i8259A_irq_domain_map, | ||
322 | .xlate = irq_domain_xlate_onecell, | ||
323 | }; | ||
324 | |||
311 | /* | 325 | /* |
312 | * On systems with i8259-style interrupt controllers we assume for | 326 | * On systems with i8259-style interrupt controllers we assume for |
313 | * driver compatibility reasons interrupts 0 - 15 to be the i8259 | 327 | * driver compatibility reasons interrupts 0 - 15 to be the i8259 |
@@ -315,17 +329,17 @@ static struct resource pic2_io_resource = { | |||
315 | */ | 329 | */ |
316 | void __init init_i8259_irqs(void) | 330 | void __init init_i8259_irqs(void) |
317 | { | 331 | { |
318 | int i; | 332 | struct irq_domain *domain; |
319 | 333 | ||
320 | insert_resource(&ioport_resource, &pic1_io_resource); | 334 | insert_resource(&ioport_resource, &pic1_io_resource); |
321 | insert_resource(&ioport_resource, &pic2_io_resource); | 335 | insert_resource(&ioport_resource, &pic2_io_resource); |
322 | 336 | ||
323 | init_8259A(0); | 337 | init_8259A(0); |
324 | 338 | ||
325 | for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++) { | 339 | domain = irq_domain_add_legacy(NULL, 16, I8259A_IRQ_BASE, 0, |
326 | irq_set_chip_and_handler(i, &i8259A_chip, handle_level_irq); | 340 | &i8259A_ops, NULL); |
327 | irq_set_probe(i); | 341 | if (!domain) |
328 | } | 342 | panic("Failed to add i8259 IRQ domain"); |
329 | 343 | ||
330 | setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2); | 344 | setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2); |
331 | } | 345 | } |
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c deleted file mode 100644 index 9e9d8b9a5b97..000000000000 --- a/arch/mips/kernel/irq-gic.c +++ /dev/null | |||
@@ -1,402 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2008 Ralf Baechle (ralf@linux-mips.org) | ||
7 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
8 | */ | ||
9 | #include <linux/bitmap.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <linux/irq.h> | ||
13 | #include <linux/clocksource.h> | ||
14 | |||
15 | #include <asm/io.h> | ||
16 | #include <asm/gic.h> | ||
17 | #include <asm/setup.h> | ||
18 | #include <asm/traps.h> | ||
19 | #include <linux/hardirq.h> | ||
20 | #include <asm-generic/bitops/find.h> | ||
21 | |||
22 | unsigned int gic_frequency; | ||
23 | unsigned int gic_present; | ||
24 | unsigned long _gic_base; | ||
25 | unsigned int gic_irq_base; | ||
26 | unsigned int gic_irq_flags[GIC_NUM_INTRS]; | ||
27 | |||
28 | /* The index into this array is the vector # of the interrupt. */ | ||
29 | struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS]; | ||
30 | |||
31 | struct gic_pcpu_mask { | ||
32 | DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS); | ||
33 | }; | ||
34 | |||
35 | struct gic_pending_regs { | ||
36 | DECLARE_BITMAP(pending, GIC_NUM_INTRS); | ||
37 | }; | ||
38 | |||
39 | struct gic_intrmask_regs { | ||
40 | DECLARE_BITMAP(intrmask, GIC_NUM_INTRS); | ||
41 | }; | ||
42 | |||
43 | static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; | ||
44 | static struct gic_pending_regs pending_regs[NR_CPUS]; | ||
45 | static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; | ||
46 | |||
47 | #if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC) | ||
48 | cycle_t gic_read_count(void) | ||
49 | { | ||
50 | unsigned int hi, hi2, lo; | ||
51 | |||
52 | do { | ||
53 | GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi); | ||
54 | GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), lo); | ||
55 | GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi2); | ||
56 | } while (hi2 != hi); | ||
57 | |||
58 | return (((cycle_t) hi) << 32) + lo; | ||
59 | } | ||
60 | |||
61 | void gic_write_compare(cycle_t cnt) | ||
62 | { | ||
63 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI), | ||
64 | (int)(cnt >> 32)); | ||
65 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO), | ||
66 | (int)(cnt & 0xffffffff)); | ||
67 | } | ||
68 | |||
69 | void gic_write_cpu_compare(cycle_t cnt, int cpu) | ||
70 | { | ||
71 | unsigned long flags; | ||
72 | |||
73 | local_irq_save(flags); | ||
74 | |||
75 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu); | ||
76 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI), | ||
77 | (int)(cnt >> 32)); | ||
78 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO), | ||
79 | (int)(cnt & 0xffffffff)); | ||
80 | |||
81 | local_irq_restore(flags); | ||
82 | } | ||
83 | |||
84 | cycle_t gic_read_compare(void) | ||
85 | { | ||
86 | unsigned int hi, lo; | ||
87 | |||
88 | GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI), hi); | ||
89 | GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO), lo); | ||
90 | |||
91 | return (((cycle_t) hi) << 32) + lo; | ||
92 | } | ||
93 | #endif | ||
94 | |||
95 | unsigned int gic_get_timer_pending(void) | ||
96 | { | ||
97 | unsigned int vpe_pending; | ||
98 | |||
99 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0); | ||
100 | GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_PEND), vpe_pending); | ||
101 | return (vpe_pending & GIC_VPE_PEND_TIMER_MSK); | ||
102 | } | ||
103 | |||
104 | void gic_bind_eic_interrupt(int irq, int set) | ||
105 | { | ||
106 | /* Convert irq vector # to hw int # */ | ||
107 | irq -= GIC_PIN_TO_VEC_OFFSET; | ||
108 | |||
109 | /* Set irq to use shadow set */ | ||
110 | GICWRITE(GIC_REG_ADDR(VPE_LOCAL, GIC_VPE_EIC_SS(irq)), set); | ||
111 | } | ||
112 | |||
113 | void gic_send_ipi(unsigned int intr) | ||
114 | { | ||
115 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); | ||
116 | } | ||
117 | |||
118 | static void gic_eic_irq_dispatch(void) | ||
119 | { | ||
120 | unsigned int cause = read_c0_cause(); | ||
121 | int irq; | ||
122 | |||
123 | irq = (cause & ST0_IM) >> STATUSB_IP2; | ||
124 | if (irq == 0) | ||
125 | irq = -1; | ||
126 | |||
127 | if (irq >= 0) | ||
128 | do_IRQ(gic_irq_base + irq); | ||
129 | else | ||
130 | spurious_interrupt(); | ||
131 | } | ||
132 | |||
133 | static void __init vpe_local_setup(unsigned int numvpes) | ||
134 | { | ||
135 | unsigned long timer_intr = GIC_INT_TMR; | ||
136 | unsigned long perf_intr = GIC_INT_PERFCTR; | ||
137 | unsigned int vpe_ctl; | ||
138 | int i; | ||
139 | |||
140 | if (cpu_has_veic) { | ||
141 | /* | ||
142 | * GIC timer interrupt -> CPU HW Int X (vector X+2) -> | ||
143 | * map to pin X+2-1 (since GIC adds 1) | ||
144 | */ | ||
145 | timer_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET); | ||
146 | /* | ||
147 | * GIC perfcnt interrupt -> CPU HW Int X (vector X+2) -> | ||
148 | * map to pin X+2-1 (since GIC adds 1) | ||
149 | */ | ||
150 | perf_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET); | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * Setup the default performance counter timer interrupts | ||
155 | * for all VPEs | ||
156 | */ | ||
157 | for (i = 0; i < numvpes; i++) { | ||
158 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i); | ||
159 | |||
160 | /* Are Interrupts locally routable? */ | ||
161 | GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl); | ||
162 | if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK) | ||
163 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), | ||
164 | GIC_MAP_TO_PIN_MSK | timer_intr); | ||
165 | if (cpu_has_veic) { | ||
166 | set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET, | ||
167 | gic_eic_irq_dispatch); | ||
168 | gic_shared_intr_map[timer_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK; | ||
169 | } | ||
170 | |||
171 | if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) | ||
172 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), | ||
173 | GIC_MAP_TO_PIN_MSK | perf_intr); | ||
174 | if (cpu_has_veic) { | ||
175 | set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, gic_eic_irq_dispatch); | ||
176 | gic_shared_intr_map[perf_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK; | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
181 | unsigned int gic_compare_int(void) | ||
182 | { | ||
183 | unsigned int pending; | ||
184 | |||
185 | GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_PEND), pending); | ||
186 | if (pending & GIC_VPE_PEND_CMP_MSK) | ||
187 | return 1; | ||
188 | else | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | void gic_get_int_mask(unsigned long *dst, const unsigned long *src) | ||
193 | { | ||
194 | unsigned int i; | ||
195 | unsigned long *pending, *intrmask, *pcpu_mask; | ||
196 | unsigned long *pending_abs, *intrmask_abs; | ||
197 | |||
198 | /* Get per-cpu bitmaps */ | ||
199 | pending = pending_regs[smp_processor_id()].pending; | ||
200 | intrmask = intrmask_regs[smp_processor_id()].intrmask; | ||
201 | pcpu_mask = pcpu_masks[smp_processor_id()].pcpu_mask; | ||
202 | |||
203 | pending_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED, | ||
204 | GIC_SH_PEND_31_0_OFS); | ||
205 | intrmask_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED, | ||
206 | GIC_SH_MASK_31_0_OFS); | ||
207 | |||
208 | for (i = 0; i < BITS_TO_LONGS(GIC_NUM_INTRS); i++) { | ||
209 | GICREAD(*pending_abs, pending[i]); | ||
210 | GICREAD(*intrmask_abs, intrmask[i]); | ||
211 | pending_abs++; | ||
212 | intrmask_abs++; | ||
213 | } | ||
214 | |||
215 | bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS); | ||
216 | bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS); | ||
217 | bitmap_and(dst, src, pending, GIC_NUM_INTRS); | ||
218 | } | ||
219 | |||
220 | unsigned int gic_get_int(void) | ||
221 | { | ||
222 | DECLARE_BITMAP(interrupts, GIC_NUM_INTRS); | ||
223 | |||
224 | bitmap_fill(interrupts, GIC_NUM_INTRS); | ||
225 | gic_get_int_mask(interrupts, interrupts); | ||
226 | |||
227 | return find_first_bit(interrupts, GIC_NUM_INTRS); | ||
228 | } | ||
229 | |||
230 | static void gic_mask_irq(struct irq_data *d) | ||
231 | { | ||
232 | GIC_CLR_INTR_MASK(d->irq - gic_irq_base); | ||
233 | } | ||
234 | |||
235 | static void gic_unmask_irq(struct irq_data *d) | ||
236 | { | ||
237 | GIC_SET_INTR_MASK(d->irq - gic_irq_base); | ||
238 | } | ||
239 | |||
240 | #ifdef CONFIG_SMP | ||
241 | static DEFINE_SPINLOCK(gic_lock); | ||
242 | |||
243 | static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, | ||
244 | bool force) | ||
245 | { | ||
246 | unsigned int irq = (d->irq - gic_irq_base); | ||
247 | cpumask_t tmp = CPU_MASK_NONE; | ||
248 | unsigned long flags; | ||
249 | int i; | ||
250 | |||
251 | cpumask_and(&tmp, cpumask, cpu_online_mask); | ||
252 | if (cpus_empty(tmp)) | ||
253 | return -1; | ||
254 | |||
255 | /* Assumption : cpumask refers to a single CPU */ | ||
256 | spin_lock_irqsave(&gic_lock, flags); | ||
257 | |||
258 | /* Re-route this IRQ */ | ||
259 | GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp)); | ||
260 | |||
261 | /* Update the pcpu_masks */ | ||
262 | for (i = 0; i < NR_CPUS; i++) | ||
263 | clear_bit(irq, pcpu_masks[i].pcpu_mask); | ||
264 | set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask); | ||
265 | |||
266 | cpumask_copy(d->affinity, cpumask); | ||
267 | spin_unlock_irqrestore(&gic_lock, flags); | ||
268 | |||
269 | return IRQ_SET_MASK_OK_NOCOPY; | ||
270 | } | ||
271 | #endif | ||
272 | |||
273 | static struct irq_chip gic_irq_controller = { | ||
274 | .name = "MIPS GIC", | ||
275 | .irq_ack = gic_irq_ack, | ||
276 | .irq_mask = gic_mask_irq, | ||
277 | .irq_mask_ack = gic_mask_irq, | ||
278 | .irq_unmask = gic_unmask_irq, | ||
279 | .irq_eoi = gic_finish_irq, | ||
280 | #ifdef CONFIG_SMP | ||
281 | .irq_set_affinity = gic_set_affinity, | ||
282 | #endif | ||
283 | }; | ||
284 | |||
285 | static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, | ||
286 | unsigned int pin, unsigned int polarity, unsigned int trigtype, | ||
287 | unsigned int flags) | ||
288 | { | ||
289 | struct gic_shared_intr_map *map_ptr; | ||
290 | |||
291 | /* Setup Intr to Pin mapping */ | ||
292 | if (pin & GIC_MAP_TO_NMI_MSK) { | ||
293 | int i; | ||
294 | |||
295 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); | ||
296 | /* FIXME: hack to route NMI to all cpu's */ | ||
297 | for (i = 0; i < NR_CPUS; i += 32) { | ||
298 | GICWRITE(GIC_REG_ADDR(SHARED, | ||
299 | GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)), | ||
300 | 0xffffffff); | ||
301 | } | ||
302 | } else { | ||
303 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), | ||
304 | GIC_MAP_TO_PIN_MSK | pin); | ||
305 | /* Setup Intr to CPU mapping */ | ||
306 | GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); | ||
307 | if (cpu_has_veic) { | ||
308 | set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET, | ||
309 | gic_eic_irq_dispatch); | ||
310 | map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET]; | ||
311 | if (map_ptr->num_shared_intr >= GIC_MAX_SHARED_INTR) | ||
312 | BUG(); | ||
313 | map_ptr->intr_list[map_ptr->num_shared_intr++] = intr; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | /* Setup Intr Polarity */ | ||
318 | GIC_SET_POLARITY(intr, polarity); | ||
319 | |||
320 | /* Setup Intr Trigger Type */ | ||
321 | GIC_SET_TRIGGER(intr, trigtype); | ||
322 | |||
323 | /* Init Intr Masks */ | ||
324 | GIC_CLR_INTR_MASK(intr); | ||
325 | |||
326 | /* Initialise per-cpu Interrupt software masks */ | ||
327 | set_bit(intr, pcpu_masks[cpu].pcpu_mask); | ||
328 | |||
329 | if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0)) | ||
330 | GIC_SET_INTR_MASK(intr); | ||
331 | if (trigtype == GIC_TRIG_EDGE) | ||
332 | gic_irq_flags[intr] |= GIC_TRIG_EDGE; | ||
333 | } | ||
334 | |||
335 | static void __init gic_basic_init(int numintrs, int numvpes, | ||
336 | struct gic_intr_map *intrmap, int mapsize) | ||
337 | { | ||
338 | unsigned int i, cpu; | ||
339 | unsigned int pin_offset = 0; | ||
340 | |||
341 | board_bind_eic_interrupt = &gic_bind_eic_interrupt; | ||
342 | |||
343 | /* Setup defaults */ | ||
344 | for (i = 0; i < numintrs; i++) { | ||
345 | GIC_SET_POLARITY(i, GIC_POL_POS); | ||
346 | GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); | ||
347 | GIC_CLR_INTR_MASK(i); | ||
348 | if (i < GIC_NUM_INTRS) { | ||
349 | gic_irq_flags[i] = 0; | ||
350 | gic_shared_intr_map[i].num_shared_intr = 0; | ||
351 | gic_shared_intr_map[i].local_intr_mask = 0; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract | ||
357 | * one because the GIC will add one (since 0=no intr). | ||
358 | */ | ||
359 | if (cpu_has_veic) | ||
360 | pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET); | ||
361 | |||
362 | /* Setup specifics */ | ||
363 | for (i = 0; i < mapsize; i++) { | ||
364 | cpu = intrmap[i].cpunum; | ||
365 | if (cpu == GIC_UNUSED) | ||
366 | continue; | ||
367 | gic_setup_intr(i, | ||
368 | intrmap[i].cpunum, | ||
369 | intrmap[i].pin + pin_offset, | ||
370 | intrmap[i].polarity, | ||
371 | intrmap[i].trigtype, | ||
372 | intrmap[i].flags); | ||
373 | } | ||
374 | |||
375 | vpe_local_setup(numvpes); | ||
376 | } | ||
377 | |||
378 | void __init gic_init(unsigned long gic_base_addr, | ||
379 | unsigned long gic_addrspace_size, | ||
380 | struct gic_intr_map *intr_map, unsigned int intr_map_size, | ||
381 | unsigned int irqbase) | ||
382 | { | ||
383 | unsigned int gicconfig; | ||
384 | int numvpes, numintrs; | ||
385 | |||
386 | _gic_base = (unsigned long) ioremap_nocache(gic_base_addr, | ||
387 | gic_addrspace_size); | ||
388 | gic_irq_base = irqbase; | ||
389 | |||
390 | GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); | ||
391 | numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >> | ||
392 | GIC_SH_CONFIG_NUMINTRS_SHF; | ||
393 | numintrs = ((numintrs + 1) * 8); | ||
394 | |||
395 | numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >> | ||
396 | GIC_SH_CONFIG_NUMVPES_SHF; | ||
397 | numvpes = numvpes + 1; | ||
398 | |||
399 | gic_basic_init(numintrs, numvpes, intr_map, intr_map_size); | ||
400 | |||
401 | gic_platform_init(numintrs, &gic_irq_controller); | ||
402 | } | ||
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index e498f2b3646a..590c2c980fd3 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/irq_cpu.h> | 36 | #include <asm/irq_cpu.h> |
37 | #include <asm/mipsregs.h> | 37 | #include <asm/mipsregs.h> |
38 | #include <asm/mipsmtregs.h> | 38 | #include <asm/mipsmtregs.h> |
39 | #include <asm/setup.h> | ||
39 | 40 | ||
40 | static inline void unmask_mips_irq(struct irq_data *d) | 41 | static inline void unmask_mips_irq(struct irq_data *d) |
41 | { | 42 | { |
@@ -94,28 +95,24 @@ static struct irq_chip mips_mt_cpu_irq_controller = { | |||
94 | .irq_eoi = unmask_mips_irq, | 95 | .irq_eoi = unmask_mips_irq, |
95 | }; | 96 | }; |
96 | 97 | ||
97 | void __init mips_cpu_irq_init(void) | 98 | asmlinkage void __weak plat_irq_dispatch(void) |
98 | { | 99 | { |
99 | int irq_base = MIPS_CPU_IRQ_BASE; | 100 | unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM; |
100 | int i; | 101 | int irq; |
101 | 102 | ||
102 | /* Mask interrupts. */ | 103 | if (!pending) { |
103 | clear_c0_status(ST0_IM); | 104 | spurious_interrupt(); |
104 | clear_c0_cause(CAUSEF_IP); | 105 | return; |
105 | 106 | } | |
106 | /* Software interrupts are used for MT/CMT IPI */ | ||
107 | for (i = irq_base; i < irq_base + 2; i++) | ||
108 | irq_set_chip_and_handler(i, cpu_has_mipsmt ? | ||
109 | &mips_mt_cpu_irq_controller : | ||
110 | &mips_cpu_irq_controller, | ||
111 | handle_percpu_irq); | ||
112 | 107 | ||
113 | for (i = irq_base + 2; i < irq_base + 8; i++) | 108 | pending >>= CAUSEB_IP; |
114 | irq_set_chip_and_handler(i, &mips_cpu_irq_controller, | 109 | while (pending) { |
115 | handle_percpu_irq); | 110 | irq = fls(pending) - 1; |
111 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | ||
112 | pending &= ~BIT(irq); | ||
113 | } | ||
116 | } | 114 | } |
117 | 115 | ||
118 | #ifdef CONFIG_IRQ_DOMAIN | ||
119 | static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq, | 116 | static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq, |
120 | irq_hw_number_t hw) | 117 | irq_hw_number_t hw) |
121 | { | 118 | { |
@@ -128,6 +125,9 @@ static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq, | |||
128 | chip = &mips_cpu_irq_controller; | 125 | chip = &mips_cpu_irq_controller; |
129 | } | 126 | } |
130 | 127 | ||
128 | if (cpu_has_vint) | ||
129 | set_vi_handler(hw, plat_irq_dispatch); | ||
130 | |||
131 | irq_set_chip_and_handler(irq, chip, handle_percpu_irq); | 131 | irq_set_chip_and_handler(irq, chip, handle_percpu_irq); |
132 | 132 | ||
133 | return 0; | 133 | return 0; |
@@ -138,8 +138,7 @@ static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = { | |||
138 | .xlate = irq_domain_xlate_onecell, | 138 | .xlate = irq_domain_xlate_onecell, |
139 | }; | 139 | }; |
140 | 140 | ||
141 | int __init mips_cpu_intc_init(struct device_node *of_node, | 141 | static void __init __mips_cpu_irq_init(struct device_node *of_node) |
142 | struct device_node *parent) | ||
143 | { | 142 | { |
144 | struct irq_domain *domain; | 143 | struct irq_domain *domain; |
145 | 144 | ||
@@ -151,7 +150,16 @@ int __init mips_cpu_intc_init(struct device_node *of_node, | |||
151 | &mips_cpu_intc_irq_domain_ops, NULL); | 150 | &mips_cpu_intc_irq_domain_ops, NULL); |
152 | if (!domain) | 151 | if (!domain) |
153 | panic("Failed to add irqdomain for MIPS CPU"); | 152 | panic("Failed to add irqdomain for MIPS CPU"); |
153 | } | ||
154 | 154 | ||
155 | void __init mips_cpu_irq_init(void) | ||
156 | { | ||
157 | __mips_cpu_irq_init(NULL); | ||
158 | } | ||
159 | |||
160 | int __init mips_cpu_irq_of_init(struct device_node *of_node, | ||
161 | struct device_node *parent) | ||
162 | { | ||
163 | __mips_cpu_irq_init(of_node); | ||
155 | return 0; | 164 | return 0; |
156 | } | 165 | } |
157 | #endif /* CONFIG_IRQ_DOMAIN */ | ||
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c index f76f7a08412d..85bbe9b96759 100644 --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c | |||
@@ -16,7 +16,7 @@ | |||
16 | void __iomem *mips_cm_base; | 16 | void __iomem *mips_cm_base; |
17 | void __iomem *mips_cm_l2sync_base; | 17 | void __iomem *mips_cm_l2sync_base; |
18 | 18 | ||
19 | phys_t __mips_cm_phys_base(void) | 19 | phys_addr_t __mips_cm_phys_base(void) |
20 | { | 20 | { |
21 | u32 config3 = read_c0_config3(); | 21 | u32 config3 = read_c0_config3(); |
22 | u32 cmgcr; | 22 | u32 cmgcr; |
@@ -30,10 +30,10 @@ phys_t __mips_cm_phys_base(void) | |||
30 | return (cmgcr & MIPS_CMGCRF_BASE) << (36 - 32); | 30 | return (cmgcr & MIPS_CMGCRF_BASE) << (36 - 32); |
31 | } | 31 | } |
32 | 32 | ||
33 | phys_t mips_cm_phys_base(void) | 33 | phys_addr_t mips_cm_phys_base(void) |
34 | __attribute__((weak, alias("__mips_cm_phys_base"))); | 34 | __attribute__((weak, alias("__mips_cm_phys_base"))); |
35 | 35 | ||
36 | phys_t __mips_cm_l2sync_phys_base(void) | 36 | phys_addr_t __mips_cm_l2sync_phys_base(void) |
37 | { | 37 | { |
38 | u32 base_reg; | 38 | u32 base_reg; |
39 | 39 | ||
@@ -49,13 +49,13 @@ phys_t __mips_cm_l2sync_phys_base(void) | |||
49 | return mips_cm_phys_base() + MIPS_CM_GCR_SIZE; | 49 | return mips_cm_phys_base() + MIPS_CM_GCR_SIZE; |
50 | } | 50 | } |
51 | 51 | ||
52 | phys_t mips_cm_l2sync_phys_base(void) | 52 | phys_addr_t mips_cm_l2sync_phys_base(void) |
53 | __attribute__((weak, alias("__mips_cm_l2sync_phys_base"))); | 53 | __attribute__((weak, alias("__mips_cm_l2sync_phys_base"))); |
54 | 54 | ||
55 | static void mips_cm_probe_l2sync(void) | 55 | static void mips_cm_probe_l2sync(void) |
56 | { | 56 | { |
57 | unsigned major_rev; | 57 | unsigned major_rev; |
58 | phys_t addr; | 58 | phys_addr_t addr; |
59 | 59 | ||
60 | /* L2-only sync was introduced with CM major revision 6 */ | 60 | /* L2-only sync was introduced with CM major revision 6 */ |
61 | major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR_MSK) >> | 61 | major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR_MSK) >> |
@@ -78,7 +78,7 @@ static void mips_cm_probe_l2sync(void) | |||
78 | 78 | ||
79 | int mips_cm_probe(void) | 79 | int mips_cm_probe(void) |
80 | { | 80 | { |
81 | phys_t addr; | 81 | phys_addr_t addr; |
82 | u32 base_reg; | 82 | u32 base_reg; |
83 | 83 | ||
84 | addr = mips_cm_phys_base(); | 84 | addr = mips_cm_phys_base(); |
diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c index ba473608a347..11964501c4b0 100644 --- a/arch/mips/kernel/mips-cpc.c +++ b/arch/mips/kernel/mips-cpc.c | |||
@@ -21,7 +21,7 @@ static DEFINE_PER_CPU_ALIGNED(spinlock_t, cpc_core_lock); | |||
21 | 21 | ||
22 | static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags); | 22 | static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags); |
23 | 23 | ||
24 | phys_t __weak mips_cpc_phys_base(void) | 24 | phys_addr_t __weak mips_cpc_phys_base(void) |
25 | { | 25 | { |
26 | u32 cpc_base; | 26 | u32 cpc_base; |
27 | 27 | ||
@@ -44,7 +44,7 @@ phys_t __weak mips_cpc_phys_base(void) | |||
44 | 44 | ||
45 | int mips_cpc_probe(void) | 45 | int mips_cpc_probe(void) |
46 | { | 46 | { |
47 | phys_t addr; | 47 | phys_addr_t addr; |
48 | unsigned cpu; | 48 | unsigned cpu; |
49 | 49 | ||
50 | for_each_possible_cpu(cpu) | 50 | for_each_possible_cpu(cpu) |
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index 2607c3a4ff7e..17eaf0cf760c 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c | |||
@@ -24,9 +24,7 @@ extern long __strncpy_from_user_nocheck_asm(char *__to, | |||
24 | const char *__from, long __len); | 24 | const char *__from, long __len); |
25 | extern long __strncpy_from_user_asm(char *__to, const char *__from, | 25 | extern long __strncpy_from_user_asm(char *__to, const char *__from, |
26 | long __len); | 26 | long __len); |
27 | extern long __strlen_kernel_nocheck_asm(const char *s); | ||
28 | extern long __strlen_kernel_asm(const char *s); | 27 | extern long __strlen_kernel_asm(const char *s); |
29 | extern long __strlen_user_nocheck_asm(const char *s); | ||
30 | extern long __strlen_user_asm(const char *s); | 28 | extern long __strlen_user_asm(const char *s); |
31 | extern long __strnlen_kernel_nocheck_asm(const char *s); | 29 | extern long __strnlen_kernel_nocheck_asm(const char *s); |
32 | extern long __strnlen_kernel_asm(const char *s); | 30 | extern long __strnlen_kernel_asm(const char *s); |
@@ -62,9 +60,7 @@ EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm); | |||
62 | EXPORT_SYMBOL(__strncpy_from_kernel_asm); | 60 | EXPORT_SYMBOL(__strncpy_from_kernel_asm); |
63 | EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm); | 61 | EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm); |
64 | EXPORT_SYMBOL(__strncpy_from_user_asm); | 62 | EXPORT_SYMBOL(__strncpy_from_user_asm); |
65 | EXPORT_SYMBOL(__strlen_kernel_nocheck_asm); | ||
66 | EXPORT_SYMBOL(__strlen_kernel_asm); | 63 | EXPORT_SYMBOL(__strlen_kernel_asm); |
67 | EXPORT_SYMBOL(__strlen_user_nocheck_asm); | ||
68 | EXPORT_SYMBOL(__strlen_user_asm); | 64 | EXPORT_SYMBOL(__strlen_user_asm); |
69 | EXPORT_SYMBOL(__strnlen_kernel_nocheck_asm); | 65 | EXPORT_SYMBOL(__strnlen_kernel_nocheck_asm); |
70 | EXPORT_SYMBOL(__strnlen_kernel_asm); | 66 | EXPORT_SYMBOL(__strnlen_kernel_asm); |
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index a8f9cdc6f8b0..9466184d0039 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c | |||
@@ -561,8 +561,8 @@ static int mipspmu_get_irq(void) | |||
561 | IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_THREAD, | 561 | IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_THREAD, |
562 | "mips_perf_pmu", NULL); | 562 | "mips_perf_pmu", NULL); |
563 | if (err) { | 563 | if (err) { |
564 | pr_warning("Unable to request IRQ%d for MIPS " | 564 | pr_warn("Unable to request IRQ%d for MIPS performance counters!\n", |
565 | "performance counters!\n", mipspmu.irq); | 565 | mipspmu.irq); |
566 | } | 566 | } |
567 | } else if (cp0_perfcount_irq < 0) { | 567 | } else if (cp0_perfcount_irq < 0) { |
568 | /* | 568 | /* |
@@ -572,8 +572,7 @@ static int mipspmu_get_irq(void) | |||
572 | perf_irq = mipsxx_pmu_handle_shared_irq; | 572 | perf_irq = mipsxx_pmu_handle_shared_irq; |
573 | err = 0; | 573 | err = 0; |
574 | } else { | 574 | } else { |
575 | pr_warning("The platform hasn't properly defined its " | 575 | pr_warn("The platform hasn't properly defined its interrupt controller\n"); |
576 | "interrupt controller.\n"); | ||
577 | err = -ENOENT; | 576 | err = -ENOENT; |
578 | } | 577 | } |
579 | 578 | ||
@@ -1614,22 +1613,13 @@ init_hw_perf_events(void) | |||
1614 | counters = counters_total_to_per_cpu(counters); | 1613 | counters = counters_total_to_per_cpu(counters); |
1615 | #endif | 1614 | #endif |
1616 | 1615 | ||
1617 | #ifdef MSC01E_INT_BASE | 1616 | if (get_c0_perfcount_int) |
1618 | if (cpu_has_veic) { | 1617 | irq = get_c0_perfcount_int(); |
1619 | /* | 1618 | else if ((cp0_perfcount_irq >= 0) && |
1620 | * Using platform specific interrupt controller defines. | 1619 | (cp0_compare_irq != cp0_perfcount_irq)) |
1621 | */ | 1620 | irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; |
1622 | irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR; | 1621 | else |
1623 | } else { | 1622 | irq = -1; |
1624 | #endif | ||
1625 | if ((cp0_perfcount_irq >= 0) && | ||
1626 | (cp0_compare_irq != cp0_perfcount_irq)) | ||
1627 | irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; | ||
1628 | else | ||
1629 | irq = -1; | ||
1630 | #ifdef MSC01E_INT_BASE | ||
1631 | } | ||
1632 | #endif | ||
1633 | 1623 | ||
1634 | mipspmu.map_raw_event = mipsxx_pmu_map_raw_event; | 1624 | mipspmu.map_raw_event = mipsxx_pmu_map_raw_event; |
1635 | 1625 | ||
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 636b0745d7c7..eb76434828e8 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <asm/isadep.h> | 42 | #include <asm/isadep.h> |
43 | #include <asm/inst.h> | 43 | #include <asm/inst.h> |
44 | #include <asm/stacktrace.h> | 44 | #include <asm/stacktrace.h> |
45 | #include <asm/irq_regs.h> | ||
45 | 46 | ||
46 | #ifdef CONFIG_HOTPLUG_CPU | 47 | #ifdef CONFIG_HOTPLUG_CPU |
47 | void arch_cpu_idle_dead(void) | 48 | void arch_cpu_idle_dead(void) |
@@ -187,21 +188,21 @@ static inline int is_ra_save_ins(union mips_instruction *ip) | |||
187 | */ | 188 | */ |
188 | if (mm_insn_16bit(ip->halfword[0])) { | 189 | if (mm_insn_16bit(ip->halfword[0])) { |
189 | mmi.word = (ip->halfword[0] << 16); | 190 | mmi.word = (ip->halfword[0] << 16); |
190 | return ((mmi.mm16_r5_format.opcode == mm_swsp16_op && | 191 | return (mmi.mm16_r5_format.opcode == mm_swsp16_op && |
191 | mmi.mm16_r5_format.rt == 31) || | 192 | mmi.mm16_r5_format.rt == 31) || |
192 | (mmi.mm16_m_format.opcode == mm_pool16c_op && | 193 | (mmi.mm16_m_format.opcode == mm_pool16c_op && |
193 | mmi.mm16_m_format.func == mm_swm16_op)); | 194 | mmi.mm16_m_format.func == mm_swm16_op); |
194 | } | 195 | } |
195 | else { | 196 | else { |
196 | mmi.halfword[0] = ip->halfword[1]; | 197 | mmi.halfword[0] = ip->halfword[1]; |
197 | mmi.halfword[1] = ip->halfword[0]; | 198 | mmi.halfword[1] = ip->halfword[0]; |
198 | return ((mmi.mm_m_format.opcode == mm_pool32b_op && | 199 | return (mmi.mm_m_format.opcode == mm_pool32b_op && |
199 | mmi.mm_m_format.rd > 9 && | 200 | mmi.mm_m_format.rd > 9 && |
200 | mmi.mm_m_format.base == 29 && | 201 | mmi.mm_m_format.base == 29 && |
201 | mmi.mm_m_format.func == mm_swm32_func) || | 202 | mmi.mm_m_format.func == mm_swm32_func) || |
202 | (mmi.i_format.opcode == mm_sw32_op && | 203 | (mmi.i_format.opcode == mm_sw32_op && |
203 | mmi.i_format.rs == 29 && | 204 | mmi.i_format.rs == 29 && |
204 | mmi.i_format.rt == 31)); | 205 | mmi.i_format.rt == 31); |
205 | } | 206 | } |
206 | #else | 207 | #else |
207 | /* sw / sd $ra, offset($sp) */ | 208 | /* sw / sd $ra, offset($sp) */ |
@@ -233,7 +234,7 @@ static inline int is_jump_ins(union mips_instruction *ip) | |||
233 | if (ip->r_format.opcode != mm_pool32a_op || | 234 | if (ip->r_format.opcode != mm_pool32a_op || |
234 | ip->r_format.func != mm_pool32axf_op) | 235 | ip->r_format.func != mm_pool32axf_op) |
235 | return 0; | 236 | return 0; |
236 | return (((ip->u_format.uimmediate >> 6) & mm_jalr_op) == mm_jalr_op); | 237 | return ((ip->u_format.uimmediate >> 6) & mm_jalr_op) == mm_jalr_op; |
237 | #else | 238 | #else |
238 | if (ip->j_format.opcode == j_op) | 239 | if (ip->j_format.opcode == j_op) |
239 | return 1; | 240 | return 1; |
@@ -260,13 +261,13 @@ static inline int is_sp_move_ins(union mips_instruction *ip) | |||
260 | union mips_instruction mmi; | 261 | union mips_instruction mmi; |
261 | 262 | ||
262 | mmi.word = (ip->halfword[0] << 16); | 263 | mmi.word = (ip->halfword[0] << 16); |
263 | return ((mmi.mm16_r3_format.opcode == mm_pool16d_op && | 264 | return (mmi.mm16_r3_format.opcode == mm_pool16d_op && |
264 | mmi.mm16_r3_format.simmediate && mm_addiusp_func) || | 265 | mmi.mm16_r3_format.simmediate && mm_addiusp_func) || |
265 | (mmi.mm16_r5_format.opcode == mm_pool16d_op && | 266 | (mmi.mm16_r5_format.opcode == mm_pool16d_op && |
266 | mmi.mm16_r5_format.rt == 29)); | 267 | mmi.mm16_r5_format.rt == 29); |
267 | } | 268 | } |
268 | return (ip->mm_i_format.opcode == mm_addiu32_op && | 269 | return ip->mm_i_format.opcode == mm_addiu32_op && |
269 | ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29); | 270 | ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29; |
270 | #else | 271 | #else |
271 | /* addiu/daddiu sp,sp,-imm */ | 272 | /* addiu/daddiu sp,sp,-imm */ |
272 | if (ip->i_format.rs != 29 || ip->i_format.rt != 29) | 273 | if (ip->i_format.rs != 29 || ip->i_format.rt != 29) |
@@ -532,3 +533,20 @@ unsigned long arch_align_stack(unsigned long sp) | |||
532 | 533 | ||
533 | return sp & ALMASK; | 534 | return sp & ALMASK; |
534 | } | 535 | } |
536 | |||
537 | static void arch_dump_stack(void *info) | ||
538 | { | ||
539 | struct pt_regs *regs; | ||
540 | |||
541 | regs = get_irq_regs(); | ||
542 | |||
543 | if (regs) | ||
544 | show_regs(regs); | ||
545 | |||
546 | dump_stack(); | ||
547 | } | ||
548 | |||
549 | void arch_trigger_all_cpu_backtrace(bool include_self) | ||
550 | { | ||
551 | smp_call_function(arch_dump_stack, NULL, 1); | ||
552 | } | ||
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index 5d39bb85bf35..452d4350ce42 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/debugfs.h> | 16 | #include <linux/debugfs.h> |
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/of_fdt.h> | 18 | #include <linux/of_fdt.h> |
19 | #include <linux/of_platform.h> | ||
19 | 20 | ||
20 | #include <asm/page.h> | 21 | #include <asm/page.h> |
21 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
@@ -54,4 +55,21 @@ void __init __dt_setup_arch(void *bph) | |||
54 | 55 | ||
55 | mips_set_machine_name(of_flat_dt_get_machine_name()); | 56 | mips_set_machine_name(of_flat_dt_get_machine_name()); |
56 | } | 57 | } |
58 | |||
59 | int __init __dt_register_buses(const char *bus0, const char *bus1) | ||
60 | { | ||
61 | static struct of_device_id of_ids[3]; | ||
62 | |||
63 | if (!of_have_populated_dt()) | ||
64 | panic("device tree not present"); | ||
65 | |||
66 | strlcpy(of_ids[0].compatible, bus0, sizeof(of_ids[0].compatible)); | ||
67 | strlcpy(of_ids[1].compatible, bus1, sizeof(of_ids[1].compatible)); | ||
68 | |||
69 | if (of_platform_populate(NULL, of_ids, NULL, NULL)) | ||
70 | panic("failed to populate DT"); | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
57 | #endif | 75 | #endif |
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index f3b635f86c39..058929041368 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
@@ -82,14 +82,14 @@ static struct resource data_resource = { .name = "Kernel data", }; | |||
82 | 82 | ||
83 | static void *detect_magic __initdata = detect_memory_region; | 83 | static void *detect_magic __initdata = detect_memory_region; |
84 | 84 | ||
85 | void __init add_memory_region(phys_t start, phys_t size, long type) | 85 | void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type) |
86 | { | 86 | { |
87 | int x = boot_mem_map.nr_map; | 87 | int x = boot_mem_map.nr_map; |
88 | int i; | 88 | int i; |
89 | 89 | ||
90 | /* Sanity check */ | 90 | /* Sanity check */ |
91 | if (start + size < start) { | 91 | if (start + size < start) { |
92 | pr_warning("Trying to add an invalid memory region, skipped\n"); | 92 | pr_warn("Trying to add an invalid memory region, skipped\n"); |
93 | return; | 93 | return; |
94 | } | 94 | } |
95 | 95 | ||
@@ -127,10 +127,10 @@ void __init add_memory_region(phys_t start, phys_t size, long type) | |||
127 | boot_mem_map.nr_map++; | 127 | boot_mem_map.nr_map++; |
128 | } | 128 | } |
129 | 129 | ||
130 | void __init detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max) | 130 | void __init detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_addr_t sz_max) |
131 | { | 131 | { |
132 | void *dm = &detect_magic; | 132 | void *dm = &detect_magic; |
133 | phys_t size; | 133 | phys_addr_t size; |
134 | 134 | ||
135 | for (size = sz_min; size < sz_max; size <<= 1) { | 135 | for (size = sz_min; size < sz_max; size <<= 1) { |
136 | if (!memcmp(dm, dm + size, sizeof(detect_magic))) | 136 | if (!memcmp(dm, dm + size, sizeof(detect_magic))) |
@@ -493,7 +493,7 @@ static int usermem __initdata; | |||
493 | 493 | ||
494 | static int __init early_parse_mem(char *p) | 494 | static int __init early_parse_mem(char *p) |
495 | { | 495 | { |
496 | phys_t start, size; | 496 | phys_addr_t start, size; |
497 | 497 | ||
498 | /* | 498 | /* |
499 | * If a user specifies memory size, we | 499 | * If a user specifies memory size, we |
@@ -545,9 +545,9 @@ static int __init early_parse_elfcorehdr(char *p) | |||
545 | early_param("elfcorehdr", early_parse_elfcorehdr); | 545 | early_param("elfcorehdr", early_parse_elfcorehdr); |
546 | #endif | 546 | #endif |
547 | 547 | ||
548 | static void __init arch_mem_addpart(phys_t mem, phys_t end, int type) | 548 | static void __init arch_mem_addpart(phys_addr_t mem, phys_addr_t end, int type) |
549 | { | 549 | { |
550 | phys_t size; | 550 | phys_addr_t size; |
551 | int i; | 551 | int i; |
552 | 552 | ||
553 | size = end - mem; | 553 | size = end - mem; |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 16f1e4f2bf3c..545bf11bd2ed 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -530,7 +530,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) | |||
530 | struct mips_abi *abi = current->thread.abi; | 530 | struct mips_abi *abi = current->thread.abi; |
531 | #ifdef CONFIG_CPU_MICROMIPS | 531 | #ifdef CONFIG_CPU_MICROMIPS |
532 | void *vdso; | 532 | void *vdso; |
533 | unsigned int tmp = (unsigned int)current->mm->context.vdso; | 533 | unsigned long tmp = (unsigned long)current->mm->context.vdso; |
534 | 534 | ||
535 | set_isa16_mode(tmp); | 535 | set_isa16_mode(tmp); |
536 | vdso = (void *)tmp; | 536 | vdso = (void *)tmp; |
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 06bb5ed6d80a..b8bd9340c9c7 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <asm/bmips.h> | 35 | #include <asm/bmips.h> |
36 | #include <asm/traps.h> | 36 | #include <asm/traps.h> |
37 | #include <asm/barrier.h> | 37 | #include <asm/barrier.h> |
38 | #include <asm/cpu-features.h> | ||
38 | 39 | ||
39 | static int __maybe_unused max_cpus = 1; | 40 | static int __maybe_unused max_cpus = 1; |
40 | 41 | ||
@@ -42,6 +43,12 @@ static int __maybe_unused max_cpus = 1; | |||
42 | int bmips_smp_enabled = 1; | 43 | int bmips_smp_enabled = 1; |
43 | int bmips_cpu_offset; | 44 | int bmips_cpu_offset; |
44 | cpumask_t bmips_booted_mask; | 45 | cpumask_t bmips_booted_mask; |
46 | unsigned long bmips_tp1_irqs = IE_IRQ1; | ||
47 | |||
48 | #define RESET_FROM_KSEG0 0x80080800 | ||
49 | #define RESET_FROM_KSEG1 0xa0080800 | ||
50 | |||
51 | static void bmips_set_reset_vec(int cpu, u32 val); | ||
45 | 52 | ||
46 | #ifdef CONFIG_SMP | 53 | #ifdef CONFIG_SMP |
47 | 54 | ||
@@ -194,6 +201,9 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle) | |||
194 | pr_info("SMP: Booting CPU%d...\n", cpu); | 201 | pr_info("SMP: Booting CPU%d...\n", cpu); |
195 | 202 | ||
196 | if (cpumask_test_cpu(cpu, &bmips_booted_mask)) { | 203 | if (cpumask_test_cpu(cpu, &bmips_booted_mask)) { |
204 | /* kseg1 might not exist if this CPU enabled XKS01 */ | ||
205 | bmips_set_reset_vec(cpu, RESET_FROM_KSEG0); | ||
206 | |||
197 | switch (current_cpu_type()) { | 207 | switch (current_cpu_type()) { |
198 | case CPU_BMIPS4350: | 208 | case CPU_BMIPS4350: |
199 | case CPU_BMIPS4380: | 209 | case CPU_BMIPS4380: |
@@ -203,8 +213,9 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle) | |||
203 | bmips5000_send_ipi_single(cpu, 0); | 213 | bmips5000_send_ipi_single(cpu, 0); |
204 | break; | 214 | break; |
205 | } | 215 | } |
206 | } | 216 | } else { |
207 | else { | 217 | bmips_set_reset_vec(cpu, RESET_FROM_KSEG1); |
218 | |||
208 | switch (current_cpu_type()) { | 219 | switch (current_cpu_type()) { |
209 | case CPU_BMIPS4350: | 220 | case CPU_BMIPS4350: |
210 | case CPU_BMIPS4380: | 221 | case CPU_BMIPS4380: |
@@ -213,17 +224,7 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle) | |||
213 | set_c0_brcm_cmt_ctrl(0x01); | 224 | set_c0_brcm_cmt_ctrl(0x01); |
214 | break; | 225 | break; |
215 | case CPU_BMIPS5000: | 226 | case CPU_BMIPS5000: |
216 | if (cpu & 0x01) | 227 | write_c0_brcm_action(ACTION_BOOT_THREAD(cpu)); |
217 | write_c0_brcm_action(ACTION_BOOT_THREAD(cpu)); | ||
218 | else { | ||
219 | /* | ||
220 | * core N thread 0 was already booted; just | ||
221 | * pulse the NMI line | ||
222 | */ | ||
223 | bmips_write_zscm_reg(0x210, 0xc0000000); | ||
224 | udelay(10); | ||
225 | bmips_write_zscm_reg(0x210, 0x00); | ||
226 | } | ||
227 | break; | 228 | break; |
228 | } | 229 | } |
229 | cpumask_set_cpu(cpu, &bmips_booted_mask); | 230 | cpumask_set_cpu(cpu, &bmips_booted_mask); |
@@ -235,31 +236,12 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle) | |||
235 | */ | 236 | */ |
236 | static void bmips_init_secondary(void) | 237 | static void bmips_init_secondary(void) |
237 | { | 238 | { |
238 | /* move NMI vector to kseg0, in case XKS01 is enabled */ | ||
239 | |||
240 | void __iomem *cbr; | ||
241 | unsigned long old_vec; | ||
242 | unsigned long relo_vector; | ||
243 | int boot_cpu; | ||
244 | |||
245 | switch (current_cpu_type()) { | 239 | switch (current_cpu_type()) { |
246 | case CPU_BMIPS4350: | 240 | case CPU_BMIPS4350: |
247 | case CPU_BMIPS4380: | 241 | case CPU_BMIPS4380: |
248 | cbr = BMIPS_GET_CBR(); | ||
249 | |||
250 | boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31)); | ||
251 | relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 : | ||
252 | BMIPS_RELO_VECTOR_CONTROL_1; | ||
253 | |||
254 | old_vec = __raw_readl(cbr + relo_vector); | ||
255 | __raw_writel(old_vec & ~0x20000000, cbr + relo_vector); | ||
256 | |||
257 | clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0); | 242 | clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0); |
258 | break; | 243 | break; |
259 | case CPU_BMIPS5000: | 244 | case CPU_BMIPS5000: |
260 | write_c0_brcm_bootvec(read_c0_brcm_bootvec() & | ||
261 | (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000)); | ||
262 | |||
263 | write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0)); | 245 | write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0)); |
264 | break; | 246 | break; |
265 | } | 247 | } |
@@ -276,7 +258,7 @@ static void bmips_smp_finish(void) | |||
276 | write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ); | 258 | write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ); |
277 | 259 | ||
278 | irq_enable_hazard(); | 260 | irq_enable_hazard(); |
279 | set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ1 | IE_IRQ5 | ST0_IE); | 261 | set_c0_status(IE_SW0 | IE_SW1 | bmips_tp1_irqs | IE_IRQ5 | ST0_IE); |
280 | irq_enable_hazard(); | 262 | irq_enable_hazard(); |
281 | } | 263 | } |
282 | 264 | ||
@@ -381,6 +363,7 @@ static int bmips_cpu_disable(void) | |||
381 | 363 | ||
382 | set_cpu_online(cpu, false); | 364 | set_cpu_online(cpu, false); |
383 | cpu_clear(cpu, cpu_callin_map); | 365 | cpu_clear(cpu, cpu_callin_map); |
366 | clear_c0_status(IE_IRQ5); | ||
384 | 367 | ||
385 | local_flush_tlb_all(); | 368 | local_flush_tlb_all(); |
386 | local_flush_icache_range(0, ~0); | 369 | local_flush_icache_range(0, ~0); |
@@ -405,7 +388,8 @@ void __ref play_dead(void) | |||
405 | * IRQ handlers; this clears ST0_IE and returns immediately. | 388 | * IRQ handlers; this clears ST0_IE and returns immediately. |
406 | */ | 389 | */ |
407 | clear_c0_cause(CAUSEF_IV | C_SW0 | C_SW1); | 390 | clear_c0_cause(CAUSEF_IV | C_SW0 | C_SW1); |
408 | change_c0_status(IE_IRQ5 | IE_IRQ1 | IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV, | 391 | change_c0_status( |
392 | IE_IRQ5 | bmips_tp1_irqs | IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV, | ||
409 | IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV); | 393 | IE_SW0 | IE_SW1 | ST0_IE | ST0_BEV); |
410 | irq_disable_hazard(); | 394 | irq_disable_hazard(); |
411 | 395 | ||
@@ -473,10 +457,61 @@ static inline void bmips_nmi_handler_setup(void) | |||
473 | &bmips_smp_int_vec_end); | 457 | &bmips_smp_int_vec_end); |
474 | } | 458 | } |
475 | 459 | ||
460 | struct reset_vec_info { | ||
461 | int cpu; | ||
462 | u32 val; | ||
463 | }; | ||
464 | |||
465 | static void bmips_set_reset_vec_remote(void *vinfo) | ||
466 | { | ||
467 | struct reset_vec_info *info = vinfo; | ||
468 | int shift = info->cpu & 0x01 ? 16 : 0; | ||
469 | u32 mask = ~(0xffff << shift), val = info->val >> 16; | ||
470 | |||
471 | preempt_disable(); | ||
472 | if (smp_processor_id() > 0) { | ||
473 | smp_call_function_single(0, &bmips_set_reset_vec_remote, | ||
474 | info, 1); | ||
475 | } else { | ||
476 | if (info->cpu & 0x02) { | ||
477 | /* BMIPS5200 "should" use mask/shift, but it's buggy */ | ||
478 | bmips_write_zscm_reg(0xa0, (val << 16) | val); | ||
479 | bmips_read_zscm_reg(0xa0); | ||
480 | } else { | ||
481 | write_c0_brcm_bootvec((read_c0_brcm_bootvec() & mask) | | ||
482 | (val << shift)); | ||
483 | } | ||
484 | } | ||
485 | preempt_enable(); | ||
486 | } | ||
487 | |||
488 | static void bmips_set_reset_vec(int cpu, u32 val) | ||
489 | { | ||
490 | struct reset_vec_info info; | ||
491 | |||
492 | if (current_cpu_type() == CPU_BMIPS5000) { | ||
493 | /* this needs to run from CPU0 (which is always online) */ | ||
494 | info.cpu = cpu; | ||
495 | info.val = val; | ||
496 | bmips_set_reset_vec_remote(&info); | ||
497 | } else { | ||
498 | void __iomem *cbr = BMIPS_GET_CBR(); | ||
499 | |||
500 | if (cpu == 0) | ||
501 | __raw_writel(val, cbr + BMIPS_RELO_VECTOR_CONTROL_0); | ||
502 | else { | ||
503 | if (current_cpu_type() != CPU_BMIPS4380) | ||
504 | return; | ||
505 | __raw_writel(val, cbr + BMIPS_RELO_VECTOR_CONTROL_1); | ||
506 | } | ||
507 | } | ||
508 | __sync(); | ||
509 | back_to_back_c0_hazard(); | ||
510 | } | ||
511 | |||
476 | void bmips_ebase_setup(void) | 512 | void bmips_ebase_setup(void) |
477 | { | 513 | { |
478 | unsigned long new_ebase = ebase; | 514 | unsigned long new_ebase = ebase; |
479 | void __iomem __maybe_unused *cbr; | ||
480 | 515 | ||
481 | BUG_ON(ebase != CKSEG0); | 516 | BUG_ON(ebase != CKSEG0); |
482 | 517 | ||
@@ -496,15 +531,14 @@ void bmips_ebase_setup(void) | |||
496 | &bmips_smp_int_vec, 0x80); | 531 | &bmips_smp_int_vec, 0x80); |
497 | __sync(); | 532 | __sync(); |
498 | return; | 533 | return; |
534 | case CPU_BMIPS3300: | ||
499 | case CPU_BMIPS4380: | 535 | case CPU_BMIPS4380: |
500 | /* | 536 | /* |
501 | * 0x8000_0000: reset/NMI (initially in kseg1) | 537 | * 0x8000_0000: reset/NMI (initially in kseg1) |
502 | * 0x8000_0400: normal vectors | 538 | * 0x8000_0400: normal vectors |
503 | */ | 539 | */ |
504 | new_ebase = 0x80000400; | 540 | new_ebase = 0x80000400; |
505 | cbr = BMIPS_GET_CBR(); | 541 | bmips_set_reset_vec(0, RESET_FROM_KSEG0); |
506 | __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0); | ||
507 | __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1); | ||
508 | break; | 542 | break; |
509 | case CPU_BMIPS5000: | 543 | case CPU_BMIPS5000: |
510 | /* | 544 | /* |
@@ -512,10 +546,8 @@ void bmips_ebase_setup(void) | |||
512 | * 0x8000_1000: normal vectors | 546 | * 0x8000_1000: normal vectors |
513 | */ | 547 | */ |
514 | new_ebase = 0x80001000; | 548 | new_ebase = 0x80001000; |
515 | write_c0_brcm_bootvec(0xa0088008); | 549 | bmips_set_reset_vec(0, RESET_FROM_KSEG0); |
516 | write_c0_ebase(new_ebase); | 550 | write_c0_ebase(new_ebase); |
517 | if (max_cpus > 2) | ||
518 | bmips_write_zscm_reg(0xa0, 0xa008a008); | ||
519 | break; | 551 | break; |
520 | default: | 552 | default: |
521 | return; | 553 | return; |
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c index fc8a51553426..1e0a93c5a3e7 100644 --- a/arch/mips/kernel/smp-cmp.c +++ b/arch/mips/kernel/smp-cmp.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/cpumask.h> | 24 | #include <linux/cpumask.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/compiler.h> | 26 | #include <linux/compiler.h> |
27 | #include <linux/irqchip/mips-gic.h> | ||
27 | 28 | ||
28 | #include <linux/atomic.h> | 29 | #include <linux/atomic.h> |
29 | #include <asm/cacheflush.h> | 30 | #include <asm/cacheflush.h> |
@@ -37,7 +38,6 @@ | |||
37 | #include <asm/mipsmtregs.h> | 38 | #include <asm/mipsmtregs.h> |
38 | #include <asm/mips_mt.h> | 39 | #include <asm/mips_mt.h> |
39 | #include <asm/amon.h> | 40 | #include <asm/amon.h> |
40 | #include <asm/gic.h> | ||
41 | 41 | ||
42 | static void cmp_init_secondary(void) | 42 | static void cmp_init_secondary(void) |
43 | { | 43 | { |
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index e6e16a1d4add..bed7590e475f 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c | |||
@@ -9,13 +9,13 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/io.h> | 11 | #include <linux/io.h> |
12 | #include <linux/irqchip/mips-gic.h> | ||
12 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
14 | #include <linux/smp.h> | 15 | #include <linux/smp.h> |
15 | #include <linux/types.h> | 16 | #include <linux/types.h> |
16 | 17 | ||
17 | #include <asm/bcache.h> | 18 | #include <asm/bcache.h> |
18 | #include <asm/gic.h> | ||
19 | #include <asm/mips-cm.h> | 19 | #include <asm/mips-cm.h> |
20 | #include <asm/mips-cpc.h> | 20 | #include <asm/mips-cpc.h> |
21 | #include <asm/mips_mt.h> | 21 | #include <asm/mips_mt.h> |
@@ -273,8 +273,8 @@ static void cps_init_secondary(void) | |||
273 | if (cpu_has_mipsmt) | 273 | if (cpu_has_mipsmt) |
274 | dmt(); | 274 | dmt(); |
275 | 275 | ||
276 | change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | | 276 | change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | |
277 | STATUSF_IP6 | STATUSF_IP7); | 277 | STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7); |
278 | } | 278 | } |
279 | 279 | ||
280 | static void cps_smp_finish(void) | 280 | static void cps_smp_finish(void) |
diff --git a/arch/mips/kernel/smp-gic.c b/arch/mips/kernel/smp-gic.c index 3b21a96d1ccb..5f0ab5bcd01e 100644 --- a/arch/mips/kernel/smp-gic.c +++ b/arch/mips/kernel/smp-gic.c | |||
@@ -12,9 +12,9 @@ | |||
12 | * option) any later version. | 12 | * option) any later version. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/irqchip/mips-gic.h> | ||
15 | #include <linux/printk.h> | 16 | #include <linux/printk.h> |
16 | 17 | ||
17 | #include <asm/gic.h> | ||
18 | #include <asm/mips-cpc.h> | 18 | #include <asm/mips-cpc.h> |
19 | #include <asm/smp-ops.h> | 19 | #include <asm/smp-ops.h> |
20 | 20 | ||
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 21f23add04f4..ad86951b73bd 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/cpumask.h> | 22 | #include <linux/cpumask.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/irqchip/mips-gic.h> | ||
24 | #include <linux/compiler.h> | 25 | #include <linux/compiler.h> |
25 | #include <linux/smp.h> | 26 | #include <linux/smp.h> |
26 | 27 | ||
@@ -34,7 +35,6 @@ | |||
34 | #include <asm/mipsregs.h> | 35 | #include <asm/mipsregs.h> |
35 | #include <asm/mipsmtregs.h> | 36 | #include <asm/mipsmtregs.h> |
36 | #include <asm/mips_mt.h> | 37 | #include <asm/mips_mt.h> |
37 | #include <asm/gic.h> | ||
38 | 38 | ||
39 | static void __init smvp_copy_vpe_config(void) | 39 | static void __init smvp_copy_vpe_config(void) |
40 | { | 40 | { |
@@ -119,7 +119,7 @@ static void vsmp_send_ipi_single(int cpu, unsigned int action) | |||
119 | unsigned long flags; | 119 | unsigned long flags; |
120 | int vpflags; | 120 | int vpflags; |
121 | 121 | ||
122 | #ifdef CONFIG_IRQ_GIC | 122 | #ifdef CONFIG_MIPS_GIC |
123 | if (gic_present) { | 123 | if (gic_present) { |
124 | gic_send_ipi_single(cpu, action); | 124 | gic_send_ipi_single(cpu, action); |
125 | return; | 125 | return; |
@@ -158,7 +158,7 @@ static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action) | |||
158 | 158 | ||
159 | static void vsmp_init_secondary(void) | 159 | static void vsmp_init_secondary(void) |
160 | { | 160 | { |
161 | #ifdef CONFIG_IRQ_GIC | 161 | #ifdef CONFIG_MIPS_GIC |
162 | /* This is Malta specific: IPI,performance and timer interrupts */ | 162 | /* This is Malta specific: IPI,performance and timer interrupts */ |
163 | if (gic_present) | 163 | if (gic_present) |
164 | change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | | 164 | change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | |
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 4a4f9dda5658..604b558809c4 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c | |||
@@ -117,6 +117,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) | |||
117 | "2: sc %[tmp], (%[addr]) \n" | 117 | "2: sc %[tmp], (%[addr]) \n" |
118 | " beqzl %[tmp], 1b \n" | 118 | " beqzl %[tmp], 1b \n" |
119 | "3: \n" | 119 | "3: \n" |
120 | " .insn \n" | ||
120 | " .section .fixup,\"ax\" \n" | 121 | " .section .fixup,\"ax\" \n" |
121 | "4: li %[err], %[efault] \n" | 122 | "4: li %[err], %[efault] \n" |
122 | " j 3b \n" | 123 | " j 3b \n" |
@@ -142,6 +143,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) | |||
142 | "2: sc %[tmp], (%[addr]) \n" | 143 | "2: sc %[tmp], (%[addr]) \n" |
143 | " bnez %[tmp], 4f \n" | 144 | " bnez %[tmp], 4f \n" |
144 | "3: \n" | 145 | "3: \n" |
146 | " .insn \n" | ||
145 | " .subsection 2 \n" | 147 | " .subsection 2 \n" |
146 | "4: b 1b \n" | 148 | "4: b 1b \n" |
147 | " .previous \n" | 149 | " .previous \n" |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 22b19c275044..ad3d2031c327 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -724,6 +724,50 @@ int process_fpemu_return(int sig, void __user *fault_addr) | |||
724 | } | 724 | } |
725 | } | 725 | } |
726 | 726 | ||
727 | static int simulate_fp(struct pt_regs *regs, unsigned int opcode, | ||
728 | unsigned long old_epc, unsigned long old_ra) | ||
729 | { | ||
730 | union mips_instruction inst = { .word = opcode }; | ||
731 | void __user *fault_addr = NULL; | ||
732 | int sig; | ||
733 | |||
734 | /* If it's obviously not an FP instruction, skip it */ | ||
735 | switch (inst.i_format.opcode) { | ||
736 | case cop1_op: | ||
737 | case cop1x_op: | ||
738 | case lwc1_op: | ||
739 | case ldc1_op: | ||
740 | case swc1_op: | ||
741 | case sdc1_op: | ||
742 | break; | ||
743 | |||
744 | default: | ||
745 | return -1; | ||
746 | } | ||
747 | |||
748 | /* | ||
749 | * do_ri skipped over the instruction via compute_return_epc, undo | ||
750 | * that for the FPU emulator. | ||
751 | */ | ||
752 | regs->cp0_epc = old_epc; | ||
753 | regs->regs[31] = old_ra; | ||
754 | |||
755 | /* Save the FP context to struct thread_struct */ | ||
756 | lose_fpu(1); | ||
757 | |||
758 | /* Run the emulator */ | ||
759 | sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, | ||
760 | &fault_addr); | ||
761 | |||
762 | /* If something went wrong, signal */ | ||
763 | process_fpemu_return(sig, fault_addr); | ||
764 | |||
765 | /* Restore the hardware register state */ | ||
766 | own_fpu(1); | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
727 | /* | 771 | /* |
728 | * XXX Delayed fp exceptions when doing a lazy ctx switch XXX | 772 | * XXX Delayed fp exceptions when doing a lazy ctx switch XXX |
729 | */ | 773 | */ |
@@ -1016,6 +1060,9 @@ asmlinkage void do_ri(struct pt_regs *regs) | |||
1016 | 1060 | ||
1017 | if (status < 0) | 1061 | if (status < 0) |
1018 | status = simulate_sync(regs, opcode); | 1062 | status = simulate_sync(regs, opcode); |
1063 | |||
1064 | if (status < 0) | ||
1065 | status = simulate_fp(regs, opcode, old_epc, old31); | ||
1019 | } | 1066 | } |
1020 | 1067 | ||
1021 | if (status < 0) | 1068 | if (status < 0) |
@@ -1380,12 +1427,19 @@ asmlinkage void do_mcheck(struct pt_regs *regs) | |||
1380 | show_regs(regs); | 1427 | show_regs(regs); |
1381 | 1428 | ||
1382 | if (multi_match) { | 1429 | if (multi_match) { |
1383 | printk("Index : %0x\n", read_c0_index()); | 1430 | pr_err("Index : %0x\n", read_c0_index()); |
1384 | printk("Pagemask: %0x\n", read_c0_pagemask()); | 1431 | pr_err("Pagemask: %0x\n", read_c0_pagemask()); |
1385 | printk("EntryHi : %0*lx\n", field, read_c0_entryhi()); | 1432 | pr_err("EntryHi : %0*lx\n", field, read_c0_entryhi()); |
1386 | printk("EntryLo0: %0*lx\n", field, read_c0_entrylo0()); | 1433 | pr_err("EntryLo0: %0*lx\n", field, read_c0_entrylo0()); |
1387 | printk("EntryLo1: %0*lx\n", field, read_c0_entrylo1()); | 1434 | pr_err("EntryLo1: %0*lx\n", field, read_c0_entrylo1()); |
1388 | printk("\n"); | 1435 | pr_err("Wired : %0x\n", read_c0_wired()); |
1436 | pr_err("Pagegrain: %0x\n", read_c0_pagegrain()); | ||
1437 | if (cpu_has_htw) { | ||
1438 | pr_err("PWField : %0*lx\n", field, read_c0_pwfield()); | ||
1439 | pr_err("PWSize : %0*lx\n", field, read_c0_pwsize()); | ||
1440 | pr_err("PWCtl : %0x\n", read_c0_pwctl()); | ||
1441 | } | ||
1442 | pr_err("\n"); | ||
1389 | dump_tlb_all(); | 1443 | dump_tlb_all(); |
1390 | } | 1444 | } |
1391 | 1445 | ||
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index 0f1af58b036a..ed2a278722a9 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c | |||
@@ -16,9 +16,11 @@ | |||
16 | #include <linux/elf.h> | 16 | #include <linux/elf.h> |
17 | #include <linux/vmalloc.h> | 17 | #include <linux/vmalloc.h> |
18 | #include <linux/unistd.h> | 18 | #include <linux/unistd.h> |
19 | #include <linux/random.h> | ||
19 | 20 | ||
20 | #include <asm/vdso.h> | 21 | #include <asm/vdso.h> |
21 | #include <asm/uasm.h> | 22 | #include <asm/uasm.h> |
23 | #include <asm/processor.h> | ||
22 | 24 | ||
23 | /* | 25 | /* |
24 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... | 26 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... |
@@ -67,7 +69,18 @@ subsys_initcall(init_vdso); | |||
67 | 69 | ||
68 | static unsigned long vdso_addr(unsigned long start) | 70 | static unsigned long vdso_addr(unsigned long start) |
69 | { | 71 | { |
70 | return STACK_TOP; | 72 | unsigned long offset = 0UL; |
73 | |||
74 | if (current->flags & PF_RANDOMIZE) { | ||
75 | offset = get_random_int(); | ||
76 | offset <<= PAGE_SHIFT; | ||
77 | if (TASK_IS_32BIT_ADDR) | ||
78 | offset &= 0xfffffful; | ||
79 | else | ||
80 | offset &= 0xffffffful; | ||
81 | } | ||
82 | |||
83 | return STACK_TOP + offset; | ||
71 | } | 84 | } |
72 | 85 | ||
73 | int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | 86 | int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) |
diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c index 468ffa043607..7edcd4946fc1 100644 --- a/arch/mips/lantiq/falcon/sysctrl.c +++ b/arch/mips/lantiq/falcon/sysctrl.c | |||
@@ -49,6 +49,7 @@ | |||
49 | 49 | ||
50 | /* Activation Status Register */ | 50 | /* Activation Status Register */ |
51 | #define ACTS_ASC0_ACT 0x00001000 | 51 | #define ACTS_ASC0_ACT 0x00001000 |
52 | #define ACTS_SSC0 0x00002000 | ||
52 | #define ACTS_ASC1_ACT 0x00000800 | 53 | #define ACTS_ASC1_ACT 0x00000800 |
53 | #define ACTS_I2C_ACT 0x00004000 | 54 | #define ACTS_I2C_ACT 0x00004000 |
54 | #define ACTS_P0 0x00010000 | 55 | #define ACTS_P0 0x00010000 |
@@ -147,12 +148,11 @@ static void falcon_gpe_enable(void) | |||
147 | if (status & (1 << (GPPC_OFFSET + 1))) | 148 | if (status & (1 << (GPPC_OFFSET + 1))) |
148 | return; | 149 | return; |
149 | 150 | ||
150 | if (status_r32(STATUS_CONFIG) == 0) | 151 | freq = (status_r32(STATUS_CONFIG) & |
152 | GPEFREQ_MASK) >> | ||
153 | GPEFREQ_OFFSET; | ||
154 | if (freq == 0) | ||
151 | freq = 1; /* use 625MHz on unfused chip */ | 155 | freq = 1; /* use 625MHz on unfused chip */ |
152 | else | ||
153 | freq = (status_r32(STATUS_CONFIG) & | ||
154 | GPEFREQ_MASK) >> | ||
155 | GPEFREQ_OFFSET; | ||
156 | 156 | ||
157 | /* apply new frequency */ | 157 | /* apply new frequency */ |
158 | sysctl_w32_mask(SYSCTL_SYS1, 7 << (GPPC_OFFSET + 1), | 158 | sysctl_w32_mask(SYSCTL_SYS1, 7 << (GPPC_OFFSET + 1), |
@@ -260,5 +260,6 @@ void __init ltq_soc_init(void) | |||
260 | clkdev_add_sys("1e800600.pad", SYSCTL_SYS1, ACTS_PADCTRL4); | 260 | clkdev_add_sys("1e800600.pad", SYSCTL_SYS1, ACTS_PADCTRL4); |
261 | clkdev_add_sys("1e100b00.serial", SYSCTL_SYS1, ACTS_ASC1_ACT); | 261 | clkdev_add_sys("1e100b00.serial", SYSCTL_SYS1, ACTS_ASC1_ACT); |
262 | clkdev_add_sys("1e100c00.serial", SYSCTL_SYS1, ACTS_ASC0_ACT); | 262 | clkdev_add_sys("1e100c00.serial", SYSCTL_SYS1, ACTS_ASC0_ACT); |
263 | clkdev_add_sys("1e100d00.spi", SYSCTL_SYS1, ACTS_SSC0); | ||
263 | clkdev_add_sys("1e200000.i2c", SYSCTL_SYS1, ACTS_I2C_ACT); | 264 | clkdev_add_sys("1e200000.i2c", SYSCTL_SYS1, ACTS_I2C_ACT); |
264 | } | 265 | } |
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 030568a70ac4..6ab10573490d 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c | |||
@@ -70,6 +70,7 @@ static struct resource ltq_eiu_irq[MAX_EIU]; | |||
70 | static void __iomem *ltq_icu_membase[MAX_IM]; | 70 | static void __iomem *ltq_icu_membase[MAX_IM]; |
71 | static void __iomem *ltq_eiu_membase; | 71 | static void __iomem *ltq_eiu_membase; |
72 | static struct irq_domain *ltq_domain; | 72 | static struct irq_domain *ltq_domain; |
73 | static int ltq_perfcount_irq; | ||
73 | 74 | ||
74 | int ltq_eiu_get_irq(int exin) | 75 | int ltq_eiu_get_irq(int exin) |
75 | { | 76 | { |
@@ -378,30 +379,6 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) | |||
378 | panic("Failed to remap icu memory"); | 379 | panic("Failed to remap icu memory"); |
379 | } | 380 | } |
380 | 381 | ||
381 | /* the external interrupts are optional and xway only */ | ||
382 | eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway"); | ||
383 | if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) { | ||
384 | /* find out how many external irq sources we have */ | ||
385 | exin_avail = of_irq_count(eiu_node); | ||
386 | |||
387 | if (exin_avail > MAX_EIU) | ||
388 | exin_avail = MAX_EIU; | ||
389 | |||
390 | ret = of_irq_to_resource_table(eiu_node, | ||
391 | ltq_eiu_irq, exin_avail); | ||
392 | if (ret != exin_avail) | ||
393 | panic("failed to load external irq resources"); | ||
394 | |||
395 | if (request_mem_region(res.start, resource_size(&res), | ||
396 | res.name) < 0) | ||
397 | pr_err("Failed to request eiu memory"); | ||
398 | |||
399 | ltq_eiu_membase = ioremap_nocache(res.start, | ||
400 | resource_size(&res)); | ||
401 | if (!ltq_eiu_membase) | ||
402 | panic("Failed to remap eiu memory"); | ||
403 | } | ||
404 | |||
405 | /* turn off all irqs by default */ | 382 | /* turn off all irqs by default */ |
406 | for (i = 0; i < MAX_IM; i++) { | 383 | for (i = 0; i < MAX_IM; i++) { |
407 | /* make sure all irqs are turned off by default */ | 384 | /* make sure all irqs are turned off by default */ |
@@ -449,7 +426,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) | |||
449 | #endif | 426 | #endif |
450 | 427 | ||
451 | /* tell oprofile which irq to use */ | 428 | /* tell oprofile which irq to use */ |
452 | cp0_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ); | 429 | ltq_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ); |
453 | 430 | ||
454 | /* | 431 | /* |
455 | * if the timer irq is not one of the mips irqs we need to | 432 | * if the timer irq is not one of the mips irqs we need to |
@@ -458,9 +435,38 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) | |||
458 | if (MIPS_CPU_TIMER_IRQ != 7) | 435 | if (MIPS_CPU_TIMER_IRQ != 7) |
459 | irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ); | 436 | irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ); |
460 | 437 | ||
438 | /* the external interrupts are optional and xway only */ | ||
439 | eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway"); | ||
440 | if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) { | ||
441 | /* find out how many external irq sources we have */ | ||
442 | exin_avail = of_irq_count(eiu_node); | ||
443 | |||
444 | if (exin_avail > MAX_EIU) | ||
445 | exin_avail = MAX_EIU; | ||
446 | |||
447 | ret = of_irq_to_resource_table(eiu_node, | ||
448 | ltq_eiu_irq, exin_avail); | ||
449 | if (ret != exin_avail) | ||
450 | panic("failed to load external irq resources"); | ||
451 | |||
452 | if (request_mem_region(res.start, resource_size(&res), | ||
453 | res.name) < 0) | ||
454 | pr_err("Failed to request eiu memory"); | ||
455 | |||
456 | ltq_eiu_membase = ioremap_nocache(res.start, | ||
457 | resource_size(&res)); | ||
458 | if (!ltq_eiu_membase) | ||
459 | panic("Failed to remap eiu memory"); | ||
460 | } | ||
461 | |||
461 | return 0; | 462 | return 0; |
462 | } | 463 | } |
463 | 464 | ||
465 | int get_c0_perfcount_int(void) | ||
466 | { | ||
467 | return ltq_perfcount_irq; | ||
468 | } | ||
469 | |||
464 | unsigned int get_c0_compare_int(void) | 470 | unsigned int get_c0_compare_int(void) |
465 | { | 471 | { |
466 | return MIPS_CPU_TIMER_IRQ; | 472 | return MIPS_CPU_TIMER_IRQ; |
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index 7447d322d14e..39ab3e786e59 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c | |||
@@ -36,6 +36,11 @@ const char *get_system_type(void) | |||
36 | return soc_info.sys_type; | 36 | return soc_info.sys_type; |
37 | } | 37 | } |
38 | 38 | ||
39 | int ltq_soc_type(void) | ||
40 | { | ||
41 | return soc_info.type; | ||
42 | } | ||
43 | |||
39 | void prom_free_prom_memory(void) | 44 | void prom_free_prom_memory(void) |
40 | { | 45 | { |
41 | } | 46 | } |
@@ -72,6 +77,8 @@ void __init plat_mem_setup(void) | |||
72 | * parsed resulting in our memory appearing | 77 | * parsed resulting in our memory appearing |
73 | */ | 78 | */ |
74 | __dt_setup_arch(__dtb_start); | 79 | __dt_setup_arch(__dtb_start); |
80 | |||
81 | strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); | ||
75 | } | 82 | } |
76 | 83 | ||
77 | void __init device_tree_init(void) | 84 | void __init device_tree_init(void) |
@@ -97,16 +104,7 @@ void __init prom_init(void) | |||
97 | 104 | ||
98 | int __init plat_of_setup(void) | 105 | int __init plat_of_setup(void) |
99 | { | 106 | { |
100 | static struct of_device_id of_ids[3]; | 107 | return __dt_register_buses(soc_info.compatible, "simple-bus"); |
101 | |||
102 | if (!of_have_populated_dt()) | ||
103 | panic("device tree not present"); | ||
104 | |||
105 | strlcpy(of_ids[0].compatible, soc_info.compatible, | ||
106 | sizeof(of_ids[0].compatible)); | ||
107 | strncpy(of_ids[1].compatible, "simple-bus", | ||
108 | sizeof(of_ids[1].compatible)); | ||
109 | return of_platform_populate(NULL, of_ids, NULL, NULL); | ||
110 | } | 108 | } |
111 | 109 | ||
112 | arch_initcall(plat_of_setup); | 110 | arch_initcall(plat_of_setup); |
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile index 087497d97357..a2edc538f477 100644 --- a/arch/mips/lantiq/xway/Makefile +++ b/arch/mips/lantiq/xway/Makefile | |||
@@ -1,3 +1,5 @@ | |||
1 | obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o dcdc.o | 1 | obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o dcdc.o |
2 | 2 | ||
3 | obj-y += vmmc.o | ||
4 | |||
3 | obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o | 5 | obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o |
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index 1fa0f175357e..fe68f9ae47c1 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
16 | #include <linux/of_platform.h> | 16 | #include <linux/of_platform.h> |
17 | #include <linux/reset-controller.h> | ||
17 | 18 | ||
18 | #include <asm/reboot.h> | 19 | #include <asm/reboot.h> |
19 | 20 | ||
@@ -113,10 +114,77 @@ void ltq_reset_once(unsigned int module, ulong u) | |||
113 | ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ); | 114 | ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ); |
114 | } | 115 | } |
115 | 116 | ||
117 | static int ltq_assert_device(struct reset_controller_dev *rcdev, | ||
118 | unsigned long id) | ||
119 | { | ||
120 | u32 val; | ||
121 | |||
122 | if (id < 8) | ||
123 | return -1; | ||
124 | |||
125 | val = ltq_rcu_r32(RCU_RST_REQ); | ||
126 | val |= BIT(id); | ||
127 | ltq_rcu_w32(val, RCU_RST_REQ); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int ltq_deassert_device(struct reset_controller_dev *rcdev, | ||
133 | unsigned long id) | ||
134 | { | ||
135 | u32 val; | ||
136 | |||
137 | if (id < 8) | ||
138 | return -1; | ||
139 | |||
140 | val = ltq_rcu_r32(RCU_RST_REQ); | ||
141 | val &= ~BIT(id); | ||
142 | ltq_rcu_w32(val, RCU_RST_REQ); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int ltq_reset_device(struct reset_controller_dev *rcdev, | ||
148 | unsigned long id) | ||
149 | { | ||
150 | ltq_assert_device(rcdev, id); | ||
151 | return ltq_deassert_device(rcdev, id); | ||
152 | } | ||
153 | |||
154 | static struct reset_control_ops reset_ops = { | ||
155 | .reset = ltq_reset_device, | ||
156 | .assert = ltq_assert_device, | ||
157 | .deassert = ltq_deassert_device, | ||
158 | }; | ||
159 | |||
160 | static struct reset_controller_dev reset_dev = { | ||
161 | .ops = &reset_ops, | ||
162 | .owner = THIS_MODULE, | ||
163 | .nr_resets = 32, | ||
164 | .of_reset_n_cells = 1, | ||
165 | }; | ||
166 | |||
167 | void ltq_rst_init(void) | ||
168 | { | ||
169 | reset_dev.of_node = of_find_compatible_node(NULL, NULL, | ||
170 | "lantiq,xway-reset"); | ||
171 | if (!reset_dev.of_node) | ||
172 | pr_err("Failed to find reset controller node"); | ||
173 | else | ||
174 | reset_controller_register(&reset_dev); | ||
175 | } | ||
176 | |||
116 | static void ltq_machine_restart(char *command) | 177 | static void ltq_machine_restart(char *command) |
117 | { | 178 | { |
179 | u32 val = ltq_rcu_r32(RCU_RST_REQ); | ||
180 | |||
181 | if (of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) | ||
182 | val |= RCU_RD_GPHY1_XRX200 | RCU_RD_GPHY0_XRX200; | ||
183 | |||
184 | val |= RCU_RD_SRST; | ||
185 | |||
118 | local_irq_disable(); | 186 | local_irq_disable(); |
119 | ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | RCU_RD_SRST, RCU_RST_REQ); | 187 | ltq_rcu_w32(val, RCU_RST_REQ); |
120 | unreachable(); | 188 | unreachable(); |
121 | } | 189 | } |
122 | 190 | ||
diff --git a/arch/mips/lantiq/xway/vmmc.c b/arch/mips/lantiq/xway/vmmc.c new file mode 100644 index 000000000000..696cd57f6f13 --- /dev/null +++ b/arch/mips/lantiq/xway/vmmc.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License version 2 as published | ||
4 | * by the Free Software Foundation. | ||
5 | * | ||
6 | * Copyright (C) 2012 John Crispin <blogic@openwrt.org> | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/of_platform.h> | ||
11 | #include <linux/of_gpio.h> | ||
12 | #include <linux/dma-mapping.h> | ||
13 | |||
14 | #include <lantiq_soc.h> | ||
15 | |||
16 | static unsigned int *cp1_base; | ||
17 | |||
18 | unsigned int *ltq_get_cp1_base(void) | ||
19 | { | ||
20 | if (!cp1_base) | ||
21 | panic("no cp1 base was set\n"); | ||
22 | |||
23 | return cp1_base; | ||
24 | } | ||
25 | EXPORT_SYMBOL(ltq_get_cp1_base); | ||
26 | |||
27 | static int vmmc_probe(struct platform_device *pdev) | ||
28 | { | ||
29 | #define CP1_SIZE (1 << 20) | ||
30 | int gpio_count; | ||
31 | dma_addr_t dma; | ||
32 | |||
33 | cp1_base = | ||
34 | (void *) CPHYSADDR(dma_alloc_coherent(NULL, CP1_SIZE, | ||
35 | &dma, GFP_ATOMIC)); | ||
36 | |||
37 | gpio_count = of_gpio_count(pdev->dev.of_node); | ||
38 | while (gpio_count > 0) { | ||
39 | enum of_gpio_flags flags; | ||
40 | int gpio = of_get_gpio_flags(pdev->dev.of_node, | ||
41 | --gpio_count, &flags); | ||
42 | if (gpio_request(gpio, "vmmc-relay")) | ||
43 | continue; | ||
44 | dev_info(&pdev->dev, "requested GPIO %d\n", gpio); | ||
45 | gpio_direction_output(gpio, | ||
46 | (flags & OF_GPIO_ACTIVE_LOW) ? (0) : (1)); | ||
47 | } | ||
48 | |||
49 | dev_info(&pdev->dev, "reserved %dMB at 0x%p", CP1_SIZE >> 20, cp1_base); | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static const struct of_device_id vmmc_match[] = { | ||
55 | { .compatible = "lantiq,vmmc-xway" }, | ||
56 | {}, | ||
57 | }; | ||
58 | MODULE_DEVICE_TABLE(of, vmmc_match); | ||
59 | |||
60 | static struct platform_driver vmmc_driver = { | ||
61 | .probe = vmmc_probe, | ||
62 | .driver = { | ||
63 | .name = "lantiq,vmmc", | ||
64 | .owner = THIS_MODULE, | ||
65 | .of_match_table = vmmc_match, | ||
66 | }, | ||
67 | }; | ||
68 | |||
69 | module_platform_driver(vmmc_driver); | ||
diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c index d4d9d31f152e..7c1e54c6a36c 100644 --- a/arch/mips/lantiq/xway/xrx200_phy_fw.c +++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c | |||
@@ -24,7 +24,28 @@ static dma_addr_t xway_gphy_load(struct platform_device *pdev) | |||
24 | void *fw_addr; | 24 | void *fw_addr; |
25 | size_t size; | 25 | size_t size; |
26 | 26 | ||
27 | if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) { | 27 | if (of_get_property(pdev->dev.of_node, "firmware1", NULL) || |
28 | of_get_property(pdev->dev.of_node, "firmware2", NULL)) { | ||
29 | switch (ltq_soc_type()) { | ||
30 | case SOC_TYPE_VR9: | ||
31 | if (of_property_read_string(pdev->dev.of_node, | ||
32 | "firmware1", &fw_name)) { | ||
33 | dev_err(&pdev->dev, | ||
34 | "failed to load firmware filename\n"); | ||
35 | return 0; | ||
36 | } | ||
37 | break; | ||
38 | case SOC_TYPE_VR9_2: | ||
39 | if (of_property_read_string(pdev->dev.of_node, | ||
40 | "firmware2", &fw_name)) { | ||
41 | dev_err(&pdev->dev, | ||
42 | "failed to load firmware filename\n"); | ||
43 | return 0; | ||
44 | } | ||
45 | break; | ||
46 | } | ||
47 | } else if (of_property_read_string(pdev->dev.of_node, | ||
48 | "firmware", &fw_name)) { | ||
28 | dev_err(&pdev->dev, "failed to load firmware filename\n"); | 49 | dev_err(&pdev->dev, "failed to load firmware filename\n"); |
29 | return 0; | 50 | return 0; |
30 | } | 51 | } |
diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c index e3acb2dad33a..8e7e378ce51c 100644 --- a/arch/mips/lib/iomap.c +++ b/arch/mips/lib/iomap.c | |||
@@ -97,14 +97,14 @@ EXPORT_SYMBOL(iowrite32be); | |||
97 | 97 | ||
98 | /* | 98 | /* |
99 | * These are the "repeat MMIO read/write" functions. | 99 | * These are the "repeat MMIO read/write" functions. |
100 | * Note the "__raw" accesses, since we don't want to | 100 | * Note the "__mem" accesses, since we want to convert |
101 | * convert to CPU byte order. We write in "IO byte | 101 | * to CPU byte order if the host bus happens to not match the |
102 | * order" (we also don't have IO barriers). | 102 | * endianness of PCI/ISA (see mach-generic/mangle-port.h). |
103 | */ | 103 | */ |
104 | static inline void mmio_insb(void __iomem *addr, u8 *dst, int count) | 104 | static inline void mmio_insb(void __iomem *addr, u8 *dst, int count) |
105 | { | 105 | { |
106 | while (--count >= 0) { | 106 | while (--count >= 0) { |
107 | u8 data = __raw_readb(addr); | 107 | u8 data = __mem_readb(addr); |
108 | *dst = data; | 108 | *dst = data; |
109 | dst++; | 109 | dst++; |
110 | } | 110 | } |
@@ -113,7 +113,7 @@ static inline void mmio_insb(void __iomem *addr, u8 *dst, int count) | |||
113 | static inline void mmio_insw(void __iomem *addr, u16 *dst, int count) | 113 | static inline void mmio_insw(void __iomem *addr, u16 *dst, int count) |
114 | { | 114 | { |
115 | while (--count >= 0) { | 115 | while (--count >= 0) { |
116 | u16 data = __raw_readw(addr); | 116 | u16 data = __mem_readw(addr); |
117 | *dst = data; | 117 | *dst = data; |
118 | dst++; | 118 | dst++; |
119 | } | 119 | } |
@@ -122,7 +122,7 @@ static inline void mmio_insw(void __iomem *addr, u16 *dst, int count) | |||
122 | static inline void mmio_insl(void __iomem *addr, u32 *dst, int count) | 122 | static inline void mmio_insl(void __iomem *addr, u32 *dst, int count) |
123 | { | 123 | { |
124 | while (--count >= 0) { | 124 | while (--count >= 0) { |
125 | u32 data = __raw_readl(addr); | 125 | u32 data = __mem_readl(addr); |
126 | *dst = data; | 126 | *dst = data; |
127 | dst++; | 127 | dst++; |
128 | } | 128 | } |
@@ -131,7 +131,7 @@ static inline void mmio_insl(void __iomem *addr, u32 *dst, int count) | |||
131 | static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count) | 131 | static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count) |
132 | { | 132 | { |
133 | while (--count >= 0) { | 133 | while (--count >= 0) { |
134 | __raw_writeb(*src, addr); | 134 | __mem_writeb(*src, addr); |
135 | src++; | 135 | src++; |
136 | } | 136 | } |
137 | } | 137 | } |
@@ -139,7 +139,7 @@ static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count) | |||
139 | static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count) | 139 | static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count) |
140 | { | 140 | { |
141 | while (--count >= 0) { | 141 | while (--count >= 0) { |
142 | __raw_writew(*src, addr); | 142 | __mem_writew(*src, addr); |
143 | src++; | 143 | src++; |
144 | } | 144 | } |
145 | } | 145 | } |
@@ -147,7 +147,7 @@ static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count) | |||
147 | static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count) | 147 | static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count) |
148 | { | 148 | { |
149 | while (--count >= 0) { | 149 | while (--count >= 0) { |
150 | __raw_writel(*src, addr); | 150 | __mem_writel(*src, addr); |
151 | src++; | 151 | src++; |
152 | } | 152 | } |
153 | } | 153 | } |
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 7b0e5462ca51..c8fe6b1968fb 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S | |||
@@ -114,8 +114,7 @@ | |||
114 | R10KCBARRIER(0(ra)) | 114 | R10KCBARRIER(0(ra)) |
115 | #ifdef __MIPSEB__ | 115 | #ifdef __MIPSEB__ |
116 | EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ | 116 | EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ |
117 | #endif | 117 | #else |
118 | #ifdef __MIPSEL__ | ||
119 | EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ | 118 | EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ |
120 | #endif | 119 | #endif |
121 | PTR_SUBU a0, t0 /* long align ptr */ | 120 | PTR_SUBU a0, t0 /* long align ptr */ |
@@ -164,8 +163,7 @@ | |||
164 | R10KCBARRIER(0(ra)) | 163 | R10KCBARRIER(0(ra)) |
165 | #ifdef __MIPSEB__ | 164 | #ifdef __MIPSEB__ |
166 | EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@) | 165 | EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@) |
167 | #endif | 166 | #else |
168 | #ifdef __MIPSEL__ | ||
169 | EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@) | 167 | EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@) |
170 | #endif | 168 | #endif |
171 | 1: jr ra | 169 | 1: jr ra |
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c index 57bcdaf1f1c8..be777d9a3f85 100644 --- a/arch/mips/lib/mips-atomic.c +++ b/arch/mips/lib/mips-atomic.c | |||
@@ -42,15 +42,11 @@ notrace void arch_local_irq_disable(void) | |||
42 | __asm__ __volatile__( | 42 | __asm__ __volatile__( |
43 | " .set push \n" | 43 | " .set push \n" |
44 | " .set noat \n" | 44 | " .set noat \n" |
45 | #if defined(CONFIG_CPU_MIPSR2) | ||
46 | /* see irqflags.h for inline function */ | ||
47 | #else | ||
48 | " mfc0 $1,$12 \n" | 45 | " mfc0 $1,$12 \n" |
49 | " ori $1,0x1f \n" | 46 | " ori $1,0x1f \n" |
50 | " xori $1,0x1f \n" | 47 | " xori $1,0x1f \n" |
51 | " .set noreorder \n" | 48 | " .set noreorder \n" |
52 | " mtc0 $1,$12 \n" | 49 | " mtc0 $1,$12 \n" |
53 | #endif | ||
54 | " " __stringify(__irq_disable_hazard) " \n" | 50 | " " __stringify(__irq_disable_hazard) " \n" |
55 | " .set pop \n" | 51 | " .set pop \n" |
56 | : /* no outputs */ | 52 | : /* no outputs */ |
@@ -72,15 +68,11 @@ notrace unsigned long arch_local_irq_save(void) | |||
72 | " .set push \n" | 68 | " .set push \n" |
73 | " .set reorder \n" | 69 | " .set reorder \n" |
74 | " .set noat \n" | 70 | " .set noat \n" |
75 | #if defined(CONFIG_CPU_MIPSR2) | ||
76 | /* see irqflags.h for inline function */ | ||
77 | #else | ||
78 | " mfc0 %[flags], $12 \n" | 71 | " mfc0 %[flags], $12 \n" |
79 | " ori $1, %[flags], 0x1f \n" | 72 | " ori $1, %[flags], 0x1f \n" |
80 | " xori $1, 0x1f \n" | 73 | " xori $1, 0x1f \n" |
81 | " .set noreorder \n" | 74 | " .set noreorder \n" |
82 | " mtc0 $1, $12 \n" | 75 | " mtc0 $1, $12 \n" |
83 | #endif | ||
84 | " " __stringify(__irq_disable_hazard) " \n" | 76 | " " __stringify(__irq_disable_hazard) " \n" |
85 | " .set pop \n" | 77 | " .set pop \n" |
86 | : [flags] "=r" (flags) | 78 | : [flags] "=r" (flags) |
@@ -103,18 +95,12 @@ notrace void arch_local_irq_restore(unsigned long flags) | |||
103 | " .set push \n" | 95 | " .set push \n" |
104 | " .set noreorder \n" | 96 | " .set noreorder \n" |
105 | " .set noat \n" | 97 | " .set noat \n" |
106 | #if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) | ||
107 | /* see irqflags.h for inline function */ | ||
108 | #elif defined(CONFIG_CPU_MIPSR2) | ||
109 | /* see irqflags.h for inline function */ | ||
110 | #else | ||
111 | " mfc0 $1, $12 \n" | 98 | " mfc0 $1, $12 \n" |
112 | " andi %[flags], 1 \n" | 99 | " andi %[flags], 1 \n" |
113 | " ori $1, 0x1f \n" | 100 | " ori $1, 0x1f \n" |
114 | " xori $1, 0x1f \n" | 101 | " xori $1, 0x1f \n" |
115 | " or %[flags], $1 \n" | 102 | " or %[flags], $1 \n" |
116 | " mtc0 %[flags], $12 \n" | 103 | " mtc0 %[flags], $12 \n" |
117 | #endif | ||
118 | " " __stringify(__irq_disable_hazard) " \n" | 104 | " " __stringify(__irq_disable_hazard) " \n" |
119 | " .set pop \n" | 105 | " .set pop \n" |
120 | : [flags] "=r" (__tmp1) | 106 | : [flags] "=r" (__tmp1) |
@@ -136,18 +122,12 @@ notrace void __arch_local_irq_restore(unsigned long flags) | |||
136 | " .set push \n" | 122 | " .set push \n" |
137 | " .set noreorder \n" | 123 | " .set noreorder \n" |
138 | " .set noat \n" | 124 | " .set noat \n" |
139 | #if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) | ||
140 | /* see irqflags.h for inline function */ | ||
141 | #elif defined(CONFIG_CPU_MIPSR2) | ||
142 | /* see irqflags.h for inline function */ | ||
143 | #else | ||
144 | " mfc0 $1, $12 \n" | 125 | " mfc0 $1, $12 \n" |
145 | " andi %[flags], 1 \n" | 126 | " andi %[flags], 1 \n" |
146 | " ori $1, 0x1f \n" | 127 | " ori $1, 0x1f \n" |
147 | " xori $1, 0x1f \n" | 128 | " xori $1, 0x1f \n" |
148 | " or %[flags], $1 \n" | 129 | " or %[flags], $1 \n" |
149 | " mtc0 %[flags], $12 \n" | 130 | " mtc0 %[flags], $12 \n" |
150 | #endif | ||
151 | " " __stringify(__irq_disable_hazard) " \n" | 131 | " " __stringify(__irq_disable_hazard) " \n" |
152 | " .set pop \n" | 132 | " .set pop \n" |
153 | : [flags] "=r" (__tmp1) | 133 | : [flags] "=r" (__tmp1) |
diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c index 1ef365ab3cd3..975a13855116 100644 --- a/arch/mips/lib/r3k_dump_tlb.c +++ b/arch/mips/lib/r3k_dump_tlb.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
10 | 10 | ||
11 | #include <asm/mipsregs.h> | 11 | #include <asm/mipsregs.h> |
12 | #include <asm/mmu_context.h> | ||
12 | #include <asm/page.h> | 13 | #include <asm/page.h> |
13 | #include <asm/pgtable.h> | 14 | #include <asm/pgtable.h> |
14 | #include <asm/tlbdebug.h> | 15 | #include <asm/tlbdebug.h> |
@@ -21,7 +22,7 @@ static void dump_tlb(int first, int last) | |||
21 | unsigned int asid; | 22 | unsigned int asid; |
22 | unsigned long entryhi, entrylo0; | 23 | unsigned long entryhi, entrylo0; |
23 | 24 | ||
24 | asid = read_c0_entryhi() & 0xfc0; | 25 | asid = read_c0_entryhi() & ASID_MASK; |
25 | 26 | ||
26 | for (i = first; i <= last; i++) { | 27 | for (i = first; i <= last; i++) { |
27 | write_c0_index(i<<8); | 28 | write_c0_index(i<<8); |
@@ -34,8 +35,8 @@ static void dump_tlb(int first, int last) | |||
34 | entrylo0 = read_c0_entrylo0(); | 35 | entrylo0 = read_c0_entrylo0(); |
35 | 36 | ||
36 | /* Unused entries have a virtual address of KSEG0. */ | 37 | /* Unused entries have a virtual address of KSEG0. */ |
37 | if ((entryhi & 0xfffff000) != 0x80000000 | 38 | if ((entryhi & PAGE_MASK) != KSEG0 |
38 | && (entryhi & 0xfc0) == asid) { | 39 | && (entryhi & ASID_MASK) == asid) { |
39 | /* | 40 | /* |
40 | * Only print entries in use | 41 | * Only print entries in use |
41 | */ | 42 | */ |
@@ -43,8 +44,8 @@ static void dump_tlb(int first, int last) | |||
43 | 44 | ||
44 | printk("va=%08lx asid=%08lx" | 45 | printk("va=%08lx asid=%08lx" |
45 | " [pa=%06lx n=%d d=%d v=%d g=%d]", | 46 | " [pa=%06lx n=%d d=%d v=%d g=%d]", |
46 | (entryhi & 0xfffff000), | 47 | entryhi & PAGE_MASK, |
47 | entryhi & 0xfc0, | 48 | entryhi & ASID_MASK, |
48 | entrylo0 & PAGE_MASK, | 49 | entrylo0 & PAGE_MASK, |
49 | (entrylo0 & (1 << 11)) ? 1 : 0, | 50 | (entrylo0 & (1 << 11)) ? 1 : 0, |
50 | (entrylo0 & (1 << 10)) ? 1 : 0, | 51 | (entrylo0 & (1 << 10)) ? 1 : 0, |
diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S index bef65c98df59..929bbacd697e 100644 --- a/arch/mips/lib/strlen_user.S +++ b/arch/mips/lib/strlen_user.S | |||
@@ -28,7 +28,6 @@ LEAF(__strlen_\func\()_asm) | |||
28 | and v0, a0 | 28 | and v0, a0 |
29 | bnez v0, .Lfault\@ | 29 | bnez v0, .Lfault\@ |
30 | 30 | ||
31 | FEXPORT(__strlen_\func\()_nocheck_asm) | ||
32 | move v0, a0 | 31 | move v0, a0 |
33 | .ifeqs "\func", "kernel" | 32 | .ifeqs "\func", "kernel" |
34 | 1: EX(lbu, v1, (v0), .Lfault\@) | 33 | 1: EX(lbu, v1, (v0), .Lfault\@) |
@@ -48,9 +47,7 @@ FEXPORT(__strlen_\func\()_nocheck_asm) | |||
48 | #ifndef CONFIG_EVA | 47 | #ifndef CONFIG_EVA |
49 | /* Set aliases */ | 48 | /* Set aliases */ |
50 | .global __strlen_user_asm | 49 | .global __strlen_user_asm |
51 | .global __strlen_user_nocheck_asm | ||
52 | .set __strlen_user_asm, __strlen_kernel_asm | 50 | .set __strlen_user_asm, __strlen_kernel_asm |
53 | .set __strlen_user_nocheck_asm, __strlen_kernel_nocheck_asm | ||
54 | #endif | 51 | #endif |
55 | 52 | ||
56 | __BUILD_STRLEN_ASM kernel | 53 | __BUILD_STRLEN_ASM kernel |
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 1b91fc6a921b..156de85b82cd 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig | |||
@@ -86,6 +86,7 @@ config LOONGSON_MACH3X | |||
86 | select LOONGSON_MC146818 | 86 | select LOONGSON_MC146818 |
87 | select ZONE_DMA32 | 87 | select ZONE_DMA32 |
88 | select LEFI_FIRMWARE_INTERFACE | 88 | select LEFI_FIRMWARE_INTERFACE |
89 | select PHYS48_TO_HT40 | ||
89 | help | 90 | help |
90 | Generic Loongson 3 family machines utilize the 3A/3B revision | 91 | Generic Loongson 3 family machines utilize the 3A/3B revision |
91 | of Loongson processor and RS780/SBX00 chipset. | 92 | of Loongson processor and RS780/SBX00 chipset. |
@@ -107,6 +108,18 @@ config CS5536_MFGPT | |||
107 | 108 | ||
108 | If unsure, say Yes. | 109 | If unsure, say Yes. |
109 | 110 | ||
111 | config RS780_HPET | ||
112 | bool "RS780/SBX00 HPET Timer" | ||
113 | depends on LOONGSON_MACH3X | ||
114 | select MIPS_EXTERNAL_TIMER | ||
115 | help | ||
116 | This option enables the hpet timer of AMD RS780/SBX00. | ||
117 | |||
118 | If you want to enable the Loongson3 CPUFreq Driver, Please enable | ||
119 | this option at first, otherwise, You will get wrong system time. | ||
120 | |||
121 | If unsure, say Yes. | ||
122 | |||
110 | config LOONGSON_SUSPEND | 123 | config LOONGSON_SUSPEND |
111 | bool | 124 | bool |
112 | default y | 125 | default y |
@@ -131,6 +144,10 @@ config SWIOTLB | |||
131 | select NEED_SG_DMA_LENGTH | 144 | select NEED_SG_DMA_LENGTH |
132 | select NEED_DMA_MAP_STATE | 145 | select NEED_DMA_MAP_STATE |
133 | 146 | ||
147 | config PHYS48_TO_HT40 | ||
148 | bool | ||
149 | default y if CPU_LOONGSON3 | ||
150 | |||
134 | config LOONGSON_MC146818 | 151 | config LOONGSON_MC146818 |
135 | bool | 152 | bool |
136 | default n | 153 | default n |
diff --git a/arch/mips/loongson/common/cs5536/cs5536_pci.c b/arch/mips/loongson/common/cs5536/cs5536_pci.c index 81bed9d18061..b739723205f8 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_pci.c +++ b/arch/mips/loongson/common/cs5536/cs5536_pci.c | |||
@@ -21,6 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <cs5536/cs5536_pci.h> | ||
24 | #include <cs5536/cs5536_vsm.h> | 25 | #include <cs5536/cs5536_vsm.h> |
25 | 26 | ||
26 | enum { | 27 | enum { |
@@ -35,21 +36,21 @@ enum { | |||
35 | }; | 36 | }; |
36 | 37 | ||
37 | static const cs5536_pci_vsm_write vsm_conf_write[] = { | 38 | static const cs5536_pci_vsm_write vsm_conf_write[] = { |
38 | [CS5536_ISA_FUNC] pci_isa_write_reg, | 39 | [CS5536_ISA_FUNC] = pci_isa_write_reg, |
39 | [reserved_func] NULL, | 40 | [reserved_func] = NULL, |
40 | [CS5536_IDE_FUNC] pci_ide_write_reg, | 41 | [CS5536_IDE_FUNC] = pci_ide_write_reg, |
41 | [CS5536_ACC_FUNC] pci_acc_write_reg, | 42 | [CS5536_ACC_FUNC] = pci_acc_write_reg, |
42 | [CS5536_OHCI_FUNC] pci_ohci_write_reg, | 43 | [CS5536_OHCI_FUNC] = pci_ohci_write_reg, |
43 | [CS5536_EHCI_FUNC] pci_ehci_write_reg, | 44 | [CS5536_EHCI_FUNC] = pci_ehci_write_reg, |
44 | }; | 45 | }; |
45 | 46 | ||
46 | static const cs5536_pci_vsm_read vsm_conf_read[] = { | 47 | static const cs5536_pci_vsm_read vsm_conf_read[] = { |
47 | [CS5536_ISA_FUNC] pci_isa_read_reg, | 48 | [CS5536_ISA_FUNC] = pci_isa_read_reg, |
48 | [reserved_func] NULL, | 49 | [reserved_func] = NULL, |
49 | [CS5536_IDE_FUNC] pci_ide_read_reg, | 50 | [CS5536_IDE_FUNC] = pci_ide_read_reg, |
50 | [CS5536_ACC_FUNC] pci_acc_read_reg, | 51 | [CS5536_ACC_FUNC] = pci_acc_read_reg, |
51 | [CS5536_OHCI_FUNC] pci_ohci_read_reg, | 52 | [CS5536_OHCI_FUNC] = pci_ohci_read_reg, |
52 | [CS5536_EHCI_FUNC] pci_ehci_read_reg, | 53 | [CS5536_EHCI_FUNC] = pci_ehci_read_reg, |
53 | }; | 54 | }; |
54 | 55 | ||
55 | /* | 56 | /* |
diff --git a/arch/mips/loongson/common/dma-swiotlb.c b/arch/mips/loongson/common/dma-swiotlb.c index c2be01f91575..2c6b989c1bc4 100644 --- a/arch/mips/loongson/common/dma-swiotlb.c +++ b/arch/mips/loongson/common/dma-swiotlb.c | |||
@@ -105,11 +105,25 @@ static int loongson_dma_set_mask(struct device *dev, u64 mask) | |||
105 | 105 | ||
106 | dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | 106 | dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) |
107 | { | 107 | { |
108 | long nid; | ||
109 | #ifdef CONFIG_PHYS48_TO_HT40 | ||
110 | /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from | ||
111 | * Loongson-3's 48bit address space and embed it into 40bit */ | ||
112 | nid = (paddr >> 44) & 0x3; | ||
113 | paddr = ((nid << 44) ^ paddr) | (nid << 37); | ||
114 | #endif | ||
108 | return paddr; | 115 | return paddr; |
109 | } | 116 | } |
110 | 117 | ||
111 | phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) | 118 | phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) |
112 | { | 119 | { |
120 | long nid; | ||
121 | #ifdef CONFIG_PHYS48_TO_HT40 | ||
122 | /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from | ||
123 | * Loongson-3's 48bit address space and embed it into 40bit */ | ||
124 | nid = (daddr >> 37) & 0x3; | ||
125 | daddr = ((nid << 37) ^ daddr) | (nid << 44); | ||
126 | #endif | ||
113 | return daddr; | 127 | return daddr; |
114 | } | 128 | } |
115 | 129 | ||
diff --git a/arch/mips/loongson/common/early_printk.c b/arch/mips/loongson/common/early_printk.c index ced461b39069..6ca632e529dc 100644 --- a/arch/mips/loongson/common/early_printk.c +++ b/arch/mips/loongson/common/early_printk.c | |||
@@ -30,7 +30,7 @@ void prom_putchar(char c) | |||
30 | int timeout; | 30 | int timeout; |
31 | unsigned char *uart_base; | 31 | unsigned char *uart_base; |
32 | 32 | ||
33 | uart_base = (unsigned char *)_loongson_uart_base; | 33 | uart_base = (unsigned char *)_loongson_uart_base[0]; |
34 | timeout = 1024; | 34 | timeout = 1024; |
35 | 35 | ||
36 | while (((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) && | 36 | while (((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) && |
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c index f15228550a22..045ea3d47c87 100644 --- a/arch/mips/loongson/common/env.c +++ b/arch/mips/loongson/common/env.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/bootinfo.h> | 21 | #include <asm/bootinfo.h> |
22 | #include <loongson.h> | 22 | #include <loongson.h> |
23 | #include <boot_param.h> | 23 | #include <boot_param.h> |
24 | #include <workarounds.h> | ||
24 | 25 | ||
25 | u32 cpu_clock_freq; | 26 | u32 cpu_clock_freq; |
26 | EXPORT_SYMBOL(cpu_clock_freq); | 27 | EXPORT_SYMBOL(cpu_clock_freq); |
@@ -31,7 +32,6 @@ u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180}; | |||
31 | u64 loongson_freqctrl[MAX_PACKAGES]; | 32 | u64 loongson_freqctrl[MAX_PACKAGES]; |
32 | 33 | ||
33 | unsigned long long smp_group[4]; | 34 | unsigned long long smp_group[4]; |
34 | int cpuhotplug_workaround = 0; | ||
35 | 35 | ||
36 | #define parse_even_earlier(res, option, p) \ | 36 | #define parse_even_earlier(res, option, p) \ |
37 | do { \ | 37 | do { \ |
@@ -67,6 +67,7 @@ void __init prom_init_env(void) | |||
67 | #else | 67 | #else |
68 | struct boot_params *boot_p; | 68 | struct boot_params *boot_p; |
69 | struct loongson_params *loongson_p; | 69 | struct loongson_params *loongson_p; |
70 | struct system_loongson *esys; | ||
70 | struct efi_cpuinfo_loongson *ecpu; | 71 | struct efi_cpuinfo_loongson *ecpu; |
71 | struct irq_source_routing_table *eirq_source; | 72 | struct irq_source_routing_table *eirq_source; |
72 | 73 | ||
@@ -74,6 +75,8 @@ void __init prom_init_env(void) | |||
74 | boot_p = (struct boot_params *)fw_arg2; | 75 | boot_p = (struct boot_params *)fw_arg2; |
75 | loongson_p = &(boot_p->efi.smbios.lp); | 76 | loongson_p = &(boot_p->efi.smbios.lp); |
76 | 77 | ||
78 | esys = (struct system_loongson *) | ||
79 | ((u64)loongson_p + loongson_p->system_offset); | ||
77 | ecpu = (struct efi_cpuinfo_loongson *) | 80 | ecpu = (struct efi_cpuinfo_loongson *) |
78 | ((u64)loongson_p + loongson_p->cpu_offset); | 81 | ((u64)loongson_p + loongson_p->cpu_offset); |
79 | eirq_source = (struct irq_source_routing_table *) | 82 | eirq_source = (struct irq_source_routing_table *) |
@@ -95,6 +98,7 @@ void __init prom_init_env(void) | |||
95 | loongson_chipcfg[2] = 0x900020001fe00180; | 98 | loongson_chipcfg[2] = 0x900020001fe00180; |
96 | loongson_chipcfg[3] = 0x900030001fe00180; | 99 | loongson_chipcfg[3] = 0x900030001fe00180; |
97 | loongson_sysconf.ht_control_base = 0x90000EFDFB000000; | 100 | loongson_sysconf.ht_control_base = 0x90000EFDFB000000; |
101 | loongson_sysconf.workarounds = WORKAROUND_CPUFREQ; | ||
98 | } else if (ecpu->cputype == Loongson_3B) { | 102 | } else if (ecpu->cputype == Loongson_3B) { |
99 | loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */ | 103 | loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */ |
100 | loongson_sysconf.cores_per_package = 8; | 104 | loongson_sysconf.cores_per_package = 8; |
@@ -111,7 +115,7 @@ void __init prom_init_env(void) | |||
111 | loongson_freqctrl[2] = 0x900040001fe001d0; | 115 | loongson_freqctrl[2] = 0x900040001fe001d0; |
112 | loongson_freqctrl[3] = 0x900060001fe001d0; | 116 | loongson_freqctrl[3] = 0x900060001fe001d0; |
113 | loongson_sysconf.ht_control_base = 0x90001EFDFB000000; | 117 | loongson_sysconf.ht_control_base = 0x90001EFDFB000000; |
114 | cpuhotplug_workaround = 1; | 118 | loongson_sysconf.workarounds = WORKAROUND_CPUHOTPLUG; |
115 | } else { | 119 | } else { |
116 | loongson_sysconf.cores_per_node = 1; | 120 | loongson_sysconf.cores_per_node = 1; |
117 | loongson_sysconf.cores_per_package = 1; | 121 | loongson_sysconf.cores_per_package = 1; |
@@ -119,6 +123,8 @@ void __init prom_init_env(void) | |||
119 | } | 123 | } |
120 | 124 | ||
121 | loongson_sysconf.nr_cpus = ecpu->nr_cpus; | 125 | loongson_sysconf.nr_cpus = ecpu->nr_cpus; |
126 | loongson_sysconf.boot_cpu_id = ecpu->cpu_startup_core_id; | ||
127 | loongson_sysconf.reserved_cpus_mask = ecpu->reserved_cores_mask; | ||
122 | if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0) | 128 | if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0) |
123 | loongson_sysconf.nr_cpus = NR_CPUS; | 129 | loongson_sysconf.nr_cpus = NR_CPUS; |
124 | loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus + | 130 | loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus + |
@@ -141,6 +147,24 @@ void __init prom_init_env(void) | |||
141 | pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n", | 147 | pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n", |
142 | loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr, | 148 | loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr, |
143 | loongson_sysconf.vgabios_addr); | 149 | loongson_sysconf.vgabios_addr); |
150 | |||
151 | memset(loongson_sysconf.ecname, 0, 32); | ||
152 | if (esys->has_ec) | ||
153 | memcpy(loongson_sysconf.ecname, esys->ec_name, 32); | ||
154 | loongson_sysconf.workarounds |= esys->workarounds; | ||
155 | |||
156 | loongson_sysconf.nr_uarts = esys->nr_uarts; | ||
157 | if (esys->nr_uarts < 1 || esys->nr_uarts > MAX_UARTS) | ||
158 | loongson_sysconf.nr_uarts = 1; | ||
159 | memcpy(loongson_sysconf.uarts, esys->uarts, | ||
160 | sizeof(struct uart_device) * loongson_sysconf.nr_uarts); | ||
161 | |||
162 | loongson_sysconf.nr_sensors = esys->nr_sensors; | ||
163 | if (loongson_sysconf.nr_sensors > MAX_SENSORS) | ||
164 | loongson_sysconf.nr_sensors = 0; | ||
165 | if (loongson_sysconf.nr_sensors) | ||
166 | memcpy(loongson_sysconf.sensors, esys->sensors, | ||
167 | sizeof(struct sensor_device) * loongson_sysconf.nr_sensors); | ||
144 | #endif | 168 | #endif |
145 | if (cpu_clock_freq == 0) { | 169 | if (cpu_clock_freq == 0) { |
146 | processor_id = (¤t_cpu_data)->processor_id; | 170 | processor_id = (¤t_cpu_data)->processor_id; |
diff --git a/arch/mips/loongson/common/gpio.c b/arch/mips/loongson/common/gpio.c index 21869908aaa4..29dbaa253061 100644 --- a/arch/mips/loongson/common/gpio.c +++ b/arch/mips/loongson/common/gpio.c | |||
@@ -37,7 +37,7 @@ int gpio_get_value(unsigned gpio) | |||
37 | val = LOONGSON_GPIODATA; | 37 | val = LOONGSON_GPIODATA; |
38 | spin_unlock(&gpio_lock); | 38 | spin_unlock(&gpio_lock); |
39 | 39 | ||
40 | return ((val & mask) != 0); | 40 | return (val & mask) != 0; |
41 | } | 41 | } |
42 | EXPORT_SYMBOL(gpio_get_value); | 42 | EXPORT_SYMBOL(gpio_get_value); |
43 | 43 | ||
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c index f6af3aba4c86..9b987fe98b5b 100644 --- a/arch/mips/loongson/common/init.c +++ b/arch/mips/loongson/common/init.c | |||
@@ -9,6 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/bootmem.h> | 11 | #include <linux/bootmem.h> |
12 | #include <asm/bootinfo.h> | ||
12 | #include <asm/smp-ops.h> | 13 | #include <asm/smp-ops.h> |
13 | 14 | ||
14 | #include <loongson.h> | 15 | #include <loongson.h> |
diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c index 1a4797984b8d..f2807bc662a3 100644 --- a/arch/mips/loongson/common/machtype.c +++ b/arch/mips/loongson/common/machtype.c | |||
@@ -19,19 +19,16 @@ | |||
19 | #define MACHTYPE_LEN 50 | 19 | #define MACHTYPE_LEN 50 |
20 | 20 | ||
21 | static const char *system_types[] = { | 21 | static const char *system_types[] = { |
22 | [MACH_LOONGSON_UNKNOWN] "unknown loongson machine", | 22 | [MACH_LOONGSON_UNKNOWN] = "unknown loongson machine", |
23 | [MACH_LEMOTE_FL2E] "lemote-fuloong-2e-box", | 23 | [MACH_LEMOTE_FL2E] = "lemote-fuloong-2e-box", |
24 | [MACH_LEMOTE_FL2F] "lemote-fuloong-2f-box", | 24 | [MACH_LEMOTE_FL2F] = "lemote-fuloong-2f-box", |
25 | [MACH_LEMOTE_ML2F7] "lemote-mengloong-2f-7inches", | 25 | [MACH_LEMOTE_ML2F7] = "lemote-mengloong-2f-7inches", |
26 | [MACH_LEMOTE_YL2F89] "lemote-yeeloong-2f-8.9inches", | 26 | [MACH_LEMOTE_YL2F89] = "lemote-yeeloong-2f-8.9inches", |
27 | [MACH_DEXXON_GDIUM2F10] "dexxon-gdium-2f", | 27 | [MACH_DEXXON_GDIUM2F10] = "dexxon-gdium-2f", |
28 | [MACH_LEMOTE_NAS] "lemote-nas-2f", | 28 | [MACH_LEMOTE_NAS] = "lemote-nas-2f", |
29 | [MACH_LEMOTE_LL2F] "lemote-lynloong-2f", | 29 | [MACH_LEMOTE_LL2F] = "lemote-lynloong-2f", |
30 | [MACH_LEMOTE_A1004] "lemote-3a-notebook-a1004", | 30 | [MACH_LOONGSON_GENERIC] = "generic-loongson-machine", |
31 | [MACH_LEMOTE_A1101] "lemote-3a-itx-a1101", | 31 | [MACH_LOONGSON_END] = NULL, |
32 | [MACH_LEMOTE_A1201] "lemote-2gq-notebook-a1201", | ||
33 | [MACH_LEMOTE_A1205] "lemote-2gq-aio-a1205", | ||
34 | [MACH_LOONGSON_END] NULL, | ||
35 | }; | 32 | }; |
36 | 33 | ||
37 | const char *get_system_type(void) | 34 | const char *get_system_type(void) |
diff --git a/arch/mips/loongson/common/rtc.c b/arch/mips/loongson/common/rtc.c index a90d87c01555..b5709af09f7f 100644 --- a/arch/mips/loongson/common/rtc.c +++ b/arch/mips/loongson/common/rtc.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/mc146818rtc.h> | 15 | #include <linux/mc146818rtc.h> |
16 | 16 | ||
17 | struct resource loongson_rtc_resources[] = { | 17 | static struct resource loongson_rtc_resources[] = { |
18 | { | 18 | { |
19 | .start = RTC_PORT(0), | 19 | .start = RTC_PORT(0), |
20 | .end = RTC_PORT(1), | 20 | .end = RTC_PORT(1), |
diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c index bd2b7095b6dc..c23fa1373729 100644 --- a/arch/mips/loongson/common/serial.c +++ b/arch/mips/loongson/common/serial.c | |||
@@ -38,20 +38,17 @@ | |||
38 | .regshift = 0, \ | 38 | .regshift = 0, \ |
39 | } | 39 | } |
40 | 40 | ||
41 | static struct plat_serial8250_port uart8250_data[][2] = { | 41 | static struct plat_serial8250_port uart8250_data[][MAX_UARTS + 1] = { |
42 | [MACH_LOONGSON_UNKNOWN] {}, | 42 | [MACH_LOONGSON_UNKNOWN] = {}, |
43 | [MACH_LEMOTE_FL2E] {PORT(4, 1843200), {} }, | 43 | [MACH_LEMOTE_FL2E] = {PORT(4, 1843200), {} }, |
44 | [MACH_LEMOTE_FL2F] {PORT(3, 1843200), {} }, | 44 | [MACH_LEMOTE_FL2F] = {PORT(3, 1843200), {} }, |
45 | [MACH_LEMOTE_ML2F7] {PORT_M(3, 3686400), {} }, | 45 | [MACH_LEMOTE_ML2F7] = {PORT_M(3, 3686400), {} }, |
46 | [MACH_LEMOTE_YL2F89] {PORT_M(3, 3686400), {} }, | 46 | [MACH_LEMOTE_YL2F89] = {PORT_M(3, 3686400), {} }, |
47 | [MACH_DEXXON_GDIUM2F10] {PORT_M(3, 3686400), {} }, | 47 | [MACH_DEXXON_GDIUM2F10] = {PORT_M(3, 3686400), {} }, |
48 | [MACH_LEMOTE_NAS] {PORT_M(3, 3686400), {} }, | 48 | [MACH_LEMOTE_NAS] = {PORT_M(3, 3686400), {} }, |
49 | [MACH_LEMOTE_LL2F] {PORT(3, 1843200), {} }, | 49 | [MACH_LEMOTE_LL2F] = {PORT(3, 1843200), {} }, |
50 | [MACH_LEMOTE_A1004] {PORT_M(2, 33177600), {} }, | 50 | [MACH_LOONGSON_GENERIC] = {PORT_M(2, 25000000), {} }, |
51 | [MACH_LEMOTE_A1101] {PORT_M(2, 25000000), {} }, | 51 | [MACH_LOONGSON_END] = {}, |
52 | [MACH_LEMOTE_A1201] {PORT_M(2, 25000000), {} }, | ||
53 | [MACH_LEMOTE_A1205] {PORT_M(2, 25000000), {} }, | ||
54 | [MACH_LOONGSON_END] {}, | ||
55 | }; | 52 | }; |
56 | 53 | ||
57 | static struct platform_device uart8250_device = { | 54 | static struct platform_device uart8250_device = { |
@@ -61,17 +58,52 @@ static struct platform_device uart8250_device = { | |||
61 | 58 | ||
62 | static int __init serial_init(void) | 59 | static int __init serial_init(void) |
63 | { | 60 | { |
61 | int i; | ||
64 | unsigned char iotype; | 62 | unsigned char iotype; |
65 | 63 | ||
66 | iotype = uart8250_data[mips_machtype][0].iotype; | 64 | iotype = uart8250_data[mips_machtype][0].iotype; |
67 | 65 | ||
68 | if (UPIO_MEM == iotype) | 66 | if (UPIO_MEM == iotype) { |
67 | uart8250_data[mips_machtype][0].mapbase = | ||
68 | loongson_uart_base[0]; | ||
69 | uart8250_data[mips_machtype][0].membase = | 69 | uart8250_data[mips_machtype][0].membase = |
70 | (void __iomem *)_loongson_uart_base; | 70 | (void __iomem *)_loongson_uart_base[0]; |
71 | } | ||
71 | else if (UPIO_PORT == iotype) | 72 | else if (UPIO_PORT == iotype) |
72 | uart8250_data[mips_machtype][0].iobase = | 73 | uart8250_data[mips_machtype][0].iobase = |
73 | loongson_uart_base - LOONGSON_PCIIO_BASE; | 74 | loongson_uart_base[0] - LOONGSON_PCIIO_BASE; |
74 | 75 | ||
76 | if (loongson_sysconf.uarts[0].uartclk) | ||
77 | uart8250_data[mips_machtype][0].uartclk = | ||
78 | loongson_sysconf.uarts[0].uartclk; | ||
79 | |||
80 | for (i = 1; i < loongson_sysconf.nr_uarts; i++) { | ||
81 | iotype = loongson_sysconf.uarts[i].iotype; | ||
82 | uart8250_data[mips_machtype][i].iotype = iotype; | ||
83 | loongson_uart_base[i] = loongson_sysconf.uarts[i].uart_base; | ||
84 | |||
85 | if (UPIO_MEM == iotype) { | ||
86 | uart8250_data[mips_machtype][i].irq = | ||
87 | MIPS_CPU_IRQ_BASE + loongson_sysconf.uarts[i].int_offset; | ||
88 | uart8250_data[mips_machtype][i].mapbase = | ||
89 | loongson_uart_base[i]; | ||
90 | uart8250_data[mips_machtype][i].membase = | ||
91 | ioremap_nocache(loongson_uart_base[i], 8); | ||
92 | } else if (UPIO_PORT == iotype) { | ||
93 | uart8250_data[mips_machtype][i].irq = | ||
94 | loongson_sysconf.uarts[i].int_offset; | ||
95 | uart8250_data[mips_machtype][i].iobase = | ||
96 | loongson_uart_base[i] - LOONGSON_PCIIO_BASE; | ||
97 | } | ||
98 | |||
99 | uart8250_data[mips_machtype][i].uartclk = | ||
100 | loongson_sysconf.uarts[i].uartclk; | ||
101 | uart8250_data[mips_machtype][i].flags = | ||
102 | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; | ||
103 | } | ||
104 | |||
105 | memset(&uart8250_data[mips_machtype][loongson_sysconf.nr_uarts], | ||
106 | 0, sizeof(struct plat_serial8250_port)); | ||
75 | uart8250_device.dev.platform_data = uart8250_data[mips_machtype]; | 107 | uart8250_device.dev.platform_data = uart8250_data[mips_machtype]; |
76 | 108 | ||
77 | return platform_device_register(&uart8250_device); | 109 | return platform_device_register(&uart8250_device); |
diff --git a/arch/mips/loongson/common/setup.c b/arch/mips/loongson/common/setup.c index bb4ac922e47a..d477dd6bb326 100644 --- a/arch/mips/loongson/common/setup.c +++ b/arch/mips/loongson/common/setup.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | 11 | ||
12 | #include <asm/wbflush.h> | 12 | #include <asm/wbflush.h> |
13 | #include <asm/bootinfo.h> | ||
13 | 14 | ||
14 | #include <loongson.h> | 15 | #include <loongson.h> |
15 | 16 | ||
diff --git a/arch/mips/loongson/common/time.c b/arch/mips/loongson/common/time.c index 262a1f65b05e..e1a5382ad47e 100644 --- a/arch/mips/loongson/common/time.c +++ b/arch/mips/loongson/common/time.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | #include <asm/mc146818-time.h> | 13 | #include <asm/mc146818-time.h> |
14 | #include <asm/time.h> | 14 | #include <asm/time.h> |
15 | #include <asm/hpet.h> | ||
15 | 16 | ||
16 | #include <loongson.h> | 17 | #include <loongson.h> |
17 | #include <cs5536/cs5536_mfgpt.h> | 18 | #include <cs5536/cs5536_mfgpt.h> |
@@ -21,7 +22,11 @@ void __init plat_time_init(void) | |||
21 | /* setup mips r4k timer */ | 22 | /* setup mips r4k timer */ |
22 | mips_hpt_frequency = cpu_clock_freq / 2; | 23 | mips_hpt_frequency = cpu_clock_freq / 2; |
23 | 24 | ||
25 | #ifdef CONFIG_RS780_HPET | ||
26 | setup_hpet_timer(); | ||
27 | #else | ||
24 | setup_mfgpt0_timer(); | 28 | setup_mfgpt0_timer(); |
29 | #endif | ||
25 | } | 30 | } |
26 | 31 | ||
27 | void read_persistent_clock(struct timespec *ts) | 32 | void read_persistent_clock(struct timespec *ts) |
diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c index 1e1eeea73fde..9de559d58e1f 100644 --- a/arch/mips/loongson/common/uart_base.c +++ b/arch/mips/loongson/common/uart_base.c | |||
@@ -13,22 +13,27 @@ | |||
13 | 13 | ||
14 | #include <loongson.h> | 14 | #include <loongson.h> |
15 | 15 | ||
16 | /* ioremapped */ | ||
17 | unsigned long _loongson_uart_base; | ||
18 | EXPORT_SYMBOL(_loongson_uart_base); | ||
19 | /* raw */ | 16 | /* raw */ |
20 | unsigned long loongson_uart_base; | 17 | unsigned long loongson_uart_base[MAX_UARTS] = {}; |
18 | /* ioremapped */ | ||
19 | unsigned long _loongson_uart_base[MAX_UARTS] = {}; | ||
20 | |||
21 | EXPORT_SYMBOL(loongson_uart_base); | 21 | EXPORT_SYMBOL(loongson_uart_base); |
22 | EXPORT_SYMBOL(_loongson_uart_base); | ||
22 | 23 | ||
23 | void prom_init_loongson_uart_base(void) | 24 | void prom_init_loongson_uart_base(void) |
24 | { | 25 | { |
25 | switch (mips_machtype) { | 26 | switch (mips_machtype) { |
27 | case MACH_LOONGSON_GENERIC: | ||
28 | /* The CPU provided serial port (CPU) */ | ||
29 | loongson_uart_base[0] = LOONGSON_REG_BASE + 0x1e0; | ||
30 | break; | ||
26 | case MACH_LEMOTE_FL2E: | 31 | case MACH_LEMOTE_FL2E: |
27 | loongson_uart_base = LOONGSON_PCIIO_BASE + 0x3f8; | 32 | loongson_uart_base[0] = LOONGSON_PCIIO_BASE + 0x3f8; |
28 | break; | 33 | break; |
29 | case MACH_LEMOTE_FL2F: | 34 | case MACH_LEMOTE_FL2F: |
30 | case MACH_LEMOTE_LL2F: | 35 | case MACH_LEMOTE_LL2F: |
31 | loongson_uart_base = LOONGSON_PCIIO_BASE + 0x2f8; | 36 | loongson_uart_base[0] = LOONGSON_PCIIO_BASE + 0x2f8; |
32 | break; | 37 | break; |
33 | case MACH_LEMOTE_ML2F7: | 38 | case MACH_LEMOTE_ML2F7: |
34 | case MACH_LEMOTE_YL2F89: | 39 | case MACH_LEMOTE_YL2F89: |
@@ -36,17 +41,10 @@ void prom_init_loongson_uart_base(void) | |||
36 | case MACH_LEMOTE_NAS: | 41 | case MACH_LEMOTE_NAS: |
37 | default: | 42 | default: |
38 | /* The CPU provided serial port (LPC) */ | 43 | /* The CPU provided serial port (LPC) */ |
39 | loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8; | 44 | loongson_uart_base[0] = LOONGSON_LIO1_BASE + 0x3f8; |
40 | break; | ||
41 | case MACH_LEMOTE_A1004: | ||
42 | case MACH_LEMOTE_A1101: | ||
43 | case MACH_LEMOTE_A1201: | ||
44 | case MACH_LEMOTE_A1205: | ||
45 | /* The CPU provided serial port (CPU) */ | ||
46 | loongson_uart_base = LOONGSON_REG_BASE + 0x1e0; | ||
47 | break; | 45 | break; |
48 | } | 46 | } |
49 | 47 | ||
50 | _loongson_uart_base = | 48 | _loongson_uart_base[0] = |
51 | (unsigned long)ioremap_nocache(loongson_uart_base, 8); | 49 | (unsigned long)ioremap_nocache(loongson_uart_base[0], 8); |
52 | } | 50 | } |
diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c index 6f8682e44483..cab5f43e0e29 100644 --- a/arch/mips/loongson/lemote-2f/irq.c +++ b/arch/mips/loongson/lemote-2f/irq.c | |||
@@ -93,13 +93,13 @@ static irqreturn_t ip6_action(int cpl, void *dev_id) | |||
93 | return IRQ_HANDLED; | 93 | return IRQ_HANDLED; |
94 | } | 94 | } |
95 | 95 | ||
96 | struct irqaction ip6_irqaction = { | 96 | static struct irqaction ip6_irqaction = { |
97 | .handler = ip6_action, | 97 | .handler = ip6_action, |
98 | .name = "cascade", | 98 | .name = "cascade", |
99 | .flags = IRQF_SHARED | IRQF_NO_THREAD, | 99 | .flags = IRQF_SHARED | IRQF_NO_THREAD, |
100 | }; | 100 | }; |
101 | 101 | ||
102 | struct irqaction cascade_irqaction = { | 102 | static struct irqaction cascade_irqaction = { |
103 | .handler = no_action, | 103 | .handler = no_action, |
104 | .name = "cascade", | 104 | .name = "cascade", |
105 | .flags = IRQF_NO_THREAD, | 105 | .flags = IRQF_NO_THREAD, |
diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c index 79ac694fe744..a26ca7fcd7e0 100644 --- a/arch/mips/loongson/lemote-2f/reset.c +++ b/arch/mips/loongson/lemote-2f/reset.c | |||
@@ -76,7 +76,7 @@ static void fl2f_shutdown(void) | |||
76 | 76 | ||
77 | /* reset support for yeeloong2f and mengloong2f notebook */ | 77 | /* reset support for yeeloong2f and mengloong2f notebook */ |
78 | 78 | ||
79 | void ml2f_reboot(void) | 79 | static void ml2f_reboot(void) |
80 | { | 80 | { |
81 | reset_cpu(); | 81 | reset_cpu(); |
82 | 82 | ||
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile index b4df775b9f30..622fead5ebc9 100644 --- a/arch/mips/loongson/loongson-3/Makefile +++ b/arch/mips/loongson/loongson-3/Makefile | |||
@@ -1,8 +1,10 @@ | |||
1 | # | 1 | # |
2 | # Makefile for Loongson-3 family machines | 2 | # Makefile for Loongson-3 family machines |
3 | # | 3 | # |
4 | obj-y += irq.o cop2-ex.o | 4 | obj-y += irq.o cop2-ex.o platform.o |
5 | 5 | ||
6 | obj-$(CONFIG_SMP) += smp.o | 6 | obj-$(CONFIG_SMP) += smp.o |
7 | 7 | ||
8 | obj-$(CONFIG_NUMA) += numa.o | 8 | obj-$(CONFIG_NUMA) += numa.o |
9 | |||
10 | obj-$(CONFIG_RS780_HPET) += hpet.o | ||
diff --git a/arch/mips/loongson/loongson-3/hpet.c b/arch/mips/loongson/loongson-3/hpet.c new file mode 100644 index 000000000000..e898d68668a9 --- /dev/null +++ b/arch/mips/loongson/loongson-3/hpet.c | |||
@@ -0,0 +1,257 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/pci.h> | ||
3 | #include <linux/percpu.h> | ||
4 | #include <linux/delay.h> | ||
5 | #include <linux/spinlock.h> | ||
6 | #include <linux/interrupt.h> | ||
7 | |||
8 | #include <asm/hpet.h> | ||
9 | #include <asm/time.h> | ||
10 | |||
11 | #define SMBUS_CFG_BASE (loongson_sysconf.ht_control_base + 0x0300a000) | ||
12 | #define SMBUS_PCI_REG40 0x40 | ||
13 | #define SMBUS_PCI_REG64 0x64 | ||
14 | #define SMBUS_PCI_REGB4 0xb4 | ||
15 | |||
16 | static DEFINE_SPINLOCK(hpet_lock); | ||
17 | DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device); | ||
18 | |||
19 | static unsigned int smbus_read(int offset) | ||
20 | { | ||
21 | return *(volatile unsigned int *)(SMBUS_CFG_BASE + offset); | ||
22 | } | ||
23 | |||
24 | static void smbus_write(int offset, int data) | ||
25 | { | ||
26 | *(volatile unsigned int *)(SMBUS_CFG_BASE + offset) = data; | ||
27 | } | ||
28 | |||
29 | static void smbus_enable(int offset, int bit) | ||
30 | { | ||
31 | unsigned int cfg = smbus_read(offset); | ||
32 | |||
33 | cfg |= bit; | ||
34 | smbus_write(offset, cfg); | ||
35 | } | ||
36 | |||
37 | static int hpet_read(int offset) | ||
38 | { | ||
39 | return *(volatile unsigned int *)(HPET_MMIO_ADDR + offset); | ||
40 | } | ||
41 | |||
42 | static void hpet_write(int offset, int data) | ||
43 | { | ||
44 | *(volatile unsigned int *)(HPET_MMIO_ADDR + offset) = data; | ||
45 | } | ||
46 | |||
47 | static void hpet_start_counter(void) | ||
48 | { | ||
49 | unsigned int cfg = hpet_read(HPET_CFG); | ||
50 | |||
51 | cfg |= HPET_CFG_ENABLE; | ||
52 | hpet_write(HPET_CFG, cfg); | ||
53 | } | ||
54 | |||
55 | static void hpet_stop_counter(void) | ||
56 | { | ||
57 | unsigned int cfg = hpet_read(HPET_CFG); | ||
58 | |||
59 | cfg &= ~HPET_CFG_ENABLE; | ||
60 | hpet_write(HPET_CFG, cfg); | ||
61 | } | ||
62 | |||
63 | static void hpet_reset_counter(void) | ||
64 | { | ||
65 | hpet_write(HPET_COUNTER, 0); | ||
66 | hpet_write(HPET_COUNTER + 4, 0); | ||
67 | } | ||
68 | |||
69 | static void hpet_restart_counter(void) | ||
70 | { | ||
71 | hpet_stop_counter(); | ||
72 | hpet_reset_counter(); | ||
73 | hpet_start_counter(); | ||
74 | } | ||
75 | |||
76 | static void hpet_enable_legacy_int(void) | ||
77 | { | ||
78 | /* Do nothing on Loongson-3 */ | ||
79 | } | ||
80 | |||
81 | static void hpet_set_mode(enum clock_event_mode mode, | ||
82 | struct clock_event_device *evt) | ||
83 | { | ||
84 | int cfg = 0; | ||
85 | |||
86 | spin_lock(&hpet_lock); | ||
87 | switch (mode) { | ||
88 | case CLOCK_EVT_MODE_PERIODIC: | ||
89 | pr_info("set clock event to periodic mode!\n"); | ||
90 | /* stop counter */ | ||
91 | hpet_stop_counter(); | ||
92 | |||
93 | /* enables the timer0 to generate a periodic interrupt */ | ||
94 | cfg = hpet_read(HPET_T0_CFG); | ||
95 | cfg &= ~HPET_TN_LEVEL; | ||
96 | cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | | ||
97 | HPET_TN_SETVAL | HPET_TN_32BIT; | ||
98 | hpet_write(HPET_T0_CFG, cfg); | ||
99 | |||
100 | /* set the comparator */ | ||
101 | hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL); | ||
102 | udelay(1); | ||
103 | hpet_write(HPET_T0_CMP, HPET_COMPARE_VAL); | ||
104 | |||
105 | /* start counter */ | ||
106 | hpet_start_counter(); | ||
107 | break; | ||
108 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
109 | case CLOCK_EVT_MODE_UNUSED: | ||
110 | cfg = hpet_read(HPET_T0_CFG); | ||
111 | cfg &= ~HPET_TN_ENABLE; | ||
112 | hpet_write(HPET_T0_CFG, cfg); | ||
113 | break; | ||
114 | case CLOCK_EVT_MODE_ONESHOT: | ||
115 | pr_info("set clock event to one shot mode!\n"); | ||
116 | cfg = hpet_read(HPET_T0_CFG); | ||
117 | /* set timer0 type | ||
118 | * 1 : periodic interrupt | ||
119 | * 0 : non-periodic(oneshot) interrupt | ||
120 | */ | ||
121 | cfg &= ~HPET_TN_PERIODIC; | ||
122 | cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; | ||
123 | hpet_write(HPET_T0_CFG, cfg); | ||
124 | break; | ||
125 | case CLOCK_EVT_MODE_RESUME: | ||
126 | hpet_enable_legacy_int(); | ||
127 | break; | ||
128 | } | ||
129 | spin_unlock(&hpet_lock); | ||
130 | } | ||
131 | |||
132 | static int hpet_next_event(unsigned long delta, | ||
133 | struct clock_event_device *evt) | ||
134 | { | ||
135 | unsigned int cnt; | ||
136 | int res; | ||
137 | |||
138 | cnt = hpet_read(HPET_COUNTER); | ||
139 | cnt += delta; | ||
140 | hpet_write(HPET_T0_CMP, cnt); | ||
141 | |||
142 | res = ((int)(hpet_read(HPET_COUNTER) - cnt) > 0) ? -ETIME : 0; | ||
143 | return res; | ||
144 | } | ||
145 | |||
146 | static irqreturn_t hpet_irq_handler(int irq, void *data) | ||
147 | { | ||
148 | int is_irq; | ||
149 | struct clock_event_device *cd; | ||
150 | unsigned int cpu = smp_processor_id(); | ||
151 | |||
152 | is_irq = hpet_read(HPET_STATUS); | ||
153 | if (is_irq & HPET_T0_IRS) { | ||
154 | /* clear the TIMER0 irq status register */ | ||
155 | hpet_write(HPET_STATUS, HPET_T0_IRS); | ||
156 | cd = &per_cpu(hpet_clockevent_device, cpu); | ||
157 | cd->event_handler(cd); | ||
158 | return IRQ_HANDLED; | ||
159 | } | ||
160 | return IRQ_NONE; | ||
161 | } | ||
162 | |||
163 | static struct irqaction hpet_irq = { | ||
164 | .handler = hpet_irq_handler, | ||
165 | .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER, | ||
166 | .name = "hpet", | ||
167 | }; | ||
168 | |||
169 | /* | ||
170 | * hpet address assignation and irq setting should be done in bios. | ||
171 | * but pmon don't do this, we just setup here directly. | ||
172 | * The operation under is normal. unfortunately, hpet_setup process | ||
173 | * is before pci initialize. | ||
174 | * | ||
175 | * { | ||
176 | * struct pci_dev *pdev; | ||
177 | * | ||
178 | * pdev = pci_get_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL); | ||
179 | * pci_write_config_word(pdev, SMBUS_PCI_REGB4, HPET_ADDR); | ||
180 | * | ||
181 | * ... | ||
182 | * } | ||
183 | */ | ||
184 | static void hpet_setup(void) | ||
185 | { | ||
186 | /* set hpet base address */ | ||
187 | smbus_write(SMBUS_PCI_REGB4, HPET_ADDR); | ||
188 | |||
189 | /* enable decodeing of access to HPET MMIO*/ | ||
190 | smbus_enable(SMBUS_PCI_REG40, (1 << 28)); | ||
191 | |||
192 | /* HPET irq enable */ | ||
193 | smbus_enable(SMBUS_PCI_REG64, (1 << 10)); | ||
194 | |||
195 | hpet_enable_legacy_int(); | ||
196 | } | ||
197 | |||
198 | void __init setup_hpet_timer(void) | ||
199 | { | ||
200 | unsigned int cpu = smp_processor_id(); | ||
201 | struct clock_event_device *cd; | ||
202 | |||
203 | hpet_setup(); | ||
204 | |||
205 | cd = &per_cpu(hpet_clockevent_device, cpu); | ||
206 | cd->name = "hpet"; | ||
207 | cd->rating = 320; | ||
208 | cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | ||
209 | cd->set_mode = hpet_set_mode; | ||
210 | cd->set_next_event = hpet_next_event; | ||
211 | cd->irq = HPET_T0_IRQ; | ||
212 | cd->cpumask = cpumask_of(cpu); | ||
213 | clockevent_set_clock(cd, HPET_FREQ); | ||
214 | cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); | ||
215 | cd->min_delta_ns = 5000; | ||
216 | |||
217 | clockevents_register_device(cd); | ||
218 | setup_irq(HPET_T0_IRQ, &hpet_irq); | ||
219 | pr_info("hpet clock event device register\n"); | ||
220 | } | ||
221 | |||
222 | static cycle_t hpet_read_counter(struct clocksource *cs) | ||
223 | { | ||
224 | return (cycle_t)hpet_read(HPET_COUNTER); | ||
225 | } | ||
226 | |||
227 | static void hpet_suspend(struct clocksource *cs) | ||
228 | { | ||
229 | } | ||
230 | |||
231 | static void hpet_resume(struct clocksource *cs) | ||
232 | { | ||
233 | hpet_setup(); | ||
234 | hpet_restart_counter(); | ||
235 | } | ||
236 | |||
237 | static struct clocksource csrc_hpet = { | ||
238 | .name = "hpet", | ||
239 | /* mips clocksource rating is less than 300, so hpet is better. */ | ||
240 | .rating = 300, | ||
241 | .read = hpet_read_counter, | ||
242 | .mask = CLOCKSOURCE_MASK(32), | ||
243 | /* oneshot mode work normal with this flag */ | ||
244 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
245 | .suspend = hpet_suspend, | ||
246 | .resume = hpet_resume, | ||
247 | .mult = 0, | ||
248 | .shift = 10, | ||
249 | }; | ||
250 | |||
251 | int __init init_hpet_clocksource(void) | ||
252 | { | ||
253 | csrc_hpet.mult = clocksource_hz2mult(HPET_FREQ, csrc_hpet.shift); | ||
254 | return clocksource_register_hz(&csrc_hpet, HPET_FREQ); | ||
255 | } | ||
256 | |||
257 | arch_initcall(init_hpet_clocksource); | ||
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c index ca1c62af5188..21221edda7a9 100644 --- a/arch/mips/loongson/loongson-3/irq.c +++ b/arch/mips/loongson/loongson-3/irq.c | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | #include "smp.h" | 10 | #include "smp.h" |
11 | 11 | ||
12 | unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15}; | 12 | unsigned int ht_irq[] = {0, 1, 3, 4, 5, 6, 7, 8, 12, 14, 15}; |
13 | 13 | ||
14 | static void ht_irqdispatch(void) | 14 | static void ht_irqdispatch(void) |
15 | { | 15 | { |
@@ -55,8 +55,8 @@ static inline void mask_loongson_irq(struct irq_data *d) | |||
55 | /* Workaround: UART IRQ may deliver to any core */ | 55 | /* Workaround: UART IRQ may deliver to any core */ |
56 | if (d->irq == LOONGSON_UART_IRQ) { | 56 | if (d->irq == LOONGSON_UART_IRQ) { |
57 | int cpu = smp_processor_id(); | 57 | int cpu = smp_processor_id(); |
58 | int node_id = cpu / loongson_sysconf.cores_per_node; | 58 | int node_id = cpu_logical_map(cpu) / loongson_sysconf.cores_per_node; |
59 | int core_id = cpu % loongson_sysconf.cores_per_node; | 59 | int core_id = cpu_logical_map(cpu) % loongson_sysconf.cores_per_node; |
60 | u64 intenclr_addr = smp_group[node_id] | | 60 | u64 intenclr_addr = smp_group[node_id] | |
61 | (u64)(&LOONGSON_INT_ROUTER_INTENCLR); | 61 | (u64)(&LOONGSON_INT_ROUTER_INTENCLR); |
62 | u64 introuter_lpc_addr = smp_group[node_id] | | 62 | u64 introuter_lpc_addr = smp_group[node_id] | |
@@ -72,8 +72,8 @@ static inline void unmask_loongson_irq(struct irq_data *d) | |||
72 | /* Workaround: UART IRQ may deliver to any core */ | 72 | /* Workaround: UART IRQ may deliver to any core */ |
73 | if (d->irq == LOONGSON_UART_IRQ) { | 73 | if (d->irq == LOONGSON_UART_IRQ) { |
74 | int cpu = smp_processor_id(); | 74 | int cpu = smp_processor_id(); |
75 | int node_id = cpu / loongson_sysconf.cores_per_node; | 75 | int node_id = cpu_logical_map(cpu) / loongson_sysconf.cores_per_node; |
76 | int core_id = cpu % loongson_sysconf.cores_per_node; | 76 | int core_id = cpu_logical_map(cpu) % loongson_sysconf.cores_per_node; |
77 | u64 intenset_addr = smp_group[node_id] | | 77 | u64 intenset_addr = smp_group[node_id] | |
78 | (u64)(&LOONGSON_INT_ROUTER_INTENSET); | 78 | (u64)(&LOONGSON_INT_ROUTER_INTENSET); |
79 | u64 introuter_lpc_addr = smp_group[node_id] | | 79 | u64 introuter_lpc_addr = smp_group[node_id] | |
@@ -102,10 +102,12 @@ void irq_router_init(void) | |||
102 | int i; | 102 | int i; |
103 | 103 | ||
104 | /* route LPC int to cpu core0 int 0 */ | 104 | /* route LPC int to cpu core0 int 0 */ |
105 | LOONGSON_INT_ROUTER_LPC = LOONGSON_INT_CORE0_INT0; | 105 | LOONGSON_INT_ROUTER_LPC = |
106 | LOONGSON_INT_COREx_INTy(loongson_sysconf.boot_cpu_id, 0); | ||
106 | /* route HT1 int0 ~ int7 to cpu core0 INT1*/ | 107 | /* route HT1 int0 ~ int7 to cpu core0 INT1*/ |
107 | for (i = 0; i < 8; i++) | 108 | for (i = 0; i < 8; i++) |
108 | LOONGSON_INT_ROUTER_HT1(i) = LOONGSON_INT_CORE0_INT1; | 109 | LOONGSON_INT_ROUTER_HT1(i) = |
110 | LOONGSON_INT_COREx_INTy(loongson_sysconf.boot_cpu_id, 1); | ||
109 | /* enable HT1 interrupt */ | 111 | /* enable HT1 interrupt */ |
110 | LOONGSON_HT1_INTN_EN(0) = 0xffffffff; | 112 | LOONGSON_HT1_INTN_EN(0) = 0xffffffff; |
111 | /* enable router interrupt intenset */ | 113 | /* enable router interrupt intenset */ |
diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson/loongson-3/numa.c index 42323bcc5d28..6cae0e75de27 100644 --- a/arch/mips/loongson/loongson-3/numa.c +++ b/arch/mips/loongson/loongson-3/numa.c | |||
@@ -224,7 +224,7 @@ static void __init node_mem_init(unsigned int node) | |||
224 | 224 | ||
225 | static __init void prom_meminit(void) | 225 | static __init void prom_meminit(void) |
226 | { | 226 | { |
227 | unsigned int node, cpu; | 227 | unsigned int node, cpu, active_cpu = 0; |
228 | 228 | ||
229 | cpu_node_probe(); | 229 | cpu_node_probe(); |
230 | init_topology_matrix(); | 230 | init_topology_matrix(); |
@@ -240,8 +240,14 @@ static __init void prom_meminit(void) | |||
240 | node = cpu / loongson_sysconf.cores_per_node; | 240 | node = cpu / loongson_sysconf.cores_per_node; |
241 | if (node >= num_online_nodes()) | 241 | if (node >= num_online_nodes()) |
242 | node = 0; | 242 | node = 0; |
243 | pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node); | 243 | |
244 | cpu_set(cpu, __node_data[(node)]->cpumask); | 244 | if (loongson_sysconf.reserved_cpus_mask & (1<<cpu)) |
245 | continue; | ||
246 | |||
247 | cpu_set(active_cpu, __node_data[(node)]->cpumask); | ||
248 | pr_info("NUMA: set cpumask cpu %d on node %d\n", active_cpu, node); | ||
249 | |||
250 | active_cpu++; | ||
245 | } | 251 | } |
246 | } | 252 | } |
247 | 253 | ||
diff --git a/arch/mips/loongson/loongson-3/platform.c b/arch/mips/loongson/loongson-3/platform.c new file mode 100644 index 000000000000..25a97cc0ee33 --- /dev/null +++ b/arch/mips/loongson/loongson-3/platform.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Lemote Inc. | ||
3 | * Author: Wu Zhangjin, wuzhangjin@gmail.com | ||
4 | * Xiang Yu, xiangy@lemote.com | ||
5 | * Chen Huacai, chenhc@lemote.com | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/err.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <asm/bootinfo.h> | ||
17 | #include <boot_param.h> | ||
18 | #include <loongson_hwmon.h> | ||
19 | #include <workarounds.h> | ||
20 | |||
21 | static int __init loongson3_platform_init(void) | ||
22 | { | ||
23 | int i; | ||
24 | struct platform_device *pdev; | ||
25 | |||
26 | if (loongson_sysconf.ecname[0] != '\0') | ||
27 | platform_device_register_simple(loongson_sysconf.ecname, -1, NULL, 0); | ||
28 | |||
29 | for (i = 0; i < loongson_sysconf.nr_sensors; i++) { | ||
30 | if (loongson_sysconf.sensors[i].type > SENSOR_FAN) | ||
31 | continue; | ||
32 | |||
33 | pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); | ||
34 | pdev->name = loongson_sysconf.sensors[i].name; | ||
35 | pdev->id = loongson_sysconf.sensors[i].id; | ||
36 | pdev->dev.platform_data = &loongson_sysconf.sensors[i]; | ||
37 | platform_device_register(pdev); | ||
38 | } | ||
39 | |||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | arch_initcall(loongson3_platform_init); | ||
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c index d8c63af6c7cc..e2eb688b5434 100644 --- a/arch/mips/loongson/loongson-3/smp.c +++ b/arch/mips/loongson/loongson-3/smp.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/tlbflush.h> | 25 | #include <asm/tlbflush.h> |
26 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
27 | #include <loongson.h> | 27 | #include <loongson.h> |
28 | #include <workarounds.h> | ||
28 | 29 | ||
29 | #include "smp.h" | 30 | #include "smp.h" |
30 | 31 | ||
@@ -239,7 +240,7 @@ static void ipi_mailbox_buf_init(void) | |||
239 | */ | 240 | */ |
240 | static void loongson3_send_ipi_single(int cpu, unsigned int action) | 241 | static void loongson3_send_ipi_single(int cpu, unsigned int action) |
241 | { | 242 | { |
242 | loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]); | 243 | loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu_logical_map(cpu)]); |
243 | } | 244 | } |
244 | 245 | ||
245 | static void | 246 | static void |
@@ -248,7 +249,7 @@ loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action) | |||
248 | unsigned int i; | 249 | unsigned int i; |
249 | 250 | ||
250 | for_each_cpu(i, mask) | 251 | for_each_cpu(i, mask) |
251 | loongson3_ipi_write32((u32)action, ipi_set0_regs[i]); | 252 | loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu_logical_map(i)]); |
252 | } | 253 | } |
253 | 254 | ||
254 | void loongson3_ipi_interrupt(struct pt_regs *regs) | 255 | void loongson3_ipi_interrupt(struct pt_regs *regs) |
@@ -257,10 +258,10 @@ void loongson3_ipi_interrupt(struct pt_regs *regs) | |||
257 | unsigned int action, c0count; | 258 | unsigned int action, c0count; |
258 | 259 | ||
259 | /* Load the ipi register to figure out what we're supposed to do */ | 260 | /* Load the ipi register to figure out what we're supposed to do */ |
260 | action = loongson3_ipi_read32(ipi_status0_regs[cpu]); | 261 | action = loongson3_ipi_read32(ipi_status0_regs[cpu_logical_map(cpu)]); |
261 | 262 | ||
262 | /* Clear the ipi register to clear the interrupt */ | 263 | /* Clear the ipi register to clear the interrupt */ |
263 | loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu]); | 264 | loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu_logical_map(cpu)]); |
264 | 265 | ||
265 | if (action & SMP_RESCHEDULE_YOURSELF) | 266 | if (action & SMP_RESCHEDULE_YOURSELF) |
266 | scheduler_ipi(); | 267 | scheduler_ipi(); |
@@ -291,12 +292,14 @@ static void loongson3_init_secondary(void) | |||
291 | /* Set interrupt mask, but don't enable */ | 292 | /* Set interrupt mask, but don't enable */ |
292 | change_c0_status(ST0_IM, imask); | 293 | change_c0_status(ST0_IM, imask); |
293 | 294 | ||
294 | for (i = 0; i < loongson_sysconf.nr_cpus; i++) | 295 | for (i = 0; i < num_possible_cpus(); i++) |
295 | loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]); | 296 | loongson3_ipi_write32(0xffffffff, ipi_en0_regs[cpu_logical_map(i)]); |
296 | 297 | ||
297 | cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package; | ||
298 | cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package; | ||
299 | per_cpu(cpu_state, cpu) = CPU_ONLINE; | 298 | per_cpu(cpu_state, cpu) = CPU_ONLINE; |
299 | cpu_data[cpu].core = | ||
300 | cpu_logical_map(cpu) % loongson_sysconf.cores_per_package; | ||
301 | cpu_data[cpu].package = | ||
302 | cpu_logical_map(cpu) / loongson_sysconf.cores_per_package; | ||
300 | 303 | ||
301 | i = 0; | 304 | i = 0; |
302 | __this_cpu_write(core0_c0count, 0); | 305 | __this_cpu_write(core0_c0count, 0); |
@@ -314,37 +317,50 @@ static void loongson3_init_secondary(void) | |||
314 | 317 | ||
315 | static void loongson3_smp_finish(void) | 318 | static void loongson3_smp_finish(void) |
316 | { | 319 | { |
320 | int cpu = smp_processor_id(); | ||
321 | |||
317 | write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); | 322 | write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); |
318 | local_irq_enable(); | 323 | local_irq_enable(); |
319 | loongson3_ipi_write64(0, | 324 | loongson3_ipi_write64(0, |
320 | (void *)(ipi_mailbox_buf[smp_processor_id()]+0x0)); | 325 | (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0)); |
321 | pr_info("CPU#%d finished, CP0_ST=%x\n", | 326 | pr_info("CPU#%d finished, CP0_ST=%x\n", |
322 | smp_processor_id(), read_c0_status()); | 327 | smp_processor_id(), read_c0_status()); |
323 | } | 328 | } |
324 | 329 | ||
325 | static void __init loongson3_smp_setup(void) | 330 | static void __init loongson3_smp_setup(void) |
326 | { | 331 | { |
327 | int i, num; | 332 | int i = 0, num = 0; /* i: physical id, num: logical id */ |
328 | 333 | ||
329 | init_cpu_possible(cpu_none_mask); | 334 | init_cpu_possible(cpu_none_mask); |
330 | set_cpu_possible(0, true); | ||
331 | |||
332 | __cpu_number_map[0] = 0; | ||
333 | __cpu_logical_map[0] = 0; | ||
334 | 335 | ||
335 | /* For unified kernel, NR_CPUS is the maximum possible value, | 336 | /* For unified kernel, NR_CPUS is the maximum possible value, |
336 | * loongson_sysconf.nr_cpus is the really present value */ | 337 | * loongson_sysconf.nr_cpus is the really present value */ |
337 | for (i = 1, num = 0; i < loongson_sysconf.nr_cpus; i++) { | 338 | while (i < loongson_sysconf.nr_cpus) { |
338 | set_cpu_possible(i, true); | 339 | if (loongson_sysconf.reserved_cpus_mask & (1<<i)) { |
339 | __cpu_number_map[i] = ++num; | 340 | /* Reserved physical CPU cores */ |
340 | __cpu_logical_map[num] = i; | 341 | __cpu_number_map[i] = -1; |
342 | } else { | ||
343 | __cpu_number_map[i] = num; | ||
344 | __cpu_logical_map[num] = i; | ||
345 | set_cpu_possible(num, true); | ||
346 | num++; | ||
347 | } | ||
348 | i++; | ||
341 | } | 349 | } |
350 | pr_info("Detected %i available CPU(s)\n", num); | ||
351 | |||
352 | while (num < loongson_sysconf.nr_cpus) { | ||
353 | __cpu_logical_map[num] = -1; | ||
354 | num++; | ||
355 | } | ||
356 | |||
342 | ipi_set0_regs_init(); | 357 | ipi_set0_regs_init(); |
343 | ipi_clear0_regs_init(); | 358 | ipi_clear0_regs_init(); |
344 | ipi_status0_regs_init(); | 359 | ipi_status0_regs_init(); |
345 | ipi_en0_regs_init(); | 360 | ipi_en0_regs_init(); |
346 | ipi_mailbox_buf_init(); | 361 | ipi_mailbox_buf_init(); |
347 | pr_info("Detected %i available secondary CPU(s)\n", num); | 362 | cpu_data[0].core = cpu_logical_map(0) % loongson_sysconf.cores_per_package; |
363 | cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package; | ||
348 | } | 364 | } |
349 | 365 | ||
350 | static void __init loongson3_prepare_cpus(unsigned int max_cpus) | 366 | static void __init loongson3_prepare_cpus(unsigned int max_cpus) |
@@ -371,10 +387,14 @@ static void loongson3_boot_secondary(int cpu, struct task_struct *idle) | |||
371 | pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n", | 387 | pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n", |
372 | cpu, startargs[0], startargs[1], startargs[2]); | 388 | cpu, startargs[0], startargs[1], startargs[2]); |
373 | 389 | ||
374 | loongson3_ipi_write64(startargs[3], (void *)(ipi_mailbox_buf[cpu]+0x18)); | 390 | loongson3_ipi_write64(startargs[3], |
375 | loongson3_ipi_write64(startargs[2], (void *)(ipi_mailbox_buf[cpu]+0x10)); | 391 | (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x18)); |
376 | loongson3_ipi_write64(startargs[1], (void *)(ipi_mailbox_buf[cpu]+0x8)); | 392 | loongson3_ipi_write64(startargs[2], |
377 | loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0)); | 393 | (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x10)); |
394 | loongson3_ipi_write64(startargs[1], | ||
395 | (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x8)); | ||
396 | loongson3_ipi_write64(startargs[0], | ||
397 | (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0)); | ||
378 | } | 398 | } |
379 | 399 | ||
380 | #ifdef CONFIG_HOTPLUG_CPU | 400 | #ifdef CONFIG_HOTPLUG_CPU |
@@ -568,7 +588,7 @@ void loongson3_disable_clock(int cpu) | |||
568 | if (loongson_sysconf.cputype == Loongson_3A) { | 588 | if (loongson_sysconf.cputype == Loongson_3A) { |
569 | LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); | 589 | LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); |
570 | } else if (loongson_sysconf.cputype == Loongson_3B) { | 590 | } else if (loongson_sysconf.cputype == Loongson_3B) { |
571 | if (!cpuhotplug_workaround) | 591 | if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG)) |
572 | LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3)); | 592 | LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3)); |
573 | } | 593 | } |
574 | } | 594 | } |
@@ -581,7 +601,7 @@ void loongson3_enable_clock(int cpu) | |||
581 | if (loongson_sysconf.cputype == Loongson_3A) { | 601 | if (loongson_sysconf.cputype == Loongson_3A) { |
582 | LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); | 602 | LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); |
583 | } else if (loongson_sysconf.cputype == Loongson_3B) { | 603 | } else if (loongson_sysconf.cputype == Loongson_3B) { |
584 | if (!cpuhotplug_workaround) | 604 | if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG)) |
585 | LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3); | 605 | LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3); |
586 | } | 606 | } |
587 | } | 607 | } |
diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig index e23c25d09963..a2b796eaf3c3 100644 --- a/arch/mips/loongson1/Kconfig +++ b/arch/mips/loongson1/Kconfig | |||
@@ -5,8 +5,8 @@ choice | |||
5 | 5 | ||
6 | config LOONGSON1_LS1B | 6 | config LOONGSON1_LS1B |
7 | bool "Loongson LS1B board" | 7 | bool "Loongson LS1B board" |
8 | select CEVT_R4K | 8 | select CEVT_R4K if !MIPS_EXTERNAL_TIMER |
9 | select CSRC_R4K | 9 | select CSRC_R4K if !MIPS_EXTERNAL_TIMER |
10 | select SYS_HAS_CPU_LOONGSON1B | 10 | select SYS_HAS_CPU_LOONGSON1B |
11 | select DMA_NONCOHERENT | 11 | select DMA_NONCOHERENT |
12 | select BOOT_ELF32 | 12 | select BOOT_ELF32 |
@@ -16,8 +16,46 @@ config LOONGSON1_LS1B | |||
16 | select SYS_SUPPORTS_HIGHMEM | 16 | select SYS_SUPPORTS_HIGHMEM |
17 | select SYS_SUPPORTS_MIPS16 | 17 | select SYS_SUPPORTS_MIPS16 |
18 | select SYS_HAS_EARLY_PRINTK | 18 | select SYS_HAS_EARLY_PRINTK |
19 | select USE_GENERIC_EARLY_PRINTK_8250 | ||
19 | select COMMON_CLK | 20 | select COMMON_CLK |
20 | 21 | ||
21 | endchoice | 22 | endchoice |
22 | 23 | ||
24 | menuconfig CEVT_CSRC_LS1X | ||
25 | bool "Use PWM Timer for clockevent/clocksource" | ||
26 | select MIPS_EXTERNAL_TIMER | ||
27 | depends on CPU_LOONGSON1 | ||
28 | help | ||
29 | This option changes the default clockevent/clocksource to PWM Timer, | ||
30 | and is required by Loongson1 CPUFreq support. | ||
31 | |||
32 | If unsure, say N. | ||
33 | |||
34 | choice | ||
35 | prompt "Select clockevent/clocksource" | ||
36 | depends on CEVT_CSRC_LS1X | ||
37 | default TIMER_USE_PWM0 | ||
38 | |||
39 | config TIMER_USE_PWM0 | ||
40 | bool "Use PWM Timer 0" | ||
41 | help | ||
42 | Use PWM Timer 0 as the default clockevent/clocksourcer. | ||
43 | |||
44 | config TIMER_USE_PWM1 | ||
45 | bool "Use PWM Timer 1" | ||
46 | help | ||
47 | Use PWM Timer 1 as the default clockevent/clocksourcer. | ||
48 | |||
49 | config TIMER_USE_PWM2 | ||
50 | bool "Use PWM Timer 2" | ||
51 | help | ||
52 | Use PWM Timer 2 as the default clockevent/clocksourcer. | ||
53 | |||
54 | config TIMER_USE_PWM3 | ||
55 | bool "Use PWM Timer 3" | ||
56 | help | ||
57 | Use PWM Timer 3 as the default clockevent/clocksourcer. | ||
58 | |||
59 | endchoice | ||
60 | |||
23 | endif # MACH_LOONGSON1 | 61 | endif # MACH_LOONGSON1 |
diff --git a/arch/mips/loongson1/common/Makefile b/arch/mips/loongson1/common/Makefile index b2797709ef5b..723b4ce3b8f0 100644 --- a/arch/mips/loongson1/common/Makefile +++ b/arch/mips/loongson1/common/Makefile | |||
@@ -2,4 +2,4 @@ | |||
2 | # Makefile for common code of loongson1 based machines. | 2 | # Makefile for common code of loongson1 based machines. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += clock.o irq.o platform.o prom.o reset.o setup.o | 5 | obj-y += time.o irq.o platform.o prom.o reset.o setup.o |
diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c deleted file mode 100644 index b4437f19c3d9..000000000000 --- a/arch/mips/loongson1/common/clock.c +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/clk.h> | ||
11 | #include <linux/err.h> | ||
12 | #include <asm/time.h> | ||
13 | #include <platform.h> | ||
14 | |||
15 | void __init plat_time_init(void) | ||
16 | { | ||
17 | struct clk *clk; | ||
18 | |||
19 | /* Initialize LS1X clocks */ | ||
20 | ls1x_clk_init(); | ||
21 | |||
22 | /* setup mips r4k timer */ | ||
23 | clk = clk_get(NULL, "cpu"); | ||
24 | if (IS_ERR(clk)) | ||
25 | panic("unable to get cpu clock, err=%ld", PTR_ERR(clk)); | ||
26 | |||
27 | mips_hpt_frequency = clk_get_rate(clk) / 2; | ||
28 | } | ||
diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson1/common/platform.c index fdf8cb5987a4..ddf1d4cbf31e 100644 --- a/arch/mips/loongson1/common/platform.c +++ b/arch/mips/loongson1/common/platform.c | |||
@@ -16,8 +16,10 @@ | |||
16 | #include <linux/usb/ehci_pdriver.h> | 16 | #include <linux/usb/ehci_pdriver.h> |
17 | #include <asm-generic/sizes.h> | 17 | #include <asm-generic/sizes.h> |
18 | 18 | ||
19 | #include <cpufreq.h> | ||
19 | #include <loongson1.h> | 20 | #include <loongson1.h> |
20 | 21 | ||
22 | /* 8250/16550 compatible UART */ | ||
21 | #define LS1X_UART(_id) \ | 23 | #define LS1X_UART(_id) \ |
22 | { \ | 24 | { \ |
23 | .mapbase = LS1X_UART ## _id ## _BASE, \ | 25 | .mapbase = LS1X_UART ## _id ## _BASE, \ |
@@ -27,7 +29,7 @@ | |||
27 | .type = PORT_16550A, \ | 29 | .type = PORT_16550A, \ |
28 | } | 30 | } |
29 | 31 | ||
30 | static struct plat_serial8250_port ls1x_serial8250_port[] = { | 32 | static struct plat_serial8250_port ls1x_serial8250_pdata[] = { |
31 | LS1X_UART(0), | 33 | LS1X_UART(0), |
32 | LS1X_UART(1), | 34 | LS1X_UART(1), |
33 | LS1X_UART(2), | 35 | LS1X_UART(2), |
@@ -35,11 +37,11 @@ static struct plat_serial8250_port ls1x_serial8250_port[] = { | |||
35 | {}, | 37 | {}, |
36 | }; | 38 | }; |
37 | 39 | ||
38 | struct platform_device ls1x_uart_device = { | 40 | struct platform_device ls1x_uart_pdev = { |
39 | .name = "serial8250", | 41 | .name = "serial8250", |
40 | .id = PLAT8250_DEV_PLATFORM, | 42 | .id = PLAT8250_DEV_PLATFORM, |
41 | .dev = { | 43 | .dev = { |
42 | .platform_data = ls1x_serial8250_port, | 44 | .platform_data = ls1x_serial8250_pdata, |
43 | }, | 45 | }, |
44 | }; | 46 | }; |
45 | 47 | ||
@@ -48,16 +50,97 @@ void __init ls1x_serial_setup(struct platform_device *pdev) | |||
48 | struct clk *clk; | 50 | struct clk *clk; |
49 | struct plat_serial8250_port *p; | 51 | struct plat_serial8250_port *p; |
50 | 52 | ||
51 | clk = clk_get(NULL, pdev->name); | 53 | clk = clk_get(&pdev->dev, pdev->name); |
52 | if (IS_ERR(clk)) | 54 | if (IS_ERR(clk)) { |
53 | panic("unable to get %s clock, err=%ld", | 55 | pr_err("unable to get %s clock, err=%ld", |
54 | pdev->name, PTR_ERR(clk)); | 56 | pdev->name, PTR_ERR(clk)); |
57 | return; | ||
58 | } | ||
59 | clk_prepare_enable(clk); | ||
55 | 60 | ||
56 | for (p = pdev->dev.platform_data; p->flags != 0; ++p) | 61 | for (p = pdev->dev.platform_data; p->flags != 0; ++p) |
57 | p->uartclk = clk_get_rate(clk); | 62 | p->uartclk = clk_get_rate(clk); |
58 | } | 63 | } |
59 | 64 | ||
65 | /* CPUFreq */ | ||
66 | static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = { | ||
67 | .clk_name = "cpu_clk", | ||
68 | .osc_clk_name = "osc_33m_clk", | ||
69 | .max_freq = 266 * 1000, | ||
70 | .min_freq = 33 * 1000, | ||
71 | }; | ||
72 | |||
73 | struct platform_device ls1x_cpufreq_pdev = { | ||
74 | .name = "ls1x-cpufreq", | ||
75 | .dev = { | ||
76 | .platform_data = &ls1x_cpufreq_pdata, | ||
77 | }, | ||
78 | }; | ||
79 | |||
60 | /* Synopsys Ethernet GMAC */ | 80 | /* Synopsys Ethernet GMAC */ |
81 | static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { | ||
82 | .phy_mask = 0, | ||
83 | }; | ||
84 | |||
85 | static struct stmmac_dma_cfg ls1x_eth_dma_cfg = { | ||
86 | .pbl = 1, | ||
87 | }; | ||
88 | |||
89 | int ls1x_eth_mux_init(struct platform_device *pdev, void *priv) | ||
90 | { | ||
91 | struct plat_stmmacenet_data *plat_dat = NULL; | ||
92 | u32 val; | ||
93 | |||
94 | val = __raw_readl(LS1X_MUX_CTRL1); | ||
95 | |||
96 | plat_dat = dev_get_platdata(&pdev->dev); | ||
97 | if (plat_dat->bus_id) { | ||
98 | __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 | | ||
99 | GMAC1_USE_UART0, LS1X_MUX_CTRL0); | ||
100 | switch (plat_dat->interface) { | ||
101 | case PHY_INTERFACE_MODE_RGMII: | ||
102 | val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23); | ||
103 | break; | ||
104 | case PHY_INTERFACE_MODE_MII: | ||
105 | val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23); | ||
106 | break; | ||
107 | default: | ||
108 | pr_err("unsupported mii mode %d\n", | ||
109 | plat_dat->interface); | ||
110 | return -ENOTSUPP; | ||
111 | } | ||
112 | val &= ~GMAC1_SHUT; | ||
113 | } else { | ||
114 | switch (plat_dat->interface) { | ||
115 | case PHY_INTERFACE_MODE_RGMII: | ||
116 | val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01); | ||
117 | break; | ||
118 | case PHY_INTERFACE_MODE_MII: | ||
119 | val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01); | ||
120 | break; | ||
121 | default: | ||
122 | pr_err("unsupported mii mode %d\n", | ||
123 | plat_dat->interface); | ||
124 | return -ENOTSUPP; | ||
125 | } | ||
126 | val &= ~GMAC0_SHUT; | ||
127 | } | ||
128 | __raw_writel(val, LS1X_MUX_CTRL1); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static struct plat_stmmacenet_data ls1x_eth0_pdata = { | ||
134 | .bus_id = 0, | ||
135 | .phy_addr = -1, | ||
136 | .interface = PHY_INTERFACE_MODE_MII, | ||
137 | .mdio_bus_data = &ls1x_mdio_bus_data, | ||
138 | .dma_cfg = &ls1x_eth_dma_cfg, | ||
139 | .has_gmac = 1, | ||
140 | .tx_coe = 1, | ||
141 | .init = ls1x_eth_mux_init, | ||
142 | }; | ||
143 | |||
61 | static struct resource ls1x_eth0_resources[] = { | 144 | static struct resource ls1x_eth0_resources[] = { |
62 | [0] = { | 145 | [0] = { |
63 | .start = LS1X_GMAC0_BASE, | 146 | .start = LS1X_GMAC0_BASE, |
@@ -71,25 +154,47 @@ static struct resource ls1x_eth0_resources[] = { | |||
71 | }, | 154 | }, |
72 | }; | 155 | }; |
73 | 156 | ||
74 | static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { | 157 | struct platform_device ls1x_eth0_pdev = { |
75 | .phy_mask = 0, | 158 | .name = "stmmaceth", |
159 | .id = 0, | ||
160 | .num_resources = ARRAY_SIZE(ls1x_eth0_resources), | ||
161 | .resource = ls1x_eth0_resources, | ||
162 | .dev = { | ||
163 | .platform_data = &ls1x_eth0_pdata, | ||
164 | }, | ||
76 | }; | 165 | }; |
77 | 166 | ||
78 | static struct plat_stmmacenet_data ls1x_eth_data = { | 167 | static struct plat_stmmacenet_data ls1x_eth1_pdata = { |
79 | .bus_id = 0, | 168 | .bus_id = 1, |
80 | .phy_addr = -1, | 169 | .phy_addr = -1, |
170 | .interface = PHY_INTERFACE_MODE_MII, | ||
81 | .mdio_bus_data = &ls1x_mdio_bus_data, | 171 | .mdio_bus_data = &ls1x_mdio_bus_data, |
172 | .dma_cfg = &ls1x_eth_dma_cfg, | ||
82 | .has_gmac = 1, | 173 | .has_gmac = 1, |
83 | .tx_coe = 1, | 174 | .tx_coe = 1, |
175 | .init = ls1x_eth_mux_init, | ||
84 | }; | 176 | }; |
85 | 177 | ||
86 | struct platform_device ls1x_eth0_device = { | 178 | static struct resource ls1x_eth1_resources[] = { |
179 | [0] = { | ||
180 | .start = LS1X_GMAC1_BASE, | ||
181 | .end = LS1X_GMAC1_BASE + SZ_64K - 1, | ||
182 | .flags = IORESOURCE_MEM, | ||
183 | }, | ||
184 | [1] = { | ||
185 | .name = "macirq", | ||
186 | .start = LS1X_GMAC1_IRQ, | ||
187 | .flags = IORESOURCE_IRQ, | ||
188 | }, | ||
189 | }; | ||
190 | |||
191 | struct platform_device ls1x_eth1_pdev = { | ||
87 | .name = "stmmaceth", | 192 | .name = "stmmaceth", |
88 | .id = 0, | 193 | .id = 1, |
89 | .num_resources = ARRAY_SIZE(ls1x_eth0_resources), | 194 | .num_resources = ARRAY_SIZE(ls1x_eth1_resources), |
90 | .resource = ls1x_eth0_resources, | 195 | .resource = ls1x_eth1_resources, |
91 | .dev = { | 196 | .dev = { |
92 | .platform_data = &ls1x_eth_data, | 197 | .platform_data = &ls1x_eth1_pdata, |
93 | }, | 198 | }, |
94 | }; | 199 | }; |
95 | 200 | ||
@@ -111,7 +216,7 @@ static struct resource ls1x_ehci_resources[] = { | |||
111 | static struct usb_ehci_pdata ls1x_ehci_pdata = { | 216 | static struct usb_ehci_pdata ls1x_ehci_pdata = { |
112 | }; | 217 | }; |
113 | 218 | ||
114 | struct platform_device ls1x_ehci_device = { | 219 | struct platform_device ls1x_ehci_pdev = { |
115 | .name = "ehci-platform", | 220 | .name = "ehci-platform", |
116 | .id = -1, | 221 | .id = -1, |
117 | .num_resources = ARRAY_SIZE(ls1x_ehci_resources), | 222 | .num_resources = ARRAY_SIZE(ls1x_ehci_resources), |
@@ -123,7 +228,7 @@ struct platform_device ls1x_ehci_device = { | |||
123 | }; | 228 | }; |
124 | 229 | ||
125 | /* Real Time Clock */ | 230 | /* Real Time Clock */ |
126 | struct platform_device ls1x_rtc_device = { | 231 | struct platform_device ls1x_rtc_pdev = { |
127 | .name = "ls1x-rtc", | 232 | .name = "ls1x-rtc", |
128 | .id = -1, | 233 | .id = -1, |
129 | }; | 234 | }; |
diff --git a/arch/mips/loongson1/common/prom.c b/arch/mips/loongson1/common/prom.c index 2a47af5a55c3..68600980ea49 100644 --- a/arch/mips/loongson1/common/prom.c +++ b/arch/mips/loongson1/common/prom.c | |||
@@ -27,7 +27,7 @@ char *prom_getenv(char *envname) | |||
27 | i = strlen(envname); | 27 | i = strlen(envname); |
28 | 28 | ||
29 | while (*env) { | 29 | while (*env) { |
30 | if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=') | 30 | if (strncmp(envname, *env, i) == 0 && *(*env + i) == '=') |
31 | return *env + i + 1; | 31 | return *env + i + 1; |
32 | env++; | 32 | env++; |
33 | } | 33 | } |
@@ -49,7 +49,7 @@ void __init prom_init_cmdline(void) | |||
49 | for (i = 1; i < prom_argc; i++) { | 49 | for (i = 1; i < prom_argc; i++) { |
50 | strcpy(c, prom_argv[i]); | 50 | strcpy(c, prom_argv[i]); |
51 | c += strlen(prom_argv[i]); | 51 | c += strlen(prom_argv[i]); |
52 | if (i < prom_argc-1) | 52 | if (i < prom_argc - 1) |
53 | *c++ = ' '; | 53 | *c++ = ' '; |
54 | } | 54 | } |
55 | *c = 0; | 55 | *c = 0; |
@@ -57,6 +57,7 @@ void __init prom_init_cmdline(void) | |||
57 | 57 | ||
58 | void __init prom_init(void) | 58 | void __init prom_init(void) |
59 | { | 59 | { |
60 | void __iomem *uart_base; | ||
60 | prom_argc = fw_arg0; | 61 | prom_argc = fw_arg0; |
61 | prom_argv = (char **)fw_arg1; | 62 | prom_argv = (char **)fw_arg1; |
62 | prom_envp = (char **)fw_arg2; | 63 | prom_envp = (char **)fw_arg2; |
@@ -65,23 +66,18 @@ void __init prom_init(void) | |||
65 | 66 | ||
66 | memsize = env_or_default("memsize", DEFAULT_MEMSIZE); | 67 | memsize = env_or_default("memsize", DEFAULT_MEMSIZE); |
67 | highmemsize = env_or_default("highmemsize", 0x0); | 68 | highmemsize = env_or_default("highmemsize", 0x0); |
68 | } | ||
69 | 69 | ||
70 | void __init prom_free_prom_memory(void) | 70 | if (strstr(arcs_cmdline, "console=ttyS3")) |
71 | { | 71 | uart_base = ioremap_nocache(LS1X_UART3_BASE, 0x0f); |
72 | else if (strstr(arcs_cmdline, "console=ttyS2")) | ||
73 | uart_base = ioremap_nocache(LS1X_UART2_BASE, 0x0f); | ||
74 | else if (strstr(arcs_cmdline, "console=ttyS1")) | ||
75 | uart_base = ioremap_nocache(LS1X_UART1_BASE, 0x0f); | ||
76 | else | ||
77 | uart_base = ioremap_nocache(LS1X_UART0_BASE, 0x0f); | ||
78 | setup_8250_early_printk_port((unsigned long)uart_base, 0, 0); | ||
72 | } | 79 | } |
73 | 80 | ||
74 | #define PORT(offset) (u8 *)(KSEG1ADDR(LS1X_UART0_BASE + offset)) | 81 | void __init prom_free_prom_memory(void) |
75 | |||
76 | void prom_putchar(char c) | ||
77 | { | 82 | { |
78 | int timeout; | ||
79 | |||
80 | timeout = 1024; | ||
81 | |||
82 | while (((readb(PORT(UART_LSR)) & UART_LSR_THRE) == 0) | ||
83 | && (timeout-- > 0)) | ||
84 | ; | ||
85 | |||
86 | writeb(c, PORT(UART_TX)); | ||
87 | } | 83 | } |
diff --git a/arch/mips/loongson1/common/reset.c b/arch/mips/loongson1/common/reset.c index 547f34b69e4c..c41e4ca56ab4 100644 --- a/arch/mips/loongson1/common/reset.c +++ b/arch/mips/loongson1/common/reset.c | |||
@@ -14,12 +14,7 @@ | |||
14 | 14 | ||
15 | #include <loongson1.h> | 15 | #include <loongson1.h> |
16 | 16 | ||
17 | static void ls1x_restart(char *command) | 17 | static void __iomem *wdt_base; |
18 | { | ||
19 | __raw_writel(0x1, LS1X_WDT_EN); | ||
20 | __raw_writel(0x5000000, LS1X_WDT_TIMER); | ||
21 | __raw_writel(0x1, LS1X_WDT_SET); | ||
22 | } | ||
23 | 18 | ||
24 | static void ls1x_halt(void) | 19 | static void ls1x_halt(void) |
25 | { | 20 | { |
@@ -29,6 +24,15 @@ static void ls1x_halt(void) | |||
29 | } | 24 | } |
30 | } | 25 | } |
31 | 26 | ||
27 | static void ls1x_restart(char *command) | ||
28 | { | ||
29 | __raw_writel(0x1, wdt_base + WDT_EN); | ||
30 | __raw_writel(0x1, wdt_base + WDT_TIMER); | ||
31 | __raw_writel(0x1, wdt_base + WDT_SET); | ||
32 | |||
33 | ls1x_halt(); | ||
34 | } | ||
35 | |||
32 | static void ls1x_power_off(void) | 36 | static void ls1x_power_off(void) |
33 | { | 37 | { |
34 | ls1x_halt(); | 38 | ls1x_halt(); |
@@ -36,6 +40,10 @@ static void ls1x_power_off(void) | |||
36 | 40 | ||
37 | static int __init ls1x_reboot_setup(void) | 41 | static int __init ls1x_reboot_setup(void) |
38 | { | 42 | { |
43 | wdt_base = ioremap_nocache(LS1X_WDT_BASE, 0x0f); | ||
44 | if (!wdt_base) | ||
45 | panic("Failed to remap watchdog registers"); | ||
46 | |||
39 | _machine_restart = ls1x_restart; | 47 | _machine_restart = ls1x_restart; |
40 | _machine_halt = ls1x_halt; | 48 | _machine_halt = ls1x_halt; |
41 | pm_power_off = ls1x_power_off; | 49 | pm_power_off = ls1x_power_off; |
diff --git a/arch/mips/loongson1/common/time.c b/arch/mips/loongson1/common/time.c new file mode 100644 index 000000000000..df0f850d6a5f --- /dev/null +++ b/arch/mips/loongson1/common/time.c | |||
@@ -0,0 +1,226 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/clk.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <asm/time.h> | ||
13 | |||
14 | #include <loongson1.h> | ||
15 | #include <platform.h> | ||
16 | |||
17 | #ifdef CONFIG_CEVT_CSRC_LS1X | ||
18 | |||
19 | #if defined(CONFIG_TIMER_USE_PWM1) | ||
20 | #define LS1X_TIMER_BASE LS1X_PWM1_BASE | ||
21 | #define LS1X_TIMER_IRQ LS1X_PWM1_IRQ | ||
22 | |||
23 | #elif defined(CONFIG_TIMER_USE_PWM2) | ||
24 | #define LS1X_TIMER_BASE LS1X_PWM2_BASE | ||
25 | #define LS1X_TIMER_IRQ LS1X_PWM2_IRQ | ||
26 | |||
27 | #elif defined(CONFIG_TIMER_USE_PWM3) | ||
28 | #define LS1X_TIMER_BASE LS1X_PWM3_BASE | ||
29 | #define LS1X_TIMER_IRQ LS1X_PWM3_IRQ | ||
30 | |||
31 | #else | ||
32 | #define LS1X_TIMER_BASE LS1X_PWM0_BASE | ||
33 | #define LS1X_TIMER_IRQ LS1X_PWM0_IRQ | ||
34 | #endif | ||
35 | |||
36 | DEFINE_RAW_SPINLOCK(ls1x_timer_lock); | ||
37 | |||
38 | static void __iomem *timer_base; | ||
39 | static uint32_t ls1x_jiffies_per_tick; | ||
40 | |||
41 | static inline void ls1x_pwmtimer_set_period(uint32_t period) | ||
42 | { | ||
43 | __raw_writel(period, timer_base + PWM_HRC); | ||
44 | __raw_writel(period, timer_base + PWM_LRC); | ||
45 | } | ||
46 | |||
47 | static inline void ls1x_pwmtimer_restart(void) | ||
48 | { | ||
49 | __raw_writel(0x0, timer_base + PWM_CNT); | ||
50 | __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); | ||
51 | } | ||
52 | |||
53 | void __init ls1x_pwmtimer_init(void) | ||
54 | { | ||
55 | timer_base = ioremap(LS1X_TIMER_BASE, 0xf); | ||
56 | if (!timer_base) | ||
57 | panic("Failed to remap timer registers"); | ||
58 | |||
59 | ls1x_jiffies_per_tick = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); | ||
60 | |||
61 | ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); | ||
62 | ls1x_pwmtimer_restart(); | ||
63 | } | ||
64 | |||
65 | static cycle_t ls1x_clocksource_read(struct clocksource *cs) | ||
66 | { | ||
67 | unsigned long flags; | ||
68 | int count; | ||
69 | u32 jifs; | ||
70 | static int old_count; | ||
71 | static u32 old_jifs; | ||
72 | |||
73 | raw_spin_lock_irqsave(&ls1x_timer_lock, flags); | ||
74 | /* | ||
75 | * Although our caller may have the read side of xtime_lock, | ||
76 | * this is now a seqlock, and we are cheating in this routine | ||
77 | * by having side effects on state that we cannot undo if | ||
78 | * there is a collision on the seqlock and our caller has to | ||
79 | * retry. (Namely, old_jifs and old_count.) So we must treat | ||
80 | * jiffies as volatile despite the lock. We read jiffies | ||
81 | * before latching the timer count to guarantee that although | ||
82 | * the jiffies value might be older than the count (that is, | ||
83 | * the counter may underflow between the last point where | ||
84 | * jiffies was incremented and the point where we latch the | ||
85 | * count), it cannot be newer. | ||
86 | */ | ||
87 | jifs = jiffies; | ||
88 | /* read the count */ | ||
89 | count = __raw_readl(timer_base + PWM_CNT); | ||
90 | |||
91 | /* | ||
92 | * It's possible for count to appear to go the wrong way for this | ||
93 | * reason: | ||
94 | * | ||
95 | * The timer counter underflows, but we haven't handled the resulting | ||
96 | * interrupt and incremented jiffies yet. | ||
97 | * | ||
98 | * Previous attempts to handle these cases intelligently were buggy, so | ||
99 | * we just do the simple thing now. | ||
100 | */ | ||
101 | if (count < old_count && jifs == old_jifs) | ||
102 | count = old_count; | ||
103 | |||
104 | old_count = count; | ||
105 | old_jifs = jifs; | ||
106 | |||
107 | raw_spin_unlock_irqrestore(&ls1x_timer_lock, flags); | ||
108 | |||
109 | return (cycle_t) (jifs * ls1x_jiffies_per_tick) + count; | ||
110 | } | ||
111 | |||
112 | static struct clocksource ls1x_clocksource = { | ||
113 | .name = "ls1x-pwmtimer", | ||
114 | .read = ls1x_clocksource_read, | ||
115 | .mask = CLOCKSOURCE_MASK(24), | ||
116 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
117 | }; | ||
118 | |||
119 | static irqreturn_t ls1x_clockevent_isr(int irq, void *devid) | ||
120 | { | ||
121 | struct clock_event_device *cd = devid; | ||
122 | |||
123 | ls1x_pwmtimer_restart(); | ||
124 | cd->event_handler(cd); | ||
125 | |||
126 | return IRQ_HANDLED; | ||
127 | } | ||
128 | |||
129 | static void ls1x_clockevent_set_mode(enum clock_event_mode mode, | ||
130 | struct clock_event_device *cd) | ||
131 | { | ||
132 | raw_spin_lock(&ls1x_timer_lock); | ||
133 | switch (mode) { | ||
134 | case CLOCK_EVT_MODE_PERIODIC: | ||
135 | ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); | ||
136 | ls1x_pwmtimer_restart(); | ||
137 | case CLOCK_EVT_MODE_RESUME: | ||
138 | __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); | ||
139 | break; | ||
140 | case CLOCK_EVT_MODE_ONESHOT: | ||
141 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
142 | __raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN, | ||
143 | timer_base + PWM_CTRL); | ||
144 | break; | ||
145 | default: | ||
146 | break; | ||
147 | } | ||
148 | raw_spin_unlock(&ls1x_timer_lock); | ||
149 | } | ||
150 | |||
151 | static int ls1x_clockevent_set_next(unsigned long evt, | ||
152 | struct clock_event_device *cd) | ||
153 | { | ||
154 | raw_spin_lock(&ls1x_timer_lock); | ||
155 | ls1x_pwmtimer_set_period(evt); | ||
156 | ls1x_pwmtimer_restart(); | ||
157 | raw_spin_unlock(&ls1x_timer_lock); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static struct clock_event_device ls1x_clockevent = { | ||
163 | .name = "ls1x-pwmtimer", | ||
164 | .features = CLOCK_EVT_FEAT_PERIODIC, | ||
165 | .rating = 300, | ||
166 | .irq = LS1X_TIMER_IRQ, | ||
167 | .set_next_event = ls1x_clockevent_set_next, | ||
168 | .set_mode = ls1x_clockevent_set_mode, | ||
169 | }; | ||
170 | |||
171 | static struct irqaction ls1x_pwmtimer_irqaction = { | ||
172 | .name = "ls1x-pwmtimer", | ||
173 | .handler = ls1x_clockevent_isr, | ||
174 | .dev_id = &ls1x_clockevent, | ||
175 | .flags = IRQF_PERCPU | IRQF_TIMER, | ||
176 | }; | ||
177 | |||
178 | static void __init ls1x_time_init(void) | ||
179 | { | ||
180 | struct clock_event_device *cd = &ls1x_clockevent; | ||
181 | int ret; | ||
182 | |||
183 | if (!mips_hpt_frequency) | ||
184 | panic("Invalid timer clock rate"); | ||
185 | |||
186 | ls1x_pwmtimer_init(); | ||
187 | |||
188 | clockevent_set_clock(cd, mips_hpt_frequency); | ||
189 | cd->max_delta_ns = clockevent_delta2ns(0xffffff, cd); | ||
190 | cd->min_delta_ns = clockevent_delta2ns(0x000300, cd); | ||
191 | cd->cpumask = cpumask_of(smp_processor_id()); | ||
192 | clockevents_register_device(cd); | ||
193 | |||
194 | ls1x_clocksource.rating = 200 + mips_hpt_frequency / 10000000; | ||
195 | ret = clocksource_register_hz(&ls1x_clocksource, mips_hpt_frequency); | ||
196 | if (ret) | ||
197 | panic(KERN_ERR "Failed to register clocksource: %d\n", ret); | ||
198 | |||
199 | setup_irq(LS1X_TIMER_IRQ, &ls1x_pwmtimer_irqaction); | ||
200 | } | ||
201 | #endif /* CONFIG_CEVT_CSRC_LS1X */ | ||
202 | |||
203 | void __init plat_time_init(void) | ||
204 | { | ||
205 | struct clk *clk = NULL; | ||
206 | |||
207 | /* initialize LS1X clocks */ | ||
208 | ls1x_clk_init(); | ||
209 | |||
210 | #ifdef CONFIG_CEVT_CSRC_LS1X | ||
211 | /* setup LS1X PWM timer */ | ||
212 | clk = clk_get(NULL, "ls1x_pwmtimer"); | ||
213 | if (IS_ERR(clk)) | ||
214 | panic("unable to get timer clock, err=%ld", PTR_ERR(clk)); | ||
215 | |||
216 | mips_hpt_frequency = clk_get_rate(clk); | ||
217 | ls1x_time_init(); | ||
218 | #else | ||
219 | /* setup mips r4k timer */ | ||
220 | clk = clk_get(NULL, "cpu_clk"); | ||
221 | if (IS_ERR(clk)) | ||
222 | panic("unable to get cpu clock, err=%ld", PTR_ERR(clk)); | ||
223 | |||
224 | mips_hpt_frequency = clk_get_rate(clk) / 2; | ||
225 | #endif /* CONFIG_CEVT_CSRC_LS1X */ | ||
226 | } | ||
diff --git a/arch/mips/loongson1/ls1b/board.c b/arch/mips/loongson1/ls1b/board.c index b26b10dac70a..58daeea25739 100644 --- a/arch/mips/loongson1/ls1b/board.c +++ b/arch/mips/loongson1/ls1b/board.c | |||
@@ -10,17 +10,19 @@ | |||
10 | #include <platform.h> | 10 | #include <platform.h> |
11 | 11 | ||
12 | static struct platform_device *ls1b_platform_devices[] __initdata = { | 12 | static struct platform_device *ls1b_platform_devices[] __initdata = { |
13 | &ls1x_uart_device, | 13 | &ls1x_uart_pdev, |
14 | &ls1x_eth0_device, | 14 | &ls1x_cpufreq_pdev, |
15 | &ls1x_ehci_device, | 15 | &ls1x_eth0_pdev, |
16 | &ls1x_rtc_device, | 16 | &ls1x_eth1_pdev, |
17 | &ls1x_ehci_pdev, | ||
18 | &ls1x_rtc_pdev, | ||
17 | }; | 19 | }; |
18 | 20 | ||
19 | static int __init ls1b_platform_init(void) | 21 | static int __init ls1b_platform_init(void) |
20 | { | 22 | { |
21 | int err; | 23 | int err; |
22 | 24 | ||
23 | ls1x_serial_setup(&ls1x_uart_device); | 25 | ls1x_serial_setup(&ls1x_uart_pdev); |
24 | 26 | ||
25 | err = platform_add_devices(ls1b_platform_devices, | 27 | err = platform_add_devices(ls1b_platform_devices, |
26 | ARRAY_SIZE(ls1b_platform_devices)); | 28 | ARRAY_SIZE(ls1b_platform_devices)); |
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index cac529a405b8..9dfcd7fc1bc3 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c | |||
@@ -643,9 +643,14 @@ static inline int cop1_64bit(struct pt_regs *xcp) | |||
643 | return !test_thread_flag(TIF_32BIT_FPREGS); | 643 | return !test_thread_flag(TIF_32BIT_FPREGS); |
644 | } | 644 | } |
645 | 645 | ||
646 | static inline bool hybrid_fprs(void) | ||
647 | { | ||
648 | return test_thread_flag(TIF_HYBRID_FPREGS); | ||
649 | } | ||
650 | |||
646 | #define SIFROMREG(si, x) \ | 651 | #define SIFROMREG(si, x) \ |
647 | do { \ | 652 | do { \ |
648 | if (cop1_64bit(xcp)) \ | 653 | if (cop1_64bit(xcp) && !hybrid_fprs()) \ |
649 | (si) = (int)get_fpr32(&ctx->fpr[x], 0); \ | 654 | (si) = (int)get_fpr32(&ctx->fpr[x], 0); \ |
650 | else \ | 655 | else \ |
651 | (si) = (int)get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \ | 656 | (si) = (int)get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \ |
@@ -653,7 +658,7 @@ do { \ | |||
653 | 658 | ||
654 | #define SITOREG(si, x) \ | 659 | #define SITOREG(si, x) \ |
655 | do { \ | 660 | do { \ |
656 | if (cop1_64bit(xcp)) { \ | 661 | if (cop1_64bit(xcp) && !hybrid_fprs()) { \ |
657 | unsigned i; \ | 662 | unsigned i; \ |
658 | set_fpr32(&ctx->fpr[x], 0, si); \ | 663 | set_fpr32(&ctx->fpr[x], 0, si); \ |
659 | for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \ | 664 | for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \ |
diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index fd134675fc2e..068f45a415fc 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c | |||
@@ -38,7 +38,7 @@ int ieee754dp_isnan(union ieee754dp x) | |||
38 | static inline int ieee754dp_issnan(union ieee754dp x) | 38 | static inline int ieee754dp_issnan(union ieee754dp x) |
39 | { | 39 | { |
40 | assert(ieee754dp_isnan(x)); | 40 | assert(ieee754dp_isnan(x)); |
41 | return ((DPMANT(x) & DP_MBIT(DP_FBITS-1)) == DP_MBIT(DP_FBITS-1)); | 41 | return (DPMANT(x) & DP_MBIT(DP_FBITS - 1)) == DP_MBIT(DP_FBITS - 1); |
42 | } | 42 | } |
43 | 43 | ||
44 | 44 | ||
diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index d348efe91445..ba88301579c2 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c | |||
@@ -38,7 +38,7 @@ int ieee754sp_isnan(union ieee754sp x) | |||
38 | static inline int ieee754sp_issnan(union ieee754sp x) | 38 | static inline int ieee754sp_issnan(union ieee754sp x) |
39 | { | 39 | { |
40 | assert(ieee754sp_isnan(x)); | 40 | assert(ieee754sp_isnan(x)); |
41 | return (SPMANT(x) & SP_MBIT(SP_FBITS-1)); | 41 | return SPMANT(x) & SP_MBIT(SP_FBITS - 1); |
42 | } | 42 | } |
43 | 43 | ||
44 | 44 | ||
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile index 7f4f93ab22b7..67ede4ef9b8d 100644 --- a/arch/mips/mm/Makefile +++ b/arch/mips/mm/Makefile | |||
@@ -4,7 +4,13 @@ | |||
4 | 4 | ||
5 | obj-y += cache.o dma-default.o extable.o fault.o \ | 5 | obj-y += cache.o dma-default.o extable.o fault.o \ |
6 | gup.o init.o mmap.o page.o page-funcs.o \ | 6 | gup.o init.o mmap.o page.o page-funcs.o \ |
7 | tlbex.o tlbex-fault.o tlb-funcs.o uasm-mips.o | 7 | tlbex.o tlbex-fault.o tlb-funcs.o |
8 | |||
9 | ifdef CONFIG_CPU_MICROMIPS | ||
10 | obj-y += uasm-micromips.o | ||
11 | else | ||
12 | obj-y += uasm-mips.o | ||
13 | endif | ||
8 | 14 | ||
9 | obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o | 15 | obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o |
10 | obj-$(CONFIG_64BIT) += pgtable-64.o | 16 | obj-$(CONFIG_64BIT) += pgtable-64.o |
@@ -22,5 +28,3 @@ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o | |||
22 | obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o | 28 | obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o |
23 | obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o | 29 | obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o |
24 | obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o | 30 | obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o |
25 | |||
26 | obj-$(CONFIG_SYS_SUPPORTS_MICROMIPS) += uasm-micromips.o | ||
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index fbcd8674ff1d..dd261df005c2 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
@@ -917,6 +917,18 @@ static inline void alias_74k_erratum(struct cpuinfo_mips *c) | |||
917 | } | 917 | } |
918 | } | 918 | } |
919 | 919 | ||
920 | static void b5k_instruction_hazard(void) | ||
921 | { | ||
922 | __sync(); | ||
923 | __sync(); | ||
924 | __asm__ __volatile__( | ||
925 | " nop; nop; nop; nop; nop; nop; nop; nop\n" | ||
926 | " nop; nop; nop; nop; nop; nop; nop; nop\n" | ||
927 | " nop; nop; nop; nop; nop; nop; nop; nop\n" | ||
928 | " nop; nop; nop; nop; nop; nop; nop; nop\n" | ||
929 | : : : "memory"); | ||
930 | } | ||
931 | |||
920 | static char *way_string[] = { NULL, "direct mapped", "2-way", | 932 | static char *way_string[] = { NULL, "direct mapped", "2-way", |
921 | "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" | 933 | "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" |
922 | }; | 934 | }; |
@@ -1683,6 +1695,37 @@ void r4k_cache_init(void) | |||
1683 | 1695 | ||
1684 | coherency_setup(); | 1696 | coherency_setup(); |
1685 | board_cache_error_setup = r4k_cache_error_setup; | 1697 | board_cache_error_setup = r4k_cache_error_setup; |
1698 | |||
1699 | /* | ||
1700 | * Per-CPU overrides | ||
1701 | */ | ||
1702 | switch (current_cpu_type()) { | ||
1703 | case CPU_BMIPS4350: | ||
1704 | case CPU_BMIPS4380: | ||
1705 | /* No IPI is needed because all CPUs share the same D$ */ | ||
1706 | flush_data_cache_page = r4k_blast_dcache_page; | ||
1707 | break; | ||
1708 | case CPU_BMIPS5000: | ||
1709 | /* We lose our superpowers if L2 is disabled */ | ||
1710 | if (c->scache.flags & MIPS_CACHE_NOT_PRESENT) | ||
1711 | break; | ||
1712 | |||
1713 | /* I$ fills from D$ just by emptying the write buffers */ | ||
1714 | flush_cache_page = (void *)b5k_instruction_hazard; | ||
1715 | flush_cache_range = (void *)b5k_instruction_hazard; | ||
1716 | flush_cache_sigtramp = (void *)b5k_instruction_hazard; | ||
1717 | local_flush_data_cache_page = (void *)b5k_instruction_hazard; | ||
1718 | flush_data_cache_page = (void *)b5k_instruction_hazard; | ||
1719 | flush_icache_range = (void *)b5k_instruction_hazard; | ||
1720 | local_flush_icache_range = (void *)b5k_instruction_hazard; | ||
1721 | |||
1722 | /* Cache aliases are handled in hardware; allow HIGHMEM */ | ||
1723 | current_cpu_data.dcache.flags &= ~MIPS_CACHE_ALIASES; | ||
1724 | |||
1725 | /* Optimization: an L2 flush implicitly flushes the L1 */ | ||
1726 | current_cpu_data.options |= MIPS_CPU_INCLUSIVE_CACHES; | ||
1727 | break; | ||
1728 | } | ||
1686 | } | 1729 | } |
1687 | 1730 | ||
1688 | static int r4k_cache_pm_notifier(struct notifier_block *self, unsigned long cmd, | 1731 | static int r4k_cache_pm_notifier(struct notifier_block *self, unsigned long cmd, |
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 33ba3c558fe4..af5f046e627e 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c | |||
@@ -61,6 +61,11 @@ static inline struct page *dma_addr_to_page(struct device *dev, | |||
61 | * Warning on the terminology - Linux calls an uncached area coherent; | 61 | * Warning on the terminology - Linux calls an uncached area coherent; |
62 | * MIPS terminology calls memory areas with hardware maintained coherency | 62 | * MIPS terminology calls memory areas with hardware maintained coherency |
63 | * coherent. | 63 | * coherent. |
64 | * | ||
65 | * Note that the R14000 and R16000 should also be checked for in this | ||
66 | * condition. However this function is only called on non-I/O-coherent | ||
67 | * systems and only the R10000 and R12000 are used in such systems, the | ||
68 | * SGI IP28 Indigo² rsp. SGI IP32 aka O2. | ||
64 | */ | 69 | */ |
65 | static inline int cpu_needs_post_dma_flush(struct device *dev) | 70 | static inline int cpu_needs_post_dma_flush(struct device *dev) |
66 | { | 71 | { |
diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c index 06ce17c2a905..7cba480568c8 100644 --- a/arch/mips/mm/gup.c +++ b/arch/mips/mm/gup.c | |||
@@ -17,7 +17,7 @@ | |||
17 | 17 | ||
18 | static inline pte_t gup_get_pte(pte_t *ptep) | 18 | static inline pte_t gup_get_pte(pte_t *ptep) |
19 | { | 19 | { |
20 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 20 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
21 | pte_t pte; | 21 | pte_t pte; |
22 | 22 | ||
23 | retry: | 23 | retry: |
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index f42e35e42790..448cde372af0 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c | |||
@@ -95,7 +95,7 @@ static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot) | |||
95 | idx += in_interrupt() ? FIX_N_COLOURS : 0; | 95 | idx += in_interrupt() ? FIX_N_COLOURS : 0; |
96 | vaddr = __fix_to_virt(FIX_CMAP_END - idx); | 96 | vaddr = __fix_to_virt(FIX_CMAP_END - idx); |
97 | pte = mk_pte(page, prot); | 97 | pte = mk_pte(page, prot); |
98 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 98 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
99 | entrylo = pte.pte_high; | 99 | entrylo = pte.pte_high; |
100 | #else | 100 | #else |
101 | entrylo = pte_to_entrylo(pte_val(pte)); | 101 | entrylo = pte_to_entrylo(pte_val(pte)); |
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c index 7f840bc08abf..8d5008cbdc0f 100644 --- a/arch/mips/mm/ioremap.c +++ b/arch/mips/mm/ioremap.c | |||
@@ -17,9 +17,9 @@ | |||
17 | #include <asm/tlbflush.h> | 17 | #include <asm/tlbflush.h> |
18 | 18 | ||
19 | static inline void remap_area_pte(pte_t * pte, unsigned long address, | 19 | static inline void remap_area_pte(pte_t * pte, unsigned long address, |
20 | phys_t size, phys_t phys_addr, unsigned long flags) | 20 | phys_addr_t size, phys_addr_t phys_addr, unsigned long flags) |
21 | { | 21 | { |
22 | phys_t end; | 22 | phys_addr_t end; |
23 | unsigned long pfn; | 23 | unsigned long pfn; |
24 | pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE | 24 | pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE |
25 | | __WRITEABLE | flags); | 25 | | __WRITEABLE | flags); |
@@ -43,9 +43,9 @@ static inline void remap_area_pte(pte_t * pte, unsigned long address, | |||
43 | } | 43 | } |
44 | 44 | ||
45 | static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, | 45 | static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, |
46 | phys_t size, phys_t phys_addr, unsigned long flags) | 46 | phys_addr_t size, phys_addr_t phys_addr, unsigned long flags) |
47 | { | 47 | { |
48 | phys_t end; | 48 | phys_addr_t end; |
49 | 49 | ||
50 | address &= ~PGDIR_MASK; | 50 | address &= ~PGDIR_MASK; |
51 | end = address + size; | 51 | end = address + size; |
@@ -64,8 +64,8 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, | |||
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | 66 | ||
67 | static int remap_area_pages(unsigned long address, phys_t phys_addr, | 67 | static int remap_area_pages(unsigned long address, phys_addr_t phys_addr, |
68 | phys_t size, unsigned long flags) | 68 | phys_addr_t size, unsigned long flags) |
69 | { | 69 | { |
70 | int error; | 70 | int error; |
71 | pgd_t * dir; | 71 | pgd_t * dir; |
@@ -111,13 +111,13 @@ static int remap_area_pages(unsigned long address, phys_t phys_addr, | |||
111 | * caller shouldn't need to know that small detail. | 111 | * caller shouldn't need to know that small detail. |
112 | */ | 112 | */ |
113 | 113 | ||
114 | #define IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL)) | 114 | #define IS_LOW512(addr) (!((phys_addr_t)(addr) & (phys_addr_t) ~0x1fffffffULL)) |
115 | 115 | ||
116 | void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) | 116 | void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long flags) |
117 | { | 117 | { |
118 | struct vm_struct * area; | 118 | struct vm_struct * area; |
119 | unsigned long offset; | 119 | unsigned long offset; |
120 | phys_t last_addr; | 120 | phys_addr_t last_addr; |
121 | void * addr; | 121 | void * addr; |
122 | 122 | ||
123 | phys_addr = fixup_bigphys_addr(phys_addr, size); | 123 | phys_addr = fixup_bigphys_addr(phys_addr, size); |
diff --git a/arch/mips/mm/sc-r5k.c b/arch/mips/mm/sc-r5k.c index 0216ed6eaa2a..751b5cd18bf2 100644 --- a/arch/mips/mm/sc-r5k.c +++ b/arch/mips/mm/sc-r5k.c | |||
@@ -81,7 +81,7 @@ static inline int __init r5k_sc_probe(void) | |||
81 | unsigned long config = read_c0_config(); | 81 | unsigned long config = read_c0_config(); |
82 | 82 | ||
83 | if (config & CONF_SC) | 83 | if (config & CONF_SC) |
84 | return(0); | 84 | return 0; |
85 | 85 | ||
86 | scache_size = (512 * 1024) << ((config & R5K_CONF_SS) >> 20); | 86 | scache_size = (512 * 1024) << ((config & R5K_CONF_SS) >> 20); |
87 | 87 | ||
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index c3917e251f59..e90b2e899291 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c | |||
@@ -332,7 +332,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) | |||
332 | { | 332 | { |
333 | ptep = pte_offset_map(pmdp, address); | 333 | ptep = pte_offset_map(pmdp, address); |
334 | 334 | ||
335 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 335 | #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
336 | write_c0_entrylo0(ptep->pte_high); | 336 | write_c0_entrylo0(ptep->pte_high); |
337 | ptep++; | 337 | ptep++; |
338 | write_c0_entrylo1(ptep->pte_high); | 338 | write_c0_entrylo1(ptep->pte_high); |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index e3328a96e809..3978a3d81366 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -637,7 +637,7 @@ static __maybe_unused void build_convert_pte_to_entrylo(u32 **p, | |||
637 | if (cpu_has_rixi) { | 637 | if (cpu_has_rixi) { |
638 | UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL)); | 638 | UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL)); |
639 | } else { | 639 | } else { |
640 | #ifdef CONFIG_64BIT_PHYS_ADDR | 640 | #ifdef CONFIG_PHYS_ADDR_T_64BIT |
641 | uasm_i_dsrl_safe(p, reg, reg, ilog2(_PAGE_GLOBAL)); | 641 | uasm_i_dsrl_safe(p, reg, reg, ilog2(_PAGE_GLOBAL)); |
642 | #else | 642 | #else |
643 | UASM_i_SRL(p, reg, reg, ilog2(_PAGE_GLOBAL)); | 643 | UASM_i_SRL(p, reg, reg, ilog2(_PAGE_GLOBAL)); |
@@ -1009,7 +1009,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) | |||
1009 | * 64bit address support (36bit on a 32bit CPU) in a 32bit | 1009 | * 64bit address support (36bit on a 32bit CPU) in a 32bit |
1010 | * Kernel is a special case. Only a few CPUs use it. | 1010 | * Kernel is a special case. Only a few CPUs use it. |
1011 | */ | 1011 | */ |
1012 | #ifdef CONFIG_64BIT_PHYS_ADDR | 1012 | #ifdef CONFIG_PHYS_ADDR_T_64BIT |
1013 | if (cpu_has_64bits) { | 1013 | if (cpu_has_64bits) { |
1014 | uasm_i_ld(p, tmp, 0, ptep); /* get even pte */ | 1014 | uasm_i_ld(p, tmp, 0, ptep); /* get even pte */ |
1015 | uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */ | 1015 | uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */ |
@@ -1510,14 +1510,14 @@ static void | |||
1510 | iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) | 1510 | iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) |
1511 | { | 1511 | { |
1512 | #ifdef CONFIG_SMP | 1512 | #ifdef CONFIG_SMP |
1513 | # ifdef CONFIG_64BIT_PHYS_ADDR | 1513 | # ifdef CONFIG_PHYS_ADDR_T_64BIT |
1514 | if (cpu_has_64bits) | 1514 | if (cpu_has_64bits) |
1515 | uasm_i_lld(p, pte, 0, ptr); | 1515 | uasm_i_lld(p, pte, 0, ptr); |
1516 | else | 1516 | else |
1517 | # endif | 1517 | # endif |
1518 | UASM_i_LL(p, pte, 0, ptr); | 1518 | UASM_i_LL(p, pte, 0, ptr); |
1519 | #else | 1519 | #else |
1520 | # ifdef CONFIG_64BIT_PHYS_ADDR | 1520 | # ifdef CONFIG_PHYS_ADDR_T_64BIT |
1521 | if (cpu_has_64bits) | 1521 | if (cpu_has_64bits) |
1522 | uasm_i_ld(p, pte, 0, ptr); | 1522 | uasm_i_ld(p, pte, 0, ptr); |
1523 | else | 1523 | else |
@@ -1530,13 +1530,13 @@ static void | |||
1530 | iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, | 1530 | iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, |
1531 | unsigned int mode) | 1531 | unsigned int mode) |
1532 | { | 1532 | { |
1533 | #ifdef CONFIG_64BIT_PHYS_ADDR | 1533 | #ifdef CONFIG_PHYS_ADDR_T_64BIT |
1534 | unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY); | 1534 | unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY); |
1535 | #endif | 1535 | #endif |
1536 | 1536 | ||
1537 | uasm_i_ori(p, pte, pte, mode); | 1537 | uasm_i_ori(p, pte, pte, mode); |
1538 | #ifdef CONFIG_SMP | 1538 | #ifdef CONFIG_SMP |
1539 | # ifdef CONFIG_64BIT_PHYS_ADDR | 1539 | # ifdef CONFIG_PHYS_ADDR_T_64BIT |
1540 | if (cpu_has_64bits) | 1540 | if (cpu_has_64bits) |
1541 | uasm_i_scd(p, pte, 0, ptr); | 1541 | uasm_i_scd(p, pte, 0, ptr); |
1542 | else | 1542 | else |
@@ -1548,7 +1548,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, | |||
1548 | else | 1548 | else |
1549 | uasm_il_beqz(p, r, pte, label_smp_pgtable_change); | 1549 | uasm_il_beqz(p, r, pte, label_smp_pgtable_change); |
1550 | 1550 | ||
1551 | # ifdef CONFIG_64BIT_PHYS_ADDR | 1551 | # ifdef CONFIG_PHYS_ADDR_T_64BIT |
1552 | if (!cpu_has_64bits) { | 1552 | if (!cpu_has_64bits) { |
1553 | /* no uasm_i_nop needed */ | 1553 | /* no uasm_i_nop needed */ |
1554 | uasm_i_ll(p, pte, sizeof(pte_t) / 2, ptr); | 1554 | uasm_i_ll(p, pte, sizeof(pte_t) / 2, ptr); |
@@ -1563,14 +1563,14 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, | |||
1563 | uasm_i_nop(p); | 1563 | uasm_i_nop(p); |
1564 | # endif | 1564 | # endif |
1565 | #else | 1565 | #else |
1566 | # ifdef CONFIG_64BIT_PHYS_ADDR | 1566 | # ifdef CONFIG_PHYS_ADDR_T_64BIT |
1567 | if (cpu_has_64bits) | 1567 | if (cpu_has_64bits) |
1568 | uasm_i_sd(p, pte, 0, ptr); | 1568 | uasm_i_sd(p, pte, 0, ptr); |
1569 | else | 1569 | else |
1570 | # endif | 1570 | # endif |
1571 | UASM_i_SW(p, pte, 0, ptr); | 1571 | UASM_i_SW(p, pte, 0, ptr); |
1572 | 1572 | ||
1573 | # ifdef CONFIG_64BIT_PHYS_ADDR | 1573 | # ifdef CONFIG_PHYS_ADDR_T_64BIT |
1574 | if (!cpu_has_64bits) { | 1574 | if (!cpu_has_64bits) { |
1575 | uasm_i_lw(p, pte, sizeof(pte_t) / 2, ptr); | 1575 | uasm_i_lw(p, pte, sizeof(pte_t) / 2, ptr); |
1576 | uasm_i_ori(p, pte, pte, hwmode); | 1576 | uasm_i_ori(p, pte, pte, hwmode); |
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 6708a2dbf934..8e02291cfc0c 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c | |||
@@ -96,9 +96,11 @@ static struct insn insn_table[] = { | |||
96 | { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, | 96 | { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, |
97 | { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, | 97 | { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, |
98 | { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, | 98 | { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, |
99 | { insn_mfhc0, M(cop0_op, mfhc0_op, 0, 0, 0, 0), RT | RD | SET}, | ||
99 | { insn_mfhi, M(spec_op, 0, 0, 0, 0, mfhi_op), RD }, | 100 | { insn_mfhi, M(spec_op, 0, 0, 0, 0, mfhi_op), RD }, |
100 | { insn_mflo, M(spec_op, 0, 0, 0, 0, mflo_op), RD }, | 101 | { insn_mflo, M(spec_op, 0, 0, 0, 0, mflo_op), RD }, |
101 | { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, | 102 | { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, |
103 | { insn_mthc0, M(cop0_op, mthc0_op, 0, 0, 0, 0), RT | RD | SET}, | ||
102 | { insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD}, | 104 | { insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD}, |
103 | { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, | 105 | { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, |
104 | { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD }, | 106 | { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD }, |
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index a01b0d6cedd2..4adf30284813 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c | |||
@@ -51,12 +51,12 @@ enum opcode { | |||
51 | insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, | 51 | insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, |
52 | insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_lb, | 52 | insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_lb, |
53 | insn_ld, insn_ldx, insn_lh, insn_ll, insn_lld, insn_lui, insn_lw, | 53 | insn_ld, insn_ldx, insn_lh, insn_ll, insn_lld, insn_lui, insn_lw, |
54 | insn_lwx, insn_mfc0, insn_mfhi, insn_mflo, insn_mtc0, insn_mul, | 54 | insn_lwx, insn_mfc0, insn_mfhc0, insn_mfhi, insn_mflo, insn_mtc0, |
55 | insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, | 55 | insn_mthc0, insn_mul, insn_or, insn_ori, insn_pref, insn_rfe, |
56 | insn_sd, insn_sll, insn_sllv, insn_slt, insn_sltiu, insn_sltu, insn_sra, | 56 | insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, insn_slt, |
57 | insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, | 57 | insn_sltiu, insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, |
58 | insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, | 58 | insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, |
59 | insn_xor, insn_xori, insn_yield, | 59 | insn_tlbwr, insn_wait, insn_wsbh, insn_xor, insn_xori, insn_yield, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | struct insn { | 62 | struct insn { |
@@ -284,9 +284,11 @@ I_u2s3u1(_lld) | |||
284 | I_u1s2(_lui) | 284 | I_u1s2(_lui) |
285 | I_u2s3u1(_lw) | 285 | I_u2s3u1(_lw) |
286 | I_u1u2u3(_mfc0) | 286 | I_u1u2u3(_mfc0) |
287 | I_u1u2u3(_mfhc0) | ||
287 | I_u1(_mfhi) | 288 | I_u1(_mfhi) |
288 | I_u1(_mflo) | 289 | I_u1(_mflo) |
289 | I_u1u2u3(_mtc0) | 290 | I_u1u2u3(_mtc0) |
291 | I_u1u2u3(_mthc0) | ||
290 | I_u3u1u2(_mul) | 292 | I_u3u1u2(_mul) |
291 | I_u2u1u3(_ori) | 293 | I_u2u1u3(_ori) |
292 | I_u3u1u2(_or) | 294 | I_u3u1u2(_or) |
diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c index 0f60256d3784..6849f533154f 100644 --- a/arch/mips/mti-malta/malta-init.c +++ b/arch/mips/mti-malta/malta-init.c | |||
@@ -111,7 +111,7 @@ static void __init mips_ejtag_setup(void) | |||
111 | flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); | 111 | flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); |
112 | } | 112 | } |
113 | 113 | ||
114 | phys_t mips_cpc_default_phys_base(void) | 114 | phys_addr_t mips_cpc_default_phys_base(void) |
115 | { | 115 | { |
116 | return CPC_BASE_ADDR; | 116 | return CPC_BASE_ADDR; |
117 | } | 117 | } |
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index e4f43baa8f67..d1392f8f5811 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/irqchip/mips-gic.h> | ||
21 | #include <linux/kernel_stat.h> | 22 | #include <linux/kernel_stat.h> |
22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
23 | #include <linux/random.h> | 24 | #include <linux/random.h> |
@@ -33,19 +34,13 @@ | |||
33 | #include <asm/mips-boards/generic.h> | 34 | #include <asm/mips-boards/generic.h> |
34 | #include <asm/mips-boards/msc01_pci.h> | 35 | #include <asm/mips-boards/msc01_pci.h> |
35 | #include <asm/msc01_ic.h> | 36 | #include <asm/msc01_ic.h> |
36 | #include <asm/gic.h> | ||
37 | #include <asm/setup.h> | 37 | #include <asm/setup.h> |
38 | #include <asm/rtlx.h> | 38 | #include <asm/rtlx.h> |
39 | 39 | ||
40 | static unsigned long _msc01_biu_base; | 40 | static void __iomem *_msc01_biu_base; |
41 | static unsigned int ipi_map[NR_CPUS]; | ||
42 | 41 | ||
43 | static DEFINE_RAW_SPINLOCK(mips_irq_lock); | 42 | static DEFINE_RAW_SPINLOCK(mips_irq_lock); |
44 | 43 | ||
45 | #ifdef CONFIG_MIPS_GIC_IPI | ||
46 | DECLARE_BITMAP(ipi_ints, GIC_NUM_INTRS); | ||
47 | #endif | ||
48 | |||
49 | static inline int mips_pcibios_iack(void) | 44 | static inline int mips_pcibios_iack(void) |
50 | { | 45 | { |
51 | int irq; | 46 | int irq; |
@@ -127,24 +122,10 @@ static void malta_hw0_irqdispatch(void) | |||
127 | #endif | 122 | #endif |
128 | } | 123 | } |
129 | 124 | ||
130 | static void malta_ipi_irqdispatch(void) | 125 | static irqreturn_t i8259_handler(int irq, void *dev_id) |
131 | { | 126 | { |
132 | #ifdef CONFIG_MIPS_GIC_IPI | 127 | malta_hw0_irqdispatch(); |
133 | unsigned long irq; | 128 | return IRQ_HANDLED; |
134 | DECLARE_BITMAP(pending, GIC_NUM_INTRS); | ||
135 | |||
136 | gic_get_int_mask(pending, ipi_ints); | ||
137 | |||
138 | irq = find_first_bit(pending, GIC_NUM_INTRS); | ||
139 | |||
140 | while (irq < GIC_NUM_INTRS) { | ||
141 | do_IRQ(MIPS_GIC_IRQ_BASE + irq); | ||
142 | |||
143 | irq = find_next_bit(pending, GIC_NUM_INTRS, irq + 1); | ||
144 | } | ||
145 | #endif | ||
146 | if (gic_compare_int()) | ||
147 | do_IRQ(MIPS_GIC_IRQ_BASE); | ||
148 | } | 129 | } |
149 | 130 | ||
150 | static void corehi_irqdispatch(void) | 131 | static void corehi_irqdispatch(void) |
@@ -203,95 +184,10 @@ static void corehi_irqdispatch(void) | |||
203 | die("CoreHi interrupt", regs); | 184 | die("CoreHi interrupt", regs); |
204 | } | 185 | } |
205 | 186 | ||
206 | static inline int clz(unsigned long x) | 187 | static irqreturn_t corehi_handler(int irq, void *dev_id) |
207 | { | ||
208 | __asm__( | ||
209 | " .set push \n" | ||
210 | " .set mips32 \n" | ||
211 | " clz %0, %1 \n" | ||
212 | " .set pop \n" | ||
213 | : "=r" (x) | ||
214 | : "r" (x)); | ||
215 | |||
216 | return x; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Version of ffs that only looks at bits 12..15. | ||
221 | */ | ||
222 | static inline unsigned int irq_ffs(unsigned int pending) | ||
223 | { | ||
224 | #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) | ||
225 | return -clz(pending) + 31 - CAUSEB_IP; | ||
226 | #else | ||
227 | unsigned int a0 = 7; | ||
228 | unsigned int t0; | ||
229 | |||
230 | t0 = pending & 0xf000; | ||
231 | t0 = t0 < 1; | ||
232 | t0 = t0 << 2; | ||
233 | a0 = a0 - t0; | ||
234 | pending = pending << t0; | ||
235 | |||
236 | t0 = pending & 0xc000; | ||
237 | t0 = t0 < 1; | ||
238 | t0 = t0 << 1; | ||
239 | a0 = a0 - t0; | ||
240 | pending = pending << t0; | ||
241 | |||
242 | t0 = pending & 0x8000; | ||
243 | t0 = t0 < 1; | ||
244 | /* t0 = t0 << 2; */ | ||
245 | a0 = a0 - t0; | ||
246 | /* pending = pending << t0; */ | ||
247 | |||
248 | return a0; | ||
249 | #endif | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * IRQs on the Malta board look basically (barring software IRQs which we | ||
254 | * don't use at all and all external interrupt sources are combined together | ||
255 | * on hardware interrupt 0 (MIPS IRQ 2)) like: | ||
256 | * | ||
257 | * MIPS IRQ Source | ||
258 | * -------- ------ | ||
259 | * 0 Software (ignored) | ||
260 | * 1 Software (ignored) | ||
261 | * 2 Combined hardware interrupt (hw0) | ||
262 | * 3 Hardware (ignored) | ||
263 | * 4 Hardware (ignored) | ||
264 | * 5 Hardware (ignored) | ||
265 | * 6 Hardware (ignored) | ||
266 | * 7 R4k timer (what we use) | ||
267 | * | ||
268 | * We handle the IRQ according to _our_ priority which is: | ||
269 | * | ||
270 | * Highest ---- R4k Timer | ||
271 | * Lowest ---- Combined hardware interrupt | ||
272 | * | ||
273 | * then we just return, if multiple IRQs are pending then we will just take | ||
274 | * another exception, big deal. | ||
275 | */ | ||
276 | |||
277 | asmlinkage void plat_irq_dispatch(void) | ||
278 | { | 188 | { |
279 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; | 189 | corehi_irqdispatch(); |
280 | int irq; | 190 | return IRQ_HANDLED; |
281 | |||
282 | if (unlikely(!pending)) { | ||
283 | spurious_interrupt(); | ||
284 | return; | ||
285 | } | ||
286 | |||
287 | irq = irq_ffs(pending); | ||
288 | |||
289 | if (irq == MIPSCPU_INT_I8259A) | ||
290 | malta_hw0_irqdispatch(); | ||
291 | else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) | ||
292 | malta_ipi_irqdispatch(); | ||
293 | else | ||
294 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | ||
295 | } | 191 | } |
296 | 192 | ||
297 | #ifdef CONFIG_MIPS_MT_SMP | 193 | #ifdef CONFIG_MIPS_MT_SMP |
@@ -312,13 +208,6 @@ static void ipi_call_dispatch(void) | |||
312 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); | 208 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); |
313 | } | 209 | } |
314 | 210 | ||
315 | #endif /* CONFIG_MIPS_MT_SMP */ | ||
316 | |||
317 | #ifdef CONFIG_MIPS_GIC_IPI | ||
318 | |||
319 | #define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3 | ||
320 | #define GIC_MIPS_CPU_IPI_CALL_IRQ 4 | ||
321 | |||
322 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) | 211 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) |
323 | { | 212 | { |
324 | #ifdef CONFIG_MIPS_VPE_APSP_API_CMP | 213 | #ifdef CONFIG_MIPS_VPE_APSP_API_CMP |
@@ -349,31 +238,16 @@ static struct irqaction irq_call = { | |||
349 | .flags = IRQF_PERCPU, | 238 | .flags = IRQF_PERCPU, |
350 | .name = "IPI_call" | 239 | .name = "IPI_call" |
351 | }; | 240 | }; |
352 | #endif /* CONFIG_MIPS_GIC_IPI */ | 241 | #endif /* CONFIG_MIPS_MT_SMP */ |
353 | |||
354 | static int gic_resched_int_base; | ||
355 | static int gic_call_int_base; | ||
356 | #define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) | ||
357 | #define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) | ||
358 | |||
359 | unsigned int plat_ipi_call_int_xlate(unsigned int cpu) | ||
360 | { | ||
361 | return GIC_CALL_INT(cpu); | ||
362 | } | ||
363 | |||
364 | unsigned int plat_ipi_resched_int_xlate(unsigned int cpu) | ||
365 | { | ||
366 | return GIC_RESCHED_INT(cpu); | ||
367 | } | ||
368 | 242 | ||
369 | static struct irqaction i8259irq = { | 243 | static struct irqaction i8259irq = { |
370 | .handler = no_action, | 244 | .handler = i8259_handler, |
371 | .name = "XT-PIC cascade", | 245 | .name = "XT-PIC cascade", |
372 | .flags = IRQF_NO_THREAD, | 246 | .flags = IRQF_NO_THREAD, |
373 | }; | 247 | }; |
374 | 248 | ||
375 | static struct irqaction corehi_irqaction = { | 249 | static struct irqaction corehi_irqaction = { |
376 | .handler = no_action, | 250 | .handler = corehi_handler, |
377 | .name = "CoreHi", | 251 | .name = "CoreHi", |
378 | .flags = IRQF_NO_THREAD, | 252 | .flags = IRQF_NO_THREAD, |
379 | }; | 253 | }; |
@@ -399,60 +273,6 @@ static msc_irqmap_t msc_eicirqmap[] __initdata = { | |||
399 | 273 | ||
400 | static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap); | 274 | static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap); |
401 | 275 | ||
402 | /* | ||
403 | * This GIC specific tabular array defines the association between External | ||
404 | * Interrupts and CPUs/Core Interrupts. The nature of the External | ||
405 | * Interrupts is also defined here - polarity/trigger. | ||
406 | */ | ||
407 | |||
408 | #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK | ||
409 | #define X GIC_UNUSED | ||
410 | |||
411 | static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { | ||
412 | { X, X, X, X, 0 }, | ||
413 | { X, X, X, X, 0 }, | ||
414 | { X, X, X, X, 0 }, | ||
415 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
416 | { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
417 | { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
418 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
419 | { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
420 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
421 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
422 | { X, X, X, X, 0 }, | ||
423 | { X, X, X, X, 0 }, | ||
424 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
425 | { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
426 | { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
427 | { X, X, X, X, 0 }, | ||
428 | /* The remainder of this table is initialised by fill_ipi_map */ | ||
429 | }; | ||
430 | #undef X | ||
431 | |||
432 | #ifdef CONFIG_MIPS_GIC_IPI | ||
433 | static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin) | ||
434 | { | ||
435 | int intr = baseintr + cpu; | ||
436 | gic_intr_map[intr].cpunum = cpu; | ||
437 | gic_intr_map[intr].pin = cpupin; | ||
438 | gic_intr_map[intr].polarity = GIC_POL_POS; | ||
439 | gic_intr_map[intr].trigtype = GIC_TRIG_EDGE; | ||
440 | gic_intr_map[intr].flags = 0; | ||
441 | ipi_map[cpu] |= (1 << (cpupin + 2)); | ||
442 | bitmap_set(ipi_ints, intr, 1); | ||
443 | } | ||
444 | |||
445 | static void __init fill_ipi_map(void) | ||
446 | { | ||
447 | int cpu; | ||
448 | |||
449 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) { | ||
450 | fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1); | ||
451 | fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2); | ||
452 | } | ||
453 | } | ||
454 | #endif | ||
455 | |||
456 | void __init arch_init_ipiirq(int irq, struct irqaction *action) | 276 | void __init arch_init_ipiirq(int irq, struct irqaction *action) |
457 | { | 277 | { |
458 | setup_irq(irq, action); | 278 | setup_irq(irq, action); |
@@ -461,6 +281,8 @@ void __init arch_init_ipiirq(int irq, struct irqaction *action) | |||
461 | 281 | ||
462 | void __init arch_init_irq(void) | 282 | void __init arch_init_irq(void) |
463 | { | 283 | { |
284 | int corehi_irq, i8259_irq; | ||
285 | |||
464 | init_i8259_irqs(); | 286 | init_i8259_irqs(); |
465 | 287 | ||
466 | if (!cpu_has_veic) | 288 | if (!cpu_has_veic) |
@@ -471,12 +293,12 @@ void __init arch_init_irq(void) | |||
471 | gic_present = 1; | 293 | gic_present = 1; |
472 | } else { | 294 | } else { |
473 | if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) { | 295 | if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) { |
474 | _msc01_biu_base = (unsigned long) | 296 | _msc01_biu_base = ioremap_nocache(MSC01_BIU_REG_BASE, |
475 | ioremap_nocache(MSC01_BIU_REG_BASE, | ||
476 | MSC01_BIU_ADDRSPACE_SZ); | 297 | MSC01_BIU_ADDRSPACE_SZ); |
477 | gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) & | 298 | gic_present = |
478 | MSC01_SC_CFG_GICPRES_MSK) >> | 299 | (__raw_readl(_msc01_biu_base + MSC01_SC_CFG_OFS) & |
479 | MSC01_SC_CFG_GICPRES_SHF; | 300 | MSC01_SC_CFG_GICPRES_MSK) >> |
301 | MSC01_SC_CFG_GICPRES_SHF; | ||
480 | } | 302 | } |
481 | } | 303 | } |
482 | if (gic_present) | 304 | if (gic_present) |
@@ -507,63 +329,20 @@ void __init arch_init_irq(void) | |||
507 | msc_nr_irqs); | 329 | msc_nr_irqs); |
508 | } | 330 | } |
509 | 331 | ||
510 | if (cpu_has_veic) { | ||
511 | set_vi_handler(MSC01E_INT_I8259A, malta_hw0_irqdispatch); | ||
512 | set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch); | ||
513 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq); | ||
514 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction); | ||
515 | } else if (cpu_has_vint) { | ||
516 | set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); | ||
517 | set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch); | ||
518 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); | ||
519 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, | ||
520 | &corehi_irqaction); | ||
521 | } else { | ||
522 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); | ||
523 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, | ||
524 | &corehi_irqaction); | ||
525 | } | ||
526 | |||
527 | if (gic_present) { | 332 | if (gic_present) { |
528 | /* FIXME */ | ||
529 | int i; | 333 | int i; |
530 | #if defined(CONFIG_MIPS_GIC_IPI) | 334 | |
531 | gic_call_int_base = GIC_NUM_INTRS - | 335 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, MIPSCPU_INT_GIC, |
532 | (NR_CPUS - nr_cpu_ids) * 2 - nr_cpu_ids; | 336 | MIPS_GIC_IRQ_BASE); |
533 | gic_resched_int_base = gic_call_int_base - nr_cpu_ids; | ||
534 | fill_ipi_map(); | ||
535 | #endif | ||
536 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, | ||
537 | ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); | ||
538 | if (!mips_cm_present()) { | 337 | if (!mips_cm_present()) { |
539 | /* Enable the GIC */ | 338 | /* Enable the GIC */ |
540 | i = REG(_msc01_biu_base, MSC01_SC_CFG); | 339 | i = __raw_readl(_msc01_biu_base + MSC01_SC_CFG_OFS); |
541 | REG(_msc01_biu_base, MSC01_SC_CFG) = | 340 | __raw_writel(i | (0x1 << MSC01_SC_CFG_GICENA_SHF), |
542 | (i | (0x1 << MSC01_SC_CFG_GICENA_SHF)); | 341 | _msc01_biu_base + MSC01_SC_CFG_OFS); |
543 | pr_debug("GIC Enabled\n"); | 342 | pr_debug("GIC Enabled\n"); |
544 | } | 343 | } |
545 | #if defined(CONFIG_MIPS_GIC_IPI) | 344 | i8259_irq = MIPS_GIC_IRQ_BASE + GIC_INT_I8259A; |
546 | /* set up ipi interrupts */ | 345 | corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI; |
547 | if (cpu_has_vint) { | ||
548 | set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch); | ||
549 | set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch); | ||
550 | } | ||
551 | /* Argh.. this really needs sorting out.. */ | ||
552 | pr_info("CPU%d: status register was %08x\n", | ||
553 | smp_processor_id(), read_c0_status()); | ||
554 | write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4); | ||
555 | pr_info("CPU%d: status register now %08x\n", | ||
556 | smp_processor_id(), read_c0_status()); | ||
557 | write_c0_status(0x1100dc00); | ||
558 | pr_info("CPU%d: status register frc %08x\n", | ||
559 | smp_processor_id(), read_c0_status()); | ||
560 | for (i = 0; i < nr_cpu_ids; i++) { | ||
561 | arch_init_ipiirq(MIPS_GIC_IRQ_BASE + | ||
562 | GIC_RESCHED_INT(i), &irq_resched); | ||
563 | arch_init_ipiirq(MIPS_GIC_IRQ_BASE + | ||
564 | GIC_CALL_INT(i), &irq_call); | ||
565 | } | ||
566 | #endif | ||
567 | } else { | 346 | } else { |
568 | #if defined(CONFIG_MIPS_MT_SMP) | 347 | #if defined(CONFIG_MIPS_MT_SMP) |
569 | /* set up ipi interrupts */ | 348 | /* set up ipi interrupts */ |
@@ -573,12 +352,6 @@ void __init arch_init_irq(void) | |||
573 | cpu_ipi_resched_irq = MSC01E_INT_SW0; | 352 | cpu_ipi_resched_irq = MSC01E_INT_SW0; |
574 | cpu_ipi_call_irq = MSC01E_INT_SW1; | 353 | cpu_ipi_call_irq = MSC01E_INT_SW1; |
575 | } else { | 354 | } else { |
576 | if (cpu_has_vint) { | ||
577 | set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, | ||
578 | ipi_resched_dispatch); | ||
579 | set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, | ||
580 | ipi_call_dispatch); | ||
581 | } | ||
582 | cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + | 355 | cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + |
583 | MIPS_CPU_IPI_RESCHED_IRQ; | 356 | MIPS_CPU_IPI_RESCHED_IRQ; |
584 | cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + | 357 | cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + |
@@ -587,7 +360,21 @@ void __init arch_init_irq(void) | |||
587 | arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); | 360 | arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); |
588 | arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); | 361 | arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); |
589 | #endif | 362 | #endif |
363 | if (cpu_has_veic) { | ||
364 | set_vi_handler(MSC01E_INT_I8259A, | ||
365 | malta_hw0_irqdispatch); | ||
366 | set_vi_handler(MSC01E_INT_COREHI, | ||
367 | corehi_irqdispatch); | ||
368 | i8259_irq = MSC01E_INT_BASE + MSC01E_INT_I8259A; | ||
369 | corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI; | ||
370 | } else { | ||
371 | i8259_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_I8259A; | ||
372 | corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI; | ||
373 | } | ||
590 | } | 374 | } |
375 | |||
376 | setup_irq(i8259_irq, &i8259irq); | ||
377 | setup_irq(corehi_irq, &corehi_irqaction); | ||
591 | } | 378 | } |
592 | 379 | ||
593 | void malta_be_init(void) | 380 | void malta_be_init(void) |
@@ -714,37 +501,3 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup) | |||
714 | 501 | ||
715 | return retval; | 502 | return retval; |
716 | } | 503 | } |
717 | |||
718 | void gic_enable_interrupt(int irq_vec) | ||
719 | { | ||
720 | GIC_SET_INTR_MASK(irq_vec); | ||
721 | } | ||
722 | |||
723 | void gic_disable_interrupt(int irq_vec) | ||
724 | { | ||
725 | GIC_CLR_INTR_MASK(irq_vec); | ||
726 | } | ||
727 | |||
728 | void gic_irq_ack(struct irq_data *d) | ||
729 | { | ||
730 | int irq = (d->irq - gic_irq_base); | ||
731 | |||
732 | GIC_CLR_INTR_MASK(irq); | ||
733 | |||
734 | if (gic_irq_flags[irq] & GIC_TRIG_EDGE) | ||
735 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); | ||
736 | } | ||
737 | |||
738 | void gic_finish_irq(struct irq_data *d) | ||
739 | { | ||
740 | /* Enable interrupts. */ | ||
741 | GIC_SET_INTR_MASK(d->irq - gic_irq_base); | ||
742 | } | ||
743 | |||
744 | void __init gic_platform_init(int irqs, struct irq_chip *irq_controller) | ||
745 | { | ||
746 | int i; | ||
747 | |||
748 | for (i = gic_irq_base; i < (gic_irq_base + irqs); i++) | ||
749 | irq_set_chip(i, irq_controller); | ||
750 | } | ||
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 3778a359f3ad..ce02dbdedc62 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
25 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/irqchip/mips-gic.h> | ||
27 | #include <linux/timex.h> | 28 | #include <linux/timex.h> |
28 | #include <linux/mc146818rtc.h> | 29 | #include <linux/mc146818rtc.h> |
29 | 30 | ||
@@ -37,7 +38,6 @@ | |||
37 | #include <asm/time.h> | 38 | #include <asm/time.h> |
38 | #include <asm/mc146818-time.h> | 39 | #include <asm/mc146818-time.h> |
39 | #include <asm/msc01_ic.h> | 40 | #include <asm/msc01_ic.h> |
40 | #include <asm/gic.h> | ||
41 | 41 | ||
42 | #include <asm/mips-boards/generic.h> | 42 | #include <asm/mips-boards/generic.h> |
43 | #include <asm/mips-boards/maltaint.h> | 43 | #include <asm/mips-boards/maltaint.h> |
@@ -46,6 +46,8 @@ static int mips_cpu_timer_irq; | |||
46 | static int mips_cpu_perf_irq; | 46 | static int mips_cpu_perf_irq; |
47 | extern int cp0_perfcount_irq; | 47 | extern int cp0_perfcount_irq; |
48 | 48 | ||
49 | static unsigned int gic_frequency; | ||
50 | |||
49 | static void mips_timer_dispatch(void) | 51 | static void mips_timer_dispatch(void) |
50 | { | 52 | { |
51 | do_IRQ(mips_cpu_timer_irq); | 53 | do_IRQ(mips_cpu_timer_irq); |
@@ -70,9 +72,7 @@ static void __init estimate_frequencies(void) | |||
70 | { | 72 | { |
71 | unsigned long flags; | 73 | unsigned long flags; |
72 | unsigned int count, start; | 74 | unsigned int count, start; |
73 | #ifdef CONFIG_IRQ_GIC | 75 | cycle_t giccount = 0, gicstart = 0; |
74 | unsigned int giccount = 0, gicstart = 0; | ||
75 | #endif | ||
76 | 76 | ||
77 | #if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ | 77 | #if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ |
78 | mips_hpt_frequency = CONFIG_KVM_GUEST_TIMER_FREQ * 1000000; | 78 | mips_hpt_frequency = CONFIG_KVM_GUEST_TIMER_FREQ * 1000000; |
@@ -87,32 +87,26 @@ static void __init estimate_frequencies(void) | |||
87 | 87 | ||
88 | /* Initialize counters. */ | 88 | /* Initialize counters. */ |
89 | start = read_c0_count(); | 89 | start = read_c0_count(); |
90 | #ifdef CONFIG_IRQ_GIC | ||
91 | if (gic_present) | 90 | if (gic_present) |
92 | GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), gicstart); | 91 | gicstart = gic_read_count(); |
93 | #endif | ||
94 | 92 | ||
95 | /* Read counter exactly on falling edge of update flag. */ | 93 | /* Read counter exactly on falling edge of update flag. */ |
96 | while (CMOS_READ(RTC_REG_A) & RTC_UIP); | 94 | while (CMOS_READ(RTC_REG_A) & RTC_UIP); |
97 | while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); | 95 | while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); |
98 | 96 | ||
99 | count = read_c0_count(); | 97 | count = read_c0_count(); |
100 | #ifdef CONFIG_IRQ_GIC | ||
101 | if (gic_present) | 98 | if (gic_present) |
102 | GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), giccount); | 99 | giccount = gic_read_count(); |
103 | #endif | ||
104 | 100 | ||
105 | local_irq_restore(flags); | 101 | local_irq_restore(flags); |
106 | 102 | ||
107 | count -= start; | 103 | count -= start; |
108 | mips_hpt_frequency = count; | 104 | mips_hpt_frequency = count; |
109 | 105 | ||
110 | #ifdef CONFIG_IRQ_GIC | ||
111 | if (gic_present) { | 106 | if (gic_present) { |
112 | giccount -= gicstart; | 107 | giccount -= gicstart; |
113 | gic_frequency = giccount; | 108 | gic_frequency = giccount; |
114 | } | 109 | } |
115 | #endif | ||
116 | } | 110 | } |
117 | 111 | ||
118 | void read_persistent_clock(struct timespec *ts) | 112 | void read_persistent_clock(struct timespec *ts) |
@@ -121,35 +115,30 @@ void read_persistent_clock(struct timespec *ts) | |||
121 | ts->tv_nsec = 0; | 115 | ts->tv_nsec = 0; |
122 | } | 116 | } |
123 | 117 | ||
124 | static void __init plat_perf_setup(void) | 118 | int get_c0_perfcount_int(void) |
125 | { | 119 | { |
126 | #ifdef MSC01E_INT_BASE | ||
127 | if (cpu_has_veic) { | 120 | if (cpu_has_veic) { |
128 | set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch); | 121 | set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch); |
129 | mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR; | 122 | mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR; |
130 | } else | 123 | } else if (gic_present) { |
131 | #endif | 124 | mips_cpu_perf_irq = gic_get_c0_perfcount_int(); |
132 | if (cp0_perfcount_irq >= 0) { | 125 | } else if (cp0_perfcount_irq >= 0) { |
133 | if (cpu_has_vint) | ||
134 | set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch); | ||
135 | mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; | 126 | mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; |
136 | #ifdef CONFIG_SMP | 127 | } else { |
137 | irq_set_handler(mips_cpu_perf_irq, handle_percpu_irq); | 128 | mips_cpu_perf_irq = -1; |
138 | #endif | ||
139 | } | 129 | } |
130 | |||
131 | return mips_cpu_perf_irq; | ||
140 | } | 132 | } |
141 | 133 | ||
142 | unsigned int get_c0_compare_int(void) | 134 | unsigned int get_c0_compare_int(void) |
143 | { | 135 | { |
144 | #ifdef MSC01E_INT_BASE | ||
145 | if (cpu_has_veic) { | 136 | if (cpu_has_veic) { |
146 | set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); | 137 | set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); |
147 | mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; | 138 | mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; |
148 | } else | 139 | } else if (gic_present) { |
149 | #endif | 140 | mips_cpu_timer_irq = gic_get_c0_compare_int(); |
150 | { | 141 | } else { |
151 | if (cpu_has_vint) | ||
152 | set_vi_handler(cp0_compare_irq, mips_timer_dispatch); | ||
153 | mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; | 142 | mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; |
154 | } | 143 | } |
155 | 144 | ||
@@ -191,16 +180,14 @@ void __init plat_time_init(void) | |||
191 | setup_pit_timer(); | 180 | setup_pit_timer(); |
192 | #endif | 181 | #endif |
193 | 182 | ||
194 | #ifdef CONFIG_IRQ_GIC | 183 | #ifdef CONFIG_MIPS_GIC |
195 | if (gic_present) { | 184 | if (gic_present) { |
196 | freq = freqround(gic_frequency, 5000); | 185 | freq = freqround(gic_frequency, 5000); |
197 | printk("GIC frequency %d.%02d MHz\n", freq/1000000, | 186 | printk("GIC frequency %d.%02d MHz\n", freq/1000000, |
198 | (freq%1000000)*100/1000000); | 187 | (freq%1000000)*100/1000000); |
199 | #ifdef CONFIG_CSRC_GIC | 188 | #ifdef CONFIG_CLKSRC_MIPS_GIC |
200 | gic_clocksource_init(gic_frequency); | 189 | gic_clocksource_init(gic_frequency); |
201 | #endif | 190 | #endif |
202 | } | 191 | } |
203 | #endif | 192 | #endif |
204 | |||
205 | plat_perf_setup(); | ||
206 | } | 193 | } |
diff --git a/arch/mips/mti-sead3/sead3-ehci.c b/arch/mips/mti-sead3/sead3-ehci.c index 772fc056a92d..014dd7ba4d68 100644 --- a/arch/mips/mti-sead3/sead3-ehci.c +++ b/arch/mips/mti-sead3/sead3-ehci.c | |||
@@ -9,6 +9,9 @@ | |||
9 | #include <linux/irq.h> | 9 | #include <linux/irq.h> |
10 | #include <linux/dma-mapping.h> | 10 | #include <linux/dma-mapping.h> |
11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
12 | #include <linux/irqchip/mips-gic.h> | ||
13 | |||
14 | #include <asm/mips-boards/sead3int.h> | ||
12 | 15 | ||
13 | struct resource ehci_resources[] = { | 16 | struct resource ehci_resources[] = { |
14 | { | 17 | { |
@@ -17,7 +20,6 @@ struct resource ehci_resources[] = { | |||
17 | .flags = IORESOURCE_MEM | 20 | .flags = IORESOURCE_MEM |
18 | }, | 21 | }, |
19 | { | 22 | { |
20 | .start = MIPS_CPU_IRQ_BASE + 2, | ||
21 | .flags = IORESOURCE_IRQ | 23 | .flags = IORESOURCE_IRQ |
22 | } | 24 | } |
23 | }; | 25 | }; |
@@ -37,6 +39,10 @@ static struct platform_device ehci_device = { | |||
37 | 39 | ||
38 | static int __init ehci_init(void) | 40 | static int __init ehci_init(void) |
39 | { | 41 | { |
42 | if (gic_present) | ||
43 | ehci_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_EHCI; | ||
44 | else | ||
45 | ehci_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_EHCI; | ||
40 | return platform_device_register(&ehci_device); | 46 | return platform_device_register(&ehci_device); |
41 | } | 47 | } |
42 | 48 | ||
diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c index 6a560ac03def..e31e17f81eef 100644 --- a/arch/mips/mti-sead3/sead3-int.c +++ b/arch/mips/mti-sead3/sead3-int.c | |||
@@ -7,9 +7,9 @@ | |||
7 | */ | 7 | */ |
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/irq.h> | 9 | #include <linux/irq.h> |
10 | #include <linux/irqchip/mips-gic.h> | ||
10 | #include <linux/io.h> | 11 | #include <linux/io.h> |
11 | 12 | ||
12 | #include <asm/gic.h> | ||
13 | #include <asm/irq_cpu.h> | 13 | #include <asm/irq_cpu.h> |
14 | #include <asm/setup.h> | 14 | #include <asm/setup.h> |
15 | 15 | ||
@@ -20,138 +20,23 @@ | |||
20 | #define SEAD_CONFIG_BASE 0x1b100110 | 20 | #define SEAD_CONFIG_BASE 0x1b100110 |
21 | #define SEAD_CONFIG_SIZE 4 | 21 | #define SEAD_CONFIG_SIZE 4 |
22 | 22 | ||
23 | static unsigned long sead3_config_reg; | 23 | static void __iomem *sead3_config_reg; |
24 | |||
25 | /* | ||
26 | * This table defines the setup for each external GIC interrupt. It is | ||
27 | * indexed by interrupt number. | ||
28 | */ | ||
29 | #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK | ||
30 | static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { | ||
31 | { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
32 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
33 | { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
34 | { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
35 | { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
36 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
37 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
38 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
39 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
40 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
41 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
42 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
43 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
44 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
45 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
46 | { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED }, | ||
47 | }; | ||
48 | |||
49 | asmlinkage void plat_irq_dispatch(void) | ||
50 | { | ||
51 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; | ||
52 | int irq; | ||
53 | |||
54 | irq = (fls(pending) - CAUSEB_IP - 1); | ||
55 | if (irq >= 0) | ||
56 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | ||
57 | else | ||
58 | spurious_interrupt(); | ||
59 | } | ||
60 | 24 | ||
61 | void __init arch_init_irq(void) | 25 | void __init arch_init_irq(void) |
62 | { | 26 | { |
63 | int i; | 27 | if (!cpu_has_veic) |
64 | |||
65 | if (!cpu_has_veic) { | ||
66 | mips_cpu_irq_init(); | 28 | mips_cpu_irq_init(); |
67 | 29 | ||
68 | if (cpu_has_vint) { | 30 | sead3_config_reg = ioremap_nocache(SEAD_CONFIG_BASE, SEAD_CONFIG_SIZE); |
69 | /* install generic handler */ | 31 | gic_present = (__raw_readl(sead3_config_reg) & |
70 | for (i = 0; i < 8; i++) | 32 | SEAD_CONFIG_GIC_PRESENT_MSK) >> |
71 | set_vi_handler(i, plat_irq_dispatch); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | sead3_config_reg = (unsigned long)ioremap_nocache(SEAD_CONFIG_BASE, | ||
76 | SEAD_CONFIG_SIZE); | ||
77 | gic_present = (REG32(sead3_config_reg) & SEAD_CONFIG_GIC_PRESENT_MSK) >> | ||
78 | SEAD_CONFIG_GIC_PRESENT_SHF; | 33 | SEAD_CONFIG_GIC_PRESENT_SHF; |
79 | pr_info("GIC: %spresent\n", (gic_present) ? "" : "not "); | 34 | pr_info("GIC: %spresent\n", (gic_present) ? "" : "not "); |
80 | pr_info("EIC: %s\n", | 35 | pr_info("EIC: %s\n", |
81 | (current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off"); | 36 | (current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off"); |
82 | 37 | ||
83 | if (gic_present) | 38 | if (gic_present) |
84 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, | 39 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, CPU_INT_GIC, |
85 | ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); | 40 | MIPS_GIC_IRQ_BASE); |
86 | } | ||
87 | |||
88 | void gic_enable_interrupt(int irq_vec) | ||
89 | { | ||
90 | unsigned int i, irq_source; | ||
91 | |||
92 | /* enable all the interrupts associated with this vector */ | ||
93 | for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) { | ||
94 | irq_source = gic_shared_intr_map[irq_vec].intr_list[i]; | ||
95 | GIC_SET_INTR_MASK(irq_source); | ||
96 | } | ||
97 | /* enable all local interrupts associated with this vector */ | ||
98 | if (gic_shared_intr_map[irq_vec].local_intr_mask) { | ||
99 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0); | ||
100 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), | ||
101 | gic_shared_intr_map[irq_vec].local_intr_mask); | ||
102 | } | ||
103 | } | 41 | } |
104 | 42 | ||
105 | void gic_disable_interrupt(int irq_vec) | ||
106 | { | ||
107 | unsigned int i, irq_source; | ||
108 | |||
109 | /* disable all the interrupts associated with this vector */ | ||
110 | for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) { | ||
111 | irq_source = gic_shared_intr_map[irq_vec].intr_list[i]; | ||
112 | GIC_CLR_INTR_MASK(irq_source); | ||
113 | } | ||
114 | /* disable all local interrupts associated with this vector */ | ||
115 | if (gic_shared_intr_map[irq_vec].local_intr_mask) { | ||
116 | GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0); | ||
117 | GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), | ||
118 | gic_shared_intr_map[irq_vec].local_intr_mask); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | void gic_irq_ack(struct irq_data *d) | ||
123 | { | ||
124 | GIC_CLR_INTR_MASK(d->irq - gic_irq_base); | ||
125 | } | ||
126 | |||
127 | void gic_finish_irq(struct irq_data *d) | ||
128 | { | ||
129 | unsigned int irq = (d->irq - gic_irq_base); | ||
130 | unsigned int i, irq_source; | ||
131 | |||
132 | /* Clear edge detectors. */ | ||
133 | for (i = 0; i < gic_shared_intr_map[irq].num_shared_intr; i++) { | ||
134 | irq_source = gic_shared_intr_map[irq].intr_list[i]; | ||
135 | if (gic_irq_flags[irq_source] & GIC_TRIG_EDGE) | ||
136 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq_source); | ||
137 | } | ||
138 | |||
139 | /* Enable interrupts. */ | ||
140 | GIC_SET_INTR_MASK(irq); | ||
141 | } | ||
142 | |||
143 | void __init gic_platform_init(int irqs, struct irq_chip *irq_controller) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | /* | ||
148 | * For non-EIC mode, we want to setup the GIC in pass-through | ||
149 | * mode, as if the GIC didn't exist. Do not map any interrupts | ||
150 | * for an external interrupt controller. | ||
151 | */ | ||
152 | if (!cpu_has_veic) | ||
153 | return; | ||
154 | |||
155 | for (i = gic_irq_base; i < (gic_irq_base + irqs); i++) | ||
156 | irq_set_chip_and_handler(i, irq_controller, handle_percpu_irq); | ||
157 | } | ||
diff --git a/arch/mips/mti-sead3/sead3-net.c b/arch/mips/mti-sead3/sead3-net.c index dd11e7eb771c..46176b804576 100644 --- a/arch/mips/mti-sead3/sead3-net.c +++ b/arch/mips/mti-sead3/sead3-net.c | |||
@@ -7,9 +7,12 @@ | |||
7 | */ | 7 | */ |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/irq.h> | 9 | #include <linux/irq.h> |
10 | #include <linux/irqchip/mips-gic.h> | ||
10 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
11 | #include <linux/smsc911x.h> | 12 | #include <linux/smsc911x.h> |
12 | 13 | ||
14 | #include <asm/mips-boards/sead3int.h> | ||
15 | |||
13 | static struct smsc911x_platform_config sead3_smsc911x_data = { | 16 | static struct smsc911x_platform_config sead3_smsc911x_data = { |
14 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, | 17 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, |
15 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, | 18 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, |
@@ -17,14 +20,13 @@ static struct smsc911x_platform_config sead3_smsc911x_data = { | |||
17 | .phy_interface = PHY_INTERFACE_MODE_MII, | 20 | .phy_interface = PHY_INTERFACE_MODE_MII, |
18 | }; | 21 | }; |
19 | 22 | ||
20 | struct resource sead3_net_resourcess[] = { | 23 | struct resource sead3_net_resources[] = { |
21 | { | 24 | { |
22 | .start = 0x1f010000, | 25 | .start = 0x1f010000, |
23 | .end = 0x1f01ffff, | 26 | .end = 0x1f01ffff, |
24 | .flags = IORESOURCE_MEM | 27 | .flags = IORESOURCE_MEM |
25 | }, | 28 | }, |
26 | { | 29 | { |
27 | .start = MIPS_CPU_IRQ_BASE + 6, | ||
28 | .flags = IORESOURCE_IRQ | 30 | .flags = IORESOURCE_IRQ |
29 | } | 31 | } |
30 | }; | 32 | }; |
@@ -35,12 +37,16 @@ static struct platform_device sead3_net_device = { | |||
35 | .dev = { | 37 | .dev = { |
36 | .platform_data = &sead3_smsc911x_data, | 38 | .platform_data = &sead3_smsc911x_data, |
37 | }, | 39 | }, |
38 | .num_resources = ARRAY_SIZE(sead3_net_resourcess), | 40 | .num_resources = ARRAY_SIZE(sead3_net_resources), |
39 | .resource = sead3_net_resourcess | 41 | .resource = sead3_net_resources |
40 | }; | 42 | }; |
41 | 43 | ||
42 | static int __init sead3_net_init(void) | 44 | static int __init sead3_net_init(void) |
43 | { | 45 | { |
46 | if (gic_present) | ||
47 | sead3_net_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_NET; | ||
48 | else | ||
49 | sead3_net_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_NET; | ||
44 | return platform_device_register(&sead3_net_device); | 50 | return platform_device_register(&sead3_net_device); |
45 | } | 51 | } |
46 | 52 | ||
diff --git a/arch/mips/mti-sead3/sead3-platform.c b/arch/mips/mti-sead3/sead3-platform.c index 6c3b33dbed18..53ee6f1f018d 100644 --- a/arch/mips/mti-sead3/sead3-platform.c +++ b/arch/mips/mti-sead3/sead3-platform.c | |||
@@ -7,12 +7,15 @@ | |||
7 | */ | 7 | */ |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/irqchip/mips-gic.h> | ||
10 | #include <linux/serial_8250.h> | 11 | #include <linux/serial_8250.h> |
11 | 12 | ||
12 | #define UART(base, int) \ | 13 | #include <asm/mips-boards/sead3int.h> |
14 | |||
15 | #define UART(base) \ | ||
13 | { \ | 16 | { \ |
14 | .mapbase = base, \ | 17 | .mapbase = base, \ |
15 | .irq = int, \ | 18 | .irq = -1, \ |
16 | .uartclk = 14745600, \ | 19 | .uartclk = 14745600, \ |
17 | .iotype = UPIO_MEM32, \ | 20 | .iotype = UPIO_MEM32, \ |
18 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \ | 21 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \ |
@@ -20,8 +23,8 @@ | |||
20 | } | 23 | } |
21 | 24 | ||
22 | static struct plat_serial8250_port uart8250_data[] = { | 25 | static struct plat_serial8250_port uart8250_data[] = { |
23 | UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */ | 26 | UART(0x1f000900), /* ttyS0 = USB */ |
24 | UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */ | 27 | UART(0x1f000800), /* ttyS1 = RS232 */ |
25 | { }, | 28 | { }, |
26 | }; | 29 | }; |
27 | 30 | ||
@@ -35,6 +38,13 @@ static struct platform_device uart8250_device = { | |||
35 | 38 | ||
36 | static int __init uart8250_init(void) | 39 | static int __init uart8250_init(void) |
37 | { | 40 | { |
41 | if (gic_present) { | ||
42 | uart8250_data[0].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART0; | ||
43 | uart8250_data[1].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART1; | ||
44 | } else { | ||
45 | uart8250_data[0].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART0; | ||
46 | uart8250_data[1].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART1; | ||
47 | } | ||
38 | return platform_device_register(&uart8250_device); | 48 | return platform_device_register(&uart8250_device); |
39 | } | 49 | } |
40 | 50 | ||
diff --git a/arch/mips/mti-sead3/sead3-serial.c b/arch/mips/mti-sead3/sead3-serial.c deleted file mode 100644 index bc52705bbee4..000000000000 --- a/arch/mips/mti-sead3/sead3-serial.c +++ /dev/null | |||
@@ -1,45 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | ||
7 | */ | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/serial_8250.h> | ||
11 | |||
12 | #define UART(base, int) \ | ||
13 | { \ | ||
14 | .mapbase = base, \ | ||
15 | .irq = int, \ | ||
16 | .uartclk = 14745600, \ | ||
17 | .iotype = UPIO_MEM32, \ | ||
18 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \ | ||
19 | .regshift = 2, \ | ||
20 | } | ||
21 | |||
22 | static struct plat_serial8250_port uart8250_data[] = { | ||
23 | UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */ | ||
24 | UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */ | ||
25 | { }, | ||
26 | }; | ||
27 | |||
28 | static struct platform_device uart8250_device = { | ||
29 | .name = "serial8250", | ||
30 | .id = PLAT8250_DEV_PLATFORM, | ||
31 | .dev = { | ||
32 | .platform_data = uart8250_data, | ||
33 | }, | ||
34 | }; | ||
35 | |||
36 | static int __init uart8250_init(void) | ||
37 | { | ||
38 | return platform_device_register(&uart8250_device); | ||
39 | } | ||
40 | |||
41 | module_init(uart8250_init); | ||
42 | |||
43 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
44 | MODULE_LICENSE("GPL"); | ||
45 | MODULE_DESCRIPTION("8250 UART probe driver for the SEAD-3 platform"); | ||
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c index 678d03d53c60..ec1dd2491f96 100644 --- a/arch/mips/mti-sead3/sead3-time.c +++ b/arch/mips/mti-sead3/sead3-time.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | 6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. |
7 | */ | 7 | */ |
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/irqchip/mips-gic.h> | ||
9 | 10 | ||
10 | #include <asm/cpu.h> | 11 | #include <asm/cpu.h> |
11 | #include <asm/setup.h> | 12 | #include <asm/setup.h> |
@@ -13,19 +14,6 @@ | |||
13 | #include <asm/irq.h> | 14 | #include <asm/irq.h> |
14 | #include <asm/mips-boards/generic.h> | 15 | #include <asm/mips-boards/generic.h> |
15 | 16 | ||
16 | static int mips_cpu_timer_irq; | ||
17 | static int mips_cpu_perf_irq; | ||
18 | |||
19 | static void mips_timer_dispatch(void) | ||
20 | { | ||
21 | do_IRQ(mips_cpu_timer_irq); | ||
22 | } | ||
23 | |||
24 | static void mips_perf_dispatch(void) | ||
25 | { | ||
26 | do_IRQ(mips_cpu_perf_irq); | ||
27 | } | ||
28 | |||
29 | static void __iomem *status_reg = (void __iomem *)0xbf000410; | 17 | static void __iomem *status_reg = (void __iomem *)0xbf000410; |
30 | 18 | ||
31 | /* | 19 | /* |
@@ -81,21 +69,20 @@ void read_persistent_clock(struct timespec *ts) | |||
81 | ts->tv_nsec = 0; | 69 | ts->tv_nsec = 0; |
82 | } | 70 | } |
83 | 71 | ||
84 | static void __init plat_perf_setup(void) | 72 | int get_c0_perfcount_int(void) |
85 | { | 73 | { |
86 | if (cp0_perfcount_irq >= 0) { | 74 | if (gic_present) |
87 | if (cpu_has_vint) | 75 | return gic_get_c0_compare_int(); |
88 | set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch); | 76 | if (cp0_perfcount_irq >= 0) |
89 | mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; | 77 | return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; |
90 | } | 78 | return -1; |
91 | } | 79 | } |
92 | 80 | ||
93 | unsigned int get_c0_compare_int(void) | 81 | unsigned int get_c0_compare_int(void) |
94 | { | 82 | { |
95 | if (cpu_has_vint) | 83 | if (gic_present) |
96 | set_vi_handler(cp0_compare_irq, mips_timer_dispatch); | 84 | return gic_get_c0_compare_int(); |
97 | mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; | 85 | return MIPS_CPU_IRQ_BASE + cp0_compare_irq; |
98 | return mips_cpu_timer_irq; | ||
99 | } | 86 | } |
100 | 87 | ||
101 | void __init plat_time_init(void) | 88 | void __init plat_time_init(void) |
@@ -108,6 +95,4 @@ void __init plat_time_init(void) | |||
108 | (est_freq % 1000000) * 100 / 1000000); | 95 | (est_freq % 1000000) * 100 / 1000000); |
109 | 96 | ||
110 | mips_scroll_message(); | 97 | mips_scroll_message(); |
111 | |||
112 | plat_perf_setup(); | ||
113 | } | 98 | } |
diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile index 9c0a6782c091..070afdb297df 100644 --- a/arch/mips/oprofile/Makefile +++ b/arch/mips/oprofile/Makefile | |||
@@ -14,3 +14,4 @@ oprofile-$(CONFIG_CPU_R10000) += op_model_mipsxx.o | |||
14 | oprofile-$(CONFIG_CPU_SB1) += op_model_mipsxx.o | 14 | oprofile-$(CONFIG_CPU_SB1) += op_model_mipsxx.o |
15 | oprofile-$(CONFIG_CPU_XLR) += op_model_mipsxx.o | 15 | oprofile-$(CONFIG_CPU_XLR) += op_model_mipsxx.o |
16 | oprofile-$(CONFIG_CPU_LOONGSON2) += op_model_loongson2.o | 16 | oprofile-$(CONFIG_CPU_LOONGSON2) += op_model_loongson2.o |
17 | oprofile-$(CONFIG_CPU_LOONGSON3) += op_model_loongson3.o | ||
diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c index 83a1dfd8f0e3..5e645c9a3162 100644 --- a/arch/mips/oprofile/backtrace.c +++ b/arch/mips/oprofile/backtrace.c | |||
@@ -65,7 +65,7 @@ static inline int is_end_of_function_marker(union mips_instruction *ip) | |||
65 | * - handle cases where the stack is adjusted inside a function | 65 | * - handle cases where the stack is adjusted inside a function |
66 | * (generally doesn't happen) | 66 | * (generally doesn't happen) |
67 | * - find optimal value for max_instr_check | 67 | * - find optimal value for max_instr_check |
68 | * - try to find a way to handle leaf functions | 68 | * - try to find a better way to handle leaf functions |
69 | */ | 69 | */ |
70 | 70 | ||
71 | static inline int unwind_user_frame(struct stackframe *old_frame, | 71 | static inline int unwind_user_frame(struct stackframe *old_frame, |
@@ -104,7 +104,7 @@ static inline int unwind_user_frame(struct stackframe *old_frame, | |||
104 | } | 104 | } |
105 | 105 | ||
106 | if (!ra_offset || !stack_size) | 106 | if (!ra_offset || !stack_size) |
107 | return -1; | 107 | goto done; |
108 | 108 | ||
109 | if (ra_offset) { | 109 | if (ra_offset) { |
110 | new_frame.ra = old_frame->sp + ra_offset; | 110 | new_frame.ra = old_frame->sp + ra_offset; |
@@ -121,6 +121,7 @@ static inline int unwind_user_frame(struct stackframe *old_frame, | |||
121 | if (new_frame.sp > old_frame->sp) | 121 | if (new_frame.sp > old_frame->sp) |
122 | return -2; | 122 | return -2; |
123 | 123 | ||
124 | done: | ||
124 | new_frame.pc = old_frame->ra; | 125 | new_frame.pc = old_frame->ra; |
125 | *old_frame = new_frame; | 126 | *old_frame = new_frame; |
126 | 127 | ||
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index e74732449478..a26cbe372e06 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | extern struct op_mips_model op_model_mipsxx_ops __weak; | 19 | extern struct op_mips_model op_model_mipsxx_ops __weak; |
20 | extern struct op_mips_model op_model_loongson2_ops __weak; | 20 | extern struct op_mips_model op_model_loongson2_ops __weak; |
21 | extern struct op_mips_model op_model_loongson3_ops __weak; | ||
21 | 22 | ||
22 | static struct op_mips_model *model; | 23 | static struct op_mips_model *model; |
23 | 24 | ||
@@ -104,8 +105,17 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
104 | case CPU_LOONGSON2: | 105 | case CPU_LOONGSON2: |
105 | lmodel = &op_model_loongson2_ops; | 106 | lmodel = &op_model_loongson2_ops; |
106 | break; | 107 | break; |
108 | case CPU_LOONGSON3: | ||
109 | lmodel = &op_model_loongson3_ops; | ||
110 | break; | ||
107 | }; | 111 | }; |
108 | 112 | ||
113 | /* | ||
114 | * Always set the backtrace. This allows unsupported CPU types to still | ||
115 | * use timer-based oprofile. | ||
116 | */ | ||
117 | ops->backtrace = op_mips_backtrace; | ||
118 | |||
109 | if (!lmodel) | 119 | if (!lmodel) |
110 | return -ENODEV; | 120 | return -ENODEV; |
111 | 121 | ||
@@ -121,7 +131,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
121 | ops->start = op_mips_start; | 131 | ops->start = op_mips_start; |
122 | ops->stop = op_mips_stop; | 132 | ops->stop = op_mips_stop; |
123 | ops->cpu_type = lmodel->cpu_type; | 133 | ops->cpu_type = lmodel->cpu_type; |
124 | ops->backtrace = op_mips_backtrace; | ||
125 | 134 | ||
126 | printk(KERN_INFO "oprofile: using %s performance monitoring.\n", | 135 | printk(KERN_INFO "oprofile: using %s performance monitoring.\n", |
127 | lmodel->cpu_type); | 136 | lmodel->cpu_type); |
diff --git a/arch/mips/oprofile/op_model_loongson3.c b/arch/mips/oprofile/op_model_loongson3.c new file mode 100644 index 000000000000..8bcf7fc40f0d --- /dev/null +++ b/arch/mips/oprofile/op_model_loongson3.c | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/cpu.h> | ||
9 | #include <linux/smp.h> | ||
10 | #include <linux/proc_fs.h> | ||
11 | #include <linux/oprofile.h> | ||
12 | #include <linux/spinlock.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <asm/uaccess.h> | ||
15 | #include <irq.h> | ||
16 | #include <loongson.h> | ||
17 | #include "op_impl.h" | ||
18 | |||
19 | #define LOONGSON3_PERFCNT_OVERFLOW (1ULL << 63) | ||
20 | |||
21 | #define LOONGSON3_PERFCTRL_EXL (1UL << 0) | ||
22 | #define LOONGSON3_PERFCTRL_KERNEL (1UL << 1) | ||
23 | #define LOONGSON3_PERFCTRL_SUPERVISOR (1UL << 2) | ||
24 | #define LOONGSON3_PERFCTRL_USER (1UL << 3) | ||
25 | #define LOONGSON3_PERFCTRL_ENABLE (1UL << 4) | ||
26 | #define LOONGSON3_PERFCTRL_W (1UL << 30) | ||
27 | #define LOONGSON3_PERFCTRL_M (1UL << 31) | ||
28 | #define LOONGSON3_PERFCTRL_EVENT(idx, event) \ | ||
29 | (((event) & (idx ? 0x0f : 0x3f)) << 5) | ||
30 | |||
31 | /* Loongson-3 PerfCount performance counter1 register */ | ||
32 | #define read_c0_perflo1() __read_64bit_c0_register($25, 0) | ||
33 | #define write_c0_perflo1(val) __write_64bit_c0_register($25, 0, val) | ||
34 | #define read_c0_perfhi1() __read_64bit_c0_register($25, 1) | ||
35 | #define write_c0_perfhi1(val) __write_64bit_c0_register($25, 1, val) | ||
36 | |||
37 | /* Loongson-3 PerfCount performance counter2 register */ | ||
38 | #define read_c0_perflo2() __read_64bit_c0_register($25, 2) | ||
39 | #define write_c0_perflo2(val) __write_64bit_c0_register($25, 2, val) | ||
40 | #define read_c0_perfhi2() __read_64bit_c0_register($25, 3) | ||
41 | #define write_c0_perfhi2(val) __write_64bit_c0_register($25, 3, val) | ||
42 | |||
43 | static int (*save_perf_irq)(void); | ||
44 | |||
45 | static struct loongson3_register_config { | ||
46 | unsigned int control1; | ||
47 | unsigned int control2; | ||
48 | unsigned long long reset_counter1; | ||
49 | unsigned long long reset_counter2; | ||
50 | int ctr1_enable, ctr2_enable; | ||
51 | } reg; | ||
52 | |||
53 | static void reset_counters(void *arg) | ||
54 | { | ||
55 | write_c0_perfhi1(0); | ||
56 | write_c0_perfhi2(0); | ||
57 | write_c0_perflo1(0xc0000000); | ||
58 | write_c0_perflo2(0x40000000); | ||
59 | } | ||
60 | |||
61 | /* Compute all of the registers in preparation for enabling profiling. */ | ||
62 | static void loongson3_reg_setup(struct op_counter_config *ctr) | ||
63 | { | ||
64 | unsigned int control1 = 0; | ||
65 | unsigned int control2 = 0; | ||
66 | |||
67 | reg.reset_counter1 = 0; | ||
68 | reg.reset_counter2 = 0; | ||
69 | /* Compute the performance counter control word. */ | ||
70 | /* For now count kernel and user mode */ | ||
71 | if (ctr[0].enabled) { | ||
72 | control1 |= LOONGSON3_PERFCTRL_EVENT(0, ctr[0].event) | | ||
73 | LOONGSON3_PERFCTRL_ENABLE; | ||
74 | if (ctr[0].kernel) | ||
75 | control1 |= LOONGSON3_PERFCTRL_KERNEL; | ||
76 | if (ctr[0].user) | ||
77 | control1 |= LOONGSON3_PERFCTRL_USER; | ||
78 | reg.reset_counter1 = 0x8000000000000000ULL - ctr[0].count; | ||
79 | } | ||
80 | |||
81 | if (ctr[1].enabled) { | ||
82 | control2 |= LOONGSON3_PERFCTRL_EVENT(1, ctr[1].event) | | ||
83 | LOONGSON3_PERFCTRL_ENABLE; | ||
84 | if (ctr[1].kernel) | ||
85 | control2 |= LOONGSON3_PERFCTRL_KERNEL; | ||
86 | if (ctr[1].user) | ||
87 | control2 |= LOONGSON3_PERFCTRL_USER; | ||
88 | reg.reset_counter2 = 0x8000000000000000ULL - ctr[1].count; | ||
89 | } | ||
90 | |||
91 | if (ctr[0].enabled) | ||
92 | control1 |= LOONGSON3_PERFCTRL_EXL; | ||
93 | if (ctr[1].enabled) | ||
94 | control2 |= LOONGSON3_PERFCTRL_EXL; | ||
95 | |||
96 | reg.control1 = control1; | ||
97 | reg.control2 = control2; | ||
98 | reg.ctr1_enable = ctr[0].enabled; | ||
99 | reg.ctr2_enable = ctr[1].enabled; | ||
100 | } | ||
101 | |||
102 | /* Program all of the registers in preparation for enabling profiling. */ | ||
103 | static void loongson3_cpu_setup(void *args) | ||
104 | { | ||
105 | uint64_t perfcount1, perfcount2; | ||
106 | |||
107 | perfcount1 = reg.reset_counter1; | ||
108 | perfcount2 = reg.reset_counter2; | ||
109 | write_c0_perfhi1(perfcount1); | ||
110 | write_c0_perfhi2(perfcount2); | ||
111 | } | ||
112 | |||
113 | static void loongson3_cpu_start(void *args) | ||
114 | { | ||
115 | /* Start all counters on current CPU */ | ||
116 | reg.control1 |= (LOONGSON3_PERFCTRL_W|LOONGSON3_PERFCTRL_M); | ||
117 | reg.control2 |= (LOONGSON3_PERFCTRL_W|LOONGSON3_PERFCTRL_M); | ||
118 | |||
119 | if (reg.ctr1_enable) | ||
120 | write_c0_perflo1(reg.control1); | ||
121 | if (reg.ctr2_enable) | ||
122 | write_c0_perflo2(reg.control2); | ||
123 | } | ||
124 | |||
125 | static void loongson3_cpu_stop(void *args) | ||
126 | { | ||
127 | /* Stop all counters on current CPU */ | ||
128 | write_c0_perflo1(0xc0000000); | ||
129 | write_c0_perflo2(0x40000000); | ||
130 | memset(®, 0, sizeof(reg)); | ||
131 | } | ||
132 | |||
133 | static int loongson3_perfcount_handler(void) | ||
134 | { | ||
135 | unsigned long flags; | ||
136 | uint64_t counter1, counter2; | ||
137 | uint32_t cause, handled = IRQ_NONE; | ||
138 | struct pt_regs *regs = get_irq_regs(); | ||
139 | |||
140 | cause = read_c0_cause(); | ||
141 | if (!(cause & CAUSEF_PCI)) | ||
142 | return handled; | ||
143 | |||
144 | counter1 = read_c0_perfhi1(); | ||
145 | counter2 = read_c0_perfhi2(); | ||
146 | |||
147 | local_irq_save(flags); | ||
148 | |||
149 | if (counter1 & LOONGSON3_PERFCNT_OVERFLOW) { | ||
150 | if (reg.ctr1_enable) | ||
151 | oprofile_add_sample(regs, 0); | ||
152 | counter1 = reg.reset_counter1; | ||
153 | } | ||
154 | if (counter2 & LOONGSON3_PERFCNT_OVERFLOW) { | ||
155 | if (reg.ctr2_enable) | ||
156 | oprofile_add_sample(regs, 1); | ||
157 | counter2 = reg.reset_counter2; | ||
158 | } | ||
159 | |||
160 | local_irq_restore(flags); | ||
161 | |||
162 | write_c0_perfhi1(counter1); | ||
163 | write_c0_perfhi2(counter2); | ||
164 | |||
165 | if (!(cause & CAUSEF_TI)) | ||
166 | handled = IRQ_HANDLED; | ||
167 | |||
168 | return handled; | ||
169 | } | ||
170 | |||
171 | static int loongson3_cpu_callback(struct notifier_block *nfb, | ||
172 | unsigned long action, void *hcpu) | ||
173 | { | ||
174 | switch (action) { | ||
175 | case CPU_STARTING: | ||
176 | case CPU_STARTING_FROZEN: | ||
177 | write_c0_perflo1(reg.control1); | ||
178 | write_c0_perflo2(reg.control2); | ||
179 | break; | ||
180 | case CPU_DYING: | ||
181 | case CPU_DYING_FROZEN: | ||
182 | write_c0_perflo1(0xc0000000); | ||
183 | write_c0_perflo2(0x40000000); | ||
184 | break; | ||
185 | } | ||
186 | |||
187 | return NOTIFY_OK; | ||
188 | } | ||
189 | |||
190 | static struct notifier_block loongson3_notifier_block = { | ||
191 | .notifier_call = loongson3_cpu_callback | ||
192 | }; | ||
193 | |||
194 | static int __init loongson3_init(void) | ||
195 | { | ||
196 | on_each_cpu(reset_counters, NULL, 1); | ||
197 | register_hotcpu_notifier(&loongson3_notifier_block); | ||
198 | save_perf_irq = perf_irq; | ||
199 | perf_irq = loongson3_perfcount_handler; | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static void loongson3_exit(void) | ||
205 | { | ||
206 | on_each_cpu(reset_counters, NULL, 1); | ||
207 | unregister_hotcpu_notifier(&loongson3_notifier_block); | ||
208 | perf_irq = save_perf_irq; | ||
209 | } | ||
210 | |||
211 | struct op_mips_model op_model_loongson3_ops = { | ||
212 | .reg_setup = loongson3_reg_setup, | ||
213 | .cpu_setup = loongson3_cpu_setup, | ||
214 | .init = loongson3_init, | ||
215 | .exit = loongson3_exit, | ||
216 | .cpu_start = loongson3_cpu_start, | ||
217 | .cpu_stop = loongson3_cpu_stop, | ||
218 | .cpu_type = "mips/loongson3", | ||
219 | .num_counters = 2 | ||
220 | }; | ||
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 42821ae2d77e..01f721a85c5b 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/smp.h> | 12 | #include <linux/smp.h> |
13 | #include <asm/irq_regs.h> | 13 | #include <asm/irq_regs.h> |
14 | #include <asm/time.h> | ||
14 | 15 | ||
15 | #include "op_impl.h" | 16 | #include "op_impl.h" |
16 | 17 | ||
@@ -35,6 +36,7 @@ | |||
35 | #define M_PERFCTL_COUNT_ALL_THREADS (1UL << 13) | 36 | #define M_PERFCTL_COUNT_ALL_THREADS (1UL << 13) |
36 | 37 | ||
37 | static int (*save_perf_irq)(void); | 38 | static int (*save_perf_irq)(void); |
39 | static int perfcount_irq; | ||
38 | 40 | ||
39 | /* | 41 | /* |
40 | * XLR has only one set of counters per core. Designate the | 42 | * XLR has only one set of counters per core. Designate the |
@@ -431,8 +433,16 @@ static int __init mipsxx_init(void) | |||
431 | save_perf_irq = perf_irq; | 433 | save_perf_irq = perf_irq; |
432 | perf_irq = mipsxx_perfcount_handler; | 434 | perf_irq = mipsxx_perfcount_handler; |
433 | 435 | ||
434 | if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq)) | 436 | if (get_c0_perfcount_int) |
435 | return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int, | 437 | perfcount_irq = get_c0_perfcount_int(); |
438 | else if ((cp0_perfcount_irq >= 0) && | ||
439 | (cp0_compare_irq != cp0_perfcount_irq)) | ||
440 | perfcount_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; | ||
441 | else | ||
442 | perfcount_irq = -1; | ||
443 | |||
444 | if (perfcount_irq >= 0) | ||
445 | return request_irq(perfcount_irq, mipsxx_perfcount_int, | ||
436 | 0, "Perfcounter", save_perf_irq); | 446 | 0, "Perfcounter", save_perf_irq); |
437 | 447 | ||
438 | return 0; | 448 | return 0; |
@@ -442,8 +452,8 @@ static void mipsxx_exit(void) | |||
442 | { | 452 | { |
443 | int counters = op_model_mipsxx_ops.num_counters; | 453 | int counters = op_model_mipsxx_ops.num_counters; |
444 | 454 | ||
445 | if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq)) | 455 | if (perfcount_irq >= 0) |
446 | free_irq(cp0_perfcount_irq, save_perf_irq); | 456 | free_irq(perfcount_irq, save_perf_irq); |
447 | 457 | ||
448 | counters = counters_per_cpu_to_total(counters); | 458 | counters = counters_per_cpu_to_total(counters); |
449 | on_each_cpu(reset_counters, (void *)(long)counters, 1); | 459 | on_each_cpu(reset_counters, (void *)(long)counters, 1); |
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 6523d558ff5a..300591c6278d 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile | |||
@@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o | |||
19 | obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ | 19 | obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ |
20 | ops-bcm63xx.o | 20 | ops-bcm63xx.o |
21 | obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o | 21 | obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o |
22 | obj-$(CONFIG_PCI_AR2315) += pci-ar2315.o | ||
22 | obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o | 23 | obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o |
23 | obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o | 24 | obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o |
24 | obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o | 25 | obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o |
@@ -42,6 +43,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o | |||
42 | obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o | 43 | obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o |
43 | obj-$(CONFIG_LANTIQ) += fixup-lantiq.o | 44 | obj-$(CONFIG_LANTIQ) += fixup-lantiq.o |
44 | obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o | 45 | obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o |
46 | obj-$(CONFIG_SOC_RT2880) += pci-rt2880.o | ||
45 | obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o | 47 | obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o |
46 | obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o | 48 | obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o |
47 | obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o | 49 | obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o |
diff --git a/arch/mips/pci/ops-bcm63xx.c b/arch/mips/pci/ops-bcm63xx.c index 13eea696bbe7..d02eb9d16b55 100644 --- a/arch/mips/pci/ops-bcm63xx.c +++ b/arch/mips/pci/ops-bcm63xx.c | |||
@@ -469,7 +469,7 @@ static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn) | |||
469 | { | 469 | { |
470 | switch (bus->number) { | 470 | switch (bus->number) { |
471 | case PCIE_BUS_BRIDGE: | 471 | case PCIE_BUS_BRIDGE: |
472 | return (PCI_SLOT(devfn) == 0); | 472 | return PCI_SLOT(devfn) == 0; |
473 | case PCIE_BUS_DEVICE: | 473 | case PCIE_BUS_DEVICE: |
474 | if (PCI_SLOT(devfn) == 0) | 474 | if (PCI_SLOT(devfn) == 0) |
475 | return bcm_pcie_readl(PCIE_DLSTATUS_REG) | 475 | return bcm_pcie_readl(PCIE_DLSTATUS_REG) |
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c index a1a7c9f4096e..b9d1fd0ff7e2 100644 --- a/arch/mips/pci/ops-nile4.c +++ b/arch/mips/pci/ops-nile4.c | |||
@@ -13,8 +13,6 @@ | |||
13 | 13 | ||
14 | volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE; | 14 | volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE; |
15 | 15 | ||
16 | static DEFINE_SPINLOCK(nile4_pci_lock); | ||
17 | |||
18 | static int nile4_pcibios_config_access(unsigned char access_type, | 16 | static int nile4_pcibios_config_access(unsigned char access_type, |
19 | struct pci_bus *bus, unsigned int devfn, int where, u32 *val) | 17 | struct pci_bus *bus, unsigned int devfn, int where, u32 *val) |
20 | { | 18 | { |
@@ -76,7 +74,6 @@ static int nile4_pcibios_config_access(unsigned char access_type, | |||
76 | static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn, | 74 | static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn, |
77 | int where, int size, u32 *val) | 75 | int where, int size, u32 *val) |
78 | { | 76 | { |
79 | unsigned long flags; | ||
80 | u32 data = 0; | 77 | u32 data = 0; |
81 | int err; | 78 | int err; |
82 | 79 | ||
@@ -85,11 +82,8 @@ static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn, | |||
85 | else if ((size == 4) && (where & 3)) | 82 | else if ((size == 4) && (where & 3)) |
86 | return PCIBIOS_BAD_REGISTER_NUMBER; | 83 | return PCIBIOS_BAD_REGISTER_NUMBER; |
87 | 84 | ||
88 | spin_lock_irqsave(&nile4_pci_lock, flags); | ||
89 | err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, | 85 | err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, |
90 | &data); | 86 | &data); |
91 | spin_unlock_irqrestore(&nile4_pci_lock, flags); | ||
92 | |||
93 | if (err) | 87 | if (err) |
94 | return err; | 88 | return err; |
95 | 89 | ||
@@ -106,7 +100,6 @@ static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn, | |||
106 | static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn, | 100 | static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn, |
107 | int where, int size, u32 val) | 101 | int where, int size, u32 val) |
108 | { | 102 | { |
109 | unsigned long flags; | ||
110 | u32 data = 0; | 103 | u32 data = 0; |
111 | int err; | 104 | int err; |
112 | 105 | ||
@@ -115,11 +108,8 @@ static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn, | |||
115 | else if ((size == 4) && (where & 3)) | 108 | else if ((size == 4) && (where & 3)) |
116 | return PCIBIOS_BAD_REGISTER_NUMBER; | 109 | return PCIBIOS_BAD_REGISTER_NUMBER; |
117 | 110 | ||
118 | spin_lock_irqsave(&nile4_pci_lock, flags); | ||
119 | err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, | 111 | err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, |
120 | &data); | 112 | &data); |
121 | spin_unlock_irqrestore(&nile4_pci_lock, flags); | ||
122 | |||
123 | if (err) | 113 | if (err) |
124 | return err; | 114 | return err; |
125 | 115 | ||
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index 50034f985be1..dd2d9f7e9412 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c | |||
@@ -193,8 +193,6 @@ static void pci_proc_init(void) | |||
193 | } | 193 | } |
194 | #endif /* CONFIG_PROC_FS && PCI_COUNTERS */ | 194 | #endif /* CONFIG_PROC_FS && PCI_COUNTERS */ |
195 | 195 | ||
196 | static DEFINE_SPINLOCK(bpci_lock); | ||
197 | |||
198 | /***************************************************************************** | 196 | /***************************************************************************** |
199 | * | 197 | * |
200 | * STRUCT: pci_io_resource | 198 | * STRUCT: pci_io_resource |
@@ -368,7 +366,6 @@ int msp_pcibios_config_access(unsigned char access_type, | |||
368 | struct msp_pci_regs *preg = (void *)PCI_BASE_REG; | 366 | struct msp_pci_regs *preg = (void *)PCI_BASE_REG; |
369 | unsigned char bus_num = bus->number; | 367 | unsigned char bus_num = bus->number; |
370 | unsigned char dev_fn = (unsigned char)devfn; | 368 | unsigned char dev_fn = (unsigned char)devfn; |
371 | unsigned long flags; | ||
372 | unsigned long intr; | 369 | unsigned long intr; |
373 | unsigned long value; | 370 | unsigned long value; |
374 | static char pciirqflag; | 371 | static char pciirqflag; |
@@ -401,10 +398,7 @@ int msp_pcibios_config_access(unsigned char access_type, | |||
401 | } | 398 | } |
402 | 399 | ||
403 | #if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) | 400 | #if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) |
404 | local_irq_save(flags); | ||
405 | vpe_status = dvpe(); | 401 | vpe_status = dvpe(); |
406 | #else | ||
407 | spin_lock_irqsave(&bpci_lock, flags); | ||
408 | #endif | 402 | #endif |
409 | 403 | ||
410 | /* | 404 | /* |
@@ -457,9 +451,6 @@ int msp_pcibios_config_access(unsigned char access_type, | |||
457 | 451 | ||
458 | #if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) | 452 | #if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) |
459 | evpe(vpe_status); | 453 | evpe(vpe_status); |
460 | local_irq_restore(flags); | ||
461 | #else | ||
462 | spin_unlock_irqrestore(&bpci_lock, flags); | ||
463 | #endif | 454 | #endif |
464 | 455 | ||
465 | return -1; | 456 | return -1; |
@@ -467,9 +458,6 @@ int msp_pcibios_config_access(unsigned char access_type, | |||
467 | 458 | ||
468 | #if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) | 459 | #if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) |
469 | evpe(vpe_status); | 460 | evpe(vpe_status); |
470 | local_irq_restore(flags); | ||
471 | #else | ||
472 | spin_unlock_irqrestore(&bpci_lock, flags); | ||
473 | #endif | 461 | #endif |
474 | 462 | ||
475 | return PCIBIOS_SUCCESSFUL; | 463 | return PCIBIOS_SUCCESSFUL; |
diff --git a/arch/mips/pci/pci-ar2315.c b/arch/mips/pci/pci-ar2315.c new file mode 100644 index 000000000000..bd2b3b60da83 --- /dev/null +++ b/arch/mips/pci/pci-ar2315.c | |||
@@ -0,0 +1,511 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or | ||
3 | * modify it under the terms of the GNU General Public License | ||
4 | * as published by the Free Software Foundation; either version 2 | ||
5 | * of the License, or (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
14 | */ | ||
15 | |||
16 | /** | ||
17 | * Both AR2315 and AR2316 chips have PCI interface unit, which supports DMA | ||
18 | * and interrupt. PCI interface supports MMIO access method, but does not | ||
19 | * seem to support I/O ports. | ||
20 | * | ||
21 | * Read/write operation in the region 0x80000000-0xBFFFFFFF causes | ||
22 | * a memory read/write command on the PCI bus. 30 LSBs of address on | ||
23 | * the bus are taken from memory read/write request and 2 MSBs are | ||
24 | * determined by PCI unit configuration. | ||
25 | * | ||
26 | * To work with the configuration space instead of memory is necessary set | ||
27 | * the CFG_SEL bit in the PCI_MISC_CONFIG register. | ||
28 | * | ||
29 | * Devices on the bus can perform DMA requests via chip BAR1. PCI host | ||
30 | * controller BARs are programmend as if an external device is programmed. | ||
31 | * Which means that during configuration, IDSEL pin of the chip should be | ||
32 | * asserted. | ||
33 | * | ||
34 | * We know (and support) only one board that uses the PCI interface - | ||
35 | * Fonera 2.0g (FON2202). It has a USB EHCI controller connected to the | ||
36 | * AR2315 PCI bus. IDSEL pin of USB controller is connected to AD[13] line | ||
37 | * and IDSEL pin of AR2315 is connected to AD[16] line. | ||
38 | */ | ||
39 | |||
40 | #include <linux/types.h> | ||
41 | #include <linux/pci.h> | ||
42 | #include <linux/platform_device.h> | ||
43 | #include <linux/kernel.h> | ||
44 | #include <linux/init.h> | ||
45 | #include <linux/mm.h> | ||
46 | #include <linux/delay.h> | ||
47 | #include <linux/bitops.h> | ||
48 | #include <linux/irq.h> | ||
49 | #include <linux/irqdomain.h> | ||
50 | #include <linux/io.h> | ||
51 | #include <asm/paccess.h> | ||
52 | |||
53 | /* | ||
54 | * PCI Bus Interface Registers | ||
55 | */ | ||
56 | #define AR2315_PCI_1MS_REG 0x0008 | ||
57 | |||
58 | #define AR2315_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */ | ||
59 | |||
60 | #define AR2315_PCI_MISC_CONFIG 0x000c | ||
61 | |||
62 | #define AR2315_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */ | ||
63 | #define AR2315_PCIMISC_CFG_SEL 0x00000002 /* Mem or Config cycles */ | ||
64 | #define AR2315_PCIMISC_GIG_MASK 0x0000000C /* bits 31-30 for pci req */ | ||
65 | #define AR2315_PCIMISC_RST_MODE 0x00000030 | ||
66 | #define AR2315_PCIRST_INPUT 0x00000000 /* 4:5=0 rst is input */ | ||
67 | #define AR2315_PCIRST_LOW 0x00000010 /* 4:5=1 rst to GND */ | ||
68 | #define AR2315_PCIRST_HIGH 0x00000020 /* 4:5=2 rst to VDD */ | ||
69 | #define AR2315_PCIGRANT_EN 0x00000000 /* 6:7=0 early grant en */ | ||
70 | #define AR2315_PCIGRANT_FRAME 0x00000040 /* 6:7=1 grant waits 4 frame */ | ||
71 | #define AR2315_PCIGRANT_IDLE 0x00000080 /* 6:7=2 grant waits 4 idle */ | ||
72 | #define AR2315_PCIGRANT_GAP 0x00000000 /* 6:7=2 grant waits 4 idle */ | ||
73 | #define AR2315_PCICACHE_DIS 0x00001000 /* PCI external access cache | ||
74 | * disable */ | ||
75 | |||
76 | #define AR2315_PCI_OUT_TSTAMP 0x0010 | ||
77 | |||
78 | #define AR2315_PCI_UNCACHE_CFG 0x0014 | ||
79 | |||
80 | #define AR2315_PCI_IN_EN 0x0100 | ||
81 | |||
82 | #define AR2315_PCI_IN_EN0 0x01 /* Enable chain 0 */ | ||
83 | #define AR2315_PCI_IN_EN1 0x02 /* Enable chain 1 */ | ||
84 | #define AR2315_PCI_IN_EN2 0x04 /* Enable chain 2 */ | ||
85 | #define AR2315_PCI_IN_EN3 0x08 /* Enable chain 3 */ | ||
86 | |||
87 | #define AR2315_PCI_IN_DIS 0x0104 | ||
88 | |||
89 | #define AR2315_PCI_IN_DIS0 0x01 /* Disable chain 0 */ | ||
90 | #define AR2315_PCI_IN_DIS1 0x02 /* Disable chain 1 */ | ||
91 | #define AR2315_PCI_IN_DIS2 0x04 /* Disable chain 2 */ | ||
92 | #define AR2315_PCI_IN_DIS3 0x08 /* Disable chain 3 */ | ||
93 | |||
94 | #define AR2315_PCI_IN_PTR 0x0200 | ||
95 | |||
96 | #define AR2315_PCI_OUT_EN 0x0400 | ||
97 | |||
98 | #define AR2315_PCI_OUT_EN0 0x01 /* Enable chain 0 */ | ||
99 | |||
100 | #define AR2315_PCI_OUT_DIS 0x0404 | ||
101 | |||
102 | #define AR2315_PCI_OUT_DIS0 0x01 /* Disable chain 0 */ | ||
103 | |||
104 | #define AR2315_PCI_OUT_PTR 0x0408 | ||
105 | |||
106 | /* PCI interrupt status (write one to clear) */ | ||
107 | #define AR2315_PCI_ISR 0x0500 | ||
108 | |||
109 | #define AR2315_PCI_INT_TX 0x00000001 /* Desc In Completed */ | ||
110 | #define AR2315_PCI_INT_TXOK 0x00000002 /* Desc In OK */ | ||
111 | #define AR2315_PCI_INT_TXERR 0x00000004 /* Desc In ERR */ | ||
112 | #define AR2315_PCI_INT_TXEOL 0x00000008 /* Desc In End-of-List */ | ||
113 | #define AR2315_PCI_INT_RX 0x00000010 /* Desc Out Completed */ | ||
114 | #define AR2315_PCI_INT_RXOK 0x00000020 /* Desc Out OK */ | ||
115 | #define AR2315_PCI_INT_RXERR 0x00000040 /* Desc Out ERR */ | ||
116 | #define AR2315_PCI_INT_RXEOL 0x00000080 /* Desc Out EOL */ | ||
117 | #define AR2315_PCI_INT_TXOOD 0x00000200 /* Desc In Out-of-Desc */ | ||
118 | #define AR2315_PCI_INT_DESCMASK 0x0000FFFF /* Desc Mask */ | ||
119 | #define AR2315_PCI_INT_EXT 0x02000000 /* Extern PCI INTA */ | ||
120 | #define AR2315_PCI_INT_ABORT 0x04000000 /* PCI bus abort event */ | ||
121 | |||
122 | /* PCI interrupt mask */ | ||
123 | #define AR2315_PCI_IMR 0x0504 | ||
124 | |||
125 | /* Global PCI interrupt enable */ | ||
126 | #define AR2315_PCI_IER 0x0508 | ||
127 | |||
128 | #define AR2315_PCI_IER_DISABLE 0x00 /* disable pci interrupts */ | ||
129 | #define AR2315_PCI_IER_ENABLE 0x01 /* enable pci interrupts */ | ||
130 | |||
131 | #define AR2315_PCI_HOST_IN_EN 0x0800 | ||
132 | #define AR2315_PCI_HOST_IN_DIS 0x0804 | ||
133 | #define AR2315_PCI_HOST_IN_PTR 0x0810 | ||
134 | #define AR2315_PCI_HOST_OUT_EN 0x0900 | ||
135 | #define AR2315_PCI_HOST_OUT_DIS 0x0904 | ||
136 | #define AR2315_PCI_HOST_OUT_PTR 0x0908 | ||
137 | |||
138 | /* | ||
139 | * PCI interrupts, which share IP5 | ||
140 | * Keep ordered according to AR2315_PCI_INT_XXX bits | ||
141 | */ | ||
142 | #define AR2315_PCI_IRQ_EXT 25 | ||
143 | #define AR2315_PCI_IRQ_ABORT 26 | ||
144 | #define AR2315_PCI_IRQ_COUNT 27 | ||
145 | |||
146 | /* Arbitrary size of memory region to access the configuration space */ | ||
147 | #define AR2315_PCI_CFG_SIZE 0x00100000 | ||
148 | |||
149 | #define AR2315_PCI_HOST_SLOT 3 | ||
150 | #define AR2315_PCI_HOST_DEVID ((0xff18 << 16) | PCI_VENDOR_ID_ATHEROS) | ||
151 | |||
152 | /* ??? access BAR */ | ||
153 | #define AR2315_PCI_HOST_MBAR0 0x10000000 | ||
154 | /* RAM access BAR */ | ||
155 | #define AR2315_PCI_HOST_MBAR1 AR2315_PCI_HOST_SDRAM_BASEADDR | ||
156 | /* ??? access BAR */ | ||
157 | #define AR2315_PCI_HOST_MBAR2 0x30000000 | ||
158 | |||
159 | struct ar2315_pci_ctrl { | ||
160 | void __iomem *cfg_mem; | ||
161 | void __iomem *mmr_mem; | ||
162 | unsigned irq; | ||
163 | unsigned irq_ext; | ||
164 | struct irq_domain *domain; | ||
165 | struct pci_controller pci_ctrl; | ||
166 | struct resource mem_res; | ||
167 | struct resource io_res; | ||
168 | }; | ||
169 | |||
170 | static inline struct ar2315_pci_ctrl *ar2315_pci_bus_to_apc(struct pci_bus *bus) | ||
171 | { | ||
172 | struct pci_controller *hose = bus->sysdata; | ||
173 | |||
174 | return container_of(hose, struct ar2315_pci_ctrl, pci_ctrl); | ||
175 | } | ||
176 | |||
177 | static inline u32 ar2315_pci_reg_read(struct ar2315_pci_ctrl *apc, u32 reg) | ||
178 | { | ||
179 | return __raw_readl(apc->mmr_mem + reg); | ||
180 | } | ||
181 | |||
182 | static inline void ar2315_pci_reg_write(struct ar2315_pci_ctrl *apc, u32 reg, | ||
183 | u32 val) | ||
184 | { | ||
185 | __raw_writel(val, apc->mmr_mem + reg); | ||
186 | } | ||
187 | |||
188 | static inline void ar2315_pci_reg_mask(struct ar2315_pci_ctrl *apc, u32 reg, | ||
189 | u32 mask, u32 val) | ||
190 | { | ||
191 | u32 ret = ar2315_pci_reg_read(apc, reg); | ||
192 | |||
193 | ret &= ~mask; | ||
194 | ret |= val; | ||
195 | ar2315_pci_reg_write(apc, reg, ret); | ||
196 | } | ||
197 | |||
198 | static int ar2315_pci_cfg_access(struct ar2315_pci_ctrl *apc, unsigned devfn, | ||
199 | int where, int size, u32 *ptr, bool write) | ||
200 | { | ||
201 | int func = PCI_FUNC(devfn); | ||
202 | int dev = PCI_SLOT(devfn); | ||
203 | u32 addr = (1 << (13 + dev)) | (func << 8) | (where & ~3); | ||
204 | u32 mask = 0xffffffff >> 8 * (4 - size); | ||
205 | u32 sh = (where & 3) * 8; | ||
206 | u32 value, isr; | ||
207 | |||
208 | /* Prevent access past the remapped area */ | ||
209 | if (addr >= AR2315_PCI_CFG_SIZE || dev > 18) | ||
210 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
211 | |||
212 | /* Clear pending errors */ | ||
213 | ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT); | ||
214 | /* Select Configuration access */ | ||
215 | ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, 0, | ||
216 | AR2315_PCIMISC_CFG_SEL); | ||
217 | |||
218 | mb(); /* PCI must see space change before we begin */ | ||
219 | |||
220 | value = __raw_readl(apc->cfg_mem + addr); | ||
221 | |||
222 | isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR); | ||
223 | |||
224 | if (isr & AR2315_PCI_INT_ABORT) | ||
225 | goto exit_err; | ||
226 | |||
227 | if (write) { | ||
228 | value = (value & ~(mask << sh)) | *ptr << sh; | ||
229 | __raw_writel(value, apc->cfg_mem + addr); | ||
230 | isr = ar2315_pci_reg_read(apc, AR2315_PCI_ISR); | ||
231 | if (isr & AR2315_PCI_INT_ABORT) | ||
232 | goto exit_err; | ||
233 | } else { | ||
234 | *ptr = (value >> sh) & mask; | ||
235 | } | ||
236 | |||
237 | goto exit; | ||
238 | |||
239 | exit_err: | ||
240 | ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT); | ||
241 | if (!write) | ||
242 | *ptr = 0xffffffff; | ||
243 | |||
244 | exit: | ||
245 | /* Select Memory access */ | ||
246 | ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_CFG_SEL, | ||
247 | 0); | ||
248 | |||
249 | return isr & AR2315_PCI_INT_ABORT ? PCIBIOS_DEVICE_NOT_FOUND : | ||
250 | PCIBIOS_SUCCESSFUL; | ||
251 | } | ||
252 | |||
253 | static inline int ar2315_pci_local_cfg_rd(struct ar2315_pci_ctrl *apc, | ||
254 | unsigned devfn, int where, u32 *val) | ||
255 | { | ||
256 | return ar2315_pci_cfg_access(apc, devfn, where, sizeof(u32), val, | ||
257 | false); | ||
258 | } | ||
259 | |||
260 | static inline int ar2315_pci_local_cfg_wr(struct ar2315_pci_ctrl *apc, | ||
261 | unsigned devfn, int where, u32 val) | ||
262 | { | ||
263 | return ar2315_pci_cfg_access(apc, devfn, where, sizeof(u32), &val, | ||
264 | true); | ||
265 | } | ||
266 | |||
267 | static int ar2315_pci_cfg_read(struct pci_bus *bus, unsigned devfn, int where, | ||
268 | int size, u32 *value) | ||
269 | { | ||
270 | struct ar2315_pci_ctrl *apc = ar2315_pci_bus_to_apc(bus); | ||
271 | |||
272 | if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT) | ||
273 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
274 | |||
275 | return ar2315_pci_cfg_access(apc, devfn, where, size, value, false); | ||
276 | } | ||
277 | |||
278 | static int ar2315_pci_cfg_write(struct pci_bus *bus, unsigned devfn, int where, | ||
279 | int size, u32 value) | ||
280 | { | ||
281 | struct ar2315_pci_ctrl *apc = ar2315_pci_bus_to_apc(bus); | ||
282 | |||
283 | if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT) | ||
284 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
285 | |||
286 | return ar2315_pci_cfg_access(apc, devfn, where, size, &value, true); | ||
287 | } | ||
288 | |||
289 | static struct pci_ops ar2315_pci_ops = { | ||
290 | .read = ar2315_pci_cfg_read, | ||
291 | .write = ar2315_pci_cfg_write, | ||
292 | }; | ||
293 | |||
294 | static int ar2315_pci_host_setup(struct ar2315_pci_ctrl *apc) | ||
295 | { | ||
296 | unsigned devfn = PCI_DEVFN(AR2315_PCI_HOST_SLOT, 0); | ||
297 | int res; | ||
298 | u32 id; | ||
299 | |||
300 | res = ar2315_pci_local_cfg_rd(apc, devfn, PCI_VENDOR_ID, &id); | ||
301 | if (res != PCIBIOS_SUCCESSFUL || id != AR2315_PCI_HOST_DEVID) | ||
302 | return -ENODEV; | ||
303 | |||
304 | /* Program MBARs */ | ||
305 | ar2315_pci_local_cfg_wr(apc, devfn, PCI_BASE_ADDRESS_0, | ||
306 | AR2315_PCI_HOST_MBAR0); | ||
307 | ar2315_pci_local_cfg_wr(apc, devfn, PCI_BASE_ADDRESS_1, | ||
308 | AR2315_PCI_HOST_MBAR1); | ||
309 | ar2315_pci_local_cfg_wr(apc, devfn, PCI_BASE_ADDRESS_2, | ||
310 | AR2315_PCI_HOST_MBAR2); | ||
311 | |||
312 | /* Run */ | ||
313 | ar2315_pci_local_cfg_wr(apc, devfn, PCI_COMMAND, PCI_COMMAND_MEMORY | | ||
314 | PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL | | ||
315 | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | | ||
316 | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc) | ||
322 | { | ||
323 | struct ar2315_pci_ctrl *apc = irq_get_handler_data(irq); | ||
324 | u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) & | ||
325 | ar2315_pci_reg_read(apc, AR2315_PCI_IMR); | ||
326 | unsigned pci_irq = 0; | ||
327 | |||
328 | if (pending) | ||
329 | pci_irq = irq_find_mapping(apc->domain, __ffs(pending)); | ||
330 | |||
331 | if (pci_irq) | ||
332 | generic_handle_irq(pci_irq); | ||
333 | else | ||
334 | spurious_interrupt(); | ||
335 | } | ||
336 | |||
337 | static void ar2315_pci_irq_mask(struct irq_data *d) | ||
338 | { | ||
339 | struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d); | ||
340 | |||
341 | ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, BIT(d->hwirq), 0); | ||
342 | } | ||
343 | |||
344 | static void ar2315_pci_irq_mask_ack(struct irq_data *d) | ||
345 | { | ||
346 | struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d); | ||
347 | u32 m = BIT(d->hwirq); | ||
348 | |||
349 | ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, m, 0); | ||
350 | ar2315_pci_reg_write(apc, AR2315_PCI_ISR, m); | ||
351 | } | ||
352 | |||
353 | static void ar2315_pci_irq_unmask(struct irq_data *d) | ||
354 | { | ||
355 | struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d); | ||
356 | |||
357 | ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, 0, BIT(d->hwirq)); | ||
358 | } | ||
359 | |||
360 | static struct irq_chip ar2315_pci_irq_chip = { | ||
361 | .name = "AR2315-PCI", | ||
362 | .irq_mask = ar2315_pci_irq_mask, | ||
363 | .irq_mask_ack = ar2315_pci_irq_mask_ack, | ||
364 | .irq_unmask = ar2315_pci_irq_unmask, | ||
365 | }; | ||
366 | |||
367 | static int ar2315_pci_irq_map(struct irq_domain *d, unsigned irq, | ||
368 | irq_hw_number_t hw) | ||
369 | { | ||
370 | irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip, handle_level_irq); | ||
371 | irq_set_chip_data(irq, d->host_data); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static struct irq_domain_ops ar2315_pci_irq_domain_ops = { | ||
376 | .map = ar2315_pci_irq_map, | ||
377 | }; | ||
378 | |||
379 | static void ar2315_pci_irq_init(struct ar2315_pci_ctrl *apc) | ||
380 | { | ||
381 | ar2315_pci_reg_mask(apc, AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0); | ||
382 | ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT | | ||
383 | AR2315_PCI_INT_EXT), 0); | ||
384 | |||
385 | apc->irq_ext = irq_create_mapping(apc->domain, AR2315_PCI_IRQ_EXT); | ||
386 | |||
387 | irq_set_chained_handler(apc->irq, ar2315_pci_irq_handler); | ||
388 | irq_set_handler_data(apc->irq, apc); | ||
389 | |||
390 | /* Clear any pending Abort or external Interrupts | ||
391 | * and enable interrupt processing */ | ||
392 | ar2315_pci_reg_write(apc, AR2315_PCI_ISR, AR2315_PCI_INT_ABORT | | ||
393 | AR2315_PCI_INT_EXT); | ||
394 | ar2315_pci_reg_mask(apc, AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE); | ||
395 | } | ||
396 | |||
397 | static int ar2315_pci_probe(struct platform_device *pdev) | ||
398 | { | ||
399 | struct ar2315_pci_ctrl *apc; | ||
400 | struct device *dev = &pdev->dev; | ||
401 | struct resource *res; | ||
402 | int irq, err; | ||
403 | |||
404 | apc = devm_kzalloc(dev, sizeof(*apc), GFP_KERNEL); | ||
405 | if (!apc) | ||
406 | return -ENOMEM; | ||
407 | |||
408 | irq = platform_get_irq(pdev, 0); | ||
409 | if (irq < 0) | ||
410 | return -EINVAL; | ||
411 | apc->irq = irq; | ||
412 | |||
413 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
414 | "ar2315-pci-ctrl"); | ||
415 | apc->mmr_mem = devm_ioremap_resource(dev, res); | ||
416 | if (IS_ERR(apc->mmr_mem)) | ||
417 | return PTR_ERR(apc->mmr_mem); | ||
418 | |||
419 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
420 | "ar2315-pci-ext"); | ||
421 | if (!res) | ||
422 | return -EINVAL; | ||
423 | |||
424 | apc->mem_res.name = "AR2315 PCI mem space"; | ||
425 | apc->mem_res.parent = res; | ||
426 | apc->mem_res.start = res->start; | ||
427 | apc->mem_res.end = res->end; | ||
428 | apc->mem_res.flags = IORESOURCE_MEM; | ||
429 | |||
430 | /* Remap PCI config space */ | ||
431 | apc->cfg_mem = devm_ioremap_nocache(dev, res->start, | ||
432 | AR2315_PCI_CFG_SIZE); | ||
433 | if (!apc->cfg_mem) { | ||
434 | dev_err(dev, "failed to remap PCI config space\n"); | ||
435 | return -ENOMEM; | ||
436 | } | ||
437 | |||
438 | /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */ | ||
439 | ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, | ||
440 | AR2315_PCIMISC_RST_MODE, | ||
441 | AR2315_PCIRST_LOW); | ||
442 | msleep(100); | ||
443 | |||
444 | /* Bring the PCI out of reset */ | ||
445 | ar2315_pci_reg_mask(apc, AR2315_PCI_MISC_CONFIG, | ||
446 | AR2315_PCIMISC_RST_MODE, | ||
447 | AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8); | ||
448 | |||
449 | ar2315_pci_reg_write(apc, AR2315_PCI_UNCACHE_CFG, | ||
450 | 0x1E | /* 1GB uncached */ | ||
451 | (1 << 5) | /* Enable uncached */ | ||
452 | (0x2 << 30) /* Base: 0x80000000 */); | ||
453 | ar2315_pci_reg_read(apc, AR2315_PCI_UNCACHE_CFG); | ||
454 | |||
455 | msleep(500); | ||
456 | |||
457 | err = ar2315_pci_host_setup(apc); | ||
458 | if (err) | ||
459 | return err; | ||
460 | |||
461 | apc->domain = irq_domain_add_linear(NULL, AR2315_PCI_IRQ_COUNT, | ||
462 | &ar2315_pci_irq_domain_ops, apc); | ||
463 | if (!apc->domain) { | ||
464 | dev_err(dev, "failed to add IRQ domain\n"); | ||
465 | return -ENOMEM; | ||
466 | } | ||
467 | |||
468 | ar2315_pci_irq_init(apc); | ||
469 | |||
470 | /* PCI controller does not support I/O ports */ | ||
471 | apc->io_res.name = "AR2315 IO space"; | ||
472 | apc->io_res.start = 0; | ||
473 | apc->io_res.end = 0; | ||
474 | apc->io_res.flags = IORESOURCE_IO, | ||
475 | |||
476 | apc->pci_ctrl.pci_ops = &ar2315_pci_ops; | ||
477 | apc->pci_ctrl.mem_resource = &apc->mem_res, | ||
478 | apc->pci_ctrl.io_resource = &apc->io_res, | ||
479 | |||
480 | register_pci_controller(&apc->pci_ctrl); | ||
481 | |||
482 | dev_info(dev, "register PCI controller\n"); | ||
483 | |||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static struct platform_driver ar2315_pci_driver = { | ||
488 | .probe = ar2315_pci_probe, | ||
489 | .driver = { | ||
490 | .name = "ar2315-pci", | ||
491 | .owner = THIS_MODULE, | ||
492 | }, | ||
493 | }; | ||
494 | |||
495 | static int __init ar2315_pci_init(void) | ||
496 | { | ||
497 | return platform_driver_register(&ar2315_pci_driver); | ||
498 | } | ||
499 | arch_initcall(ar2315_pci_init); | ||
500 | |||
501 | int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
502 | { | ||
503 | struct ar2315_pci_ctrl *apc = ar2315_pci_bus_to_apc(dev->bus); | ||
504 | |||
505 | return slot ? 0 : apc->irq_ext; | ||
506 | } | ||
507 | |||
508 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
509 | { | ||
510 | return 0; | ||
511 | } | ||
diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c index d471a26dd5f8..2b534aea20e4 100644 --- a/arch/mips/pci/pci-ar71xx.c +++ b/arch/mips/pci/pci-ar71xx.c | |||
@@ -50,7 +50,6 @@ | |||
50 | 50 | ||
51 | struct ar71xx_pci_controller { | 51 | struct ar71xx_pci_controller { |
52 | void __iomem *cfg_base; | 52 | void __iomem *cfg_base; |
53 | spinlock_t lock; | ||
54 | int irq; | 53 | int irq; |
55 | int irq_base; | 54 | int irq_base; |
56 | struct pci_controller pci_ctrl; | 55 | struct pci_controller pci_ctrl; |
@@ -182,7 +181,6 @@ static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, | |||
182 | { | 181 | { |
183 | struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); | 182 | struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); |
184 | void __iomem *base = apc->cfg_base; | 183 | void __iomem *base = apc->cfg_base; |
185 | unsigned long flags; | ||
186 | u32 data; | 184 | u32 data; |
187 | int err; | 185 | int err; |
188 | int ret; | 186 | int ret; |
@@ -190,8 +188,6 @@ static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, | |||
190 | ret = PCIBIOS_SUCCESSFUL; | 188 | ret = PCIBIOS_SUCCESSFUL; |
191 | data = ~0; | 189 | data = ~0; |
192 | 190 | ||
193 | spin_lock_irqsave(&apc->lock, flags); | ||
194 | |||
195 | err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, | 191 | err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, |
196 | AR71XX_PCI_CFG_CMD_READ); | 192 | AR71XX_PCI_CFG_CMD_READ); |
197 | if (err) | 193 | if (err) |
@@ -199,8 +195,6 @@ static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, | |||
199 | else | 195 | else |
200 | data = __raw_readl(base + AR71XX_PCI_REG_CFG_RDDATA); | 196 | data = __raw_readl(base + AR71XX_PCI_REG_CFG_RDDATA); |
201 | 197 | ||
202 | spin_unlock_irqrestore(&apc->lock, flags); | ||
203 | |||
204 | *value = (data >> (8 * (where & 3))) & ar71xx_pci_read_mask[size & 7]; | 198 | *value = (data >> (8 * (where & 3))) & ar71xx_pci_read_mask[size & 7]; |
205 | 199 | ||
206 | return ret; | 200 | return ret; |
@@ -211,15 +205,12 @@ static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, | |||
211 | { | 205 | { |
212 | struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); | 206 | struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); |
213 | void __iomem *base = apc->cfg_base; | 207 | void __iomem *base = apc->cfg_base; |
214 | unsigned long flags; | ||
215 | int err; | 208 | int err; |
216 | int ret; | 209 | int ret; |
217 | 210 | ||
218 | value = value << (8 * (where & 3)); | 211 | value = value << (8 * (where & 3)); |
219 | ret = PCIBIOS_SUCCESSFUL; | 212 | ret = PCIBIOS_SUCCESSFUL; |
220 | 213 | ||
221 | spin_lock_irqsave(&apc->lock, flags); | ||
222 | |||
223 | err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, | 214 | err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, |
224 | AR71XX_PCI_CFG_CMD_WRITE); | 215 | AR71XX_PCI_CFG_CMD_WRITE); |
225 | if (err) | 216 | if (err) |
@@ -227,8 +218,6 @@ static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, | |||
227 | else | 218 | else |
228 | __raw_writel(value, base + AR71XX_PCI_REG_CFG_WRDATA); | 219 | __raw_writel(value, base + AR71XX_PCI_REG_CFG_WRDATA); |
229 | 220 | ||
230 | spin_unlock_irqrestore(&apc->lock, flags); | ||
231 | |||
232 | return ret; | 221 | return ret; |
233 | } | 222 | } |
234 | 223 | ||
@@ -360,8 +349,6 @@ static int ar71xx_pci_probe(struct platform_device *pdev) | |||
360 | if (!apc) | 349 | if (!apc) |
361 | return -ENOMEM; | 350 | return -ENOMEM; |
362 | 351 | ||
363 | spin_lock_init(&apc->lock); | ||
364 | |||
365 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); | 352 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); |
366 | apc->cfg_base = devm_ioremap_resource(&pdev->dev, res); | 353 | apc->cfg_base = devm_ioremap_resource(&pdev->dev, res); |
367 | if (IS_ERR(apc->cfg_base)) | 354 | if (IS_ERR(apc->cfg_base)) |
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 785b2659b519..b7a6fcbb8852 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c | |||
@@ -9,7 +9,6 @@ | |||
9 | * by the Free Software Foundation. | 9 | * by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/spinlock.h> | ||
13 | #include <linux/irq.h> | 12 | #include <linux/irq.h> |
14 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
@@ -48,8 +47,6 @@ struct ar724x_pci_controller { | |||
48 | bool bar0_is_cached; | 47 | bool bar0_is_cached; |
49 | u32 bar0_value; | 48 | u32 bar0_value; |
50 | 49 | ||
51 | spinlock_t lock; | ||
52 | |||
53 | struct pci_controller pci_controller; | 50 | struct pci_controller pci_controller; |
54 | struct resource io_res; | 51 | struct resource io_res; |
55 | struct resource mem_res; | 52 | struct resource mem_res; |
@@ -75,7 +72,6 @@ pci_bus_to_ar724x_controller(struct pci_bus *bus) | |||
75 | static int ar724x_pci_local_write(struct ar724x_pci_controller *apc, | 72 | static int ar724x_pci_local_write(struct ar724x_pci_controller *apc, |
76 | int where, int size, u32 value) | 73 | int where, int size, u32 value) |
77 | { | 74 | { |
78 | unsigned long flags; | ||
79 | void __iomem *base; | 75 | void __iomem *base; |
80 | u32 data; | 76 | u32 data; |
81 | int s; | 77 | int s; |
@@ -86,8 +82,6 @@ static int ar724x_pci_local_write(struct ar724x_pci_controller *apc, | |||
86 | return PCIBIOS_DEVICE_NOT_FOUND; | 82 | return PCIBIOS_DEVICE_NOT_FOUND; |
87 | 83 | ||
88 | base = apc->crp_base; | 84 | base = apc->crp_base; |
89 | |||
90 | spin_lock_irqsave(&apc->lock, flags); | ||
91 | data = __raw_readl(base + (where & ~3)); | 85 | data = __raw_readl(base + (where & ~3)); |
92 | 86 | ||
93 | switch (size) { | 87 | switch (size) { |
@@ -105,14 +99,12 @@ static int ar724x_pci_local_write(struct ar724x_pci_controller *apc, | |||
105 | data = value; | 99 | data = value; |
106 | break; | 100 | break; |
107 | default: | 101 | default: |
108 | spin_unlock_irqrestore(&apc->lock, flags); | ||
109 | return PCIBIOS_BAD_REGISTER_NUMBER; | 102 | return PCIBIOS_BAD_REGISTER_NUMBER; |
110 | } | 103 | } |
111 | 104 | ||
112 | __raw_writel(data, base + (where & ~3)); | 105 | __raw_writel(data, base + (where & ~3)); |
113 | /* flush write */ | 106 | /* flush write */ |
114 | __raw_readl(base + (where & ~3)); | 107 | __raw_readl(base + (where & ~3)); |
115 | spin_unlock_irqrestore(&apc->lock, flags); | ||
116 | 108 | ||
117 | return PCIBIOS_SUCCESSFUL; | 109 | return PCIBIOS_SUCCESSFUL; |
118 | } | 110 | } |
@@ -121,7 +113,6 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, | |||
121 | int size, uint32_t *value) | 113 | int size, uint32_t *value) |
122 | { | 114 | { |
123 | struct ar724x_pci_controller *apc; | 115 | struct ar724x_pci_controller *apc; |
124 | unsigned long flags; | ||
125 | void __iomem *base; | 116 | void __iomem *base; |
126 | u32 data; | 117 | u32 data; |
127 | 118 | ||
@@ -133,8 +124,6 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, | |||
133 | return PCIBIOS_DEVICE_NOT_FOUND; | 124 | return PCIBIOS_DEVICE_NOT_FOUND; |
134 | 125 | ||
135 | base = apc->devcfg_base; | 126 | base = apc->devcfg_base; |
136 | |||
137 | spin_lock_irqsave(&apc->lock, flags); | ||
138 | data = __raw_readl(base + (where & ~3)); | 127 | data = __raw_readl(base + (where & ~3)); |
139 | 128 | ||
140 | switch (size) { | 129 | switch (size) { |
@@ -153,13 +142,9 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, | |||
153 | case 4: | 142 | case 4: |
154 | break; | 143 | break; |
155 | default: | 144 | default: |
156 | spin_unlock_irqrestore(&apc->lock, flags); | ||
157 | |||
158 | return PCIBIOS_BAD_REGISTER_NUMBER; | 145 | return PCIBIOS_BAD_REGISTER_NUMBER; |
159 | } | 146 | } |
160 | 147 | ||
161 | spin_unlock_irqrestore(&apc->lock, flags); | ||
162 | |||
163 | if (where == PCI_BASE_ADDRESS_0 && size == 4 && | 148 | if (where == PCI_BASE_ADDRESS_0 && size == 4 && |
164 | apc->bar0_is_cached) { | 149 | apc->bar0_is_cached) { |
165 | /* use the cached value */ | 150 | /* use the cached value */ |
@@ -175,7 +160,6 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, | |||
175 | int size, uint32_t value) | 160 | int size, uint32_t value) |
176 | { | 161 | { |
177 | struct ar724x_pci_controller *apc; | 162 | struct ar724x_pci_controller *apc; |
178 | unsigned long flags; | ||
179 | void __iomem *base; | 163 | void __iomem *base; |
180 | u32 data; | 164 | u32 data; |
181 | int s; | 165 | int s; |
@@ -209,8 +193,6 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, | |||
209 | } | 193 | } |
210 | 194 | ||
211 | base = apc->devcfg_base; | 195 | base = apc->devcfg_base; |
212 | |||
213 | spin_lock_irqsave(&apc->lock, flags); | ||
214 | data = __raw_readl(base + (where & ~3)); | 196 | data = __raw_readl(base + (where & ~3)); |
215 | 197 | ||
216 | switch (size) { | 198 | switch (size) { |
@@ -228,15 +210,12 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, | |||
228 | data = value; | 210 | data = value; |
229 | break; | 211 | break; |
230 | default: | 212 | default: |
231 | spin_unlock_irqrestore(&apc->lock, flags); | ||
232 | |||
233 | return PCIBIOS_BAD_REGISTER_NUMBER; | 213 | return PCIBIOS_BAD_REGISTER_NUMBER; |
234 | } | 214 | } |
235 | 215 | ||
236 | __raw_writel(data, base + (where & ~3)); | 216 | __raw_writel(data, base + (where & ~3)); |
237 | /* flush write */ | 217 | /* flush write */ |
238 | __raw_readl(base + (where & ~3)); | 218 | __raw_readl(base + (where & ~3)); |
239 | spin_unlock_irqrestore(&apc->lock, flags); | ||
240 | 219 | ||
241 | return PCIBIOS_SUCCESSFUL; | 220 | return PCIBIOS_SUCCESSFUL; |
242 | } | 221 | } |
@@ -380,8 +359,6 @@ static int ar724x_pci_probe(struct platform_device *pdev) | |||
380 | if (apc->irq < 0) | 359 | if (apc->irq < 0) |
381 | return -EINVAL; | 360 | return -EINVAL; |
382 | 361 | ||
383 | spin_lock_init(&apc->lock); | ||
384 | |||
385 | res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); | 362 | res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); |
386 | if (!res) | 363 | if (!res) |
387 | return -EINVAL; | 364 | return -EINVAL; |
diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c index 59cccd95688b..d07e04121cc6 100644 --- a/arch/mips/pci/pci-octeon.c +++ b/arch/mips/pci/pci-octeon.c | |||
@@ -708,7 +708,7 @@ static int __init octeon_pci_setup(void) | |||
708 | 708 | ||
709 | if (IS_ERR(platform_device_register_simple("octeon_pci_edac", | 709 | if (IS_ERR(platform_device_register_simple("octeon_pci_edac", |
710 | -1, NULL, 0))) | 710 | -1, NULL, 0))) |
711 | pr_err("Registation of co_pci_edac failed!\n"); | 711 | pr_err("Registration of co_pci_edac failed!\n"); |
712 | 712 | ||
713 | octeon_pci_dma_init(); | 713 | octeon_pci_dma_init(); |
714 | 714 | ||
diff --git a/arch/mips/pci/pci-rt2880.c b/arch/mips/pci/pci-rt2880.c new file mode 100644 index 000000000000..a4574947e698 --- /dev/null +++ b/arch/mips/pci/pci-rt2880.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * Ralink RT288x SoC PCI register definitions | ||
3 | * | ||
4 | * Copyright (C) 2009 John Crispin <blogic@openwrt.org> | ||
5 | * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> | ||
6 | * | ||
7 | * Parts of this file are based on Ralink's 2.6.21 BSP | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published | ||
11 | * by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/of_irq.h> | ||
21 | #include <linux/of_pci.h> | ||
22 | |||
23 | #include <asm/mach-ralink/rt288x.h> | ||
24 | |||
25 | #define RT2880_PCI_BASE 0x00440000 | ||
26 | #define RT288X_CPU_IRQ_PCI 4 | ||
27 | |||
28 | #define RT2880_PCI_MEM_BASE 0x20000000 | ||
29 | #define RT2880_PCI_MEM_SIZE 0x10000000 | ||
30 | #define RT2880_PCI_IO_BASE 0x00460000 | ||
31 | #define RT2880_PCI_IO_SIZE 0x00010000 | ||
32 | |||
33 | #define RT2880_PCI_REG_PCICFG_ADDR 0x00 | ||
34 | #define RT2880_PCI_REG_PCIMSK_ADDR 0x0c | ||
35 | #define RT2880_PCI_REG_BAR0SETUP_ADDR 0x10 | ||
36 | #define RT2880_PCI_REG_IMBASEBAR0_ADDR 0x18 | ||
37 | #define RT2880_PCI_REG_CONFIG_ADDR 0x20 | ||
38 | #define RT2880_PCI_REG_CONFIG_DATA 0x24 | ||
39 | #define RT2880_PCI_REG_MEMBASE 0x28 | ||
40 | #define RT2880_PCI_REG_IOBASE 0x2c | ||
41 | #define RT2880_PCI_REG_ID 0x30 | ||
42 | #define RT2880_PCI_REG_CLASS 0x34 | ||
43 | #define RT2880_PCI_REG_SUBID 0x38 | ||
44 | #define RT2880_PCI_REG_ARBCTL 0x80 | ||
45 | |||
46 | static void __iomem *rt2880_pci_base; | ||
47 | static DEFINE_SPINLOCK(rt2880_pci_lock); | ||
48 | |||
49 | static u32 rt2880_pci_reg_read(u32 reg) | ||
50 | { | ||
51 | return readl(rt2880_pci_base + reg); | ||
52 | } | ||
53 | |||
54 | static void rt2880_pci_reg_write(u32 val, u32 reg) | ||
55 | { | ||
56 | writel(val, rt2880_pci_base + reg); | ||
57 | } | ||
58 | |||
59 | static inline u32 rt2880_pci_get_cfgaddr(unsigned int bus, unsigned int slot, | ||
60 | unsigned int func, unsigned int where) | ||
61 | { | ||
62 | return ((bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | | ||
63 | 0x80000000); | ||
64 | } | ||
65 | |||
66 | static int rt2880_pci_config_read(struct pci_bus *bus, unsigned int devfn, | ||
67 | int where, int size, u32 *val) | ||
68 | { | ||
69 | unsigned long flags; | ||
70 | u32 address; | ||
71 | u32 data; | ||
72 | |||
73 | address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), | ||
74 | PCI_FUNC(devfn), where); | ||
75 | |||
76 | spin_lock_irqsave(&rt2880_pci_lock, flags); | ||
77 | rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); | ||
78 | data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); | ||
79 | spin_unlock_irqrestore(&rt2880_pci_lock, flags); | ||
80 | |||
81 | switch (size) { | ||
82 | case 1: | ||
83 | *val = (data >> ((where & 3) << 3)) & 0xff; | ||
84 | break; | ||
85 | case 2: | ||
86 | *val = (data >> ((where & 3) << 3)) & 0xffff; | ||
87 | break; | ||
88 | case 4: | ||
89 | *val = data; | ||
90 | break; | ||
91 | } | ||
92 | |||
93 | return PCIBIOS_SUCCESSFUL; | ||
94 | } | ||
95 | |||
96 | static int rt2880_pci_config_write(struct pci_bus *bus, unsigned int devfn, | ||
97 | int where, int size, u32 val) | ||
98 | { | ||
99 | unsigned long flags; | ||
100 | u32 address; | ||
101 | u32 data; | ||
102 | |||
103 | address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), | ||
104 | PCI_FUNC(devfn), where); | ||
105 | |||
106 | spin_lock_irqsave(&rt2880_pci_lock, flags); | ||
107 | rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); | ||
108 | data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); | ||
109 | |||
110 | switch (size) { | ||
111 | case 1: | ||
112 | data = (data & ~(0xff << ((where & 3) << 3))) | | ||
113 | (val << ((where & 3) << 3)); | ||
114 | break; | ||
115 | case 2: | ||
116 | data = (data & ~(0xffff << ((where & 3) << 3))) | | ||
117 | (val << ((where & 3) << 3)); | ||
118 | break; | ||
119 | case 4: | ||
120 | data = val; | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | rt2880_pci_reg_write(data, RT2880_PCI_REG_CONFIG_DATA); | ||
125 | spin_unlock_irqrestore(&rt2880_pci_lock, flags); | ||
126 | |||
127 | return PCIBIOS_SUCCESSFUL; | ||
128 | } | ||
129 | |||
130 | static struct pci_ops rt2880_pci_ops = { | ||
131 | .read = rt2880_pci_config_read, | ||
132 | .write = rt2880_pci_config_write, | ||
133 | }; | ||
134 | |||
135 | static struct resource rt2880_pci_mem_resource = { | ||
136 | .name = "PCI MEM space", | ||
137 | .start = RT2880_PCI_MEM_BASE, | ||
138 | .end = RT2880_PCI_MEM_BASE + RT2880_PCI_MEM_SIZE - 1, | ||
139 | .flags = IORESOURCE_MEM, | ||
140 | }; | ||
141 | |||
142 | static struct resource rt2880_pci_io_resource = { | ||
143 | .name = "PCI IO space", | ||
144 | .start = RT2880_PCI_IO_BASE, | ||
145 | .end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1, | ||
146 | .flags = IORESOURCE_IO, | ||
147 | }; | ||
148 | |||
149 | static struct pci_controller rt2880_pci_controller = { | ||
150 | .pci_ops = &rt2880_pci_ops, | ||
151 | .mem_resource = &rt2880_pci_mem_resource, | ||
152 | .io_resource = &rt2880_pci_io_resource, | ||
153 | }; | ||
154 | |||
155 | static inline u32 rt2880_pci_read_u32(unsigned long reg) | ||
156 | { | ||
157 | unsigned long flags; | ||
158 | u32 address; | ||
159 | u32 ret; | ||
160 | |||
161 | address = rt2880_pci_get_cfgaddr(0, 0, 0, reg); | ||
162 | |||
163 | spin_lock_irqsave(&rt2880_pci_lock, flags); | ||
164 | rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); | ||
165 | ret = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); | ||
166 | spin_unlock_irqrestore(&rt2880_pci_lock, flags); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static inline void rt2880_pci_write_u32(unsigned long reg, u32 val) | ||
172 | { | ||
173 | unsigned long flags; | ||
174 | u32 address; | ||
175 | |||
176 | address = rt2880_pci_get_cfgaddr(0, 0, 0, reg); | ||
177 | |||
178 | spin_lock_irqsave(&rt2880_pci_lock, flags); | ||
179 | rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); | ||
180 | rt2880_pci_reg_write(val, RT2880_PCI_REG_CONFIG_DATA); | ||
181 | spin_unlock_irqrestore(&rt2880_pci_lock, flags); | ||
182 | } | ||
183 | |||
184 | int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
185 | { | ||
186 | u16 cmd; | ||
187 | int irq = -1; | ||
188 | |||
189 | if (dev->bus->number != 0) | ||
190 | return irq; | ||
191 | |||
192 | switch (PCI_SLOT(dev->devfn)) { | ||
193 | case 0x00: | ||
194 | rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); | ||
195 | (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); | ||
196 | break; | ||
197 | case 0x11: | ||
198 | irq = RT288X_CPU_IRQ_PCI; | ||
199 | break; | ||
200 | default: | ||
201 | pr_err("%s:%s[%d] trying to alloc unknown pci irq\n", | ||
202 | __FILE__, __func__, __LINE__); | ||
203 | BUG(); | ||
204 | break; | ||
205 | } | ||
206 | |||
207 | pci_write_config_byte((struct pci_dev *) dev, | ||
208 | PCI_CACHE_LINE_SIZE, 0x14); | ||
209 | pci_write_config_byte((struct pci_dev *) dev, PCI_LATENCY_TIMER, 0xFF); | ||
210 | pci_read_config_word((struct pci_dev *) dev, PCI_COMMAND, &cmd); | ||
211 | cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | | ||
212 | PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK | | ||
213 | PCI_COMMAND_SERR | PCI_COMMAND_WAIT | PCI_COMMAND_PARITY; | ||
214 | pci_write_config_word((struct pci_dev *) dev, PCI_COMMAND, cmd); | ||
215 | pci_write_config_byte((struct pci_dev *) dev, PCI_INTERRUPT_LINE, | ||
216 | dev->irq); | ||
217 | return irq; | ||
218 | } | ||
219 | |||
220 | static int rt288x_pci_probe(struct platform_device *pdev) | ||
221 | { | ||
222 | void __iomem *io_map_base; | ||
223 | int i; | ||
224 | |||
225 | rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE); | ||
226 | |||
227 | io_map_base = ioremap(RT2880_PCI_IO_BASE, RT2880_PCI_IO_SIZE); | ||
228 | rt2880_pci_controller.io_map_base = (unsigned long) io_map_base; | ||
229 | set_io_port_base((unsigned long) io_map_base); | ||
230 | |||
231 | ioport_resource.start = RT2880_PCI_IO_BASE; | ||
232 | ioport_resource.end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1; | ||
233 | |||
234 | rt2880_pci_reg_write(0, RT2880_PCI_REG_PCICFG_ADDR); | ||
235 | for (i = 0; i < 0xfffff; i++) | ||
236 | ; | ||
237 | |||
238 | rt2880_pci_reg_write(0x79, RT2880_PCI_REG_ARBCTL); | ||
239 | rt2880_pci_reg_write(0x07FF0001, RT2880_PCI_REG_BAR0SETUP_ADDR); | ||
240 | rt2880_pci_reg_write(RT2880_PCI_MEM_BASE, RT2880_PCI_REG_MEMBASE); | ||
241 | rt2880_pci_reg_write(RT2880_PCI_IO_BASE, RT2880_PCI_REG_IOBASE); | ||
242 | rt2880_pci_reg_write(0x08000000, RT2880_PCI_REG_IMBASEBAR0_ADDR); | ||
243 | rt2880_pci_reg_write(0x08021814, RT2880_PCI_REG_ID); | ||
244 | rt2880_pci_reg_write(0x00800001, RT2880_PCI_REG_CLASS); | ||
245 | rt2880_pci_reg_write(0x28801814, RT2880_PCI_REG_SUBID); | ||
246 | rt2880_pci_reg_write(0x000c0000, RT2880_PCI_REG_PCIMSK_ADDR); | ||
247 | |||
248 | rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); | ||
249 | (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); | ||
250 | |||
251 | register_pci_controller(&rt2880_pci_controller); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
256 | { | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static const struct of_device_id rt288x_pci_match[] = { | ||
261 | { .compatible = "ralink,rt288x-pci" }, | ||
262 | {}, | ||
263 | }; | ||
264 | MODULE_DEVICE_TABLE(of, rt288x_pci_match); | ||
265 | |||
266 | static struct platform_driver rt288x_pci_driver = { | ||
267 | .probe = rt288x_pci_probe, | ||
268 | .driver = { | ||
269 | .name = "rt288x-pci", | ||
270 | .owner = THIS_MODULE, | ||
271 | .of_match_table = rt288x_pci_match, | ||
272 | }, | ||
273 | }; | ||
274 | |||
275 | int __init pcibios_init(void) | ||
276 | { | ||
277 | int ret = platform_driver_register(&rt288x_pci_driver); | ||
278 | |||
279 | if (ret) | ||
280 | pr_info("rt288x-pci: Error registering platform driver!"); | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | arch_initcall(pcibios_init); | ||
diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c index 72919aeef42b..0bcc0b1cfddc 100644 --- a/arch/mips/pci/pci-rt3883.c +++ b/arch/mips/pci/pci-rt3883.c | |||
@@ -61,7 +61,6 @@ | |||
61 | 61 | ||
62 | struct rt3883_pci_controller { | 62 | struct rt3883_pci_controller { |
63 | void __iomem *base; | 63 | void __iomem *base; |
64 | spinlock_t lock; | ||
65 | 64 | ||
66 | struct device_node *intc_of_node; | 65 | struct device_node *intc_of_node; |
67 | struct irq_domain *irq_domain; | 66 | struct irq_domain *irq_domain; |
@@ -111,10 +110,8 @@ static u32 rt3883_pci_read_cfg32(struct rt3883_pci_controller *rpc, | |||
111 | 110 | ||
112 | address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); | 111 | address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); |
113 | 112 | ||
114 | spin_lock_irqsave(&rpc->lock, flags); | ||
115 | rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); | 113 | rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); |
116 | ret = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); | 114 | ret = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); |
117 | spin_unlock_irqrestore(&rpc->lock, flags); | ||
118 | 115 | ||
119 | return ret; | 116 | return ret; |
120 | } | 117 | } |
@@ -128,10 +125,8 @@ static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc, | |||
128 | 125 | ||
129 | address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); | 126 | address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); |
130 | 127 | ||
131 | spin_lock_irqsave(&rpc->lock, flags); | ||
132 | rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); | 128 | rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); |
133 | rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA); | 129 | rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA); |
134 | spin_unlock_irqrestore(&rpc->lock, flags); | ||
135 | } | 130 | } |
136 | 131 | ||
137 | static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc) | 132 | static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc) |
@@ -252,10 +247,8 @@ static int rt3883_pci_config_read(struct pci_bus *bus, unsigned int devfn, | |||
252 | address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), | 247 | address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), |
253 | PCI_FUNC(devfn), where); | 248 | PCI_FUNC(devfn), where); |
254 | 249 | ||
255 | spin_lock_irqsave(&rpc->lock, flags); | ||
256 | rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); | 250 | rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); |
257 | data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); | 251 | data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); |
258 | spin_unlock_irqrestore(&rpc->lock, flags); | ||
259 | 252 | ||
260 | switch (size) { | 253 | switch (size) { |
261 | case 1: | 254 | case 1: |
@@ -288,7 +281,6 @@ static int rt3883_pci_config_write(struct pci_bus *bus, unsigned int devfn, | |||
288 | address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), | 281 | address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), |
289 | PCI_FUNC(devfn), where); | 282 | PCI_FUNC(devfn), where); |
290 | 283 | ||
291 | spin_lock_irqsave(&rpc->lock, flags); | ||
292 | rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); | 284 | rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); |
293 | data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); | 285 | data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); |
294 | 286 | ||
@@ -307,7 +299,6 @@ static int rt3883_pci_config_write(struct pci_bus *bus, unsigned int devfn, | |||
307 | } | 299 | } |
308 | 300 | ||
309 | rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA); | 301 | rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA); |
310 | spin_unlock_irqrestore(&rpc->lock, flags); | ||
311 | 302 | ||
312 | return PCIBIOS_SUCCESSFUL; | 303 | return PCIBIOS_SUCCESSFUL; |
313 | } | 304 | } |
diff --git a/arch/mips/pci/pci-tx4939.c b/arch/mips/pci/pci-tx4939.c index c10fbf2a19dc..cd8ed09c4f53 100644 --- a/arch/mips/pci/pci-tx4939.c +++ b/arch/mips/pci/pci-tx4939.c | |||
@@ -103,5 +103,5 @@ void __init tx4939_setup_pcierr_irq(void) | |||
103 | tx4927_pcierr_interrupt, | 103 | tx4927_pcierr_interrupt, |
104 | 0, "PCI error", | 104 | 0, "PCI error", |
105 | (void *)TX4939_PCIC_REG)) | 105 | (void *)TX4939_PCIC_REG)) |
106 | pr_warning("Failed to request irq for PCIERR\n"); | 106 | pr_warn("Failed to request irq for PCIERR\n"); |
107 | } | 107 | } |
diff --git a/arch/mips/pmcs-msp71xx/msp_prom.c b/arch/mips/pmcs-msp71xx/msp_prom.c index 1c9897531660..ef620a4c82a5 100644 --- a/arch/mips/pmcs-msp71xx/msp_prom.c +++ b/arch/mips/pmcs-msp71xx/msp_prom.c | |||
@@ -295,7 +295,7 @@ char *prom_getenv(char *env_name) | |||
295 | 295 | ||
296 | while (*var) { | 296 | while (*var) { |
297 | if (strncmp(env_name, *var, i) == 0) { | 297 | if (strncmp(env_name, *var, i) == 0) { |
298 | return (*var + strlen(env_name) + 1); | 298 | return *var + strlen(env_name) + 1; |
299 | } | 299 | } |
300 | var++; | 300 | var++; |
301 | } | 301 | } |
diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig index 77e8a9620e18..b1c52ca580f9 100644 --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig | |||
@@ -16,6 +16,7 @@ choice | |||
16 | config SOC_RT288X | 16 | config SOC_RT288X |
17 | bool "RT288x" | 17 | bool "RT288x" |
18 | select MIPS_L1_CACHE_SHIFT_4 | 18 | select MIPS_L1_CACHE_SHIFT_4 |
19 | select HW_HAS_PCI | ||
19 | 20 | ||
20 | config SOC_RT305X | 21 | config SOC_RT305X |
21 | bool "RT305x" | 22 | bool "RT305x" |
@@ -26,7 +27,7 @@ choice | |||
26 | select HW_HAS_PCI | 27 | select HW_HAS_PCI |
27 | 28 | ||
28 | config SOC_MT7620 | 29 | config SOC_MT7620 |
29 | bool "MT7620" | 30 | bool "MT7620/8" |
30 | 31 | ||
31 | endchoice | 32 | endchoice |
32 | 33 | ||
diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile index 2c09c8aa0ae2..a6c9d0061326 100644 --- a/arch/mips/ralink/Makefile +++ b/arch/mips/ralink/Makefile | |||
@@ -10,9 +10,13 @@ obj-y := prom.o of.o reset.o clk.o irq.o timer.o | |||
10 | 10 | ||
11 | obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o | 11 | obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o |
12 | 12 | ||
13 | obj-$(CONFIG_RALINK_ILL_ACC) += ill_acc.o | ||
14 | |||
13 | obj-$(CONFIG_SOC_RT288X) += rt288x.o | 15 | obj-$(CONFIG_SOC_RT288X) += rt288x.o |
14 | obj-$(CONFIG_SOC_RT305X) += rt305x.o | 16 | obj-$(CONFIG_SOC_RT305X) += rt305x.o |
15 | obj-$(CONFIG_SOC_RT3883) += rt3883.o | 17 | obj-$(CONFIG_SOC_RT3883) += rt3883.o |
16 | obj-$(CONFIG_SOC_MT7620) += mt7620.o | 18 | obj-$(CONFIG_SOC_MT7620) += mt7620.o |
17 | 19 | ||
18 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 20 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
21 | |||
22 | obj-$(CONFIG_DEBUG_FS) += bootrom.o | ||
diff --git a/arch/mips/ralink/bootrom.c b/arch/mips/ralink/bootrom.c new file mode 100644 index 000000000000..5403468394fb --- /dev/null +++ b/arch/mips/ralink/bootrom.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License version 2 as published | ||
4 | * by the Free Software Foundation. | ||
5 | * | ||
6 | * Copyright (C) 2013 John Crispin <blogic@openwrt.org> | ||
7 | */ | ||
8 | |||
9 | #include <linux/debugfs.h> | ||
10 | #include <linux/seq_file.h> | ||
11 | |||
12 | #define BOOTROM_OFFSET 0x10118000 | ||
13 | #define BOOTROM_SIZE 0x8000 | ||
14 | |||
15 | static void __iomem *membase = (void __iomem *) KSEG1ADDR(BOOTROM_OFFSET); | ||
16 | |||
17 | static int bootrom_show(struct seq_file *s, void *unused) | ||
18 | { | ||
19 | seq_write(s, membase, BOOTROM_SIZE); | ||
20 | |||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | static int bootrom_open(struct inode *inode, struct file *file) | ||
25 | { | ||
26 | return single_open(file, bootrom_show, NULL); | ||
27 | } | ||
28 | |||
29 | static const struct file_operations bootrom_file_ops = { | ||
30 | .open = bootrom_open, | ||
31 | .read = seq_read, | ||
32 | .llseek = seq_lseek, | ||
33 | .release = single_release, | ||
34 | }; | ||
35 | |||
36 | static int bootrom_setup(void) | ||
37 | { | ||
38 | if (!debugfs_create_file("bootrom", 0444, | ||
39 | NULL, NULL, &bootrom_file_ops)) { | ||
40 | pr_err("Failed to create bootrom debugfs file\n"); | ||
41 | |||
42 | return -EINVAL; | ||
43 | } | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | postcore_initcall(bootrom_setup); | ||
diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c index 5d0983d47161..feb5a9bf98b4 100644 --- a/arch/mips/ralink/clk.c +++ b/arch/mips/ralink/clk.c | |||
@@ -56,6 +56,12 @@ unsigned long clk_get_rate(struct clk *clk) | |||
56 | } | 56 | } |
57 | EXPORT_SYMBOL_GPL(clk_get_rate); | 57 | EXPORT_SYMBOL_GPL(clk_get_rate); |
58 | 58 | ||
59 | int clk_set_rate(struct clk *clk, unsigned long rate) | ||
60 | { | ||
61 | return -1; | ||
62 | } | ||
63 | EXPORT_SYMBOL_GPL(clk_set_rate); | ||
64 | |||
59 | void __init plat_time_init(void) | 65 | void __init plat_time_init(void) |
60 | { | 66 | { |
61 | struct clk *clk; | 67 | struct clk *clk; |
diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h index 42dfd6100a2d..8e7d8e618fb9 100644 --- a/arch/mips/ralink/common.h +++ b/arch/mips/ralink/common.h | |||
@@ -11,25 +11,6 @@ | |||
11 | 11 | ||
12 | #define RAMIPS_SYS_TYPE_LEN 32 | 12 | #define RAMIPS_SYS_TYPE_LEN 32 |
13 | 13 | ||
14 | struct ralink_pinmux_grp { | ||
15 | const char *name; | ||
16 | u32 mask; | ||
17 | int gpio_first; | ||
18 | int gpio_last; | ||
19 | }; | ||
20 | |||
21 | struct ralink_pinmux { | ||
22 | struct ralink_pinmux_grp *mode; | ||
23 | struct ralink_pinmux_grp *uart; | ||
24 | int uart_shift; | ||
25 | u32 uart_mask; | ||
26 | void (*wdt_reset)(void); | ||
27 | struct ralink_pinmux_grp *pci; | ||
28 | int pci_shift; | ||
29 | u32 pci_mask; | ||
30 | }; | ||
31 | extern struct ralink_pinmux rt_gpio_pinmux; | ||
32 | |||
33 | struct ralink_soc_info { | 14 | struct ralink_soc_info { |
34 | unsigned char sys_type[RAMIPS_SYS_TYPE_LEN]; | 15 | unsigned char sys_type[RAMIPS_SYS_TYPE_LEN]; |
35 | unsigned char *compatible; | 16 | unsigned char *compatible; |
diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c index b46d0419d09b..255d695ec8c6 100644 --- a/arch/mips/ralink/early_printk.c +++ b/arch/mips/ralink/early_printk.c | |||
@@ -12,21 +12,24 @@ | |||
12 | #include <asm/addrspace.h> | 12 | #include <asm/addrspace.h> |
13 | 13 | ||
14 | #ifdef CONFIG_SOC_RT288X | 14 | #ifdef CONFIG_SOC_RT288X |
15 | #define EARLY_UART_BASE 0x300c00 | 15 | #define EARLY_UART_BASE 0x300c00 |
16 | #define CHIPID_BASE 0x300004 | ||
17 | #elif defined(CONFIG_SOC_MT7621) | ||
18 | #define EARLY_UART_BASE 0x1E000c00 | ||
19 | #define CHIPID_BASE 0x1E000004 | ||
16 | #else | 20 | #else |
17 | #define EARLY_UART_BASE 0x10000c00 | 21 | #define EARLY_UART_BASE 0x10000c00 |
22 | #define CHIPID_BASE 0x10000004 | ||
18 | #endif | 23 | #endif |
19 | 24 | ||
20 | #define UART_REG_RX 0x00 | 25 | #define MT7628_CHIP_NAME1 0x20203832 |
21 | #define UART_REG_TX 0x04 | 26 | |
22 | #define UART_REG_IER 0x08 | 27 | #define UART_REG_TX 0x04 |
23 | #define UART_REG_IIR 0x0c | 28 | #define UART_REG_LSR 0x14 |
24 | #define UART_REG_FCR 0x10 | 29 | #define UART_REG_LSR_RT2880 0x1c |
25 | #define UART_REG_LCR 0x14 | ||
26 | #define UART_REG_MCR 0x18 | ||
27 | #define UART_REG_LSR 0x1c | ||
28 | 30 | ||
29 | static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE); | 31 | static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE); |
32 | static __iomem void *chipid_membase = (__iomem void *) KSEG1ADDR(CHIPID_BASE); | ||
30 | 33 | ||
31 | static inline void uart_w32(u32 val, unsigned reg) | 34 | static inline void uart_w32(u32 val, unsigned reg) |
32 | { | 35 | { |
@@ -38,11 +41,23 @@ static inline u32 uart_r32(unsigned reg) | |||
38 | return __raw_readl(uart_membase + reg); | 41 | return __raw_readl(uart_membase + reg); |
39 | } | 42 | } |
40 | 43 | ||
44 | static inline int soc_is_mt7628(void) | ||
45 | { | ||
46 | return IS_ENABLED(CONFIG_SOC_MT7620) && | ||
47 | (__raw_readl(chipid_membase) == MT7628_CHIP_NAME1); | ||
48 | } | ||
49 | |||
41 | void prom_putchar(unsigned char ch) | 50 | void prom_putchar(unsigned char ch) |
42 | { | 51 | { |
43 | while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) | 52 | if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) { |
44 | ; | 53 | uart_w32(ch, UART_TX); |
45 | uart_w32(ch, UART_REG_TX); | 54 | while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) |
46 | while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) | 55 | ; |
47 | ; | 56 | } else { |
57 | while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0) | ||
58 | ; | ||
59 | uart_w32(ch, UART_REG_TX); | ||
60 | while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0) | ||
61 | ; | ||
62 | } | ||
48 | } | 63 | } |
diff --git a/arch/mips/ralink/ill_acc.c b/arch/mips/ralink/ill_acc.c new file mode 100644 index 000000000000..e20b02e3ae28 --- /dev/null +++ b/arch/mips/ralink/ill_acc.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License version 2 as published | ||
4 | * by the Free Software Foundation. | ||
5 | * | ||
6 | * Copyright (C) 2013 John Crispin <blogic@openwrt.org> | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/of_platform.h> | ||
11 | #include <linux/of_irq.h> | ||
12 | |||
13 | #include <asm/mach-ralink/ralink_regs.h> | ||
14 | |||
15 | #define REG_ILL_ACC_ADDR 0x10 | ||
16 | #define REG_ILL_ACC_TYPE 0x14 | ||
17 | |||
18 | #define ILL_INT_STATUS BIT(31) | ||
19 | #define ILL_ACC_WRITE BIT(30) | ||
20 | #define ILL_ACC_LEN_M 0xff | ||
21 | #define ILL_ACC_OFF_M 0xf | ||
22 | #define ILL_ACC_OFF_S 16 | ||
23 | #define ILL_ACC_ID_M 0x7 | ||
24 | #define ILL_ACC_ID_S 8 | ||
25 | |||
26 | #define DRV_NAME "ill_acc" | ||
27 | |||
28 | static const char * const ill_acc_ids[] = { | ||
29 | "cpu", "dma", "ppe", "pdma rx", "pdma tx", "pci/e", "wmac", "usb", | ||
30 | }; | ||
31 | |||
32 | static irqreturn_t ill_acc_irq_handler(int irq, void *_priv) | ||
33 | { | ||
34 | struct device *dev = (struct device *) _priv; | ||
35 | u32 addr = rt_memc_r32(REG_ILL_ACC_ADDR); | ||
36 | u32 type = rt_memc_r32(REG_ILL_ACC_TYPE); | ||
37 | |||
38 | dev_err(dev, "illegal %s access from %s - addr:0x%08x offset:%d len:%d\n", | ||
39 | (type & ILL_ACC_WRITE) ? ("write") : ("read"), | ||
40 | ill_acc_ids[(type >> ILL_ACC_ID_S) & ILL_ACC_ID_M], | ||
41 | addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M, | ||
42 | type & ILL_ACC_LEN_M); | ||
43 | |||
44 | rt_memc_w32(REG_ILL_ACC_TYPE, REG_ILL_ACC_TYPE); | ||
45 | |||
46 | return IRQ_HANDLED; | ||
47 | } | ||
48 | |||
49 | static int __init ill_acc_of_setup(void) | ||
50 | { | ||
51 | struct platform_device *pdev; | ||
52 | struct device_node *np; | ||
53 | int irq; | ||
54 | |||
55 | /* somehow this driver breaks on RT5350 */ | ||
56 | if (of_machine_is_compatible("ralink,rt5350-soc")) | ||
57 | return -EINVAL; | ||
58 | |||
59 | np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-memc"); | ||
60 | if (!np) | ||
61 | return -EINVAL; | ||
62 | |||
63 | pdev = of_find_device_by_node(np); | ||
64 | if (!pdev) { | ||
65 | pr_err("%s: failed to lookup pdev\n", np->name); | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | |||
69 | irq = irq_of_parse_and_map(np, 0); | ||
70 | if (!irq) { | ||
71 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
72 | return -EINVAL; | ||
73 | } | ||
74 | |||
75 | if (request_irq(irq, ill_acc_irq_handler, 0, "ill_acc", &pdev->dev)) { | ||
76 | dev_err(&pdev->dev, "failed to request irq\n"); | ||
77 | return -EINVAL; | ||
78 | } | ||
79 | |||
80 | rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE); | ||
81 | |||
82 | dev_info(&pdev->dev, "irq registered\n"); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | arch_initcall(ill_acc_of_setup); | ||
diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c index 781b3d14a489..7cf91b92e9d1 100644 --- a/arch/mips/ralink/irq.c +++ b/arch/mips/ralink/irq.c | |||
@@ -20,14 +20,6 @@ | |||
20 | 20 | ||
21 | #include "common.h" | 21 | #include "common.h" |
22 | 22 | ||
23 | /* INTC register offsets */ | ||
24 | #define INTC_REG_STATUS0 0x00 | ||
25 | #define INTC_REG_STATUS1 0x04 | ||
26 | #define INTC_REG_TYPE 0x20 | ||
27 | #define INTC_REG_RAW_STATUS 0x30 | ||
28 | #define INTC_REG_ENABLE 0x34 | ||
29 | #define INTC_REG_DISABLE 0x38 | ||
30 | |||
31 | #define INTC_INT_GLOBAL BIT(31) | 23 | #define INTC_INT_GLOBAL BIT(31) |
32 | 24 | ||
33 | #define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2) | 25 | #define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2) |
@@ -44,16 +36,36 @@ | |||
44 | 36 | ||
45 | #define RALINK_INTC_IRQ_PERFC (RALINK_INTC_IRQ_BASE + 9) | 37 | #define RALINK_INTC_IRQ_PERFC (RALINK_INTC_IRQ_BASE + 9) |
46 | 38 | ||
39 | enum rt_intc_regs_enum { | ||
40 | INTC_REG_STATUS0 = 0, | ||
41 | INTC_REG_STATUS1, | ||
42 | INTC_REG_TYPE, | ||
43 | INTC_REG_RAW_STATUS, | ||
44 | INTC_REG_ENABLE, | ||
45 | INTC_REG_DISABLE, | ||
46 | }; | ||
47 | |||
48 | static u32 rt_intc_regs[] = { | ||
49 | [INTC_REG_STATUS0] = 0x00, | ||
50 | [INTC_REG_STATUS1] = 0x04, | ||
51 | [INTC_REG_TYPE] = 0x20, | ||
52 | [INTC_REG_RAW_STATUS] = 0x30, | ||
53 | [INTC_REG_ENABLE] = 0x34, | ||
54 | [INTC_REG_DISABLE] = 0x38, | ||
55 | }; | ||
56 | |||
47 | static void __iomem *rt_intc_membase; | 57 | static void __iomem *rt_intc_membase; |
48 | 58 | ||
59 | static int rt_perfcount_irq; | ||
60 | |||
49 | static inline void rt_intc_w32(u32 val, unsigned reg) | 61 | static inline void rt_intc_w32(u32 val, unsigned reg) |
50 | { | 62 | { |
51 | __raw_writel(val, rt_intc_membase + reg); | 63 | __raw_writel(val, rt_intc_membase + rt_intc_regs[reg]); |
52 | } | 64 | } |
53 | 65 | ||
54 | static inline u32 rt_intc_r32(unsigned reg) | 66 | static inline u32 rt_intc_r32(unsigned reg) |
55 | { | 67 | { |
56 | return __raw_readl(rt_intc_membase + reg); | 68 | return __raw_readl(rt_intc_membase + rt_intc_regs[reg]); |
57 | } | 69 | } |
58 | 70 | ||
59 | static void ralink_intc_irq_unmask(struct irq_data *d) | 71 | static void ralink_intc_irq_unmask(struct irq_data *d) |
@@ -73,6 +85,11 @@ static struct irq_chip ralink_intc_irq_chip = { | |||
73 | .irq_mask_ack = ralink_intc_irq_mask, | 85 | .irq_mask_ack = ralink_intc_irq_mask, |
74 | }; | 86 | }; |
75 | 87 | ||
88 | int get_c0_perfcount_int(void) | ||
89 | { | ||
90 | return rt_perfcount_irq; | ||
91 | } | ||
92 | |||
76 | unsigned int get_c0_compare_int(void) | 93 | unsigned int get_c0_compare_int(void) |
77 | { | 94 | { |
78 | return CP0_LEGACY_COMPARE_IRQ; | 95 | return CP0_LEGACY_COMPARE_IRQ; |
@@ -134,6 +151,10 @@ static int __init intc_of_init(struct device_node *node, | |||
134 | struct irq_domain *domain; | 151 | struct irq_domain *domain; |
135 | int irq; | 152 | int irq; |
136 | 153 | ||
154 | if (!of_property_read_u32_array(node, "ralink,intc-registers", | ||
155 | rt_intc_regs, 6)) | ||
156 | pr_info("intc: using register map from devicetree\n"); | ||
157 | |||
137 | irq = irq_of_parse_and_map(node, 0); | 158 | irq = irq_of_parse_and_map(node, 0); |
138 | if (!irq) | 159 | if (!irq) |
139 | panic("Failed to get INTC IRQ"); | 160 | panic("Failed to get INTC IRQ"); |
@@ -167,13 +188,13 @@ static int __init intc_of_init(struct device_node *node, | |||
167 | irq_set_handler_data(irq, domain); | 188 | irq_set_handler_data(irq, domain); |
168 | 189 | ||
169 | /* tell the kernel which irq is used for performance monitoring */ | 190 | /* tell the kernel which irq is used for performance monitoring */ |
170 | cp0_perfcount_irq = irq_create_mapping(domain, 9); | 191 | rt_perfcount_irq = irq_create_mapping(domain, 9); |
171 | 192 | ||
172 | return 0; | 193 | return 0; |
173 | } | 194 | } |
174 | 195 | ||
175 | static struct of_device_id __initdata of_irq_ids[] = { | 196 | static struct of_device_id __initdata of_irq_ids[] = { |
176 | { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init }, | 197 | { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init }, |
177 | { .compatible = "ralink,rt2880-intc", .data = intc_of_init }, | 198 | { .compatible = "ralink,rt2880-intc", .data = intc_of_init }, |
178 | {}, | 199 | {}, |
179 | }; | 200 | }; |
diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index a3ad56c2372d..2ea5ff6dc22e 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c | |||
@@ -17,124 +17,214 @@ | |||
17 | #include <asm/mipsregs.h> | 17 | #include <asm/mipsregs.h> |
18 | #include <asm/mach-ralink/ralink_regs.h> | 18 | #include <asm/mach-ralink/ralink_regs.h> |
19 | #include <asm/mach-ralink/mt7620.h> | 19 | #include <asm/mach-ralink/mt7620.h> |
20 | #include <asm/mach-ralink/pinmux.h> | ||
20 | 21 | ||
21 | #include "common.h" | 22 | #include "common.h" |
22 | 23 | ||
24 | /* analog */ | ||
25 | #define PMU0_CFG 0x88 | ||
26 | #define PMU_SW_SET BIT(28) | ||
27 | #define A_DCDC_EN BIT(24) | ||
28 | #define A_SSC_PERI BIT(19) | ||
29 | #define A_SSC_GEN BIT(18) | ||
30 | #define A_SSC_M 0x3 | ||
31 | #define A_SSC_S 16 | ||
32 | #define A_DLY_M 0x7 | ||
33 | #define A_DLY_S 8 | ||
34 | #define A_VTUNE_M 0xff | ||
35 | |||
36 | /* digital */ | ||
37 | #define PMU1_CFG 0x8C | ||
38 | #define DIG_SW_SEL BIT(25) | ||
39 | |||
40 | /* is this a MT7620 or a MT7628 */ | ||
41 | enum mt762x_soc_type mt762x_soc; | ||
42 | |||
23 | /* does the board have sdram or ddram */ | 43 | /* does the board have sdram or ddram */ |
24 | static int dram_type; | 44 | static int dram_type; |
25 | 45 | ||
26 | static struct ralink_pinmux_grp mode_mux[] = { | 46 | static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 1, 2) }; |
27 | { | 47 | static struct rt2880_pmx_func spi_grp[] = { FUNC("spi", 0, 3, 4) }; |
28 | .name = "i2c", | 48 | static struct rt2880_pmx_func uartlite_grp[] = { FUNC("uartlite", 0, 15, 2) }; |
29 | .mask = MT7620_GPIO_MODE_I2C, | 49 | static struct rt2880_pmx_func mdio_grp[] = { FUNC("mdio", 0, 22, 2) }; |
30 | .gpio_first = 1, | 50 | static struct rt2880_pmx_func rgmii1_grp[] = { FUNC("rgmii1", 0, 24, 12) }; |
31 | .gpio_last = 2, | 51 | static struct rt2880_pmx_func refclk_grp[] = { FUNC("spi refclk", 0, 37, 3) }; |
32 | }, { | 52 | static struct rt2880_pmx_func ephy_grp[] = { FUNC("ephy", 0, 40, 5) }; |
33 | .name = "spi", | 53 | static struct rt2880_pmx_func rgmii2_grp[] = { FUNC("rgmii2", 0, 60, 12) }; |
34 | .mask = MT7620_GPIO_MODE_SPI, | 54 | static struct rt2880_pmx_func wled_grp[] = { FUNC("wled", 0, 72, 1) }; |
35 | .gpio_first = 3, | 55 | static struct rt2880_pmx_func pa_grp[] = { FUNC("pa", 0, 18, 4) }; |
36 | .gpio_last = 6, | 56 | static struct rt2880_pmx_func uartf_grp[] = { |
37 | }, { | 57 | FUNC("uartf", MT7620_GPIO_MODE_UARTF, 7, 8), |
38 | .name = "uartlite", | 58 | FUNC("pcm uartf", MT7620_GPIO_MODE_PCM_UARTF, 7, 8), |
39 | .mask = MT7620_GPIO_MODE_UART1, | 59 | FUNC("pcm i2s", MT7620_GPIO_MODE_PCM_I2S, 7, 8), |
40 | .gpio_first = 15, | 60 | FUNC("i2s uartf", MT7620_GPIO_MODE_I2S_UARTF, 7, 8), |
41 | .gpio_last = 16, | 61 | FUNC("pcm gpio", MT7620_GPIO_MODE_PCM_GPIO, 11, 4), |
42 | }, { | 62 | FUNC("gpio uartf", MT7620_GPIO_MODE_GPIO_UARTF, 7, 4), |
43 | .name = "wdt", | 63 | FUNC("gpio i2s", MT7620_GPIO_MODE_GPIO_I2S, 7, 4), |
44 | .mask = MT7620_GPIO_MODE_WDT, | 64 | }; |
45 | .gpio_first = 17, | 65 | static struct rt2880_pmx_func wdt_grp[] = { |
46 | .gpio_last = 17, | 66 | FUNC("wdt rst", 0, 17, 1), |
47 | }, { | 67 | FUNC("wdt refclk", 0, 17, 1), |
48 | .name = "mdio", | 68 | }; |
49 | .mask = MT7620_GPIO_MODE_MDIO, | 69 | static struct rt2880_pmx_func pcie_rst_grp[] = { |
50 | .gpio_first = 22, | 70 | FUNC("pcie rst", MT7620_GPIO_MODE_PCIE_RST, 36, 1), |
51 | .gpio_last = 23, | 71 | FUNC("pcie refclk", MT7620_GPIO_MODE_PCIE_REF, 36, 1) |
52 | }, { | 72 | }; |
53 | .name = "rgmii1", | 73 | static struct rt2880_pmx_func nd_sd_grp[] = { |
54 | .mask = MT7620_GPIO_MODE_RGMII1, | 74 | FUNC("nand", MT7620_GPIO_MODE_NAND, 45, 15), |
55 | .gpio_first = 24, | 75 | FUNC("sd", MT7620_GPIO_MODE_SD, 45, 15) |
56 | .gpio_last = 35, | 76 | }; |
57 | }, { | 77 | |
58 | .name = "spi refclk", | 78 | static struct rt2880_pmx_group mt7620a_pinmux_data[] = { |
59 | .mask = MT7620_GPIO_MODE_SPI_REF_CLK, | 79 | GRP("i2c", i2c_grp, 1, MT7620_GPIO_MODE_I2C), |
60 | .gpio_first = 37, | 80 | GRP("uartf", uartf_grp, MT7620_GPIO_MODE_UART0_MASK, |
61 | .gpio_last = 39, | 81 | MT7620_GPIO_MODE_UART0_SHIFT), |
62 | }, { | 82 | GRP("spi", spi_grp, 1, MT7620_GPIO_MODE_SPI), |
63 | .name = "jtag", | 83 | GRP("uartlite", uartlite_grp, 1, MT7620_GPIO_MODE_UART1), |
64 | .mask = MT7620_GPIO_MODE_JTAG, | 84 | GRP_G("wdt", wdt_grp, MT7620_GPIO_MODE_WDT_MASK, |
65 | .gpio_first = 40, | 85 | MT7620_GPIO_MODE_WDT_GPIO, MT7620_GPIO_MODE_WDT_SHIFT), |
66 | .gpio_last = 44, | 86 | GRP("mdio", mdio_grp, 1, MT7620_GPIO_MODE_MDIO), |
67 | }, { | 87 | GRP("rgmii1", rgmii1_grp, 1, MT7620_GPIO_MODE_RGMII1), |
68 | /* shared lines with jtag */ | 88 | GRP("spi refclk", refclk_grp, 1, MT7620_GPIO_MODE_SPI_REF_CLK), |
69 | .name = "ephy", | 89 | GRP_G("pcie", pcie_rst_grp, MT7620_GPIO_MODE_PCIE_MASK, |
70 | .mask = MT7620_GPIO_MODE_EPHY, | 90 | MT7620_GPIO_MODE_PCIE_GPIO, MT7620_GPIO_MODE_PCIE_SHIFT), |
71 | .gpio_first = 40, | 91 | GRP_G("nd_sd", nd_sd_grp, MT7620_GPIO_MODE_ND_SD_MASK, |
72 | .gpio_last = 44, | 92 | MT7620_GPIO_MODE_ND_SD_GPIO, MT7620_GPIO_MODE_ND_SD_SHIFT), |
73 | }, { | 93 | GRP("rgmii2", rgmii2_grp, 1, MT7620_GPIO_MODE_RGMII2), |
74 | .name = "nand", | 94 | GRP("wled", wled_grp, 1, MT7620_GPIO_MODE_WLED), |
75 | .mask = MT7620_GPIO_MODE_JTAG, | 95 | GRP("ephy", ephy_grp, 1, MT7620_GPIO_MODE_EPHY), |
76 | .gpio_first = 45, | 96 | GRP("pa", pa_grp, 1, MT7620_GPIO_MODE_PA), |
77 | .gpio_last = 59, | 97 | { 0 } |
78 | }, { | 98 | }; |
79 | .name = "rgmii2", | 99 | |
80 | .mask = MT7620_GPIO_MODE_RGMII2, | 100 | static struct rt2880_pmx_func pwm1_grp_mt7628[] = { |
81 | .gpio_first = 60, | 101 | FUNC("sdcx", 3, 19, 1), |
82 | .gpio_last = 71, | 102 | FUNC("utif", 2, 19, 1), |
83 | }, { | 103 | FUNC("gpio", 1, 19, 1), |
84 | .name = "wled", | 104 | FUNC("pwm", 0, 19, 1), |
85 | .mask = MT7620_GPIO_MODE_WLED, | 105 | }; |
86 | .gpio_first = 72, | 106 | |
87 | .gpio_last = 72, | 107 | static struct rt2880_pmx_func pwm0_grp_mt7628[] = { |
88 | }, {0} | 108 | FUNC("sdcx", 3, 18, 1), |
109 | FUNC("utif", 2, 18, 1), | ||
110 | FUNC("gpio", 1, 18, 1), | ||
111 | FUNC("pwm", 0, 18, 1), | ||
112 | }; | ||
113 | |||
114 | static struct rt2880_pmx_func uart2_grp_mt7628[] = { | ||
115 | FUNC("sdcx", 3, 20, 2), | ||
116 | FUNC("pwm", 2, 20, 2), | ||
117 | FUNC("gpio", 1, 20, 2), | ||
118 | FUNC("uart", 0, 20, 2), | ||
119 | }; | ||
120 | |||
121 | static struct rt2880_pmx_func uart1_grp_mt7628[] = { | ||
122 | FUNC("sdcx", 3, 45, 2), | ||
123 | FUNC("pwm", 2, 45, 2), | ||
124 | FUNC("gpio", 1, 45, 2), | ||
125 | FUNC("uart", 0, 45, 2), | ||
126 | }; | ||
127 | |||
128 | static struct rt2880_pmx_func i2c_grp_mt7628[] = { | ||
129 | FUNC("-", 3, 4, 2), | ||
130 | FUNC("debug", 2, 4, 2), | ||
131 | FUNC("gpio", 1, 4, 2), | ||
132 | FUNC("i2c", 0, 4, 2), | ||
133 | }; | ||
134 | |||
135 | static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 36, 1) }; | ||
136 | static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 37, 1) }; | ||
137 | static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 15, 38) }; | ||
138 | static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) }; | ||
139 | |||
140 | static struct rt2880_pmx_func sd_mode_grp_mt7628[] = { | ||
141 | FUNC("jtag", 3, 22, 8), | ||
142 | FUNC("utif", 2, 22, 8), | ||
143 | FUNC("gpio", 1, 22, 8), | ||
144 | FUNC("sdcx", 0, 22, 8), | ||
145 | }; | ||
146 | |||
147 | static struct rt2880_pmx_func uart0_grp_mt7628[] = { | ||
148 | FUNC("-", 3, 12, 2), | ||
149 | FUNC("-", 2, 12, 2), | ||
150 | FUNC("gpio", 1, 12, 2), | ||
151 | FUNC("uart", 0, 12, 2), | ||
152 | }; | ||
153 | |||
154 | static struct rt2880_pmx_func i2s_grp_mt7628[] = { | ||
155 | FUNC("antenna", 3, 0, 4), | ||
156 | FUNC("pcm", 2, 0, 4), | ||
157 | FUNC("gpio", 1, 0, 4), | ||
158 | FUNC("i2s", 0, 0, 4), | ||
159 | }; | ||
160 | |||
161 | static struct rt2880_pmx_func spi_cs1_grp_mt7628[] = { | ||
162 | FUNC("-", 3, 6, 1), | ||
163 | FUNC("refclk", 2, 6, 1), | ||
164 | FUNC("gpio", 1, 6, 1), | ||
165 | FUNC("spi", 0, 6, 1), | ||
166 | }; | ||
167 | |||
168 | static struct rt2880_pmx_func spis_grp_mt7628[] = { | ||
169 | FUNC("pwm", 3, 14, 4), | ||
170 | FUNC("util", 2, 14, 4), | ||
171 | FUNC("gpio", 1, 14, 4), | ||
172 | FUNC("spis", 0, 14, 4), | ||
89 | }; | 173 | }; |
90 | 174 | ||
91 | static struct ralink_pinmux_grp uart_mux[] = { | 175 | static struct rt2880_pmx_func gpio_grp_mt7628[] = { |
92 | { | 176 | FUNC("pcie", 3, 11, 1), |
93 | .name = "uartf", | 177 | FUNC("refclk", 2, 11, 1), |
94 | .mask = MT7620_GPIO_MODE_UARTF, | 178 | FUNC("gpio", 1, 11, 1), |
95 | .gpio_first = 7, | 179 | FUNC("gpio", 0, 11, 1), |
96 | .gpio_last = 14, | ||
97 | }, { | ||
98 | .name = "pcm uartf", | ||
99 | .mask = MT7620_GPIO_MODE_PCM_UARTF, | ||
100 | .gpio_first = 7, | ||
101 | .gpio_last = 14, | ||
102 | }, { | ||
103 | .name = "pcm i2s", | ||
104 | .mask = MT7620_GPIO_MODE_PCM_I2S, | ||
105 | .gpio_first = 7, | ||
106 | .gpio_last = 14, | ||
107 | }, { | ||
108 | .name = "i2s uartf", | ||
109 | .mask = MT7620_GPIO_MODE_I2S_UARTF, | ||
110 | .gpio_first = 7, | ||
111 | .gpio_last = 14, | ||
112 | }, { | ||
113 | .name = "pcm gpio", | ||
114 | .mask = MT7620_GPIO_MODE_PCM_GPIO, | ||
115 | .gpio_first = 11, | ||
116 | .gpio_last = 14, | ||
117 | }, { | ||
118 | .name = "gpio uartf", | ||
119 | .mask = MT7620_GPIO_MODE_GPIO_UARTF, | ||
120 | .gpio_first = 7, | ||
121 | .gpio_last = 10, | ||
122 | }, { | ||
123 | .name = "gpio i2s", | ||
124 | .mask = MT7620_GPIO_MODE_GPIO_I2S, | ||
125 | .gpio_first = 7, | ||
126 | .gpio_last = 10, | ||
127 | }, { | ||
128 | .name = "gpio", | ||
129 | .mask = MT7620_GPIO_MODE_GPIO, | ||
130 | }, {0} | ||
131 | }; | 180 | }; |
132 | 181 | ||
133 | struct ralink_pinmux rt_gpio_pinmux = { | 182 | #define MT7628_GPIO_MODE_MASK 0x3 |
134 | .mode = mode_mux, | 183 | |
135 | .uart = uart_mux, | 184 | #define MT7628_GPIO_MODE_PWM1 30 |
136 | .uart_shift = MT7620_GPIO_MODE_UART0_SHIFT, | 185 | #define MT7628_GPIO_MODE_PWM0 28 |
137 | .uart_mask = MT7620_GPIO_MODE_UART0_MASK, | 186 | #define MT7628_GPIO_MODE_UART2 26 |
187 | #define MT7628_GPIO_MODE_UART1 24 | ||
188 | #define MT7628_GPIO_MODE_I2C 20 | ||
189 | #define MT7628_GPIO_MODE_REFCLK 18 | ||
190 | #define MT7628_GPIO_MODE_PERST 16 | ||
191 | #define MT7628_GPIO_MODE_WDT 14 | ||
192 | #define MT7628_GPIO_MODE_SPI 12 | ||
193 | #define MT7628_GPIO_MODE_SDMODE 10 | ||
194 | #define MT7628_GPIO_MODE_UART0 8 | ||
195 | #define MT7628_GPIO_MODE_I2S 6 | ||
196 | #define MT7628_GPIO_MODE_CS1 4 | ||
197 | #define MT7628_GPIO_MODE_SPIS 2 | ||
198 | #define MT7628_GPIO_MODE_GPIO 0 | ||
199 | |||
200 | static struct rt2880_pmx_group mt7628an_pinmux_data[] = { | ||
201 | GRP_G("pmw1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
202 | 1, MT7628_GPIO_MODE_PWM1), | ||
203 | GRP_G("pmw1", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
204 | 1, MT7628_GPIO_MODE_PWM0), | ||
205 | GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
206 | 1, MT7628_GPIO_MODE_UART2), | ||
207 | GRP_G("uart1", uart1_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
208 | 1, MT7628_GPIO_MODE_UART1), | ||
209 | GRP_G("i2c", i2c_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
210 | 1, MT7628_GPIO_MODE_I2C), | ||
211 | GRP("refclk", refclk_grp_mt7628, 1, MT7628_GPIO_MODE_REFCLK), | ||
212 | GRP("perst", perst_grp_mt7628, 1, MT7628_GPIO_MODE_PERST), | ||
213 | GRP("wdt", wdt_grp_mt7628, 1, MT7628_GPIO_MODE_WDT), | ||
214 | GRP("spi", spi_grp_mt7628, 1, MT7628_GPIO_MODE_SPI), | ||
215 | GRP_G("sdmode", sd_mode_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
216 | 1, MT7628_GPIO_MODE_SDMODE), | ||
217 | GRP_G("uart0", uart0_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
218 | 1, MT7628_GPIO_MODE_UART0), | ||
219 | GRP_G("i2s", i2s_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
220 | 1, MT7628_GPIO_MODE_I2S), | ||
221 | GRP_G("spi cs1", spi_cs1_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
222 | 1, MT7628_GPIO_MODE_CS1), | ||
223 | GRP_G("spis", spis_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
224 | 1, MT7628_GPIO_MODE_SPIS), | ||
225 | GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK, | ||
226 | 1, MT7628_GPIO_MODE_GPIO), | ||
227 | { 0 } | ||
138 | }; | 228 | }; |
139 | 229 | ||
140 | static __init u32 | 230 | static __init u32 |
@@ -287,29 +377,42 @@ void __init ralink_clk_init(void) | |||
287 | 377 | ||
288 | xtal_rate = mt7620_get_xtal_rate(); | 378 | xtal_rate = mt7620_get_xtal_rate(); |
289 | 379 | ||
290 | cpu_pll_rate = mt7620_get_cpu_pll_rate(xtal_rate); | ||
291 | pll_rate = mt7620_get_pll_rate(xtal_rate, cpu_pll_rate); | ||
292 | |||
293 | cpu_rate = mt7620_get_cpu_rate(pll_rate); | ||
294 | dram_rate = mt7620_get_dram_rate(pll_rate); | ||
295 | sys_rate = mt7620_get_sys_rate(cpu_rate); | ||
296 | periph_rate = mt7620_get_periph_rate(xtal_rate); | ||
297 | |||
298 | #define RFMT(label) label ":%lu.%03luMHz " | 380 | #define RFMT(label) label ":%lu.%03luMHz " |
299 | #define RINT(x) ((x) / 1000000) | 381 | #define RINT(x) ((x) / 1000000) |
300 | #define RFRAC(x) (((x) / 1000) % 1000) | 382 | #define RFRAC(x) (((x) / 1000) % 1000) |
301 | 383 | ||
302 | pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"), | 384 | if (mt762x_soc == MT762X_SOC_MT7628AN) { |
303 | RINT(xtal_rate), RFRAC(xtal_rate), | 385 | if (xtal_rate == MHZ(40)) |
304 | RINT(cpu_pll_rate), RFRAC(cpu_pll_rate), | 386 | cpu_rate = MHZ(580); |
305 | RINT(pll_rate), RFRAC(pll_rate)); | 387 | else |
388 | cpu_rate = MHZ(575); | ||
389 | dram_rate = sys_rate = cpu_rate / 3; | ||
390 | periph_rate = MHZ(40); | ||
391 | |||
392 | ralink_clk_add("10000d00.uartlite", periph_rate); | ||
393 | ralink_clk_add("10000e00.uartlite", periph_rate); | ||
394 | } else { | ||
395 | cpu_pll_rate = mt7620_get_cpu_pll_rate(xtal_rate); | ||
396 | pll_rate = mt7620_get_pll_rate(xtal_rate, cpu_pll_rate); | ||
397 | |||
398 | cpu_rate = mt7620_get_cpu_rate(pll_rate); | ||
399 | dram_rate = mt7620_get_dram_rate(pll_rate); | ||
400 | sys_rate = mt7620_get_sys_rate(cpu_rate); | ||
401 | periph_rate = mt7620_get_periph_rate(xtal_rate); | ||
402 | |||
403 | pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"), | ||
404 | RINT(xtal_rate), RFRAC(xtal_rate), | ||
405 | RINT(cpu_pll_rate), RFRAC(cpu_pll_rate), | ||
406 | RINT(pll_rate), RFRAC(pll_rate)); | ||
407 | |||
408 | ralink_clk_add("10000500.uart", periph_rate); | ||
409 | } | ||
306 | 410 | ||
307 | pr_debug(RFMT("CPU") RFMT("DRAM") RFMT("SYS") RFMT("PERIPH"), | 411 | pr_debug(RFMT("CPU") RFMT("DRAM") RFMT("SYS") RFMT("PERIPH"), |
308 | RINT(cpu_rate), RFRAC(cpu_rate), | 412 | RINT(cpu_rate), RFRAC(cpu_rate), |
309 | RINT(dram_rate), RFRAC(dram_rate), | 413 | RINT(dram_rate), RFRAC(dram_rate), |
310 | RINT(sys_rate), RFRAC(sys_rate), | 414 | RINT(sys_rate), RFRAC(sys_rate), |
311 | RINT(periph_rate), RFRAC(periph_rate)); | 415 | RINT(periph_rate), RFRAC(periph_rate)); |
312 | |||
313 | #undef RFRAC | 416 | #undef RFRAC |
314 | #undef RINT | 417 | #undef RINT |
315 | #undef RFMT | 418 | #undef RFMT |
@@ -317,9 +420,9 @@ void __init ralink_clk_init(void) | |||
317 | ralink_clk_add("cpu", cpu_rate); | 420 | ralink_clk_add("cpu", cpu_rate); |
318 | ralink_clk_add("10000100.timer", periph_rate); | 421 | ralink_clk_add("10000100.timer", periph_rate); |
319 | ralink_clk_add("10000120.watchdog", periph_rate); | 422 | ralink_clk_add("10000120.watchdog", periph_rate); |
320 | ralink_clk_add("10000500.uart", periph_rate); | ||
321 | ralink_clk_add("10000b00.spi", sys_rate); | 423 | ralink_clk_add("10000b00.spi", sys_rate); |
322 | ralink_clk_add("10000c00.uartlite", periph_rate); | 424 | ralink_clk_add("10000c00.uartlite", periph_rate); |
425 | ralink_clk_add("10180000.wmac", xtal_rate); | ||
323 | } | 426 | } |
324 | 427 | ||
325 | void __init ralink_of_remap(void) | 428 | void __init ralink_of_remap(void) |
@@ -331,6 +434,52 @@ void __init ralink_of_remap(void) | |||
331 | panic("Failed to remap core resources"); | 434 | panic("Failed to remap core resources"); |
332 | } | 435 | } |
333 | 436 | ||
437 | static __init void | ||
438 | mt7620_dram_init(struct ralink_soc_info *soc_info) | ||
439 | { | ||
440 | switch (dram_type) { | ||
441 | case SYSCFG0_DRAM_TYPE_SDRAM: | ||
442 | pr_info("Board has SDRAM\n"); | ||
443 | soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; | ||
444 | soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; | ||
445 | break; | ||
446 | |||
447 | case SYSCFG0_DRAM_TYPE_DDR1: | ||
448 | pr_info("Board has DDR1\n"); | ||
449 | soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; | ||
450 | soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; | ||
451 | break; | ||
452 | |||
453 | case SYSCFG0_DRAM_TYPE_DDR2: | ||
454 | pr_info("Board has DDR2\n"); | ||
455 | soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; | ||
456 | soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; | ||
457 | break; | ||
458 | default: | ||
459 | BUG(); | ||
460 | } | ||
461 | } | ||
462 | |||
463 | static __init void | ||
464 | mt7628_dram_init(struct ralink_soc_info *soc_info) | ||
465 | { | ||
466 | switch (dram_type) { | ||
467 | case SYSCFG0_DRAM_TYPE_DDR1_MT7628: | ||
468 | pr_info("Board has DDR1\n"); | ||
469 | soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; | ||
470 | soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; | ||
471 | break; | ||
472 | |||
473 | case SYSCFG0_DRAM_TYPE_DDR2_MT7628: | ||
474 | pr_info("Board has DDR2\n"); | ||
475 | soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; | ||
476 | soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; | ||
477 | break; | ||
478 | default: | ||
479 | BUG(); | ||
480 | } | ||
481 | } | ||
482 | |||
334 | void prom_soc_init(struct ralink_soc_info *soc_info) | 483 | void prom_soc_init(struct ralink_soc_info *soc_info) |
335 | { | 484 | { |
336 | void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7620_SYSC_BASE); | 485 | void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7620_SYSC_BASE); |
@@ -339,22 +488,36 @@ void prom_soc_init(struct ralink_soc_info *soc_info) | |||
339 | u32 n1; | 488 | u32 n1; |
340 | u32 rev; | 489 | u32 rev; |
341 | u32 cfg0; | 490 | u32 cfg0; |
491 | u32 pmu0; | ||
492 | u32 pmu1; | ||
493 | u32 bga; | ||
342 | 494 | ||
343 | n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); | 495 | n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); |
344 | n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); | 496 | n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); |
345 | 497 | rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); | |
346 | if (n0 == MT7620N_CHIP_NAME0 && n1 == MT7620N_CHIP_NAME1) { | 498 | bga = (rev >> CHIP_REV_PKG_SHIFT) & CHIP_REV_PKG_MASK; |
347 | name = "MT7620N"; | 499 | |
348 | soc_info->compatible = "ralink,mt7620n-soc"; | 500 | if (n0 == MT7620_CHIP_NAME0 && n1 == MT7620_CHIP_NAME1) { |
349 | } else if (n0 == MT7620A_CHIP_NAME0 && n1 == MT7620A_CHIP_NAME1) { | 501 | if (bga) { |
350 | name = "MT7620A"; | 502 | mt762x_soc = MT762X_SOC_MT7620A; |
351 | soc_info->compatible = "ralink,mt7620a-soc"; | 503 | name = "MT7620A"; |
504 | soc_info->compatible = "ralink,mt7620a-soc"; | ||
505 | } else { | ||
506 | mt762x_soc = MT762X_SOC_MT7620N; | ||
507 | name = "MT7620N"; | ||
508 | soc_info->compatible = "ralink,mt7620n-soc"; | ||
509 | #ifdef CONFIG_PCI | ||
510 | panic("mt7620n is only supported for non pci kernels"); | ||
511 | #endif | ||
512 | } | ||
513 | } else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) { | ||
514 | mt762x_soc = MT762X_SOC_MT7628AN; | ||
515 | name = "MT7628AN"; | ||
516 | soc_info->compatible = "ralink,mt7628an-soc"; | ||
352 | } else { | 517 | } else { |
353 | panic("mt7620: unknown SoC, n0:%08x n1:%08x", n0, n1); | 518 | panic("mt762x: unknown SoC, n0:%08x n1:%08x\n", n0, n1); |
354 | } | 519 | } |
355 | 520 | ||
356 | rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); | ||
357 | |||
358 | snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, | 521 | snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, |
359 | "Ralink %s ver:%u eco:%u", | 522 | "Ralink %s ver:%u eco:%u", |
360 | name, | 523 | name, |
@@ -364,26 +527,22 @@ void prom_soc_init(struct ralink_soc_info *soc_info) | |||
364 | cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); | 527 | cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); |
365 | dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; | 528 | dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; |
366 | 529 | ||
367 | switch (dram_type) { | ||
368 | case SYSCFG0_DRAM_TYPE_SDRAM: | ||
369 | pr_info("Board has SDRAM\n"); | ||
370 | soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; | ||
371 | soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; | ||
372 | break; | ||
373 | |||
374 | case SYSCFG0_DRAM_TYPE_DDR1: | ||
375 | pr_info("Board has DDR1\n"); | ||
376 | soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; | ||
377 | soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; | ||
378 | break; | ||
379 | |||
380 | case SYSCFG0_DRAM_TYPE_DDR2: | ||
381 | pr_info("Board has DDR2\n"); | ||
382 | soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; | ||
383 | soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; | ||
384 | break; | ||
385 | default: | ||
386 | BUG(); | ||
387 | } | ||
388 | soc_info->mem_base = MT7620_DRAM_BASE; | 530 | soc_info->mem_base = MT7620_DRAM_BASE; |
531 | if (mt762x_soc == MT762X_SOC_MT7628AN) | ||
532 | mt7628_dram_init(soc_info); | ||
533 | else | ||
534 | mt7620_dram_init(soc_info); | ||
535 | |||
536 | pmu0 = __raw_readl(sysc + PMU0_CFG); | ||
537 | pmu1 = __raw_readl(sysc + PMU1_CFG); | ||
538 | |||
539 | pr_info("Analog PMU set to %s control\n", | ||
540 | (pmu0 & PMU_SW_SET) ? ("sw") : ("hw")); | ||
541 | pr_info("Digital PMU set to %s control\n", | ||
542 | (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw")); | ||
543 | |||
544 | if (mt762x_soc == MT762X_SOC_MT7628AN) | ||
545 | rt2880_pinmux_data = mt7628an_pinmux_data; | ||
546 | else | ||
547 | rt2880_pinmux_data = mt7620a_pinmux_data; | ||
389 | } | 548 | } |
diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c index 7c4598cb6de8..0d30dcd63246 100644 --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c | |||
@@ -53,6 +53,17 @@ void __init device_tree_init(void) | |||
53 | unflatten_and_copy_device_tree(); | 53 | unflatten_and_copy_device_tree(); |
54 | } | 54 | } |
55 | 55 | ||
56 | static int memory_dtb; | ||
57 | |||
58 | static int __init early_init_dt_find_memory(unsigned long node, | ||
59 | const char *uname, int depth, void *data) | ||
60 | { | ||
61 | if (depth == 1 && !strcmp(uname, "memory@0")) | ||
62 | memory_dtb = 1; | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
56 | void __init plat_mem_setup(void) | 67 | void __init plat_mem_setup(void) |
57 | { | 68 | { |
58 | set_io_port_base(KSEG1); | 69 | set_io_port_base(KSEG1); |
@@ -63,7 +74,12 @@ void __init plat_mem_setup(void) | |||
63 | */ | 74 | */ |
64 | __dt_setup_arch(__dtb_start); | 75 | __dt_setup_arch(__dtb_start); |
65 | 76 | ||
66 | if (soc_info.mem_size) | 77 | strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); |
78 | |||
79 | of_scan_flat_dt(early_init_dt_find_memory, NULL); | ||
80 | if (memory_dtb) | ||
81 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | ||
82 | else if (soc_info.mem_size) | ||
67 | add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M, | 83 | add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M, |
68 | BOOT_MEM_RAM); | 84 | BOOT_MEM_RAM); |
69 | else | 85 | else |
@@ -74,19 +90,9 @@ void __init plat_mem_setup(void) | |||
74 | 90 | ||
75 | static int __init plat_of_setup(void) | 91 | static int __init plat_of_setup(void) |
76 | { | 92 | { |
77 | static struct of_device_id of_ids[3]; | 93 | __dt_register_buses(soc_info.compatible, "palmbus"); |
78 | int len = sizeof(of_ids[0].compatible); | ||
79 | |||
80 | if (!of_have_populated_dt()) | ||
81 | panic("device tree not present"); | ||
82 | |||
83 | strlcpy(of_ids[0].compatible, soc_info.compatible, len); | ||
84 | strlcpy(of_ids[1].compatible, "palmbus", len); | ||
85 | |||
86 | if (of_platform_populate(NULL, of_ids, NULL, NULL)) | ||
87 | panic("failed to populate DT"); | ||
88 | 94 | ||
89 | /* make sure ithat the reset controller is setup early */ | 95 | /* make sure that the reset controller is setup early */ |
90 | ralink_rst_init(); | 96 | ralink_rst_init(); |
91 | 97 | ||
92 | return 0; | 98 | return 0; |
diff --git a/arch/mips/ralink/prom.c b/arch/mips/ralink/prom.c index 9c64f029d047..09419f67da39 100644 --- a/arch/mips/ralink/prom.c +++ b/arch/mips/ralink/prom.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "common.h" | 18 | #include "common.h" |
19 | 19 | ||
20 | struct ralink_soc_info soc_info; | 20 | struct ralink_soc_info soc_info; |
21 | struct rt2880_pmx_group *rt2880_pinmux_data = NULL; | ||
21 | 22 | ||
22 | const char *get_system_type(void) | 23 | const char *get_system_type(void) |
23 | { | 24 | { |
diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c index f87de1ab2198..738cec865f41 100644 --- a/arch/mips/ralink/rt288x.c +++ b/arch/mips/ralink/rt288x.c | |||
@@ -17,46 +17,27 @@ | |||
17 | #include <asm/mipsregs.h> | 17 | #include <asm/mipsregs.h> |
18 | #include <asm/mach-ralink/ralink_regs.h> | 18 | #include <asm/mach-ralink/ralink_regs.h> |
19 | #include <asm/mach-ralink/rt288x.h> | 19 | #include <asm/mach-ralink/rt288x.h> |
20 | #include <asm/mach-ralink/pinmux.h> | ||
20 | 21 | ||
21 | #include "common.h" | 22 | #include "common.h" |
22 | 23 | ||
23 | static struct ralink_pinmux_grp mode_mux[] = { | 24 | static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; |
24 | { | 25 | static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; |
25 | .name = "i2c", | 26 | static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 7, 8) }; |
26 | .mask = RT2880_GPIO_MODE_I2C, | 27 | static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; |
27 | .gpio_first = 1, | 28 | static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; |
28 | .gpio_last = 2, | 29 | static struct rt2880_pmx_func sdram_func[] = { FUNC("sdram", 0, 24, 16) }; |
29 | }, { | 30 | static struct rt2880_pmx_func pci_func[] = { FUNC("pci", 0, 40, 32) }; |
30 | .name = "spi", | 31 | |
31 | .mask = RT2880_GPIO_MODE_SPI, | 32 | static struct rt2880_pmx_group rt2880_pinmux_data_act[] = { |
32 | .gpio_first = 3, | 33 | GRP("i2c", i2c_func, 1, RT2880_GPIO_MODE_I2C), |
33 | .gpio_last = 6, | 34 | GRP("spi", spi_func, 1, RT2880_GPIO_MODE_SPI), |
34 | }, { | 35 | GRP("uartlite", uartlite_func, 1, RT2880_GPIO_MODE_UART0), |
35 | .name = "uartlite", | 36 | GRP("jtag", jtag_func, 1, RT2880_GPIO_MODE_JTAG), |
36 | .mask = RT2880_GPIO_MODE_UART0, | 37 | GRP("mdio", mdio_func, 1, RT2880_GPIO_MODE_MDIO), |
37 | .gpio_first = 7, | 38 | GRP("sdram", sdram_func, 1, RT2880_GPIO_MODE_SDRAM), |
38 | .gpio_last = 14, | 39 | GRP("pci", pci_func, 1, RT2880_GPIO_MODE_PCI), |
39 | }, { | 40 | { 0 } |
40 | .name = "jtag", | ||
41 | .mask = RT2880_GPIO_MODE_JTAG, | ||
42 | .gpio_first = 17, | ||
43 | .gpio_last = 21, | ||
44 | }, { | ||
45 | .name = "mdio", | ||
46 | .mask = RT2880_GPIO_MODE_MDIO, | ||
47 | .gpio_first = 22, | ||
48 | .gpio_last = 23, | ||
49 | }, { | ||
50 | .name = "sdram", | ||
51 | .mask = RT2880_GPIO_MODE_SDRAM, | ||
52 | .gpio_first = 24, | ||
53 | .gpio_last = 39, | ||
54 | }, { | ||
55 | .name = "pci", | ||
56 | .mask = RT2880_GPIO_MODE_PCI, | ||
57 | .gpio_first = 40, | ||
58 | .gpio_last = 71, | ||
59 | }, {0} | ||
60 | }; | 41 | }; |
61 | 42 | ||
62 | static void rt288x_wdt_reset(void) | 43 | static void rt288x_wdt_reset(void) |
@@ -69,14 +50,9 @@ static void rt288x_wdt_reset(void) | |||
69 | rt_sysc_w32(t, SYSC_REG_CLKCFG); | 50 | rt_sysc_w32(t, SYSC_REG_CLKCFG); |
70 | } | 51 | } |
71 | 52 | ||
72 | struct ralink_pinmux rt_gpio_pinmux = { | ||
73 | .mode = mode_mux, | ||
74 | .wdt_reset = rt288x_wdt_reset, | ||
75 | }; | ||
76 | |||
77 | void __init ralink_clk_init(void) | 53 | void __init ralink_clk_init(void) |
78 | { | 54 | { |
79 | unsigned long cpu_rate; | 55 | unsigned long cpu_rate, wmac_rate = 40000000; |
80 | u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); | 56 | u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); |
81 | t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK); | 57 | t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK); |
82 | 58 | ||
@@ -101,6 +77,7 @@ void __init ralink_clk_init(void) | |||
101 | ralink_clk_add("300500.uart", cpu_rate / 2); | 77 | ralink_clk_add("300500.uart", cpu_rate / 2); |
102 | ralink_clk_add("300c00.uartlite", cpu_rate / 2); | 78 | ralink_clk_add("300c00.uartlite", cpu_rate / 2); |
103 | ralink_clk_add("400000.ethernet", cpu_rate / 2); | 79 | ralink_clk_add("400000.ethernet", cpu_rate / 2); |
80 | ralink_clk_add("480000.wmac", wmac_rate); | ||
104 | } | 81 | } |
105 | 82 | ||
106 | void __init ralink_of_remap(void) | 83 | void __init ralink_of_remap(void) |
@@ -140,4 +117,6 @@ void prom_soc_init(struct ralink_soc_info *soc_info) | |||
140 | soc_info->mem_base = RT2880_SDRAM_BASE; | 117 | soc_info->mem_base = RT2880_SDRAM_BASE; |
141 | soc_info->mem_size_min = RT2880_MEM_SIZE_MIN; | 118 | soc_info->mem_size_min = RT2880_MEM_SIZE_MIN; |
142 | soc_info->mem_size_max = RT2880_MEM_SIZE_MAX; | 119 | soc_info->mem_size_max = RT2880_MEM_SIZE_MAX; |
120 | |||
121 | rt2880_pinmux_data = rt2880_pinmux_data_act; | ||
143 | } | 122 | } |
diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c index bb82a82da9e7..c40776ab67db 100644 --- a/arch/mips/ralink/rt305x.c +++ b/arch/mips/ralink/rt305x.c | |||
@@ -17,90 +17,78 @@ | |||
17 | #include <asm/mipsregs.h> | 17 | #include <asm/mipsregs.h> |
18 | #include <asm/mach-ralink/ralink_regs.h> | 18 | #include <asm/mach-ralink/ralink_regs.h> |
19 | #include <asm/mach-ralink/rt305x.h> | 19 | #include <asm/mach-ralink/rt305x.h> |
20 | #include <asm/mach-ralink/pinmux.h> | ||
20 | 21 | ||
21 | #include "common.h" | 22 | #include "common.h" |
22 | 23 | ||
23 | enum rt305x_soc_type rt305x_soc; | 24 | enum rt305x_soc_type rt305x_soc; |
24 | 25 | ||
25 | static struct ralink_pinmux_grp mode_mux[] = { | 26 | static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; |
26 | { | 27 | static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; |
27 | .name = "i2c", | 28 | static struct rt2880_pmx_func uartf_func[] = { |
28 | .mask = RT305X_GPIO_MODE_I2C, | 29 | FUNC("uartf", RT305X_GPIO_MODE_UARTF, 7, 8), |
29 | .gpio_first = RT305X_GPIO_I2C_SD, | 30 | FUNC("pcm uartf", RT305X_GPIO_MODE_PCM_UARTF, 7, 8), |
30 | .gpio_last = RT305X_GPIO_I2C_SCLK, | 31 | FUNC("pcm i2s", RT305X_GPIO_MODE_PCM_I2S, 7, 8), |
31 | }, { | 32 | FUNC("i2s uartf", RT305X_GPIO_MODE_I2S_UARTF, 7, 8), |
32 | .name = "spi", | 33 | FUNC("pcm gpio", RT305X_GPIO_MODE_PCM_GPIO, 11, 4), |
33 | .mask = RT305X_GPIO_MODE_SPI, | 34 | FUNC("gpio uartf", RT305X_GPIO_MODE_GPIO_UARTF, 7, 4), |
34 | .gpio_first = RT305X_GPIO_SPI_EN, | 35 | FUNC("gpio i2s", RT305X_GPIO_MODE_GPIO_I2S, 7, 4), |
35 | .gpio_last = RT305X_GPIO_SPI_CLK, | 36 | }; |
36 | }, { | 37 | static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; |
37 | .name = "uartlite", | 38 | static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; |
38 | .mask = RT305X_GPIO_MODE_UART1, | 39 | static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; |
39 | .gpio_first = RT305X_GPIO_UART1_TXD, | 40 | static struct rt2880_pmx_func rt5350_led_func[] = { FUNC("led", 0, 22, 5) }; |
40 | .gpio_last = RT305X_GPIO_UART1_RXD, | 41 | static struct rt2880_pmx_func rt5350_cs1_func[] = { |
41 | }, { | 42 | FUNC("spi_cs1", 0, 27, 1), |
42 | .name = "jtag", | 43 | FUNC("wdg_cs1", 1, 27, 1), |
43 | .mask = RT305X_GPIO_MODE_JTAG, | 44 | }; |
44 | .gpio_first = RT305X_GPIO_JTAG_TDO, | 45 | static struct rt2880_pmx_func sdram_func[] = { FUNC("sdram", 0, 24, 16) }; |
45 | .gpio_last = RT305X_GPIO_JTAG_TDI, | 46 | static struct rt2880_pmx_func rt3352_rgmii_func[] = { |
46 | }, { | 47 | FUNC("rgmii", 0, 24, 12) |
47 | .name = "mdio", | 48 | }; |
48 | .mask = RT305X_GPIO_MODE_MDIO, | 49 | static struct rt2880_pmx_func rgmii_func[] = { FUNC("rgmii", 0, 40, 12) }; |
49 | .gpio_first = RT305X_GPIO_MDIO_MDC, | 50 | static struct rt2880_pmx_func rt3352_lna_func[] = { FUNC("lna", 0, 36, 2) }; |
50 | .gpio_last = RT305X_GPIO_MDIO_MDIO, | 51 | static struct rt2880_pmx_func rt3352_pa_func[] = { FUNC("pa", 0, 38, 2) }; |
51 | }, { | 52 | static struct rt2880_pmx_func rt3352_led_func[] = { FUNC("led", 0, 40, 5) }; |
52 | .name = "sdram", | 53 | |
53 | .mask = RT305X_GPIO_MODE_SDRAM, | 54 | static struct rt2880_pmx_group rt3050_pinmux_data[] = { |
54 | .gpio_first = RT305X_GPIO_SDRAM_MD16, | 55 | GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), |
55 | .gpio_last = RT305X_GPIO_SDRAM_MD31, | 56 | GRP("spi", spi_func, 1, RT305X_GPIO_MODE_SPI), |
56 | }, { | 57 | GRP("uartf", uartf_func, RT305X_GPIO_MODE_UART0_MASK, |
57 | .name = "rgmii", | 58 | RT305X_GPIO_MODE_UART0_SHIFT), |
58 | .mask = RT305X_GPIO_MODE_RGMII, | 59 | GRP("uartlite", uartlite_func, 1, RT305X_GPIO_MODE_UART1), |
59 | .gpio_first = RT305X_GPIO_GE0_TXD0, | 60 | GRP("jtag", jtag_func, 1, RT305X_GPIO_MODE_JTAG), |
60 | .gpio_last = RT305X_GPIO_GE0_RXCLK, | 61 | GRP("mdio", mdio_func, 1, RT305X_GPIO_MODE_MDIO), |
61 | }, {0} | 62 | GRP("rgmii", rgmii_func, 1, RT305X_GPIO_MODE_RGMII), |
63 | GRP("sdram", sdram_func, 1, RT305X_GPIO_MODE_SDRAM), | ||
64 | { 0 } | ||
62 | }; | 65 | }; |
63 | 66 | ||
64 | static struct ralink_pinmux_grp uart_mux[] = { | 67 | static struct rt2880_pmx_group rt3352_pinmux_data[] = { |
65 | { | 68 | GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), |
66 | .name = "uartf", | 69 | GRP("spi", spi_func, 1, RT305X_GPIO_MODE_SPI), |
67 | .mask = RT305X_GPIO_MODE_UARTF, | 70 | GRP("uartf", uartf_func, RT305X_GPIO_MODE_UART0_MASK, |
68 | .gpio_first = RT305X_GPIO_7, | 71 | RT305X_GPIO_MODE_UART0_SHIFT), |
69 | .gpio_last = RT305X_GPIO_14, | 72 | GRP("uartlite", uartlite_func, 1, RT305X_GPIO_MODE_UART1), |
70 | }, { | 73 | GRP("jtag", jtag_func, 1, RT305X_GPIO_MODE_JTAG), |
71 | .name = "pcm uartf", | 74 | GRP("mdio", mdio_func, 1, RT305X_GPIO_MODE_MDIO), |
72 | .mask = RT305X_GPIO_MODE_PCM_UARTF, | 75 | GRP("rgmii", rt3352_rgmii_func, 1, RT305X_GPIO_MODE_RGMII), |
73 | .gpio_first = RT305X_GPIO_7, | 76 | GRP("lna", rt3352_lna_func, 1, RT3352_GPIO_MODE_LNA), |
74 | .gpio_last = RT305X_GPIO_14, | 77 | GRP("pa", rt3352_pa_func, 1, RT3352_GPIO_MODE_PA), |
75 | }, { | 78 | GRP("led", rt3352_led_func, 1, RT5350_GPIO_MODE_PHY_LED), |
76 | .name = "pcm i2s", | 79 | { 0 } |
77 | .mask = RT305X_GPIO_MODE_PCM_I2S, | 80 | }; |
78 | .gpio_first = RT305X_GPIO_7, | 81 | |
79 | .gpio_last = RT305X_GPIO_14, | 82 | static struct rt2880_pmx_group rt5350_pinmux_data[] = { |
80 | }, { | 83 | GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), |
81 | .name = "i2s uartf", | 84 | GRP("spi", spi_func, 1, RT305X_GPIO_MODE_SPI), |
82 | .mask = RT305X_GPIO_MODE_I2S_UARTF, | 85 | GRP("uartf", uartf_func, RT305X_GPIO_MODE_UART0_MASK, |
83 | .gpio_first = RT305X_GPIO_7, | 86 | RT305X_GPIO_MODE_UART0_SHIFT), |
84 | .gpio_last = RT305X_GPIO_14, | 87 | GRP("uartlite", uartlite_func, 1, RT305X_GPIO_MODE_UART1), |
85 | }, { | 88 | GRP("jtag", jtag_func, 1, RT305X_GPIO_MODE_JTAG), |
86 | .name = "pcm gpio", | 89 | GRP("led", rt5350_led_func, 1, RT5350_GPIO_MODE_PHY_LED), |
87 | .mask = RT305X_GPIO_MODE_PCM_GPIO, | 90 | GRP("spi_cs1", rt5350_cs1_func, 2, RT5350_GPIO_MODE_SPI_CS1), |
88 | .gpio_first = RT305X_GPIO_10, | 91 | { 0 } |
89 | .gpio_last = RT305X_GPIO_14, | ||
90 | }, { | ||
91 | .name = "gpio uartf", | ||
92 | .mask = RT305X_GPIO_MODE_GPIO_UARTF, | ||
93 | .gpio_first = RT305X_GPIO_7, | ||
94 | .gpio_last = RT305X_GPIO_10, | ||
95 | }, { | ||
96 | .name = "gpio i2s", | ||
97 | .mask = RT305X_GPIO_MODE_GPIO_I2S, | ||
98 | .gpio_first = RT305X_GPIO_7, | ||
99 | .gpio_last = RT305X_GPIO_10, | ||
100 | }, { | ||
101 | .name = "gpio", | ||
102 | .mask = RT305X_GPIO_MODE_GPIO, | ||
103 | }, {0} | ||
104 | }; | 92 | }; |
105 | 93 | ||
106 | static void rt305x_wdt_reset(void) | 94 | static void rt305x_wdt_reset(void) |
@@ -114,14 +102,6 @@ static void rt305x_wdt_reset(void) | |||
114 | rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG); | 102 | rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG); |
115 | } | 103 | } |
116 | 104 | ||
117 | struct ralink_pinmux rt_gpio_pinmux = { | ||
118 | .mode = mode_mux, | ||
119 | .uart = uart_mux, | ||
120 | .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT, | ||
121 | .uart_mask = RT305X_GPIO_MODE_UART0_MASK, | ||
122 | .wdt_reset = rt305x_wdt_reset, | ||
123 | }; | ||
124 | |||
125 | static unsigned long rt5350_get_mem_size(void) | 105 | static unsigned long rt5350_get_mem_size(void) |
126 | { | 106 | { |
127 | void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE); | 107 | void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE); |
@@ -290,11 +270,14 @@ void prom_soc_init(struct ralink_soc_info *soc_info) | |||
290 | soc_info->mem_base = RT305X_SDRAM_BASE; | 270 | soc_info->mem_base = RT305X_SDRAM_BASE; |
291 | if (soc_is_rt5350()) { | 271 | if (soc_is_rt5350()) { |
292 | soc_info->mem_size = rt5350_get_mem_size(); | 272 | soc_info->mem_size = rt5350_get_mem_size(); |
273 | rt2880_pinmux_data = rt5350_pinmux_data; | ||
293 | } else if (soc_is_rt305x() || soc_is_rt3350()) { | 274 | } else if (soc_is_rt305x() || soc_is_rt3350()) { |
294 | soc_info->mem_size_min = RT305X_MEM_SIZE_MIN; | 275 | soc_info->mem_size_min = RT305X_MEM_SIZE_MIN; |
295 | soc_info->mem_size_max = RT305X_MEM_SIZE_MAX; | 276 | soc_info->mem_size_max = RT305X_MEM_SIZE_MAX; |
277 | rt2880_pinmux_data = rt3050_pinmux_data; | ||
296 | } else if (soc_is_rt3352()) { | 278 | } else if (soc_is_rt3352()) { |
297 | soc_info->mem_size_min = RT3352_MEM_SIZE_MIN; | 279 | soc_info->mem_size_min = RT3352_MEM_SIZE_MIN; |
298 | soc_info->mem_size_max = RT3352_MEM_SIZE_MAX; | 280 | soc_info->mem_size_max = RT3352_MEM_SIZE_MAX; |
281 | rt2880_pinmux_data = rt3352_pinmux_data; | ||
299 | } | 282 | } |
300 | } | 283 | } |
diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c index b474ac284b83..86a535c770d8 100644 --- a/arch/mips/ralink/rt3883.c +++ b/arch/mips/ralink/rt3883.c | |||
@@ -17,132 +17,50 @@ | |||
17 | #include <asm/mipsregs.h> | 17 | #include <asm/mipsregs.h> |
18 | #include <asm/mach-ralink/ralink_regs.h> | 18 | #include <asm/mach-ralink/ralink_regs.h> |
19 | #include <asm/mach-ralink/rt3883.h> | 19 | #include <asm/mach-ralink/rt3883.h> |
20 | #include <asm/mach-ralink/pinmux.h> | ||
20 | 21 | ||
21 | #include "common.h" | 22 | #include "common.h" |
22 | 23 | ||
23 | static struct ralink_pinmux_grp mode_mux[] = { | 24 | static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; |
24 | { | 25 | static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; |
25 | .name = "i2c", | 26 | static struct rt2880_pmx_func uartf_func[] = { |
26 | .mask = RT3883_GPIO_MODE_I2C, | 27 | FUNC("uartf", RT3883_GPIO_MODE_UARTF, 7, 8), |
27 | .gpio_first = RT3883_GPIO_I2C_SD, | 28 | FUNC("pcm uartf", RT3883_GPIO_MODE_PCM_UARTF, 7, 8), |
28 | .gpio_last = RT3883_GPIO_I2C_SCLK, | 29 | FUNC("pcm i2s", RT3883_GPIO_MODE_PCM_I2S, 7, 8), |
29 | }, { | 30 | FUNC("i2s uartf", RT3883_GPIO_MODE_I2S_UARTF, 7, 8), |
30 | .name = "spi", | 31 | FUNC("pcm gpio", RT3883_GPIO_MODE_PCM_GPIO, 11, 4), |
31 | .mask = RT3883_GPIO_MODE_SPI, | 32 | FUNC("gpio uartf", RT3883_GPIO_MODE_GPIO_UARTF, 7, 4), |
32 | .gpio_first = RT3883_GPIO_SPI_CS0, | 33 | FUNC("gpio i2s", RT3883_GPIO_MODE_GPIO_I2S, 7, 4), |
33 | .gpio_last = RT3883_GPIO_SPI_MISO, | ||
34 | }, { | ||
35 | .name = "uartlite", | ||
36 | .mask = RT3883_GPIO_MODE_UART1, | ||
37 | .gpio_first = RT3883_GPIO_UART1_TXD, | ||
38 | .gpio_last = RT3883_GPIO_UART1_RXD, | ||
39 | }, { | ||
40 | .name = "jtag", | ||
41 | .mask = RT3883_GPIO_MODE_JTAG, | ||
42 | .gpio_first = RT3883_GPIO_JTAG_TDO, | ||
43 | .gpio_last = RT3883_GPIO_JTAG_TCLK, | ||
44 | }, { | ||
45 | .name = "mdio", | ||
46 | .mask = RT3883_GPIO_MODE_MDIO, | ||
47 | .gpio_first = RT3883_GPIO_MDIO_MDC, | ||
48 | .gpio_last = RT3883_GPIO_MDIO_MDIO, | ||
49 | }, { | ||
50 | .name = "ge1", | ||
51 | .mask = RT3883_GPIO_MODE_GE1, | ||
52 | .gpio_first = RT3883_GPIO_GE1_TXD0, | ||
53 | .gpio_last = RT3883_GPIO_GE1_RXCLK, | ||
54 | }, { | ||
55 | .name = "ge2", | ||
56 | .mask = RT3883_GPIO_MODE_GE2, | ||
57 | .gpio_first = RT3883_GPIO_GE2_TXD0, | ||
58 | .gpio_last = RT3883_GPIO_GE2_RXCLK, | ||
59 | }, { | ||
60 | .name = "pci", | ||
61 | .mask = RT3883_GPIO_MODE_PCI, | ||
62 | .gpio_first = RT3883_GPIO_PCI_AD0, | ||
63 | .gpio_last = RT3883_GPIO_PCI_AD31, | ||
64 | }, { | ||
65 | .name = "lna a", | ||
66 | .mask = RT3883_GPIO_MODE_LNA_A, | ||
67 | .gpio_first = RT3883_GPIO_LNA_PE_A0, | ||
68 | .gpio_last = RT3883_GPIO_LNA_PE_A2, | ||
69 | }, { | ||
70 | .name = "lna g", | ||
71 | .mask = RT3883_GPIO_MODE_LNA_G, | ||
72 | .gpio_first = RT3883_GPIO_LNA_PE_G0, | ||
73 | .gpio_last = RT3883_GPIO_LNA_PE_G2, | ||
74 | }, {0} | ||
75 | }; | 34 | }; |
76 | 35 | static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; | |
77 | static struct ralink_pinmux_grp uart_mux[] = { | 36 | static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; |
78 | { | 37 | static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; |
79 | .name = "uartf", | 38 | static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) }; |
80 | .mask = RT3883_GPIO_MODE_UARTF, | 39 | static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna a", 0, 35, 3) }; |
81 | .gpio_first = RT3883_GPIO_7, | 40 | static struct rt2880_pmx_func pci_func[] = { |
82 | .gpio_last = RT3883_GPIO_14, | 41 | FUNC("pci-dev", 0, 40, 32), |
83 | }, { | 42 | FUNC("pci-host2", 1, 40, 32), |
84 | .name = "pcm uartf", | 43 | FUNC("pci-host1", 2, 40, 32), |
85 | .mask = RT3883_GPIO_MODE_PCM_UARTF, | 44 | FUNC("pci-fnc", 3, 40, 32) |
86 | .gpio_first = RT3883_GPIO_7, | ||
87 | .gpio_last = RT3883_GPIO_14, | ||
88 | }, { | ||
89 | .name = "pcm i2s", | ||
90 | .mask = RT3883_GPIO_MODE_PCM_I2S, | ||
91 | .gpio_first = RT3883_GPIO_7, | ||
92 | .gpio_last = RT3883_GPIO_14, | ||
93 | }, { | ||
94 | .name = "i2s uartf", | ||
95 | .mask = RT3883_GPIO_MODE_I2S_UARTF, | ||
96 | .gpio_first = RT3883_GPIO_7, | ||
97 | .gpio_last = RT3883_GPIO_14, | ||
98 | }, { | ||
99 | .name = "pcm gpio", | ||
100 | .mask = RT3883_GPIO_MODE_PCM_GPIO, | ||
101 | .gpio_first = RT3883_GPIO_11, | ||
102 | .gpio_last = RT3883_GPIO_14, | ||
103 | }, { | ||
104 | .name = "gpio uartf", | ||
105 | .mask = RT3883_GPIO_MODE_GPIO_UARTF, | ||
106 | .gpio_first = RT3883_GPIO_7, | ||
107 | .gpio_last = RT3883_GPIO_10, | ||
108 | }, { | ||
109 | .name = "gpio i2s", | ||
110 | .mask = RT3883_GPIO_MODE_GPIO_I2S, | ||
111 | .gpio_first = RT3883_GPIO_7, | ||
112 | .gpio_last = RT3883_GPIO_10, | ||
113 | }, { | ||
114 | .name = "gpio", | ||
115 | .mask = RT3883_GPIO_MODE_GPIO, | ||
116 | }, {0} | ||
117 | }; | 45 | }; |
118 | 46 | static struct rt2880_pmx_func ge1_func[] = { FUNC("ge1", 0, 72, 12) }; | |
119 | static struct ralink_pinmux_grp pci_mux[] = { | 47 | static struct rt2880_pmx_func ge2_func[] = { FUNC("ge1", 0, 84, 12) }; |
120 | { | 48 | |
121 | .name = "pci-dev", | 49 | static struct rt2880_pmx_group rt3883_pinmux_data[] = { |
122 | .mask = 0, | 50 | GRP("i2c", i2c_func, 1, RT3883_GPIO_MODE_I2C), |
123 | .gpio_first = RT3883_GPIO_PCI_AD0, | 51 | GRP("spi", spi_func, 1, RT3883_GPIO_MODE_SPI), |
124 | .gpio_last = RT3883_GPIO_PCI_AD31, | 52 | GRP("uartf", uartf_func, RT3883_GPIO_MODE_UART0_MASK, |
125 | }, { | 53 | RT3883_GPIO_MODE_UART0_SHIFT), |
126 | .name = "pci-host2", | 54 | GRP("uartlite", uartlite_func, 1, RT3883_GPIO_MODE_UART1), |
127 | .mask = 1, | 55 | GRP("jtag", jtag_func, 1, RT3883_GPIO_MODE_JTAG), |
128 | .gpio_first = RT3883_GPIO_PCI_AD0, | 56 | GRP("mdio", mdio_func, 1, RT3883_GPIO_MODE_MDIO), |
129 | .gpio_last = RT3883_GPIO_PCI_AD31, | 57 | GRP("lna a", lna_a_func, 1, RT3883_GPIO_MODE_LNA_A), |
130 | }, { | 58 | GRP("lna g", lna_g_func, 1, RT3883_GPIO_MODE_LNA_G), |
131 | .name = "pci-host1", | 59 | GRP("pci", pci_func, RT3883_GPIO_MODE_PCI_MASK, |
132 | .mask = 2, | 60 | RT3883_GPIO_MODE_PCI_SHIFT), |
133 | .gpio_first = RT3883_GPIO_PCI_AD0, | 61 | GRP("ge1", ge1_func, 1, RT3883_GPIO_MODE_GE1), |
134 | .gpio_last = RT3883_GPIO_PCI_AD31, | 62 | GRP("ge2", ge2_func, 1, RT3883_GPIO_MODE_GE2), |
135 | }, { | 63 | { 0 } |
136 | .name = "pci-fnc", | ||
137 | .mask = 3, | ||
138 | .gpio_first = RT3883_GPIO_PCI_AD0, | ||
139 | .gpio_last = RT3883_GPIO_PCI_AD31, | ||
140 | }, { | ||
141 | .name = "pci-gpio", | ||
142 | .mask = 7, | ||
143 | .gpio_first = RT3883_GPIO_PCI_AD0, | ||
144 | .gpio_last = RT3883_GPIO_PCI_AD31, | ||
145 | }, {0} | ||
146 | }; | 64 | }; |
147 | 65 | ||
148 | static void rt3883_wdt_reset(void) | 66 | static void rt3883_wdt_reset(void) |
@@ -155,17 +73,6 @@ static void rt3883_wdt_reset(void) | |||
155 | rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1); | 73 | rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1); |
156 | } | 74 | } |
157 | 75 | ||
158 | struct ralink_pinmux rt_gpio_pinmux = { | ||
159 | .mode = mode_mux, | ||
160 | .uart = uart_mux, | ||
161 | .uart_shift = RT3883_GPIO_MODE_UART0_SHIFT, | ||
162 | .uart_mask = RT3883_GPIO_MODE_UART0_MASK, | ||
163 | .wdt_reset = rt3883_wdt_reset, | ||
164 | .pci = pci_mux, | ||
165 | .pci_shift = RT3883_GPIO_MODE_PCI_SHIFT, | ||
166 | .pci_mask = RT3883_GPIO_MODE_PCI_MASK, | ||
167 | }; | ||
168 | |||
169 | void __init ralink_clk_init(void) | 76 | void __init ralink_clk_init(void) |
170 | { | 77 | { |
171 | unsigned long cpu_rate, sys_rate; | 78 | unsigned long cpu_rate, sys_rate; |
@@ -204,6 +111,7 @@ void __init ralink_clk_init(void) | |||
204 | ralink_clk_add("10000b00.spi", sys_rate); | 111 | ralink_clk_add("10000b00.spi", sys_rate); |
205 | ralink_clk_add("10000c00.uartlite", 40000000); | 112 | ralink_clk_add("10000c00.uartlite", 40000000); |
206 | ralink_clk_add("10100000.ethernet", sys_rate); | 113 | ralink_clk_add("10100000.ethernet", sys_rate); |
114 | ralink_clk_add("10180000.wmac", 40000000); | ||
207 | } | 115 | } |
208 | 116 | ||
209 | void __init ralink_of_remap(void) | 117 | void __init ralink_of_remap(void) |
@@ -243,4 +151,6 @@ void prom_soc_init(struct ralink_soc_info *soc_info) | |||
243 | soc_info->mem_base = RT3883_SDRAM_BASE; | 151 | soc_info->mem_base = RT3883_SDRAM_BASE; |
244 | soc_info->mem_size_min = RT3883_MEM_SIZE_MIN; | 152 | soc_info->mem_size_min = RT3883_MEM_SIZE_MIN; |
245 | soc_info->mem_size_max = RT3883_MEM_SIZE_MAX; | 153 | soc_info->mem_size_max = RT3883_MEM_SIZE_MAX; |
154 | |||
155 | rt2880_pinmux_data = rt3883_pinmux_data; | ||
246 | } | 156 | } |
diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index a18007613c30..5aa3df853082 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c | |||
@@ -79,7 +79,7 @@ static inline void rb532_set_bit(unsigned bitval, | |||
79 | */ | 79 | */ |
80 | static inline int rb532_get_bit(unsigned offset, void __iomem *ioaddr) | 80 | static inline int rb532_get_bit(unsigned offset, void __iomem *ioaddr) |
81 | { | 81 | { |
82 | return (readl(ioaddr) & (1 << offset)); | 82 | return readl(ioaddr) & (1 << offset); |
83 | } | 83 | } |
84 | 84 | ||
85 | /* | 85 | /* |
diff --git a/arch/mips/rb532/prom.c b/arch/mips/rb532/prom.c index a757ded437cd..657210e767c2 100644 --- a/arch/mips/rb532/prom.c +++ b/arch/mips/rb532/prom.c | |||
@@ -122,8 +122,8 @@ void __init prom_setup_cmdline(void) | |||
122 | void __init prom_init(void) | 122 | void __init prom_init(void) |
123 | { | 123 | { |
124 | struct ddr_ram __iomem *ddr; | 124 | struct ddr_ram __iomem *ddr; |
125 | phys_t memsize; | 125 | phys_addr_t memsize; |
126 | phys_t ddrbase; | 126 | phys_addr_t ddrbase; |
127 | 127 | ||
128 | ddr = ioremap_nocache(ddr_reg[0].start, | 128 | ddr = ioremap_nocache(ddr_reg[0].start, |
129 | ddr_reg[0].end - ddr_reg[0].start); | 129 | ddr_reg[0].end - ddr_reg[0].start); |
@@ -133,8 +133,8 @@ void __init prom_init(void) | |||
133 | return; | 133 | return; |
134 | } | 134 | } |
135 | 135 | ||
136 | ddrbase = (phys_t)&ddr->ddrbase; | 136 | ddrbase = (phys_addr_t)&ddr->ddrbase; |
137 | memsize = (phys_t)&ddr->ddrmask; | 137 | memsize = (phys_addr_t)&ddr->ddrmask; |
138 | memsize = 0 - memsize; | 138 | memsize = 0 - memsize; |
139 | 139 | ||
140 | prom_setup_cmdline(); | 140 | prom_setup_cmdline(); |
diff --git a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c index 7cec0a4e527d..6b009c45abed 100644 --- a/arch/mips/sgi-ip22/ip22-mc.c +++ b/arch/mips/sgi-ip22/ip22-mc.c | |||
@@ -24,14 +24,12 @@ EXPORT_SYMBOL(sgimc); | |||
24 | 24 | ||
25 | static inline unsigned long get_bank_addr(unsigned int memconfig) | 25 | static inline unsigned long get_bank_addr(unsigned int memconfig) |
26 | { | 26 | { |
27 | return ((memconfig & SGIMC_MCONFIG_BASEADDR) << | 27 | return (memconfig & SGIMC_MCONFIG_BASEADDR) << ((sgimc->systemid & SGIMC_SYSID_MASKREV) >= 5 ? 24 : 22); |
28 | ((sgimc->systemid & SGIMC_SYSID_MASKREV) >= 5 ? 24 : 22)); | ||
29 | } | 28 | } |
30 | 29 | ||
31 | static inline unsigned long get_bank_size(unsigned int memconfig) | 30 | static inline unsigned long get_bank_size(unsigned int memconfig) |
32 | { | 31 | { |
33 | return ((memconfig & SGIMC_MCONFIG_RMASK) + 0x0100) << | 32 | return ((memconfig & SGIMC_MCONFIG_RMASK) + 0x0100) << ((sgimc->systemid & SGIMC_SYSID_MASKREV) >= 5 ? 16 : 14); |
34 | ((sgimc->systemid & SGIMC_SYSID_MASKREV) >= 5 ? 16 : 14); | ||
35 | } | 33 | } |
36 | 34 | ||
37 | static inline unsigned int get_bank_config(int bank) | 35 | static inline unsigned int get_bank_config(int bank) |
diff --git a/arch/mips/sgi-ip22/ip28-berr.c b/arch/mips/sgi-ip22/ip28-berr.c index 3f47346608d7..712cc0f6a58d 100644 --- a/arch/mips/sgi-ip22/ip28-berr.c +++ b/arch/mips/sgi-ip22/ip28-berr.c | |||
@@ -338,7 +338,7 @@ static int check_microtlb(u32 hi, u32 lo, unsigned long vaddr) | |||
338 | PHYS_TO_XKSEG_UNCACHED(pte); | 338 | PHYS_TO_XKSEG_UNCACHED(pte); |
339 | a = (a & 0x3f) << 6; /* PFN */ | 339 | a = (a & 0x3f) << 6; /* PFN */ |
340 | a += vaddr & ((1 << pgsz) - 1); | 340 | a += vaddr & ((1 << pgsz) - 1); |
341 | return (cpu_err_addr == a); | 341 | return cpu_err_addr == a; |
342 | } | 342 | } |
343 | } | 343 | } |
344 | } | 344 | } |
@@ -351,7 +351,7 @@ static int check_vdma_memaddr(void) | |||
351 | u32 a = sgimc->maddronly; | 351 | u32 a = sgimc->maddronly; |
352 | 352 | ||
353 | if (!(sgimc->dma_ctrl & 0x100)) /* Xlate-bit clear ? */ | 353 | if (!(sgimc->dma_ctrl & 0x100)) /* Xlate-bit clear ? */ |
354 | return (cpu_err_addr == a); | 354 | return cpu_err_addr == a; |
355 | 355 | ||
356 | if (check_microtlb(sgimc->dtlb_hi0, sgimc->dtlb_lo0, a) || | 356 | if (check_microtlb(sgimc->dtlb_hi0, sgimc->dtlb_lo0, a) || |
357 | check_microtlb(sgimc->dtlb_hi1, sgimc->dtlb_lo1, a) || | 357 | check_microtlb(sgimc->dtlb_hi1, sgimc->dtlb_lo1, a) || |
@@ -367,7 +367,7 @@ static int check_vdma_gioaddr(void) | |||
367 | if (gio_err_stat & GIO_ERRMASK) { | 367 | if (gio_err_stat & GIO_ERRMASK) { |
368 | u32 a = sgimc->gio_dma_trans; | 368 | u32 a = sgimc->gio_dma_trans; |
369 | a = (sgimc->gmaddronly & ~a) | (sgimc->gio_dma_sbits & a); | 369 | a = (sgimc->gmaddronly & ~a) | (sgimc->gio_dma_sbits & a); |
370 | return (gio_err_addr == a); | 370 | return gio_err_addr == a; |
371 | } | 371 | } |
372 | return 0; | 372 | return 0; |
373 | } | 373 | } |
diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c index 7a53b1e28a93..ecbb62f339c5 100644 --- a/arch/mips/sgi-ip27/ip27-klnuma.c +++ b/arch/mips/sgi-ip27/ip27-klnuma.c | |||
@@ -125,8 +125,7 @@ unsigned long node_getfirstfree(cnodeid_t cnode) | |||
125 | #endif | 125 | #endif |
126 | offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase; | 126 | offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase; |
127 | if ((cnode == 0) || (cpu_isset(cnode, ktext_repmask))) | 127 | if ((cnode == 0) || (cpu_isset(cnode, ktext_repmask))) |
128 | return (TO_NODE(nasid, offset) >> PAGE_SHIFT); | 128 | return TO_NODE(nasid, offset) >> PAGE_SHIFT; |
129 | else | 129 | else |
130 | return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> | 130 | return KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> PAGE_SHIFT; |
131 | PAGE_SHIFT); | ||
132 | } | 131 | } |
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index a304bcc37e4f..0b68469e063f 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c | |||
@@ -42,8 +42,7 @@ static int fine_mode; | |||
42 | 42 | ||
43 | static int is_fine_dirmode(void) | 43 | static int is_fine_dirmode(void) |
44 | { | 44 | { |
45 | return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) | 45 | return ((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE; |
46 | >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE); | ||
47 | } | 46 | } |
48 | 47 | ||
49 | static hubreg_t get_region(cnodeid_t cnode) | 48 | static hubreg_t get_region(cnodeid_t cnode) |
@@ -288,7 +287,7 @@ static unsigned long __init slot_psize_compute(cnodeid_t node, int slot) | |||
288 | if (size <= 128) { | 287 | if (size <= 128) { |
289 | if (slot % 4 == 0) { | 288 | if (slot % 4 == 0) { |
290 | size <<= 20; /* size in bytes */ | 289 | size <<= 20; /* size in bytes */ |
291 | return(size >> PAGE_SHIFT); | 290 | return size >> PAGE_SHIFT; |
292 | } else | 291 | } else |
293 | return 0; | 292 | return 0; |
294 | } else { | 293 | } else { |
diff --git a/arch/mips/sibyte/common/cfe.c b/arch/mips/sibyte/common/cfe.c index 588e1806a1a3..c1a11a11db7f 100644 --- a/arch/mips/sibyte/common/cfe.c +++ b/arch/mips/sibyte/common/cfe.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #define MAX_RAM_SIZE (~0ULL) | 38 | #define MAX_RAM_SIZE (~0ULL) |
39 | #else | 39 | #else |
40 | #ifdef CONFIG_HIGHMEM | 40 | #ifdef CONFIG_HIGHMEM |
41 | #ifdef CONFIG_64BIT_PHYS_ADDR | 41 | #ifdef CONFIG_PHYS_ADDR_T_64BIT |
42 | #define MAX_RAM_SIZE (~0ULL) | 42 | #define MAX_RAM_SIZE (~0ULL) |
43 | #else | 43 | #else |
44 | #define MAX_RAM_SIZE (0xffffffffULL) | 44 | #define MAX_RAM_SIZE (0xffffffffULL) |
@@ -49,8 +49,8 @@ | |||
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | #define SIBYTE_MAX_MEM_REGIONS 8 | 51 | #define SIBYTE_MAX_MEM_REGIONS 8 |
52 | phys_t board_mem_region_addrs[SIBYTE_MAX_MEM_REGIONS]; | 52 | phys_addr_t board_mem_region_addrs[SIBYTE_MAX_MEM_REGIONS]; |
53 | phys_t board_mem_region_sizes[SIBYTE_MAX_MEM_REGIONS]; | 53 | phys_addr_t board_mem_region_sizes[SIBYTE_MAX_MEM_REGIONS]; |
54 | unsigned int board_mem_region_count; | 54 | unsigned int board_mem_region_count; |
55 | 55 | ||
56 | int cfe_cons_handle; | 56 | int cfe_cons_handle; |
@@ -96,7 +96,7 @@ static void __noreturn cfe_linux_halt(void) | |||
96 | 96 | ||
97 | static __init void prom_meminit(void) | 97 | static __init void prom_meminit(void) |
98 | { | 98 | { |
99 | u64 addr, size, type; /* regardless of 64BIT_PHYS_ADDR */ | 99 | u64 addr, size, type; /* regardless of PHYS_ADDR_T_64BIT */ |
100 | int mem_flags = 0; | 100 | int mem_flags = 0; |
101 | unsigned int idx; | 101 | unsigned int idx; |
102 | int rd_flag; | 102 | int rd_flag; |
diff --git a/arch/mips/sibyte/swarm/platform.c b/arch/mips/sibyte/swarm/platform.c index 9480c14ec66a..1cecdcf85cf1 100644 --- a/arch/mips/sibyte/swarm/platform.c +++ b/arch/mips/sibyte/swarm/platform.c | |||
@@ -50,7 +50,7 @@ static struct platform_device swarm_pata_device = { | |||
50 | static int __init swarm_pata_init(void) | 50 | static int __init swarm_pata_init(void) |
51 | { | 51 | { |
52 | u8 __iomem *base; | 52 | u8 __iomem *base; |
53 | phys_t offset, size; | 53 | phys_addr_t offset, size; |
54 | struct resource *r; | 54 | struct resource *r; |
55 | 55 | ||
56 | if (!SIBYTE_HAVE_IDE) | 56 | if (!SIBYTE_HAVE_IDE) |
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c index b732600b47f5..e62466445f08 100644 --- a/arch/mips/sibyte/swarm/rtc_m41t81.c +++ b/arch/mips/sibyte/swarm/rtc_m41t81.c | |||
@@ -109,7 +109,7 @@ static int m41t81_read(uint8_t addr) | |||
109 | return -1; | 109 | return -1; |
110 | } | 110 | } |
111 | 111 | ||
112 | return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff); | 112 | return __raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff; |
113 | } | 113 | } |
114 | 114 | ||
115 | static int m41t81_write(uint8_t addr, int b) | 115 | static int m41t81_write(uint8_t addr, int b) |
@@ -229,5 +229,5 @@ int m41t81_probe(void) | |||
229 | tmp = m41t81_read(M41T81REG_SC); | 229 | tmp = m41t81_read(M41T81REG_SC); |
230 | m41t81_write(M41T81REG_SC, tmp & 0x7f); | 230 | m41t81_write(M41T81REG_SC, tmp & 0x7f); |
231 | 231 | ||
232 | return (m41t81_read(M41T81REG_SC) != -1); | 232 | return m41t81_read(M41T81REG_SC) != -1; |
233 | } | 233 | } |
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c index 178a824b28d4..50a82c495427 100644 --- a/arch/mips/sibyte/swarm/rtc_xicor1241.c +++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c | |||
@@ -84,7 +84,7 @@ static int xicor_read(uint8_t addr) | |||
84 | return -1; | 84 | return -1; |
85 | } | 85 | } |
86 | 86 | ||
87 | return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff); | 87 | return __raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int xicor_write(uint8_t addr, int b) | 90 | static int xicor_write(uint8_t addr, int b) |
@@ -206,5 +206,5 @@ unsigned long xicor_get_time(void) | |||
206 | 206 | ||
207 | int xicor_probe(void) | 207 | int xicor_probe(void) |
208 | { | 208 | { |
209 | return (xicor_read(X1241REG_SC) != -1); | 209 | return xicor_read(X1241REG_SC) != -1; |
210 | } | 210 | } |
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index 3462c831d0ea..494fb0a475ac 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c | |||
@@ -76,7 +76,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup) | |||
76 | printk("DBE physical address: %010Lx\n", | 76 | printk("DBE physical address: %010Lx\n", |
77 | __read_64bit_c0_register($26, 1)); | 77 | __read_64bit_c0_register($26, 1)); |
78 | } | 78 | } |
79 | return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL); | 79 | return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL; |
80 | } | 80 | } |
81 | 81 | ||
82 | enum swarm_rtc_type { | 82 | enum swarm_rtc_type { |
diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c index e714d6ce9a82..a4664cb6c1e1 100644 --- a/arch/mips/txx9/generic/setup_tx4927.c +++ b/arch/mips/txx9/generic/setup_tx4927.c | |||
@@ -29,8 +29,8 @@ static void __init tx4927_wdr_init(void) | |||
29 | { | 29 | { |
30 | /* report watchdog reset status */ | 30 | /* report watchdog reset status */ |
31 | if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST) | 31 | if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST) |
32 | pr_warning("Watchdog reset detected at 0x%lx\n", | 32 | pr_warn("Watchdog reset detected at 0x%lx\n", |
33 | read_c0_errorepc()); | 33 | read_c0_errorepc()); |
34 | /* clear WatchDogReset (W1C) */ | 34 | /* clear WatchDogReset (W1C) */ |
35 | tx4927_ccfg_set(TX4927_CCFG_WDRST); | 35 | tx4927_ccfg_set(TX4927_CCFG_WDRST); |
36 | /* do reset on watchdog */ | 36 | /* do reset on watchdog */ |
diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index 0a3bf2dfaba1..58cdb2aba5e1 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c | |||
@@ -31,8 +31,8 @@ static void __init tx4938_wdr_init(void) | |||
31 | { | 31 | { |
32 | /* report watchdog reset status */ | 32 | /* report watchdog reset status */ |
33 | if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST) | 33 | if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST) |
34 | pr_warning("Watchdog reset detected at 0x%lx\n", | 34 | pr_warn("Watchdog reset detected at 0x%lx\n", |
35 | read_c0_errorepc()); | 35 | read_c0_errorepc()); |
36 | /* clear WatchDogReset (W1C) */ | 36 | /* clear WatchDogReset (W1C) */ |
37 | tx4938_ccfg_set(TX4938_CCFG_WDRST); | 37 | tx4938_ccfg_set(TX4938_CCFG_WDRST); |
38 | /* do reset on watchdog */ | 38 | /* do reset on watchdog */ |
diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index b7eccbd17bf7..e3733cde50d6 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c | |||
@@ -35,8 +35,8 @@ static void __init tx4939_wdr_init(void) | |||
35 | { | 35 | { |
36 | /* report watchdog reset status */ | 36 | /* report watchdog reset status */ |
37 | if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST) | 37 | if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST) |
38 | pr_warning("Watchdog reset detected at 0x%lx\n", | 38 | pr_warn("Watchdog reset detected at 0x%lx\n", |
39 | read_c0_errorepc()); | 39 | read_c0_errorepc()); |
40 | /* clear WatchDogReset (W1C) */ | 40 | /* clear WatchDogReset (W1C) */ |
41 | tx4939_ccfg_set(TX4939_CCFG_WDRST); | 41 | tx4939_ccfg_set(TX4939_CCFG_WDRST); |
42 | /* do reset on watchdog */ | 42 | /* do reset on watchdog */ |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 88eace4e28c3..af696874248b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -88,6 +88,7 @@ config PPC | |||
88 | select ARCH_MIGHT_HAVE_PC_PARPORT | 88 | select ARCH_MIGHT_HAVE_PC_PARPORT |
89 | select ARCH_MIGHT_HAVE_PC_SERIO | 89 | select ARCH_MIGHT_HAVE_PC_SERIO |
90 | select BINFMT_ELF | 90 | select BINFMT_ELF |
91 | select ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
91 | select OF | 92 | select OF |
92 | select OF_EARLY_FLATTREE | 93 | select OF_EARLY_FLATTREE |
93 | select OF_RESERVED_MEM | 94 | select OF_RESERVED_MEM |
@@ -148,6 +149,8 @@ config PPC | |||
148 | select HAVE_ARCH_AUDITSYSCALL | 149 | select HAVE_ARCH_AUDITSYSCALL |
149 | select ARCH_SUPPORTS_ATOMIC_RMW | 150 | select ARCH_SUPPORTS_ATOMIC_RMW |
150 | select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN | 151 | select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN |
152 | select NO_BOOTMEM | ||
153 | select HAVE_GENERIC_RCU_GUP | ||
151 | 154 | ||
152 | config GENERIC_CSUM | 155 | config GENERIC_CSUM |
153 | def_bool CPU_LITTLE_ENDIAN | 156 | def_bool CPU_LITTLE_ENDIAN |
@@ -549,7 +552,7 @@ config PPC_4K_PAGES | |||
549 | bool "4k page size" | 552 | bool "4k page size" |
550 | 553 | ||
551 | config PPC_16K_PAGES | 554 | config PPC_16K_PAGES |
552 | bool "16k page size" if 44x | 555 | bool "16k page size" if 44x || PPC_8xx |
553 | 556 | ||
554 | config PPC_64K_PAGES | 557 | config PPC_64K_PAGES |
555 | bool "64k page size" if 44x || PPC_STD_MMU_64 || PPC_BOOK3E_64 | 558 | bool "64k page size" if 44x || PPC_STD_MMU_64 || PPC_BOOK3E_64 |
diff --git a/arch/powerpc/boot/dts/b4860emu.dts b/arch/powerpc/boot/dts/b4860emu.dts index 85646b4f96e1..2aa5cd318ce8 100644 --- a/arch/powerpc/boot/dts/b4860emu.dts +++ b/arch/powerpc/boot/dts/b4860emu.dts | |||
@@ -193,9 +193,9 @@ | |||
193 | fsl,liodn-bits = <12>; | 193 | fsl,liodn-bits = <12>; |
194 | }; | 194 | }; |
195 | 195 | ||
196 | clockgen: global-utilities@e1000 { | 196 | /include/ "fsl/qoriq-clockgen2.dtsi" |
197 | global-utilities@e1000 { | ||
197 | compatible = "fsl,b4-clockgen", "fsl,qoriq-clockgen-2.0"; | 198 | compatible = "fsl,b4-clockgen", "fsl,qoriq-clockgen-2.0"; |
198 | reg = <0xe1000 0x1000>; | ||
199 | }; | 199 | }; |
200 | 200 | ||
201 | /include/ "fsl/qoriq-dma-0.dtsi" | 201 | /include/ "fsl/qoriq-dma-0.dtsi" |
diff --git a/arch/powerpc/boot/dts/b4qds.dtsi b/arch/powerpc/boot/dts/b4qds.dtsi index 8b47edcfabf0..e5bde0b85135 100644 --- a/arch/powerpc/boot/dts/b4qds.dtsi +++ b/arch/powerpc/boot/dts/b4qds.dtsi | |||
@@ -152,6 +152,29 @@ | |||
152 | reg = <0x68>; | 152 | reg = <0x68>; |
153 | }; | 153 | }; |
154 | }; | 154 | }; |
155 | |||
156 | i2c@2 { | ||
157 | #address-cells = <1>; | ||
158 | #size-cells = <0>; | ||
159 | reg = <0x2>; | ||
160 | |||
161 | ina220@40 { | ||
162 | compatible = "ti,ina220"; | ||
163 | reg = <0x40>; | ||
164 | shunt-resistor = <1000>; | ||
165 | }; | ||
166 | }; | ||
167 | |||
168 | i2c@3 { | ||
169 | #address-cells = <1>; | ||
170 | #size-cells = <0>; | ||
171 | reg = <0x3>; | ||
172 | |||
173 | adt7461@4c { | ||
174 | compatible = "adi,adt7461"; | ||
175 | reg = <0x4c>; | ||
176 | }; | ||
177 | }; | ||
155 | }; | 178 | }; |
156 | }; | 179 | }; |
157 | 180 | ||
diff --git a/arch/powerpc/boot/dts/bsc9131rdb.dtsi b/arch/powerpc/boot/dts/bsc9131rdb.dtsi index 9e6c01339ccc..45efcbadb23c 100644 --- a/arch/powerpc/boot/dts/bsc9131rdb.dtsi +++ b/arch/powerpc/boot/dts/bsc9131rdb.dtsi | |||
@@ -40,31 +40,6 @@ | |||
40 | compatible = "fsl,ifc-nand"; | 40 | compatible = "fsl,ifc-nand"; |
41 | reg = <0x0 0x0 0x4000>; | 41 | reg = <0x0 0x0 0x4000>; |
42 | 42 | ||
43 | partition@0 { | ||
44 | /* This location must not be altered */ | ||
45 | /* 3MB for u-boot Bootloader Image */ | ||
46 | reg = <0x0 0x00300000>; | ||
47 | label = "NAND U-Boot Image"; | ||
48 | read-only; | ||
49 | }; | ||
50 | |||
51 | partition@300000 { | ||
52 | /* 1MB for DTB Image */ | ||
53 | reg = <0x00300000 0x00100000>; | ||
54 | label = "NAND DTB Image"; | ||
55 | }; | ||
56 | |||
57 | partition@400000 { | ||
58 | /* 8MB for Linux Kernel Image */ | ||
59 | reg = <0x00400000 0x00800000>; | ||
60 | label = "NAND Linux Kernel Image"; | ||
61 | }; | ||
62 | |||
63 | partition@c00000 { | ||
64 | /* Rest space for Root file System Image */ | ||
65 | reg = <0x00c00000 0x07400000>; | ||
66 | label = "NAND RFS Image"; | ||
67 | }; | ||
68 | }; | 43 | }; |
69 | }; | 44 | }; |
70 | 45 | ||
@@ -82,31 +57,6 @@ | |||
82 | reg = <0>; | 57 | reg = <0>; |
83 | spi-max-frequency = <50000000>; | 58 | spi-max-frequency = <50000000>; |
84 | 59 | ||
85 | /* 512KB for u-boot Bootloader Image */ | ||
86 | partition@0 { | ||
87 | reg = <0x0 0x00080000>; | ||
88 | label = "SPI Flash U-Boot Image"; | ||
89 | read-only; | ||
90 | }; | ||
91 | |||
92 | /* 512KB for DTB Image */ | ||
93 | partition@80000 { | ||
94 | reg = <0x00080000 0x00080000>; | ||
95 | label = "SPI Flash DTB Image"; | ||
96 | }; | ||
97 | |||
98 | /* 4MB for Linux Kernel Image */ | ||
99 | partition@100000 { | ||
100 | reg = <0x00100000 0x00400000>; | ||
101 | label = "SPI Flash Kernel Image"; | ||
102 | }; | ||
103 | |||
104 | /*11MB for RFS Image */ | ||
105 | partition@500000 { | ||
106 | reg = <0x00500000 0x00B00000>; | ||
107 | label = "SPI Flash RFS Image"; | ||
108 | }; | ||
109 | |||
110 | }; | 60 | }; |
111 | }; | 61 | }; |
112 | 62 | ||
diff --git a/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi index d67894459ac8..86161ae6c966 100644 --- a/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4420si-post.dtsi | |||
@@ -80,33 +80,9 @@ | |||
80 | compatible = "fsl,b4420-device-config", "fsl,qoriq-device-config-2.0"; | 80 | compatible = "fsl,b4420-device-config", "fsl,qoriq-device-config-2.0"; |
81 | }; | 81 | }; |
82 | 82 | ||
83 | clockgen: global-utilities@e1000 { | 83 | /include/ "qoriq-clockgen2.dtsi" |
84 | global-utilities@e1000 { | ||
84 | compatible = "fsl,b4420-clockgen", "fsl,qoriq-clockgen-2.0"; | 85 | compatible = "fsl,b4420-clockgen", "fsl,qoriq-clockgen-2.0"; |
85 | ranges = <0x0 0xe1000 0x1000>; | ||
86 | #address-cells = <1>; | ||
87 | #size-cells = <1>; | ||
88 | |||
89 | sysclk: sysclk { | ||
90 | #clock-cells = <0>; | ||
91 | compatible = "fsl,qoriq-sysclk-2.0"; | ||
92 | clock-output-names = "sysclk"; | ||
93 | }; | ||
94 | |||
95 | pll0: pll0@800 { | ||
96 | #clock-cells = <1>; | ||
97 | reg = <0x800 0x4>; | ||
98 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
99 | clocks = <&sysclk>; | ||
100 | clock-output-names = "pll0", "pll0-div2", "pll0-div4"; | ||
101 | }; | ||
102 | |||
103 | pll1: pll1@820 { | ||
104 | #clock-cells = <1>; | ||
105 | reg = <0x820 0x4>; | ||
106 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
107 | clocks = <&sysclk>; | ||
108 | clock-output-names = "pll1", "pll1-div2", "pll1-div4"; | ||
109 | }; | ||
110 | 86 | ||
111 | mux0: mux0@0 { | 87 | mux0: mux0@0 { |
112 | #clock-cells = <0>; | 88 | #clock-cells = <0>; |
diff --git a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi index 582381dba1d7..65100b9636b7 100644 --- a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi | |||
@@ -124,33 +124,9 @@ | |||
124 | compatible = "fsl,b4860-device-config", "fsl,qoriq-device-config-2.0"; | 124 | compatible = "fsl,b4860-device-config", "fsl,qoriq-device-config-2.0"; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | clockgen: global-utilities@e1000 { | 127 | /include/ "qoriq-clockgen2.dtsi" |
128 | global-utilities@e1000 { | ||
128 | compatible = "fsl,b4860-clockgen", "fsl,qoriq-clockgen-2.0"; | 129 | compatible = "fsl,b4860-clockgen", "fsl,qoriq-clockgen-2.0"; |
129 | ranges = <0x0 0xe1000 0x1000>; | ||
130 | #address-cells = <1>; | ||
131 | #size-cells = <1>; | ||
132 | |||
133 | sysclk: sysclk { | ||
134 | #clock-cells = <0>; | ||
135 | compatible = "fsl,qoriq-sysclk-2.0"; | ||
136 | clock-output-names = "sysclk"; | ||
137 | }; | ||
138 | |||
139 | pll0: pll0@800 { | ||
140 | #clock-cells = <1>; | ||
141 | reg = <0x800 0x4>; | ||
142 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
143 | clocks = <&sysclk>; | ||
144 | clock-output-names = "pll0", "pll0-div2", "pll0-div4"; | ||
145 | }; | ||
146 | |||
147 | pll1: pll1@820 { | ||
148 | #clock-cells = <1>; | ||
149 | reg = <0x820 0x4>; | ||
150 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
151 | clocks = <&sysclk>; | ||
152 | clock-output-names = "pll1", "pll1-div2", "pll1-div4"; | ||
153 | }; | ||
154 | 130 | ||
155 | mux0: mux0@0 { | 131 | mux0: mux0@0 { |
156 | #clock-cells = <0>; | 132 | #clock-cells = <0>; |
diff --git a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi index 69ce1026c948..efd74db4f9b0 100644 --- a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi | |||
@@ -305,53 +305,9 @@ | |||
305 | #sleep-cells = <2>; | 305 | #sleep-cells = <2>; |
306 | }; | 306 | }; |
307 | 307 | ||
308 | clockgen: global-utilities@e1000 { | 308 | /include/ "qoriq-clockgen1.dtsi" |
309 | global-utilities@e1000 { | ||
309 | compatible = "fsl,p2041-clockgen", "fsl,qoriq-clockgen-1.0"; | 310 | compatible = "fsl,p2041-clockgen", "fsl,qoriq-clockgen-1.0"; |
310 | ranges = <0x0 0xe1000 0x1000>; | ||
311 | reg = <0xe1000 0x1000>; | ||
312 | clock-frequency = <0>; | ||
313 | #address-cells = <1>; | ||
314 | #size-cells = <1>; | ||
315 | |||
316 | sysclk: sysclk { | ||
317 | #clock-cells = <0>; | ||
318 | compatible = "fsl,qoriq-sysclk-1.0"; | ||
319 | clock-output-names = "sysclk"; | ||
320 | }; | ||
321 | |||
322 | pll0: pll0@800 { | ||
323 | #clock-cells = <1>; | ||
324 | reg = <0x800 0x4>; | ||
325 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
326 | clocks = <&sysclk>; | ||
327 | clock-output-names = "pll0", "pll0-div2"; | ||
328 | }; | ||
329 | |||
330 | pll1: pll1@820 { | ||
331 | #clock-cells = <1>; | ||
332 | reg = <0x820 0x4>; | ||
333 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
334 | clocks = <&sysclk>; | ||
335 | clock-output-names = "pll1", "pll1-div2"; | ||
336 | }; | ||
337 | |||
338 | mux0: mux0@0 { | ||
339 | #clock-cells = <0>; | ||
340 | reg = <0x0 0x4>; | ||
341 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
342 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
343 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
344 | clock-output-names = "cmux0"; | ||
345 | }; | ||
346 | |||
347 | mux1: mux1@20 { | ||
348 | #clock-cells = <0>; | ||
349 | reg = <0x20 0x4>; | ||
350 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
351 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
352 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
353 | clock-output-names = "cmux1"; | ||
354 | }; | ||
355 | 311 | ||
356 | mux2: mux2@40 { | 312 | mux2: mux2@40 { |
357 | #clock-cells = <0>; | 313 | #clock-cells = <0>; |
diff --git a/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi index cd63cb1b1042..d7425ef1ae41 100644 --- a/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi | |||
@@ -332,53 +332,9 @@ | |||
332 | #sleep-cells = <2>; | 332 | #sleep-cells = <2>; |
333 | }; | 333 | }; |
334 | 334 | ||
335 | clockgen: global-utilities@e1000 { | 335 | /include/ "qoriq-clockgen1.dtsi" |
336 | global-utilities@e1000 { | ||
336 | compatible = "fsl,p3041-clockgen", "fsl,qoriq-clockgen-1.0"; | 337 | compatible = "fsl,p3041-clockgen", "fsl,qoriq-clockgen-1.0"; |
337 | ranges = <0x0 0xe1000 0x1000>; | ||
338 | reg = <0xe1000 0x1000>; | ||
339 | clock-frequency = <0>; | ||
340 | #address-cells = <1>; | ||
341 | #size-cells = <1>; | ||
342 | |||
343 | sysclk: sysclk { | ||
344 | #clock-cells = <0>; | ||
345 | compatible = "fsl,qoriq-sysclk-1.0"; | ||
346 | clock-output-names = "sysclk"; | ||
347 | }; | ||
348 | |||
349 | pll0: pll0@800 { | ||
350 | #clock-cells = <1>; | ||
351 | reg = <0x800 0x4>; | ||
352 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
353 | clocks = <&sysclk>; | ||
354 | clock-output-names = "pll0", "pll0-div2"; | ||
355 | }; | ||
356 | |||
357 | pll1: pll1@820 { | ||
358 | #clock-cells = <1>; | ||
359 | reg = <0x820 0x4>; | ||
360 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
361 | clocks = <&sysclk>; | ||
362 | clock-output-names = "pll1", "pll1-div2"; | ||
363 | }; | ||
364 | |||
365 | mux0: mux0@0 { | ||
366 | #clock-cells = <0>; | ||
367 | reg = <0x0 0x4>; | ||
368 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
369 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
370 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
371 | clock-output-names = "cmux0"; | ||
372 | }; | ||
373 | |||
374 | mux1: mux1@20 { | ||
375 | #clock-cells = <0>; | ||
376 | reg = <0x20 0x4>; | ||
377 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
378 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
379 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
380 | clock-output-names = "cmux1"; | ||
381 | }; | ||
382 | 338 | ||
383 | mux2: mux2@40 { | 339 | mux2: mux2@40 { |
384 | #clock-cells = <0>; | 340 | #clock-cells = <0>; |
diff --git a/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi index 12947ccddf25..7005a4a4cef0 100644 --- a/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p4080si-post.dtsi | |||
@@ -352,35 +352,9 @@ | |||
352 | #sleep-cells = <2>; | 352 | #sleep-cells = <2>; |
353 | }; | 353 | }; |
354 | 354 | ||
355 | clockgen: global-utilities@e1000 { | 355 | /include/ "qoriq-clockgen1.dtsi" |
356 | global-utilities@e1000 { | ||
356 | compatible = "fsl,p4080-clockgen", "fsl,qoriq-clockgen-1.0"; | 357 | compatible = "fsl,p4080-clockgen", "fsl,qoriq-clockgen-1.0"; |
357 | ranges = <0x0 0xe1000 0x1000>; | ||
358 | reg = <0xe1000 0x1000>; | ||
359 | clock-frequency = <0>; | ||
360 | #address-cells = <1>; | ||
361 | #size-cells = <1>; | ||
362 | |||
363 | sysclk: sysclk { | ||
364 | #clock-cells = <0>; | ||
365 | compatible = "fsl,qoriq-sysclk-1.0"; | ||
366 | clock-output-names = "sysclk"; | ||
367 | }; | ||
368 | |||
369 | pll0: pll0@800 { | ||
370 | #clock-cells = <1>; | ||
371 | reg = <0x800 0x4>; | ||
372 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
373 | clocks = <&sysclk>; | ||
374 | clock-output-names = "pll0", "pll0-div2"; | ||
375 | }; | ||
376 | |||
377 | pll1: pll1@820 { | ||
378 | #clock-cells = <1>; | ||
379 | reg = <0x820 0x4>; | ||
380 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
381 | clocks = <&sysclk>; | ||
382 | clock-output-names = "pll1", "pll1-div2"; | ||
383 | }; | ||
384 | 358 | ||
385 | pll2: pll2@840 { | 359 | pll2: pll2@840 { |
386 | #clock-cells = <1>; | 360 | #clock-cells = <1>; |
@@ -398,24 +372,6 @@ | |||
398 | clock-output-names = "pll3", "pll3-div2"; | 372 | clock-output-names = "pll3", "pll3-div2"; |
399 | }; | 373 | }; |
400 | 374 | ||
401 | mux0: mux0@0 { | ||
402 | #clock-cells = <0>; | ||
403 | reg = <0x0 0x4>; | ||
404 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
405 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
406 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
407 | clock-output-names = "cmux0"; | ||
408 | }; | ||
409 | |||
410 | mux1: mux1@20 { | ||
411 | #clock-cells = <0>; | ||
412 | reg = <0x20 0x4>; | ||
413 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
414 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
415 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
416 | clock-output-names = "cmux1"; | ||
417 | }; | ||
418 | |||
419 | mux2: mux2@40 { | 375 | mux2: mux2@40 { |
420 | #clock-cells = <0>; | 376 | #clock-cells = <0>; |
421 | reg = <0x40 0x4>; | 377 | reg = <0x40 0x4>; |
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi index 4c4a2b0436b2..55834211bd28 100644 --- a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi | |||
@@ -337,53 +337,9 @@ | |||
337 | #sleep-cells = <2>; | 337 | #sleep-cells = <2>; |
338 | }; | 338 | }; |
339 | 339 | ||
340 | clockgen: global-utilities@e1000 { | 340 | /include/ "qoriq-clockgen1.dtsi" |
341 | global-utilities@e1000 { | ||
341 | compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0"; | 342 | compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0"; |
342 | ranges = <0x0 0xe1000 0x1000>; | ||
343 | reg = <0xe1000 0x1000>; | ||
344 | clock-frequency = <0>; | ||
345 | #address-cells = <1>; | ||
346 | #size-cells = <1>; | ||
347 | |||
348 | sysclk: sysclk { | ||
349 | #clock-cells = <0>; | ||
350 | compatible = "fsl,qoriq-sysclk-1.0"; | ||
351 | clock-output-names = "sysclk"; | ||
352 | }; | ||
353 | |||
354 | pll0: pll0@800 { | ||
355 | #clock-cells = <1>; | ||
356 | reg = <0x800 0x4>; | ||
357 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
358 | clocks = <&sysclk>; | ||
359 | clock-output-names = "pll0", "pll0-div2"; | ||
360 | }; | ||
361 | |||
362 | pll1: pll1@820 { | ||
363 | #clock-cells = <1>; | ||
364 | reg = <0x820 0x4>; | ||
365 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
366 | clocks = <&sysclk>; | ||
367 | clock-output-names = "pll1", "pll1-div2"; | ||
368 | }; | ||
369 | |||
370 | mux0: mux0@0 { | ||
371 | #clock-cells = <0>; | ||
372 | reg = <0x0 0x4>; | ||
373 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
374 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
375 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
376 | clock-output-names = "cmux0"; | ||
377 | }; | ||
378 | |||
379 | mux1: mux1@20 { | ||
380 | #clock-cells = <0>; | ||
381 | reg = <0x20 0x4>; | ||
382 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
383 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
384 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
385 | clock-output-names = "cmux1"; | ||
386 | }; | ||
387 | }; | 343 | }; |
388 | 344 | ||
389 | rcpm: global-utilities@e2000 { | 345 | rcpm: global-utilities@e2000 { |
diff --git a/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi index 67296fdd9698..6e4cd6ce363c 100644 --- a/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi | |||
@@ -297,53 +297,9 @@ | |||
297 | #sleep-cells = <2>; | 297 | #sleep-cells = <2>; |
298 | }; | 298 | }; |
299 | 299 | ||
300 | clockgen: global-utilities@e1000 { | 300 | /include/ "qoriq-clockgen1.dtsi" |
301 | global-utilities@e1000 { | ||
301 | compatible = "fsl,p5040-clockgen", "fsl,qoriq-clockgen-1.0"; | 302 | compatible = "fsl,p5040-clockgen", "fsl,qoriq-clockgen-1.0"; |
302 | ranges = <0x0 0xe1000 0x1000>; | ||
303 | reg = <0xe1000 0x1000>; | ||
304 | clock-frequency = <0>; | ||
305 | #address-cells = <1>; | ||
306 | #size-cells = <1>; | ||
307 | |||
308 | sysclk: sysclk { | ||
309 | #clock-cells = <0>; | ||
310 | compatible = "fsl,qoriq-sysclk-1.0"; | ||
311 | clock-output-names = "sysclk"; | ||
312 | }; | ||
313 | |||
314 | pll0: pll0@800 { | ||
315 | #clock-cells = <1>; | ||
316 | reg = <0x800 0x4>; | ||
317 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
318 | clocks = <&sysclk>; | ||
319 | clock-output-names = "pll0", "pll0-div2"; | ||
320 | }; | ||
321 | |||
322 | pll1: pll1@820 { | ||
323 | #clock-cells = <1>; | ||
324 | reg = <0x820 0x4>; | ||
325 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
326 | clocks = <&sysclk>; | ||
327 | clock-output-names = "pll1", "pll1-div2"; | ||
328 | }; | ||
329 | |||
330 | mux0: mux0@0 { | ||
331 | #clock-cells = <0>; | ||
332 | reg = <0x0 0x4>; | ||
333 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
334 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
335 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
336 | clock-output-names = "cmux0"; | ||
337 | }; | ||
338 | |||
339 | mux1: mux1@20 { | ||
340 | #clock-cells = <0>; | ||
341 | reg = <0x20 0x4>; | ||
342 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
343 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
344 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
345 | clock-output-names = "cmux1"; | ||
346 | }; | ||
347 | 303 | ||
348 | mux2: mux2@40 { | 304 | mux2: mux2@40 { |
349 | #clock-cells = <0>; | 305 | #clock-cells = <0>; |
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-clockgen1.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-clockgen1.dtsi new file mode 100644 index 000000000000..4ece1edbff63 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/qoriq-clockgen1.dtsi | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * QorIQ clock control device tree stub [ controller @ offset 0xe1000 ] | ||
3 | * | ||
4 | * Copyright 2014 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | global-utilities@e1000 { | ||
36 | compatible = "fsl,qoriq-clockgen-1.0"; | ||
37 | ranges = <0x0 0xe1000 0x1000>; | ||
38 | reg = <0xe1000 0x1000>; | ||
39 | clock-frequency = <0>; | ||
40 | #address-cells = <1>; | ||
41 | #size-cells = <1>; | ||
42 | |||
43 | sysclk: sysclk { | ||
44 | #clock-cells = <0>; | ||
45 | compatible = "fsl,qoriq-sysclk-1.0", "fixed-clock"; | ||
46 | clock-output-names = "sysclk"; | ||
47 | }; | ||
48 | pll0: pll0@800 { | ||
49 | #clock-cells = <1>; | ||
50 | reg = <0x800 0x4>; | ||
51 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
52 | clocks = <&sysclk>; | ||
53 | clock-output-names = "pll0", "pll0-div2"; | ||
54 | }; | ||
55 | pll1: pll1@820 { | ||
56 | #clock-cells = <1>; | ||
57 | reg = <0x820 0x4>; | ||
58 | compatible = "fsl,qoriq-core-pll-1.0"; | ||
59 | clocks = <&sysclk>; | ||
60 | clock-output-names = "pll1", "pll1-div2"; | ||
61 | }; | ||
62 | mux0: mux0@0 { | ||
63 | #clock-cells = <0>; | ||
64 | reg = <0x0 0x4>; | ||
65 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
66 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
67 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
68 | clock-output-names = "cmux0"; | ||
69 | }; | ||
70 | mux1: mux1@20 { | ||
71 | #clock-cells = <0>; | ||
72 | reg = <0x20 0x4>; | ||
73 | compatible = "fsl,qoriq-core-mux-1.0"; | ||
74 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | ||
75 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | ||
76 | clock-output-names = "cmux1"; | ||
77 | }; | ||
78 | platform_pll: platform-pll@c00 { | ||
79 | #clock-cells = <1>; | ||
80 | reg = <0xc00 0x4>; | ||
81 | compatible = "fsl,qoriq-platform-pll-1.0"; | ||
82 | clocks = <&sysclk>; | ||
83 | clock-output-names = "platform-pll", "platform-pll-div2"; | ||
84 | }; | ||
85 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-clockgen2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-clockgen2.dtsi new file mode 100644 index 000000000000..48e0b6e4ce33 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/qoriq-clockgen2.dtsi | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * QorIQ clock control device tree stub [ controller @ offset 0xe1000 ] | ||
3 | * | ||
4 | * Copyright 2014 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | global-utilities@e1000 { | ||
36 | compatible = "fsl,qoriq-clockgen-2.0"; | ||
37 | ranges = <0x0 0xe1000 0x1000>; | ||
38 | reg = <0xe1000 0x1000>; | ||
39 | #address-cells = <1>; | ||
40 | #size-cells = <1>; | ||
41 | |||
42 | sysclk: sysclk { | ||
43 | #clock-cells = <0>; | ||
44 | compatible = "fsl,qoriq-sysclk-2.0", "fixed-clock"; | ||
45 | clock-output-names = "sysclk"; | ||
46 | }; | ||
47 | pll0: pll0@800 { | ||
48 | #clock-cells = <1>; | ||
49 | reg = <0x800 0x4>; | ||
50 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
51 | clocks = <&sysclk>; | ||
52 | clock-output-names = "pll0", "pll0-div2", "pll0-div4"; | ||
53 | }; | ||
54 | pll1: pll1@820 { | ||
55 | #clock-cells = <1>; | ||
56 | reg = <0x820 0x4>; | ||
57 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
58 | clocks = <&sysclk>; | ||
59 | clock-output-names = "pll1", "pll1-div2", "pll1-div4"; | ||
60 | }; | ||
61 | platform_pll: platform-pll@c00 { | ||
62 | #clock-cells = <1>; | ||
63 | reg = <0xc00 0x4>; | ||
64 | compatible = "fsl,qoriq-platform-pll-2.0"; | ||
65 | clocks = <&sysclk>; | ||
66 | clock-output-names = "platform-pll", "platform-pll-div2"; | ||
67 | }; | ||
68 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi index 12e597eea3c8..15ae462e758f 100644 --- a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi | |||
@@ -281,35 +281,9 @@ | |||
281 | fsl,liodn-bits = <12>; | 281 | fsl,liodn-bits = <12>; |
282 | }; | 282 | }; |
283 | 283 | ||
284 | clockgen: global-utilities@e1000 { | 284 | /include/ "qoriq-clockgen2.dtsi" |
285 | global-utilities@e1000 { | ||
285 | compatible = "fsl,t1040-clockgen", "fsl,qoriq-clockgen-2.0"; | 286 | compatible = "fsl,t1040-clockgen", "fsl,qoriq-clockgen-2.0"; |
286 | ranges = <0x0 0xe1000 0x1000>; | ||
287 | reg = <0xe1000 0x1000>; | ||
288 | #address-cells = <1>; | ||
289 | #size-cells = <1>; | ||
290 | |||
291 | sysclk: sysclk { | ||
292 | #clock-cells = <0>; | ||
293 | compatible = "fsl,qoriq-sysclk-2.0"; | ||
294 | clock-output-names = "sysclk", "fixed-clock"; | ||
295 | }; | ||
296 | |||
297 | |||
298 | pll0: pll0@800 { | ||
299 | #clock-cells = <1>; | ||
300 | reg = <0x800 4>; | ||
301 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
302 | clocks = <&sysclk>; | ||
303 | clock-output-names = "pll0", "pll0-div2", "pll0-div4"; | ||
304 | }; | ||
305 | |||
306 | pll1: pll1@820 { | ||
307 | #clock-cells = <1>; | ||
308 | reg = <0x820 4>; | ||
309 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
310 | clocks = <&sysclk>; | ||
311 | clock-output-names = "pll1", "pll1-div2", "pll1-div4"; | ||
312 | }; | ||
313 | 287 | ||
314 | mux0: mux0@0 { | 288 | mux0: mux0@0 { |
315 | #clock-cells = <0>; | 289 | #clock-cells = <0>; |
diff --git a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi index aecee9690a88..1ce91e3485a9 100644 --- a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi | |||
@@ -305,34 +305,9 @@ | |||
305 | fsl,liodn-bits = <12>; | 305 | fsl,liodn-bits = <12>; |
306 | }; | 306 | }; |
307 | 307 | ||
308 | clockgen: global-utilities@e1000 { | 308 | /include/ "qoriq-clockgen2.dtsi" |
309 | global-utilities@e1000 { | ||
309 | compatible = "fsl,t2080-clockgen", "fsl,qoriq-clockgen-2.0"; | 310 | compatible = "fsl,t2080-clockgen", "fsl,qoriq-clockgen-2.0"; |
310 | ranges = <0x0 0xe1000 0x1000>; | ||
311 | reg = <0xe1000 0x1000>; | ||
312 | #address-cells = <1>; | ||
313 | #size-cells = <1>; | ||
314 | |||
315 | sysclk: sysclk { | ||
316 | #clock-cells = <0>; | ||
317 | compatible = "fsl,qoriq-sysclk-2.0"; | ||
318 | clock-output-names = "sysclk", "fixed-clock"; | ||
319 | }; | ||
320 | |||
321 | pll0: pll0@800 { | ||
322 | #clock-cells = <1>; | ||
323 | reg = <0x800 4>; | ||
324 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
325 | clocks = <&sysclk>; | ||
326 | clock-output-names = "pll0", "pll0-div2", "pll0-div4"; | ||
327 | }; | ||
328 | |||
329 | pll1: pll1@820 { | ||
330 | #clock-cells = <1>; | ||
331 | reg = <0x820 4>; | ||
332 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
333 | clocks = <&sysclk>; | ||
334 | clock-output-names = "pll1", "pll1-div2", "pll1-div4"; | ||
335 | }; | ||
336 | 311 | ||
337 | mux0: mux0@0 { | 312 | mux0: mux0@0 { |
338 | #clock-cells = <0>; | 313 | #clock-cells = <0>; |
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi index 7e2fc7cdce48..0e96fcabe812 100644 --- a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi | |||
@@ -368,34 +368,9 @@ | |||
368 | fsl,liodn-bits = <12>; | 368 | fsl,liodn-bits = <12>; |
369 | }; | 369 | }; |
370 | 370 | ||
371 | clockgen: global-utilities@e1000 { | 371 | /include/ "qoriq-clockgen2.dtsi" |
372 | global-utilities@e1000 { | ||
372 | compatible = "fsl,t4240-clockgen", "fsl,qoriq-clockgen-2.0"; | 373 | compatible = "fsl,t4240-clockgen", "fsl,qoriq-clockgen-2.0"; |
373 | ranges = <0x0 0xe1000 0x1000>; | ||
374 | reg = <0xe1000 0x1000>; | ||
375 | #address-cells = <1>; | ||
376 | #size-cells = <1>; | ||
377 | |||
378 | sysclk: sysclk { | ||
379 | #clock-cells = <0>; | ||
380 | compatible = "fsl,qoriq-sysclk-2.0"; | ||
381 | clock-output-names = "sysclk"; | ||
382 | }; | ||
383 | |||
384 | pll0: pll0@800 { | ||
385 | #clock-cells = <1>; | ||
386 | reg = <0x800 0x4>; | ||
387 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
388 | clocks = <&sysclk>; | ||
389 | clock-output-names = "pll0", "pll0-div2", "pll0-div4"; | ||
390 | }; | ||
391 | |||
392 | pll1: pll1@820 { | ||
393 | #clock-cells = <1>; | ||
394 | reg = <0x820 0x4>; | ||
395 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
396 | clocks = <&sysclk>; | ||
397 | clock-output-names = "pll1", "pll1-div2", "pll1-div4"; | ||
398 | }; | ||
399 | 374 | ||
400 | pll2: pll2@840 { | 375 | pll2: pll2@840 { |
401 | #clock-cells = <1>; | 376 | #clock-cells = <1>; |
diff --git a/arch/powerpc/boot/dts/p3041ds.dts b/arch/powerpc/boot/dts/p3041ds.dts index 2fed3bc0b990..394ea9c943c9 100644 --- a/arch/powerpc/boot/dts/p3041ds.dts +++ b/arch/powerpc/boot/dts/p3041ds.dts | |||
@@ -98,6 +98,26 @@ | |||
98 | reg = <0x68>; | 98 | reg = <0x68>; |
99 | interrupts = <0x1 0x1 0 0>; | 99 | interrupts = <0x1 0x1 0 0>; |
100 | }; | 100 | }; |
101 | ina220@40 { | ||
102 | compatible = "ti,ina220"; | ||
103 | reg = <0x40>; | ||
104 | shunt-resistor = <1000>; | ||
105 | }; | ||
106 | ina220@41 { | ||
107 | compatible = "ti,ina220"; | ||
108 | reg = <0x41>; | ||
109 | shunt-resistor = <1000>; | ||
110 | }; | ||
111 | ina220@44 { | ||
112 | compatible = "ti,ina220"; | ||
113 | reg = <0x44>; | ||
114 | shunt-resistor = <1000>; | ||
115 | }; | ||
116 | ina220@45 { | ||
117 | compatible = "ti,ina220"; | ||
118 | reg = <0x45>; | ||
119 | shunt-resistor = <1000>; | ||
120 | }; | ||
101 | adt7461@4c { | 121 | adt7461@4c { |
102 | compatible = "adi,adt7461"; | 122 | compatible = "adi,adt7461"; |
103 | reg = <0x4c>; | 123 | reg = <0x4c>; |
diff --git a/arch/powerpc/boot/dts/p5020ds.dts b/arch/powerpc/boot/dts/p5020ds.dts index 2869fea717dd..b7f3057cd894 100644 --- a/arch/powerpc/boot/dts/p5020ds.dts +++ b/arch/powerpc/boot/dts/p5020ds.dts | |||
@@ -98,6 +98,26 @@ | |||
98 | reg = <0x68>; | 98 | reg = <0x68>; |
99 | interrupts = <0x1 0x1 0 0>; | 99 | interrupts = <0x1 0x1 0 0>; |
100 | }; | 100 | }; |
101 | ina220@40 { | ||
102 | compatible = "ti,ina220"; | ||
103 | reg = <0x40>; | ||
104 | shunt-resistor = <1000>; | ||
105 | }; | ||
106 | ina220@41 { | ||
107 | compatible = "ti,ina220"; | ||
108 | reg = <0x41>; | ||
109 | shunt-resistor = <1000>; | ||
110 | }; | ||
111 | ina220@44 { | ||
112 | compatible = "ti,ina220"; | ||
113 | reg = <0x44>; | ||
114 | shunt-resistor = <1000>; | ||
115 | }; | ||
116 | ina220@45 { | ||
117 | compatible = "ti,ina220"; | ||
118 | reg = <0x45>; | ||
119 | shunt-resistor = <1000>; | ||
120 | }; | ||
101 | adt7461@4c { | 121 | adt7461@4c { |
102 | compatible = "adi,adt7461"; | 122 | compatible = "adi,adt7461"; |
103 | reg = <0x4c>; | 123 | reg = <0x4c>; |
diff --git a/arch/powerpc/boot/dts/p5040ds.dts b/arch/powerpc/boot/dts/p5040ds.dts index 860b5ccf76c0..7e04bf487c04 100644 --- a/arch/powerpc/boot/dts/p5040ds.dts +++ b/arch/powerpc/boot/dts/p5040ds.dts | |||
@@ -95,6 +95,26 @@ | |||
95 | reg = <0x68>; | 95 | reg = <0x68>; |
96 | interrupts = <0x1 0x1 0 0>; | 96 | interrupts = <0x1 0x1 0 0>; |
97 | }; | 97 | }; |
98 | ina220@40 { | ||
99 | compatible = "ti,ina220"; | ||
100 | reg = <0x40>; | ||
101 | shunt-resistor = <1000>; | ||
102 | }; | ||
103 | ina220@41 { | ||
104 | compatible = "ti,ina220"; | ||
105 | reg = <0x41>; | ||
106 | shunt-resistor = <1000>; | ||
107 | }; | ||
108 | ina220@44 { | ||
109 | compatible = "ti,ina220"; | ||
110 | reg = <0x44>; | ||
111 | shunt-resistor = <1000>; | ||
112 | }; | ||
113 | ina220@45 { | ||
114 | compatible = "ti,ina220"; | ||
115 | reg = <0x45>; | ||
116 | shunt-resistor = <1000>; | ||
117 | }; | ||
98 | adt7461@4c { | 118 | adt7461@4c { |
99 | compatible = "adi,adt7461"; | 119 | compatible = "adi,adt7461"; |
100 | reg = <0x4c>; | 120 | reg = <0x4c>; |
diff --git a/arch/powerpc/boot/dts/t104xrdb.dtsi b/arch/powerpc/boot/dts/t104xrdb.dtsi index 1cf0f3c5f7e5..187add885cae 100644 --- a/arch/powerpc/boot/dts/t104xrdb.dtsi +++ b/arch/powerpc/boot/dts/t104xrdb.dtsi | |||
@@ -83,6 +83,13 @@ | |||
83 | }; | 83 | }; |
84 | }; | 84 | }; |
85 | 85 | ||
86 | i2c@118000 { | ||
87 | adt7461@4c { | ||
88 | compatible = "adi,adt7461"; | ||
89 | reg = <0x4c>; | ||
90 | }; | ||
91 | }; | ||
92 | |||
86 | i2c@118100 { | 93 | i2c@118100 { |
87 | pca9546@77 { | 94 | pca9546@77 { |
88 | compatible = "nxp,pca9546"; | 95 | compatible = "nxp,pca9546"; |
diff --git a/arch/powerpc/boot/dts/t208xqds.dtsi b/arch/powerpc/boot/dts/t208xqds.dtsi index 555dc6e03d89..59061834d54e 100644 --- a/arch/powerpc/boot/dts/t208xqds.dtsi +++ b/arch/powerpc/boot/dts/t208xqds.dtsi | |||
@@ -169,6 +169,17 @@ | |||
169 | shunt-resistor = <1000>; | 169 | shunt-resistor = <1000>; |
170 | }; | 170 | }; |
171 | }; | 171 | }; |
172 | |||
173 | i2c@3 { | ||
174 | #address-cells = <1>; | ||
175 | #size-cells = <0>; | ||
176 | reg = <0x3>; | ||
177 | |||
178 | adt7461@4c { | ||
179 | compatible = "adi,adt7461"; | ||
180 | reg = <0x4c>; | ||
181 | }; | ||
182 | }; | ||
172 | }; | 183 | }; |
173 | }; | 184 | }; |
174 | 185 | ||
diff --git a/arch/powerpc/boot/dts/t4240emu.dts b/arch/powerpc/boot/dts/t4240emu.dts index bc12127a03fb..decaf357db9c 100644 --- a/arch/powerpc/boot/dts/t4240emu.dts +++ b/arch/powerpc/boot/dts/t4240emu.dts | |||
@@ -250,9 +250,9 @@ | |||
250 | fsl,liodn-bits = <12>; | 250 | fsl,liodn-bits = <12>; |
251 | }; | 251 | }; |
252 | 252 | ||
253 | clockgen: global-utilities@e1000 { | 253 | /include/ "fsl/qoriq-clockgen2.dtsi" |
254 | global-utilities@e1000 { | ||
254 | compatible = "fsl,t4240-clockgen", "fsl,qoriq-clockgen-2.0"; | 255 | compatible = "fsl,t4240-clockgen", "fsl,qoriq-clockgen-2.0"; |
255 | reg = <0xe1000 0x1000>; | ||
256 | }; | 256 | }; |
257 | 257 | ||
258 | /include/ "fsl/qoriq-dma-0.dtsi" | 258 | /include/ "fsl/qoriq-dma-0.dtsi" |
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index d367a0aece2a..d80161b633f4 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c | |||
@@ -144,13 +144,24 @@ static char cmdline[BOOT_COMMAND_LINE_SIZE] | |||
144 | 144 | ||
145 | static void prep_cmdline(void *chosen) | 145 | static void prep_cmdline(void *chosen) |
146 | { | 146 | { |
147 | unsigned int getline_timeout = 5000; | ||
148 | int v; | ||
149 | int n; | ||
150 | |||
151 | /* Wait-for-input time */ | ||
152 | n = getprop(chosen, "linux,cmdline-timeout", &v, sizeof(v)); | ||
153 | if (n == sizeof(v)) | ||
154 | getline_timeout = v; | ||
155 | |||
147 | if (cmdline[0] == '\0') | 156 | if (cmdline[0] == '\0') |
148 | getprop(chosen, "bootargs", cmdline, BOOT_COMMAND_LINE_SIZE-1); | 157 | getprop(chosen, "bootargs", cmdline, BOOT_COMMAND_LINE_SIZE-1); |
149 | 158 | ||
150 | printf("\n\rLinux/PowerPC load: %s", cmdline); | 159 | printf("\n\rLinux/PowerPC load: %s", cmdline); |
160 | |||
151 | /* If possible, edit the command line */ | 161 | /* If possible, edit the command line */ |
152 | if (console_ops.edit_cmdline) | 162 | if (console_ops.edit_cmdline && getline_timeout) |
153 | console_ops.edit_cmdline(cmdline, BOOT_COMMAND_LINE_SIZE); | 163 | console_ops.edit_cmdline(cmdline, BOOT_COMMAND_LINE_SIZE, getline_timeout); |
164 | |||
154 | printf("\n\r"); | 165 | printf("\n\r"); |
155 | 166 | ||
156 | /* Put the command line back into the devtree for the kernel */ | 167 | /* Put the command line back into the devtree for the kernel */ |
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 8aad3c55aeda..5e75e1c5518e 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h | |||
@@ -58,7 +58,7 @@ extern struct dt_ops dt_ops; | |||
58 | struct console_ops { | 58 | struct console_ops { |
59 | int (*open)(void); | 59 | int (*open)(void); |
60 | void (*write)(const char *buf, int len); | 60 | void (*write)(const char *buf, int len); |
61 | void (*edit_cmdline)(char *buf, int len); | 61 | void (*edit_cmdline)(char *buf, int len, unsigned int getline_timeout); |
62 | void (*close)(void); | 62 | void (*close)(void); |
63 | void *data; | 63 | void *data; |
64 | }; | 64 | }; |
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c index f2156f07571f..167ee9433de6 100644 --- a/arch/powerpc/boot/serial.c +++ b/arch/powerpc/boot/serial.c | |||
@@ -33,7 +33,7 @@ static void serial_write(const char *buf, int len) | |||
33 | scdp->putc(*buf++); | 33 | scdp->putc(*buf++); |
34 | } | 34 | } |
35 | 35 | ||
36 | static void serial_edit_cmdline(char *buf, int len) | 36 | static void serial_edit_cmdline(char *buf, int len, unsigned int timeout) |
37 | { | 37 | { |
38 | int timer = 0, count; | 38 | int timer = 0, count; |
39 | char ch, *cp; | 39 | char ch, *cp; |
@@ -44,7 +44,7 @@ static void serial_edit_cmdline(char *buf, int len) | |||
44 | cp = &buf[count]; | 44 | cp = &buf[count]; |
45 | count++; | 45 | count++; |
46 | 46 | ||
47 | while (timer++ < 5*1000) { | 47 | do { |
48 | if (scdp->tstc()) { | 48 | if (scdp->tstc()) { |
49 | while (((ch = scdp->getc()) != '\n') && (ch != '\r')) { | 49 | while (((ch = scdp->getc()) != '\n') && (ch != '\r')) { |
50 | /* Test for backspace/delete */ | 50 | /* Test for backspace/delete */ |
@@ -70,7 +70,7 @@ static void serial_edit_cmdline(char *buf, int len) | |||
70 | break; /* Exit 'timer' loop */ | 70 | break; /* Exit 'timer' loop */ |
71 | } | 71 | } |
72 | udelay(1000); /* 1 msec */ | 72 | udelay(1000); /* 1 msec */ |
73 | } | 73 | } while (timer++ < timeout); |
74 | *cp = 0; | 74 | *cp = 0; |
75 | } | 75 | } |
76 | 76 | ||
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig index 688e9e4d29a1..611efe99faeb 100644 --- a/arch/powerpc/configs/corenet32_smp_defconfig +++ b/arch/powerpc/configs/corenet32_smp_defconfig | |||
@@ -144,6 +144,7 @@ CONFIG_RTC_DRV_DS1374=y | |||
144 | CONFIG_RTC_DRV_DS3232=y | 144 | CONFIG_RTC_DRV_DS3232=y |
145 | CONFIG_UIO=y | 145 | CONFIG_UIO=y |
146 | CONFIG_STAGING=y | 146 | CONFIG_STAGING=y |
147 | CONFIG_MEMORY=y | ||
147 | CONFIG_VIRT_DRIVERS=y | 148 | CONFIG_VIRT_DRIVERS=y |
148 | CONFIG_FSL_HV_MANAGER=y | 149 | CONFIG_FSL_HV_MANAGER=y |
149 | CONFIG_EXT2_FS=y | 150 | CONFIG_EXT2_FS=y |
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig index 6db97e4414b2..be24a18c0d96 100644 --- a/arch/powerpc/configs/corenet64_smp_defconfig +++ b/arch/powerpc/configs/corenet64_smp_defconfig | |||
@@ -118,6 +118,7 @@ CONFIG_FSL_DMA=y | |||
118 | CONFIG_VIRT_DRIVERS=y | 118 | CONFIG_VIRT_DRIVERS=y |
119 | CONFIG_FSL_HV_MANAGER=y | 119 | CONFIG_FSL_HV_MANAGER=y |
120 | CONFIG_FSL_CORENET_CF=y | 120 | CONFIG_FSL_CORENET_CF=y |
121 | CONFIG_MEMORY=y | ||
121 | CONFIG_EXT2_FS=y | 122 | CONFIG_EXT2_FS=y |
122 | CONFIG_EXT3_FS=y | 123 | CONFIG_EXT3_FS=y |
123 | CONFIG_ISO9660_FS=m | 124 | CONFIG_ISO9660_FS=m |
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig index d2c415489f72..02395fab19bd 100644 --- a/arch/powerpc/configs/mpc85xx_defconfig +++ b/arch/powerpc/configs/mpc85xx_defconfig | |||
@@ -215,6 +215,7 @@ CONFIG_RTC_DRV_DS3232=y | |||
215 | CONFIG_RTC_DRV_CMOS=y | 215 | CONFIG_RTC_DRV_CMOS=y |
216 | CONFIG_DMADEVICES=y | 216 | CONFIG_DMADEVICES=y |
217 | CONFIG_FSL_DMA=y | 217 | CONFIG_FSL_DMA=y |
218 | CONFIG_MEMORY=y | ||
218 | # CONFIG_NET_DMA is not set | 219 | # CONFIG_NET_DMA is not set |
219 | CONFIG_EXT2_FS=y | 220 | CONFIG_EXT2_FS=y |
220 | CONFIG_EXT3_FS=y | 221 | CONFIG_EXT3_FS=y |
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig index 87460083dbc7..b5d1b82a1b43 100644 --- a/arch/powerpc/configs/mpc85xx_smp_defconfig +++ b/arch/powerpc/configs/mpc85xx_smp_defconfig | |||
@@ -216,6 +216,7 @@ CONFIG_RTC_DRV_DS3232=y | |||
216 | CONFIG_RTC_DRV_CMOS=y | 216 | CONFIG_RTC_DRV_CMOS=y |
217 | CONFIG_DMADEVICES=y | 217 | CONFIG_DMADEVICES=y |
218 | CONFIG_FSL_DMA=y | 218 | CONFIG_FSL_DMA=y |
219 | CONFIG_MEMORY=y | ||
219 | # CONFIG_NET_DMA is not set | 220 | # CONFIG_NET_DMA is not set |
220 | CONFIG_EXT2_FS=y | 221 | CONFIG_EXT2_FS=y |
221 | CONFIG_EXT3_FS=y | 222 | CONFIG_EXT3_FS=y |
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index bd3bd573d0ae..59abc620f8e8 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h | |||
@@ -14,9 +14,9 @@ | |||
14 | * | 14 | * |
15 | * The bitop functions are defined to work on unsigned longs, so for a | 15 | * The bitop functions are defined to work on unsigned longs, so for a |
16 | * ppc64 system the bits end up numbered: | 16 | * ppc64 system the bits end up numbered: |
17 | * |63..............0|127............64|191...........128|255...........196| | 17 | * |63..............0|127............64|191...........128|255...........192| |
18 | * and on ppc32: | 18 | * and on ppc32: |
19 | * |31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224| | 19 | * |31.....0|63....32|95....64|127...96|159..128|191..160|223..192|255..224| |
20 | * | 20 | * |
21 | * There are a few little-endian macros used mostly for filesystem | 21 | * There are a few little-endian macros used mostly for filesystem |
22 | * bitmaps, these work on similar bit arrays layouts, but | 22 | * bitmaps, these work on similar bit arrays layouts, but |
@@ -213,7 +213,7 @@ static __inline__ unsigned long ffz(unsigned long x) | |||
213 | return __ilog2(x & -x); | 213 | return __ilog2(x & -x); |
214 | } | 214 | } |
215 | 215 | ||
216 | static __inline__ int __ffs(unsigned long x) | 216 | static __inline__ unsigned long __ffs(unsigned long x) |
217 | { | 217 | { |
218 | return __ilog2(x & -x); | 218 | return __ilog2(x & -x); |
219 | } | 219 | } |
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index daa5af91163c..22d5a7da9e68 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -448,13 +448,9 @@ extern const char *powerpc_base_platform; | |||
448 | CPU_FTR_PURR | CPU_FTR_REAL_LE | CPU_FTR_DABRX) | 448 | CPU_FTR_PURR | CPU_FTR_REAL_LE | CPU_FTR_DABRX) |
449 | #define CPU_FTRS_COMPATIBLE (CPU_FTR_USE_TB | CPU_FTR_PPCAS_ARCH_V2) | 449 | #define CPU_FTRS_COMPATIBLE (CPU_FTR_USE_TB | CPU_FTR_PPCAS_ARCH_V2) |
450 | 450 | ||
451 | #define CPU_FTRS_A2 (CPU_FTR_USE_TB | CPU_FTR_SMT | CPU_FTR_DBELL | \ | ||
452 | CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN | \ | ||
453 | CPU_FTR_ICSWX | CPU_FTR_DABRX ) | ||
454 | |||
455 | #ifdef __powerpc64__ | 451 | #ifdef __powerpc64__ |
456 | #ifdef CONFIG_PPC_BOOK3E | 452 | #ifdef CONFIG_PPC_BOOK3E |
457 | #define CPU_FTRS_POSSIBLE (CPU_FTRS_E6500 | CPU_FTRS_E5500 | CPU_FTRS_A2) | 453 | #define CPU_FTRS_POSSIBLE (CPU_FTRS_E6500 | CPU_FTRS_E5500) |
458 | #else | 454 | #else |
459 | #define CPU_FTRS_POSSIBLE \ | 455 | #define CPU_FTRS_POSSIBLE \ |
460 | (CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ | 456 | (CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ |
@@ -505,13 +501,13 @@ enum { | |||
505 | 501 | ||
506 | #ifdef __powerpc64__ | 502 | #ifdef __powerpc64__ |
507 | #ifdef CONFIG_PPC_BOOK3E | 503 | #ifdef CONFIG_PPC_BOOK3E |
508 | #define CPU_FTRS_ALWAYS (CPU_FTRS_E6500 & CPU_FTRS_E5500 & CPU_FTRS_A2) | 504 | #define CPU_FTRS_ALWAYS (CPU_FTRS_E6500 & CPU_FTRS_E5500) |
509 | #else | 505 | #else |
510 | #define CPU_FTRS_ALWAYS \ | 506 | #define CPU_FTRS_ALWAYS \ |
511 | (CPU_FTRS_POWER4 & CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \ | 507 | (CPU_FTRS_POWER4 & CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \ |
512 | CPU_FTRS_POWER6 & CPU_FTRS_POWER7 & CPU_FTRS_CELL & \ | 508 | CPU_FTRS_POWER6 & CPU_FTRS_POWER7 & CPU_FTRS_CELL & \ |
513 | CPU_FTRS_PA6T & CPU_FTRS_POWER8 & CPU_FTRS_POWER8E & \ | 509 | CPU_FTRS_PA6T & CPU_FTRS_POWER8 & CPU_FTRS_POWER8E & \ |
514 | CPU_FTRS_POWER8_DD1 & CPU_FTRS_POSSIBLE) | 510 | CPU_FTRS_POWER8_DD1 & ~CPU_FTR_HVMODE & CPU_FTRS_POSSIBLE) |
515 | #endif | 511 | #endif |
516 | #else | 512 | #else |
517 | enum { | 513 | enum { |
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index ca07f9c27335..0652ebe117af 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
@@ -39,6 +39,7 @@ struct device_node; | |||
39 | #define EEH_PROBE_MODE_DEV 0x04 /* From PCI device */ | 39 | #define EEH_PROBE_MODE_DEV 0x04 /* From PCI device */ |
40 | #define EEH_PROBE_MODE_DEVTREE 0x08 /* From device tree */ | 40 | #define EEH_PROBE_MODE_DEVTREE 0x08 /* From device tree */ |
41 | #define EEH_ENABLE_IO_FOR_LOG 0x10 /* Enable IO for log */ | 41 | #define EEH_ENABLE_IO_FOR_LOG 0x10 /* Enable IO for log */ |
42 | #define EEH_EARLY_DUMP_LOG 0x20 /* Dump log immediately */ | ||
42 | 43 | ||
43 | /* | 44 | /* |
44 | * Delay for PE reset, all in ms | 45 | * Delay for PE reset, all in ms |
@@ -72,6 +73,7 @@ struct device_node; | |||
72 | #define EEH_PE_ISOLATED (1 << 0) /* Isolated PE */ | 73 | #define EEH_PE_ISOLATED (1 << 0) /* Isolated PE */ |
73 | #define EEH_PE_RECOVERING (1 << 1) /* Recovering PE */ | 74 | #define EEH_PE_RECOVERING (1 << 1) /* Recovering PE */ |
74 | #define EEH_PE_CFG_BLOCKED (1 << 2) /* Block config access */ | 75 | #define EEH_PE_CFG_BLOCKED (1 << 2) /* Block config access */ |
76 | #define EEH_PE_RESET (1 << 3) /* PE reset in progress */ | ||
75 | 77 | ||
76 | #define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */ | 78 | #define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */ |
77 | #define EEH_PE_CFG_RESTRICTED (1 << 9) /* Block config on error */ | 79 | #define EEH_PE_CFG_RESTRICTED (1 << 9) /* Block config on error */ |
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index 888d8f3f2524..57d289acb803 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h | |||
@@ -28,8 +28,7 @@ | |||
28 | the loader. We need to make sure that it is out of the way of the program | 28 | the loader. We need to make sure that it is out of the way of the program |
29 | that it will "exec", and that there is sufficient room for the brk. */ | 29 | that it will "exec", and that there is sufficient room for the brk. */ |
30 | 30 | ||
31 | extern unsigned long randomize_et_dyn(unsigned long base); | 31 | #define ELF_ET_DYN_BASE 0x20000000 |
32 | #define ELF_ET_DYN_BASE (randomize_et_dyn(0x20000000)) | ||
33 | 32 | ||
34 | #define ELF_CORE_EFLAGS (is_elf2_task() ? 2 : 0) | 33 | #define ELF_CORE_EFLAGS (is_elf2_task() ? 2 : 0) |
35 | 34 | ||
diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h index 77ced0b3d81d..43b6bb1a4a9c 100644 --- a/arch/powerpc/include/asm/fsl_guts.h +++ b/arch/powerpc/include/asm/fsl_guts.h | |||
@@ -68,7 +68,10 @@ struct ccsr_guts { | |||
68 | u8 res0b4[0xc0 - 0xb4]; | 68 | u8 res0b4[0xc0 - 0xb4]; |
69 | __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register | 69 | __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register |
70 | Called 'elbcvselcr' on 86xx SOCs */ | 70 | Called 'elbcvselcr' on 86xx SOCs */ |
71 | u8 res0c4[0x224 - 0xc4]; | 71 | u8 res0c4[0x100 - 0xc4]; |
72 | __be32 rcwsr[16]; /* 0x.0100 - Reset Control Word Status registers | ||
73 | There are 16 registers */ | ||
74 | u8 res140[0x224 - 0x140]; | ||
72 | __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */ | 75 | __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */ |
73 | __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */ | 76 | __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */ |
74 | u8 res22c[0x604 - 0x22c]; | 77 | u8 res22c[0x604 - 0x22c]; |
diff --git a/arch/powerpc/include/asm/hardirq.h b/arch/powerpc/include/asm/hardirq.h index 1bbb3013d6aa..8add8b861e8d 100644 --- a/arch/powerpc/include/asm/hardirq.h +++ b/arch/powerpc/include/asm/hardirq.h | |||
@@ -21,7 +21,12 @@ DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); | |||
21 | 21 | ||
22 | #define __ARCH_IRQ_STAT | 22 | #define __ARCH_IRQ_STAT |
23 | 23 | ||
24 | #define local_softirq_pending() __get_cpu_var(irq_stat).__softirq_pending | 24 | #define local_softirq_pending() __this_cpu_read(irq_stat.__softirq_pending) |
25 | |||
26 | #define __ARCH_SET_SOFTIRQ_PENDING | ||
27 | |||
28 | #define set_softirq_pending(x) __this_cpu_write(irq_stat.__softirq_pending, (x)) | ||
29 | #define or_softirq_pending(x) __this_cpu_or(irq_stat.__softirq_pending, (x)) | ||
25 | 30 | ||
26 | static inline void ack_bad_irq(unsigned int irq) | 31 | static inline void ack_bad_irq(unsigned int irq) |
27 | { | 32 | { |
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h index 766b77d527ac..1d53a65b4ec1 100644 --- a/arch/powerpc/include/asm/hugetlb.h +++ b/arch/powerpc/include/asm/hugetlb.h | |||
@@ -48,7 +48,7 @@ static inline unsigned int hugepd_shift(hugepd_t hpd) | |||
48 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 48 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
49 | 49 | ||
50 | 50 | ||
51 | static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, | 51 | static inline pte_t *hugepte_offset(hugepd_t hpd, unsigned long addr, |
52 | unsigned pdshift) | 52 | unsigned pdshift) |
53 | { | 53 | { |
54 | /* | 54 | /* |
@@ -58,9 +58,9 @@ static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, | |||
58 | */ | 58 | */ |
59 | unsigned long idx = 0; | 59 | unsigned long idx = 0; |
60 | 60 | ||
61 | pte_t *dir = hugepd_page(*hpdp); | 61 | pte_t *dir = hugepd_page(hpd); |
62 | #ifndef CONFIG_PPC_FSL_BOOK3E | 62 | #ifndef CONFIG_PPC_FSL_BOOK3E |
63 | idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp); | 63 | idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(hpd); |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | return dir + idx; | 66 | return dir + idx; |
@@ -193,7 +193,7 @@ static inline void flush_hugetlb_page(struct vm_area_struct *vma, | |||
193 | } | 193 | } |
194 | 194 | ||
195 | #define hugepd_shift(x) 0 | 195 | #define hugepd_shift(x) 0 |
196 | static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, | 196 | static inline pte_t *hugepte_offset(hugepd_t hpd, unsigned long addr, |
197 | unsigned pdshift) | 197 | unsigned pdshift) |
198 | { | 198 | { |
199 | return 0; | 199 | return 0; |
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index 9eaf301ac952..a8d2ef30d473 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h | |||
@@ -855,9 +855,6 @@ static inline void * bus_to_virt(unsigned long address) | |||
855 | 855 | ||
856 | #define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) | 856 | #define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) |
857 | 857 | ||
858 | void __iomem *devm_ioremap_prot(struct device *dev, resource_size_t offset, | ||
859 | size_t size, unsigned long flags); | ||
860 | |||
861 | #endif /* __KERNEL__ */ | 858 | #endif /* __KERNEL__ */ |
862 | 859 | ||
863 | #endif /* _ASM_POWERPC_IO_H */ | 860 | #endif /* _ASM_POWERPC_IO_H */ |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 307347f8ddbd..c8175a3fe560 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -42,7 +42,7 @@ struct machdep_calls { | |||
42 | unsigned long newpp, | 42 | unsigned long newpp, |
43 | unsigned long vpn, | 43 | unsigned long vpn, |
44 | int bpsize, int apsize, | 44 | int bpsize, int apsize, |
45 | int ssize, int local); | 45 | int ssize, unsigned long flags); |
46 | void (*hpte_updateboltedpp)(unsigned long newpp, | 46 | void (*hpte_updateboltedpp)(unsigned long newpp, |
47 | unsigned long ea, | 47 | unsigned long ea, |
48 | int psize, int ssize); | 48 | int psize, int ssize); |
@@ -60,7 +60,7 @@ struct machdep_calls { | |||
60 | void (*hugepage_invalidate)(unsigned long vsid, | 60 | void (*hugepage_invalidate)(unsigned long vsid, |
61 | unsigned long addr, | 61 | unsigned long addr, |
62 | unsigned char *hpte_slot_array, | 62 | unsigned char *hpte_slot_array, |
63 | int psize, int ssize); | 63 | int psize, int ssize, int local); |
64 | /* special for kexec, to be called in real mode, linear mapping is | 64 | /* special for kexec, to be called in real mode, linear mapping is |
65 | * destroyed as well */ | 65 | * destroyed as well */ |
66 | void (*hpte_clear_all)(void); | 66 | void (*hpte_clear_all)(void); |
@@ -142,7 +142,6 @@ struct machdep_calls { | |||
142 | #endif | 142 | #endif |
143 | 143 | ||
144 | void (*restart)(char *cmd); | 144 | void (*restart)(char *cmd); |
145 | void (*power_off)(void); | ||
146 | void (*halt)(void); | 145 | void (*halt)(void); |
147 | void (*panic)(char *str); | 146 | void (*panic)(char *str); |
148 | void (*cpu_die)(void); | 147 | void (*cpu_die)(void); |
@@ -292,10 +291,6 @@ struct machdep_calls { | |||
292 | #ifdef CONFIG_ARCH_RANDOM | 291 | #ifdef CONFIG_ARCH_RANDOM |
293 | int (*get_random_long)(unsigned long *v); | 292 | int (*get_random_long)(unsigned long *v); |
294 | #endif | 293 | #endif |
295 | |||
296 | #ifdef CONFIG_MEMORY_HOTREMOVE | ||
297 | int (*remove_memory)(u64, u64); | ||
298 | #endif | ||
299 | }; | 294 | }; |
300 | 295 | ||
301 | extern void e500_idle(void); | 296 | extern void e500_idle(void); |
@@ -343,16 +338,6 @@ extern sys_ctrler_t sys_ctrler; | |||
343 | 338 | ||
344 | #endif /* CONFIG_PPC_PMAC */ | 339 | #endif /* CONFIG_PPC_PMAC */ |
345 | 340 | ||
346 | |||
347 | /* Functions to produce codes on the leds. | ||
348 | * The SRC code should be unique for the message category and should | ||
349 | * be limited to the lower 24 bits (the upper 8 are set by these funcs), | ||
350 | * and (for boot & dump) should be sorted numerically in the order | ||
351 | * the events occur. | ||
352 | */ | ||
353 | /* Print a boot progress message. */ | ||
354 | void ppc64_boot_msg(unsigned int src, const char *msg); | ||
355 | |||
356 | static inline void log_error(char *buf, unsigned int err_type, int fatal) | 341 | static inline void log_error(char *buf, unsigned int err_type, int fatal) |
357 | { | 342 | { |
358 | if (ppc_md.log_error) | 343 | if (ppc_md.log_error) |
diff --git a/arch/powerpc/include/asm/mmu-8xx.h b/arch/powerpc/include/asm/mmu-8xx.h index 3d11d3ce79ec..986b9e1e1044 100644 --- a/arch/powerpc/include/asm/mmu-8xx.h +++ b/arch/powerpc/include/asm/mmu-8xx.h | |||
@@ -56,6 +56,7 @@ | |||
56 | * additional information from the MI_EPN, and MI_TWC registers. | 56 | * additional information from the MI_EPN, and MI_TWC registers. |
57 | */ | 57 | */ |
58 | #define SPRN_MI_RPN 790 | 58 | #define SPRN_MI_RPN 790 |
59 | #define MI_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */ | ||
59 | 60 | ||
60 | /* Define an RPN value for mapping kernel memory to large virtual | 61 | /* Define an RPN value for mapping kernel memory to large virtual |
61 | * pages for boot initialization. This has real page number of 0, | 62 | * pages for boot initialization. This has real page number of 0, |
@@ -129,6 +130,7 @@ | |||
129 | * additional information from the MD_EPN, and MD_TWC registers. | 130 | * additional information from the MD_EPN, and MD_TWC registers. |
130 | */ | 131 | */ |
131 | #define SPRN_MD_RPN 798 | 132 | #define SPRN_MD_RPN 798 |
133 | #define MD_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */ | ||
132 | 134 | ||
133 | /* This is a temporary storage register that could be used to save | 135 | /* This is a temporary storage register that could be used to save |
134 | * a processor working register during a tablewalk. | 136 | * a processor working register during a tablewalk. |
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index aeebc94b2bce..4f13c3ed7acf 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h | |||
@@ -316,27 +316,33 @@ static inline unsigned long hpt_hash(unsigned long vpn, | |||
316 | return hash & 0x7fffffffffUL; | 316 | return hash & 0x7fffffffffUL; |
317 | } | 317 | } |
318 | 318 | ||
319 | #define HPTE_LOCAL_UPDATE 0x1 | ||
320 | #define HPTE_NOHPTE_UPDATE 0x2 | ||
321 | |||
319 | extern int __hash_page_4K(unsigned long ea, unsigned long access, | 322 | extern int __hash_page_4K(unsigned long ea, unsigned long access, |
320 | unsigned long vsid, pte_t *ptep, unsigned long trap, | 323 | unsigned long vsid, pte_t *ptep, unsigned long trap, |
321 | unsigned int local, int ssize, int subpage_prot); | 324 | unsigned long flags, int ssize, int subpage_prot); |
322 | extern int __hash_page_64K(unsigned long ea, unsigned long access, | 325 | extern int __hash_page_64K(unsigned long ea, unsigned long access, |
323 | unsigned long vsid, pte_t *ptep, unsigned long trap, | 326 | unsigned long vsid, pte_t *ptep, unsigned long trap, |
324 | unsigned int local, int ssize); | 327 | unsigned long flags, int ssize); |
325 | struct mm_struct; | 328 | struct mm_struct; |
326 | unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap); | 329 | unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap); |
327 | extern int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, unsigned long trap); | 330 | extern int hash_page_mm(struct mm_struct *mm, unsigned long ea, |
328 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); | 331 | unsigned long access, unsigned long trap, |
332 | unsigned long flags); | ||
333 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap, | ||
334 | unsigned long dsisr); | ||
329 | int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, | 335 | int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, |
330 | pte_t *ptep, unsigned long trap, int local, int ssize, | 336 | pte_t *ptep, unsigned long trap, unsigned long flags, |
331 | unsigned int shift, unsigned int mmu_psize); | 337 | int ssize, unsigned int shift, unsigned int mmu_psize); |
332 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 338 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
333 | extern int __hash_page_thp(unsigned long ea, unsigned long access, | 339 | extern int __hash_page_thp(unsigned long ea, unsigned long access, |
334 | unsigned long vsid, pmd_t *pmdp, unsigned long trap, | 340 | unsigned long vsid, pmd_t *pmdp, unsigned long trap, |
335 | int local, int ssize, unsigned int psize); | 341 | unsigned long flags, int ssize, unsigned int psize); |
336 | #else | 342 | #else |
337 | static inline int __hash_page_thp(unsigned long ea, unsigned long access, | 343 | static inline int __hash_page_thp(unsigned long ea, unsigned long access, |
338 | unsigned long vsid, pmd_t *pmdp, | 344 | unsigned long vsid, pmd_t *pmdp, |
339 | unsigned long trap, int local, | 345 | unsigned long trap, unsigned long flags, |
340 | int ssize, unsigned int psize) | 346 | int ssize, unsigned int psize) |
341 | { | 347 | { |
342 | BUG(); | 348 | BUG(); |
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 9124b0ede1fc..5cd8d2fddba9 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h | |||
@@ -154,6 +154,10 @@ struct opal_sg_list { | |||
154 | #define OPAL_HANDLE_HMI 98 | 154 | #define OPAL_HANDLE_HMI 98 |
155 | #define OPAL_REGISTER_DUMP_REGION 101 | 155 | #define OPAL_REGISTER_DUMP_REGION 101 |
156 | #define OPAL_UNREGISTER_DUMP_REGION 102 | 156 | #define OPAL_UNREGISTER_DUMP_REGION 102 |
157 | #define OPAL_WRITE_TPO 103 | ||
158 | #define OPAL_READ_TPO 104 | ||
159 | #define OPAL_IPMI_SEND 107 | ||
160 | #define OPAL_IPMI_RECV 108 | ||
157 | 161 | ||
158 | #ifndef __ASSEMBLY__ | 162 | #ifndef __ASSEMBLY__ |
159 | 163 | ||
@@ -284,62 +288,6 @@ enum OpalMessageType { | |||
284 | OPAL_MSG_TYPE_MAX, | 288 | OPAL_MSG_TYPE_MAX, |
285 | }; | 289 | }; |
286 | 290 | ||
287 | /* Machine check related definitions */ | ||
288 | enum OpalMCE_Version { | ||
289 | OpalMCE_V1 = 1, | ||
290 | }; | ||
291 | |||
292 | enum OpalMCE_Severity { | ||
293 | OpalMCE_SEV_NO_ERROR = 0, | ||
294 | OpalMCE_SEV_WARNING = 1, | ||
295 | OpalMCE_SEV_ERROR_SYNC = 2, | ||
296 | OpalMCE_SEV_FATAL = 3, | ||
297 | }; | ||
298 | |||
299 | enum OpalMCE_Disposition { | ||
300 | OpalMCE_DISPOSITION_RECOVERED = 0, | ||
301 | OpalMCE_DISPOSITION_NOT_RECOVERED = 1, | ||
302 | }; | ||
303 | |||
304 | enum OpalMCE_Initiator { | ||
305 | OpalMCE_INITIATOR_UNKNOWN = 0, | ||
306 | OpalMCE_INITIATOR_CPU = 1, | ||
307 | }; | ||
308 | |||
309 | enum OpalMCE_ErrorType { | ||
310 | OpalMCE_ERROR_TYPE_UNKNOWN = 0, | ||
311 | OpalMCE_ERROR_TYPE_UE = 1, | ||
312 | OpalMCE_ERROR_TYPE_SLB = 2, | ||
313 | OpalMCE_ERROR_TYPE_ERAT = 3, | ||
314 | OpalMCE_ERROR_TYPE_TLB = 4, | ||
315 | }; | ||
316 | |||
317 | enum OpalMCE_UeErrorType { | ||
318 | OpalMCE_UE_ERROR_INDETERMINATE = 0, | ||
319 | OpalMCE_UE_ERROR_IFETCH = 1, | ||
320 | OpalMCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2, | ||
321 | OpalMCE_UE_ERROR_LOAD_STORE = 3, | ||
322 | OpalMCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4, | ||
323 | }; | ||
324 | |||
325 | enum OpalMCE_SlbErrorType { | ||
326 | OpalMCE_SLB_ERROR_INDETERMINATE = 0, | ||
327 | OpalMCE_SLB_ERROR_PARITY = 1, | ||
328 | OpalMCE_SLB_ERROR_MULTIHIT = 2, | ||
329 | }; | ||
330 | |||
331 | enum OpalMCE_EratErrorType { | ||
332 | OpalMCE_ERAT_ERROR_INDETERMINATE = 0, | ||
333 | OpalMCE_ERAT_ERROR_PARITY = 1, | ||
334 | OpalMCE_ERAT_ERROR_MULTIHIT = 2, | ||
335 | }; | ||
336 | |||
337 | enum OpalMCE_TlbErrorType { | ||
338 | OpalMCE_TLB_ERROR_INDETERMINATE = 0, | ||
339 | OpalMCE_TLB_ERROR_PARITY = 1, | ||
340 | OpalMCE_TLB_ERROR_MULTIHIT = 2, | ||
341 | }; | ||
342 | |||
343 | enum OpalThreadStatus { | 291 | enum OpalThreadStatus { |
344 | OPAL_THREAD_INACTIVE = 0x0, | 292 | OPAL_THREAD_INACTIVE = 0x0, |
345 | OPAL_THREAD_STARTED = 0x1, | 293 | OPAL_THREAD_STARTED = 0x1, |
@@ -452,52 +400,15 @@ struct opal_msg { | |||
452 | __be64 params[8]; | 400 | __be64 params[8]; |
453 | }; | 401 | }; |
454 | 402 | ||
455 | struct opal_machine_check_event { | 403 | enum { |
456 | enum OpalMCE_Version version:8; /* 0x00 */ | 404 | OPAL_IPMI_MSG_FORMAT_VERSION_1 = 1, |
457 | uint8_t in_use; /* 0x01 */ | 405 | }; |
458 | enum OpalMCE_Severity severity:8; /* 0x02 */ | ||
459 | enum OpalMCE_Initiator initiator:8; /* 0x03 */ | ||
460 | enum OpalMCE_ErrorType error_type:8; /* 0x04 */ | ||
461 | enum OpalMCE_Disposition disposition:8; /* 0x05 */ | ||
462 | uint8_t reserved_1[2]; /* 0x06 */ | ||
463 | uint64_t gpr3; /* 0x08 */ | ||
464 | uint64_t srr0; /* 0x10 */ | ||
465 | uint64_t srr1; /* 0x18 */ | ||
466 | union { /* 0x20 */ | ||
467 | struct { | ||
468 | enum OpalMCE_UeErrorType ue_error_type:8; | ||
469 | uint8_t effective_address_provided; | ||
470 | uint8_t physical_address_provided; | ||
471 | uint8_t reserved_1[5]; | ||
472 | uint64_t effective_address; | ||
473 | uint64_t physical_address; | ||
474 | uint8_t reserved_2[8]; | ||
475 | } ue_error; | ||
476 | |||
477 | struct { | ||
478 | enum OpalMCE_SlbErrorType slb_error_type:8; | ||
479 | uint8_t effective_address_provided; | ||
480 | uint8_t reserved_1[6]; | ||
481 | uint64_t effective_address; | ||
482 | uint8_t reserved_2[16]; | ||
483 | } slb_error; | ||
484 | |||
485 | struct { | ||
486 | enum OpalMCE_EratErrorType erat_error_type:8; | ||
487 | uint8_t effective_address_provided; | ||
488 | uint8_t reserved_1[6]; | ||
489 | uint64_t effective_address; | ||
490 | uint8_t reserved_2[16]; | ||
491 | } erat_error; | ||
492 | 406 | ||
493 | struct { | 407 | struct opal_ipmi_msg { |
494 | enum OpalMCE_TlbErrorType tlb_error_type:8; | 408 | uint8_t version; |
495 | uint8_t effective_address_provided; | 409 | uint8_t netfn; |
496 | uint8_t reserved_1[6]; | 410 | uint8_t cmd; |
497 | uint64_t effective_address; | 411 | uint8_t data[]; |
498 | uint8_t reserved_2[16]; | ||
499 | } tlb_error; | ||
500 | } u; | ||
501 | }; | 412 | }; |
502 | 413 | ||
503 | /* FSP memory errors handling */ | 414 | /* FSP memory errors handling */ |
@@ -819,6 +730,9 @@ int64_t opal_rtc_read(__be32 *year_month_day, | |||
819 | __be64 *hour_minute_second_millisecond); | 730 | __be64 *hour_minute_second_millisecond); |
820 | int64_t opal_rtc_write(uint32_t year_month_day, | 731 | int64_t opal_rtc_write(uint32_t year_month_day, |
821 | uint64_t hour_minute_second_millisecond); | 732 | uint64_t hour_minute_second_millisecond); |
733 | int64_t opal_tpo_read(uint64_t token, __be32 *year_mon_day, __be32 *hour_min); | ||
734 | int64_t opal_tpo_write(uint64_t token, uint32_t year_mon_day, | ||
735 | uint32_t hour_min); | ||
822 | int64_t opal_cec_power_down(uint64_t request); | 736 | int64_t opal_cec_power_down(uint64_t request); |
823 | int64_t opal_cec_reboot(void); | 737 | int64_t opal_cec_reboot(void); |
824 | int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset); | 738 | int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset); |
@@ -963,6 +877,10 @@ int64_t opal_handle_hmi(void); | |||
963 | int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end); | 877 | int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end); |
964 | int64_t opal_unregister_dump_region(uint32_t id); | 878 | int64_t opal_unregister_dump_region(uint32_t id); |
965 | int64_t opal_pci_set_phb_cxl_mode(uint64_t phb_id, uint64_t mode, uint64_t pe_number); | 879 | int64_t opal_pci_set_phb_cxl_mode(uint64_t phb_id, uint64_t mode, uint64_t pe_number); |
880 | int64_t opal_ipmi_send(uint64_t interface, struct opal_ipmi_msg *msg, | ||
881 | uint64_t msg_len); | ||
882 | int64_t opal_ipmi_recv(uint64_t interface, struct opal_ipmi_msg *msg, | ||
883 | uint64_t *msg_len); | ||
966 | 884 | ||
967 | /* Internal functions */ | 885 | /* Internal functions */ |
968 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, | 886 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, |
@@ -992,8 +910,6 @@ extern int opal_async_wait_response(uint64_t token, struct opal_msg *msg); | |||
992 | extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data); | 910 | extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data); |
993 | 911 | ||
994 | struct rtc_time; | 912 | struct rtc_time; |
995 | extern int opal_set_rtc_time(struct rtc_time *tm); | ||
996 | extern void opal_get_rtc_time(struct rtc_time *tm); | ||
997 | extern unsigned long opal_get_boot_time(void); | 913 | extern unsigned long opal_get_boot_time(void); |
998 | extern void opal_nvram_init(void); | 914 | extern void opal_nvram_init(void); |
999 | extern void opal_flash_init(void); | 915 | extern void opal_flash_init(void); |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index a5139ea6910b..24a386cbb928 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -42,7 +42,6 @@ extern unsigned int debug_smp_processor_id(void); /* from linux/smp.h */ | |||
42 | #define get_slb_shadow() (get_paca()->slb_shadow_ptr) | 42 | #define get_slb_shadow() (get_paca()->slb_shadow_ptr) |
43 | 43 | ||
44 | struct task_struct; | 44 | struct task_struct; |
45 | struct opal_machine_check_event; | ||
46 | 45 | ||
47 | /* | 46 | /* |
48 | * Defines the layout of the paca. | 47 | * Defines the layout of the paca. |
@@ -153,12 +152,6 @@ struct paca_struct { | |||
153 | u64 tm_scratch; /* TM scratch area for reclaim */ | 152 | u64 tm_scratch; /* TM scratch area for reclaim */ |
154 | #endif | 153 | #endif |
155 | 154 | ||
156 | #ifdef CONFIG_PPC_POWERNV | ||
157 | /* Pointer to OPAL machine check event structure set by the | ||
158 | * early exception handler for use by high level C handler | ||
159 | */ | ||
160 | struct opal_machine_check_event *opal_mc_evt; | ||
161 | #endif | ||
162 | #ifdef CONFIG_PPC_BOOK3S_64 | 155 | #ifdef CONFIG_PPC_BOOK3S_64 |
163 | /* Exclusive emergency stack pointer for machine check exception. */ | 156 | /* Exclusive emergency stack pointer for machine check exception. */ |
164 | void *mc_emergency_sp; | 157 | void *mc_emergency_sp; |
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index 26fe1ae15212..69c059887a2c 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h | |||
@@ -379,12 +379,14 @@ static inline int hugepd_ok(hugepd_t hpd) | |||
379 | } | 379 | } |
380 | #endif | 380 | #endif |
381 | 381 | ||
382 | #define is_hugepd(pdep) (hugepd_ok(*((hugepd_t *)(pdep)))) | 382 | #define is_hugepd(hpd) (hugepd_ok(hpd)) |
383 | #define pgd_huge pgd_huge | ||
383 | int pgd_huge(pgd_t pgd); | 384 | int pgd_huge(pgd_t pgd); |
384 | #else /* CONFIG_HUGETLB_PAGE */ | 385 | #else /* CONFIG_HUGETLB_PAGE */ |
385 | #define is_hugepd(pdep) 0 | 386 | #define is_hugepd(pdep) 0 |
386 | #define pgd_huge(pgd) 0 | 387 | #define pgd_huge(pgd) 0 |
387 | #endif /* CONFIG_HUGETLB_PAGE */ | 388 | #endif /* CONFIG_HUGETLB_PAGE */ |
389 | #define __hugepd(x) ((hugepd_t) { (x) }) | ||
388 | 390 | ||
389 | struct page; | 391 | struct page; |
390 | extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); | 392 | extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); |
diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h index 945e47adf7db..234e07c47803 100644 --- a/arch/powerpc/include/asm/pgtable-ppc32.h +++ b/arch/powerpc/include/asm/pgtable-ppc32.h | |||
@@ -170,6 +170,25 @@ static inline unsigned long pte_update(pte_t *p, | |||
170 | #ifdef PTE_ATOMIC_UPDATES | 170 | #ifdef PTE_ATOMIC_UPDATES |
171 | unsigned long old, tmp; | 171 | unsigned long old, tmp; |
172 | 172 | ||
173 | #ifdef CONFIG_PPC_8xx | ||
174 | unsigned long tmp2; | ||
175 | |||
176 | __asm__ __volatile__("\ | ||
177 | 1: lwarx %0,0,%4\n\ | ||
178 | andc %1,%0,%5\n\ | ||
179 | or %1,%1,%6\n\ | ||
180 | /* 0x200 == Extended encoding, bit 22 */ \ | ||
181 | /* Bit 22 has to be 1 if neither _PAGE_USER nor _PAGE_RW are set */ \ | ||
182 | rlwimi %1,%1,32-2,0x200\n /* get _PAGE_USER */ \ | ||
183 | rlwinm %3,%1,32-1,0x200\n /* get _PAGE_RW */ \ | ||
184 | or %1,%3,%1\n\ | ||
185 | xori %1,%1,0x200\n" | ||
186 | " stwcx. %1,0,%4\n\ | ||
187 | bne- 1b" | ||
188 | : "=&r" (old), "=&r" (tmp), "=m" (*p), "=&r" (tmp2) | ||
189 | : "r" (p), "r" (clr), "r" (set), "m" (*p) | ||
190 | : "cc" ); | ||
191 | #else /* CONFIG_PPC_8xx */ | ||
173 | __asm__ __volatile__("\ | 192 | __asm__ __volatile__("\ |
174 | 1: lwarx %0,0,%3\n\ | 193 | 1: lwarx %0,0,%3\n\ |
175 | andc %1,%0,%4\n\ | 194 | andc %1,%0,%4\n\ |
@@ -180,6 +199,7 @@ static inline unsigned long pte_update(pte_t *p, | |||
180 | : "=&r" (old), "=&r" (tmp), "=m" (*p) | 199 | : "=&r" (old), "=&r" (tmp), "=m" (*p) |
181 | : "r" (p), "r" (clr), "r" (set), "m" (*p) | 200 | : "r" (p), "r" (clr), "r" (set), "m" (*p) |
182 | : "cc" ); | 201 | : "cc" ); |
202 | #endif /* CONFIG_PPC_8xx */ | ||
183 | #else /* PTE_ATOMIC_UPDATES */ | 203 | #else /* PTE_ATOMIC_UPDATES */ |
184 | unsigned long old = pte_val(*p); | 204 | unsigned long old = pte_val(*p); |
185 | *p = __pte((old & ~clr) | set); | 205 | *p = __pte((old & ~clr) | set); |
diff --git a/arch/powerpc/include/asm/pgtable-ppc64-4k.h b/arch/powerpc/include/asm/pgtable-ppc64-4k.h index 7b935683f268..132ee1d482c2 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64-4k.h +++ b/arch/powerpc/include/asm/pgtable-ppc64-4k.h | |||
@@ -57,7 +57,21 @@ | |||
57 | #define pgd_present(pgd) (pgd_val(pgd) != 0) | 57 | #define pgd_present(pgd) (pgd_val(pgd) != 0) |
58 | #define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0) | 58 | #define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0) |
59 | #define pgd_page_vaddr(pgd) (pgd_val(pgd) & ~PGD_MASKED_BITS) | 59 | #define pgd_page_vaddr(pgd) (pgd_val(pgd) & ~PGD_MASKED_BITS) |
60 | #define pgd_page(pgd) virt_to_page(pgd_page_vaddr(pgd)) | 60 | |
61 | #ifndef __ASSEMBLY__ | ||
62 | |||
63 | static inline pte_t pgd_pte(pgd_t pgd) | ||
64 | { | ||
65 | return __pte(pgd_val(pgd)); | ||
66 | } | ||
67 | |||
68 | static inline pgd_t pte_pgd(pte_t pte) | ||
69 | { | ||
70 | return __pgd(pte_val(pte)); | ||
71 | } | ||
72 | extern struct page *pgd_page(pgd_t pgd); | ||
73 | |||
74 | #endif /* !__ASSEMBLY__ */ | ||
61 | 75 | ||
62 | #define pud_offset(pgdp, addr) \ | 76 | #define pud_offset(pgdp, addr) \ |
63 | (((pud_t *) pgd_page_vaddr(*(pgdp))) + \ | 77 | (((pud_t *) pgd_page_vaddr(*(pgdp))) + \ |
diff --git a/arch/powerpc/include/asm/pgtable-ppc64-64k.h b/arch/powerpc/include/asm/pgtable-ppc64-64k.h index a56b82fb0609..1de35bbd02a6 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64-64k.h +++ b/arch/powerpc/include/asm/pgtable-ppc64-64k.h | |||
@@ -38,4 +38,7 @@ | |||
38 | /* Bits to mask out from a PGD/PUD to get to the PMD page */ | 38 | /* Bits to mask out from a PGD/PUD to get to the PMD page */ |
39 | #define PUD_MASKED_BITS 0x1ff | 39 | #define PUD_MASKED_BITS 0x1ff |
40 | 40 | ||
41 | #define pgd_pte(pgd) (pud_pte(((pud_t){ pgd }))) | ||
42 | #define pte_pgd(pte) ((pgd_t)pte_pud(pte)) | ||
43 | |||
41 | #endif /* _ASM_POWERPC_PGTABLE_PPC64_64K_H */ | 44 | #endif /* _ASM_POWERPC_PGTABLE_PPC64_64K_H */ |
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index 9b4b1904efae..b9dcc936e2d1 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h | |||
@@ -152,7 +152,7 @@ | |||
152 | #define pmd_none(pmd) (!pmd_val(pmd)) | 152 | #define pmd_none(pmd) (!pmd_val(pmd)) |
153 | #define pmd_bad(pmd) (!is_kernel_addr(pmd_val(pmd)) \ | 153 | #define pmd_bad(pmd) (!is_kernel_addr(pmd_val(pmd)) \ |
154 | || (pmd_val(pmd) & PMD_BAD_BITS)) | 154 | || (pmd_val(pmd) & PMD_BAD_BITS)) |
155 | #define pmd_present(pmd) (pmd_val(pmd) != 0) | 155 | #define pmd_present(pmd) (!pmd_none(pmd)) |
156 | #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) | 156 | #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) |
157 | #define pmd_page_vaddr(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS) | 157 | #define pmd_page_vaddr(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS) |
158 | extern struct page *pmd_page(pmd_t pmd); | 158 | extern struct page *pmd_page(pmd_t pmd); |
@@ -164,9 +164,21 @@ extern struct page *pmd_page(pmd_t pmd); | |||
164 | #define pud_present(pud) (pud_val(pud) != 0) | 164 | #define pud_present(pud) (pud_val(pud) != 0) |
165 | #define pud_clear(pudp) (pud_val(*(pudp)) = 0) | 165 | #define pud_clear(pudp) (pud_val(*(pudp)) = 0) |
166 | #define pud_page_vaddr(pud) (pud_val(pud) & ~PUD_MASKED_BITS) | 166 | #define pud_page_vaddr(pud) (pud_val(pud) & ~PUD_MASKED_BITS) |
167 | #define pud_page(pud) virt_to_page(pud_page_vaddr(pud)) | ||
168 | 167 | ||
168 | extern struct page *pud_page(pud_t pud); | ||
169 | |||
170 | static inline pte_t pud_pte(pud_t pud) | ||
171 | { | ||
172 | return __pte(pud_val(pud)); | ||
173 | } | ||
174 | |||
175 | static inline pud_t pte_pud(pte_t pte) | ||
176 | { | ||
177 | return __pud(pte_val(pte)); | ||
178 | } | ||
179 | #define pud_write(pud) pte_write(pud_pte(pud)) | ||
169 | #define pgd_set(pgdp, pudp) ({pgd_val(*(pgdp)) = (unsigned long)(pudp);}) | 180 | #define pgd_set(pgdp, pudp) ({pgd_val(*(pgdp)) = (unsigned long)(pudp);}) |
181 | #define pgd_write(pgd) pte_write(pgd_pte(pgd)) | ||
170 | 182 | ||
171 | /* | 183 | /* |
172 | * Find an entry in a page-table-directory. We combine the address region | 184 | * Find an entry in a page-table-directory. We combine the address region |
@@ -422,7 +434,22 @@ extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
422 | pmd_t *pmdp, pmd_t pmd); | 434 | pmd_t *pmdp, pmd_t pmd); |
423 | extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, | 435 | extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, |
424 | pmd_t *pmd); | 436 | pmd_t *pmd); |
425 | 437 | /* | |
438 | * | ||
439 | * For core kernel code by design pmd_trans_huge is never run on any hugetlbfs | ||
440 | * page. The hugetlbfs page table walking and mangling paths are totally | ||
441 | * separated form the core VM paths and they're differentiated by | ||
442 | * VM_HUGETLB being set on vm_flags well before any pmd_trans_huge could run. | ||
443 | * | ||
444 | * pmd_trans_huge() is defined as false at build time if | ||
445 | * CONFIG_TRANSPARENT_HUGEPAGE=n to optimize away code blocks at build | ||
446 | * time in such case. | ||
447 | * | ||
448 | * For ppc64 we need to differntiate from explicit hugepages from THP, because | ||
449 | * for THP we also track the subpage details at the pmd level. We don't do | ||
450 | * that for explicit huge pages. | ||
451 | * | ||
452 | */ | ||
426 | static inline int pmd_trans_huge(pmd_t pmd) | 453 | static inline int pmd_trans_huge(pmd_t pmd) |
427 | { | 454 | { |
428 | /* | 455 | /* |
@@ -431,16 +458,6 @@ static inline int pmd_trans_huge(pmd_t pmd) | |||
431 | return (pmd_val(pmd) & 0x3) && (pmd_val(pmd) & _PAGE_THP_HUGE); | 458 | return (pmd_val(pmd) & 0x3) && (pmd_val(pmd) & _PAGE_THP_HUGE); |
432 | } | 459 | } |
433 | 460 | ||
434 | static inline int pmd_large(pmd_t pmd) | ||
435 | { | ||
436 | /* | ||
437 | * leaf pte for huge page, bottom two bits != 00 | ||
438 | */ | ||
439 | if (pmd_trans_huge(pmd)) | ||
440 | return pmd_val(pmd) & _PAGE_PRESENT; | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static inline int pmd_trans_splitting(pmd_t pmd) | 461 | static inline int pmd_trans_splitting(pmd_t pmd) |
445 | { | 462 | { |
446 | if (pmd_trans_huge(pmd)) | 463 | if (pmd_trans_huge(pmd)) |
@@ -451,6 +468,14 @@ static inline int pmd_trans_splitting(pmd_t pmd) | |||
451 | extern int has_transparent_hugepage(void); | 468 | extern int has_transparent_hugepage(void); |
452 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | 469 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
453 | 470 | ||
471 | static inline int pmd_large(pmd_t pmd) | ||
472 | { | ||
473 | /* | ||
474 | * leaf pte for huge page, bottom two bits != 00 | ||
475 | */ | ||
476 | return ((pmd_val(pmd) & 0x3) != 0x0); | ||
477 | } | ||
478 | |||
454 | static inline pte_t pmd_pte(pmd_t pmd) | 479 | static inline pte_t pmd_pte(pmd_t pmd) |
455 | { | 480 | { |
456 | return __pte(pmd_val(pmd)); | 481 | return __pte(pmd_val(pmd)); |
@@ -576,6 +601,5 @@ static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl, | |||
576 | */ | 601 | */ |
577 | return true; | 602 | return true; |
578 | } | 603 | } |
579 | |||
580 | #endif /* __ASSEMBLY__ */ | 604 | #endif /* __ASSEMBLY__ */ |
581 | #endif /* _ASM_POWERPC_PGTABLE_PPC64_H_ */ | 605 | #endif /* _ASM_POWERPC_PGTABLE_PPC64_H_ */ |
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 316f9a5da173..a8805fee0df9 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h | |||
@@ -274,11 +274,9 @@ extern void paging_init(void); | |||
274 | */ | 274 | */ |
275 | extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); | 275 | extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); |
276 | 276 | ||
277 | extern int gup_hugepd(hugepd_t *hugepd, unsigned pdshift, unsigned long addr, | ||
278 | unsigned long end, int write, struct page **pages, int *nr); | ||
279 | |||
280 | extern int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, | 277 | extern int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, |
281 | unsigned long end, int write, struct page **pages, int *nr); | 278 | unsigned long end, int write, |
279 | struct page **pages, int *nr); | ||
282 | #ifndef CONFIG_TRANSPARENT_HUGEPAGE | 280 | #ifndef CONFIG_TRANSPARENT_HUGEPAGE |
283 | #define pmd_large(pmd) 0 | 281 | #define pmd_large(pmd) 0 |
284 | #define has_transparent_hugepage() 0 | 282 | #define has_transparent_hugepage() 0 |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index dda7ac4c80bd..29c3798cf800 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -451,7 +451,7 @@ extern unsigned long cpuidle_disable; | |||
451 | enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF}; | 451 | enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF}; |
452 | 452 | ||
453 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ | 453 | extern int powersave_nap; /* set if nap mode can be used in idle loop */ |
454 | extern void power7_nap(int check_irq); | 454 | extern unsigned long power7_nap(int check_irq); |
455 | extern void power7_sleep(void); | 455 | extern void power7_sleep(void); |
456 | extern void flush_instruction_cache(void); | 456 | extern void flush_instruction_cache(void); |
457 | extern void hard_reset_now(void); | 457 | extern void hard_reset_now(void); |
diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h index d44826e4ff97..daa4616e61c4 100644 --- a/arch/powerpc/include/asm/pte-8xx.h +++ b/arch/powerpc/include/asm/pte-8xx.h | |||
@@ -48,19 +48,22 @@ | |||
48 | */ | 48 | */ |
49 | #define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */ | 49 | #define _PAGE_RW 0x0400 /* lsb PP bits, inverted in HW */ |
50 | #define _PAGE_USER 0x0800 /* msb PP bits */ | 50 | #define _PAGE_USER 0x0800 /* msb PP bits */ |
51 | /* set when neither _PAGE_USER nor _PAGE_RW are set */ | ||
52 | #define _PAGE_KNLRO 0x0200 | ||
51 | 53 | ||
52 | #define _PMD_PRESENT 0x0001 | 54 | #define _PMD_PRESENT 0x0001 |
53 | #define _PMD_BAD 0x0ff0 | 55 | #define _PMD_BAD 0x0ff0 |
54 | #define _PMD_PAGE_MASK 0x000c | 56 | #define _PMD_PAGE_MASK 0x000c |
55 | #define _PMD_PAGE_8M 0x000c | 57 | #define _PMD_PAGE_8M 0x000c |
56 | 58 | ||
57 | #define _PTE_NONE_MASK _PAGE_ACCESSED | 59 | #define _PTE_NONE_MASK _PAGE_KNLRO |
58 | 60 | ||
59 | /* Until my rework is finished, 8xx still needs atomic PTE updates */ | 61 | /* Until my rework is finished, 8xx still needs atomic PTE updates */ |
60 | #define PTE_ATOMIC_UPDATES 1 | 62 | #define PTE_ATOMIC_UPDATES 1 |
61 | 63 | ||
62 | /* We need to add _PAGE_SHARED to kernel pages */ | 64 | /* We need to add _PAGE_SHARED to kernel pages */ |
63 | #define _PAGE_KERNEL_RO (_PAGE_SHARED) | 65 | #define _PAGE_KERNEL_RO (_PAGE_SHARED | _PAGE_KNLRO) |
66 | #define _PAGE_KERNEL_ROX (_PAGE_EXEC | _PAGE_KNLRO) | ||
64 | #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE) | 67 | #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE) |
65 | 68 | ||
66 | #endif /* __KERNEL__ */ | 69 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h index 11ba86e17631..fbdf18cf954c 100644 --- a/arch/powerpc/include/asm/setup.h +++ b/arch/powerpc/include/asm/setup.h | |||
@@ -8,7 +8,6 @@ extern void ppc_printk_progress(char *s, unsigned short hex); | |||
8 | 8 | ||
9 | extern unsigned int rtas_data; | 9 | extern unsigned int rtas_data; |
10 | extern int mem_init_done; /* set on boot once kmalloc can be called */ | 10 | extern int mem_init_done; /* set on boot once kmalloc can be called */ |
11 | extern int init_bootmem_done; /* set once bootmem is available */ | ||
12 | extern unsigned long long memory_limit; | 11 | extern unsigned long long memory_limit; |
13 | extern unsigned long klimit; | 12 | extern unsigned long klimit; |
14 | extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); | 13 | extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); |
@@ -24,7 +23,7 @@ extern void reloc_got2(unsigned long); | |||
24 | #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x))) | 23 | #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x))) |
25 | 24 | ||
26 | void check_for_initrd(void); | 25 | void check_for_initrd(void); |
27 | void do_init_bootmem(void); | 26 | void initmem_init(void); |
28 | void setup_panic(void); | 27 | void setup_panic(void); |
29 | #define ARCH_PANIC_TIMEOUT 180 | 28 | #define ARCH_PANIC_TIMEOUT 180 |
30 | 29 | ||
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index b034ecdb7c74..ebc4f165690a 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h | |||
@@ -71,13 +71,12 @@ struct thread_info { | |||
71 | #define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT) | 71 | #define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT) |
72 | 72 | ||
73 | /* how to get the thread information struct from C */ | 73 | /* how to get the thread information struct from C */ |
74 | register unsigned long __current_r1 asm("r1"); | ||
74 | static inline struct thread_info *current_thread_info(void) | 75 | static inline struct thread_info *current_thread_info(void) |
75 | { | 76 | { |
76 | register unsigned long sp asm("r1"); | ||
77 | |||
78 | /* gcc4, at least, is smart enough to turn this into a single | 77 | /* gcc4, at least, is smart enough to turn this into a single |
79 | * rlwinm for ppc32 and clrrdi for ppc64 */ | 78 | * rlwinm for ppc32 and clrrdi for ppc64 */ |
80 | return (struct thread_info *)(sp & ~(THREAD_SIZE-1)); | 79 | return (struct thread_info *)(__current_r1 & ~(THREAD_SIZE-1)); |
81 | } | 80 | } |
82 | 81 | ||
83 | #endif /* __ASSEMBLY__ */ | 82 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h index 2def01ed0cb2..23d351ca0303 100644 --- a/arch/powerpc/include/asm/tlbflush.h +++ b/arch/powerpc/include/asm/tlbflush.h | |||
@@ -107,14 +107,14 @@ extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch); | |||
107 | 107 | ||
108 | static inline void arch_enter_lazy_mmu_mode(void) | 108 | static inline void arch_enter_lazy_mmu_mode(void) |
109 | { | 109 | { |
110 | struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); | 110 | struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); |
111 | 111 | ||
112 | batch->active = 1; | 112 | batch->active = 1; |
113 | } | 113 | } |
114 | 114 | ||
115 | static inline void arch_leave_lazy_mmu_mode(void) | 115 | static inline void arch_leave_lazy_mmu_mode(void) |
116 | { | 116 | { |
117 | struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); | 117 | struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); |
118 | 118 | ||
119 | if (batch->index) | 119 | if (batch->index) |
120 | __flush_tlb_pending(batch); | 120 | __flush_tlb_pending(batch); |
@@ -125,9 +125,11 @@ static inline void arch_leave_lazy_mmu_mode(void) | |||
125 | 125 | ||
126 | 126 | ||
127 | extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, | 127 | extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, |
128 | int ssize, int local); | 128 | int ssize, unsigned long flags); |
129 | extern void flush_hash_range(unsigned long number, int local); | 129 | extern void flush_hash_range(unsigned long number, int local); |
130 | 130 | extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr, | |
131 | pmd_t *pmdp, unsigned int psize, int ssize, | ||
132 | unsigned long flags); | ||
131 | 133 | ||
132 | static inline void local_flush_tlb_mm(struct mm_struct *mm) | 134 | static inline void local_flush_tlb_mm(struct mm_struct *mm) |
133 | { | 135 | { |
diff --git a/arch/powerpc/include/asm/vga.h b/arch/powerpc/include/asm/vga.h index a2eac409c1ec..e5f8dd366212 100644 --- a/arch/powerpc/include/asm/vga.h +++ b/arch/powerpc/include/asm/vga.h | |||
@@ -38,12 +38,10 @@ static inline u16 scr_readw(volatile const u16 *addr) | |||
38 | 38 | ||
39 | #endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */ | 39 | #endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */ |
40 | 40 | ||
41 | extern unsigned long vgacon_remap_base; | ||
42 | |||
43 | #ifdef __powerpc64__ | 41 | #ifdef __powerpc64__ |
44 | #define VGA_MAP_MEM(x,s) ((unsigned long) ioremap((x), s)) | 42 | #define VGA_MAP_MEM(x,s) ((unsigned long) ioremap((x), s)) |
45 | #else | 43 | #else |
46 | #define VGA_MAP_MEM(x,s) (x + vgacon_remap_base) | 44 | #define VGA_MAP_MEM(x,s) (x) |
47 | #endif | 45 | #endif |
48 | 46 | ||
49 | #define vga_readb(x) (*(x)) | 47 | #define vga_readb(x) (*(x)) |
diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h index 0d050ea37a04..6997f4a271df 100644 --- a/arch/powerpc/include/asm/xics.h +++ b/arch/powerpc/include/asm/xics.h | |||
@@ -98,7 +98,7 @@ DECLARE_PER_CPU(struct xics_cppr, xics_cppr); | |||
98 | 98 | ||
99 | static inline void xics_push_cppr(unsigned int vec) | 99 | static inline void xics_push_cppr(unsigned int vec) |
100 | { | 100 | { |
101 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | 101 | struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr); |
102 | 102 | ||
103 | if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1)) | 103 | if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1)) |
104 | return; | 104 | return; |
@@ -111,7 +111,7 @@ static inline void xics_push_cppr(unsigned int vec) | |||
111 | 111 | ||
112 | static inline unsigned char xics_pop_cppr(void) | 112 | static inline unsigned char xics_pop_cppr(void) |
113 | { | 113 | { |
114 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | 114 | struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr); |
115 | 115 | ||
116 | if (WARN_ON(os_cppr->index < 1)) | 116 | if (WARN_ON(os_cppr->index < 1)) |
117 | return LOWEST_PRIORITY; | 117 | return LOWEST_PRIORITY; |
@@ -121,7 +121,7 @@ static inline unsigned char xics_pop_cppr(void) | |||
121 | 121 | ||
122 | static inline void xics_set_base_cppr(unsigned char cppr) | 122 | static inline void xics_set_base_cppr(unsigned char cppr) |
123 | { | 123 | { |
124 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | 124 | struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr); |
125 | 125 | ||
126 | /* we only really want to set the priority when there's | 126 | /* we only really want to set the priority when there's |
127 | * just one cppr value on the stack | 127 | * just one cppr value on the stack |
@@ -133,7 +133,7 @@ static inline void xics_set_base_cppr(unsigned char cppr) | |||
133 | 133 | ||
134 | static inline unsigned char xics_cppr_top(void) | 134 | static inline unsigned char xics_cppr_top(void) |
135 | { | 135 | { |
136 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | 136 | struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr); |
137 | 137 | ||
138 | return os_cppr->stack[os_cppr->index]; | 138 | return os_cppr->stack[os_cppr->index]; |
139 | } | 139 | } |
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 34f55524d456..86150fbb42c3 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -908,7 +908,7 @@ int fix_alignment(struct pt_regs *regs) | |||
908 | flush_fp_to_thread(current); | 908 | flush_fp_to_thread(current); |
909 | } | 909 | } |
910 | 910 | ||
911 | if ((nb == 16)) { | 911 | if (nb == 16) { |
912 | if (flags & F) { | 912 | if (flags & F) { |
913 | /* Special case for 16-byte FP loads and stores */ | 913 | /* Special case for 16-byte FP loads and stores */ |
914 | PPC_WARN_ALIGNMENT(fp_pair, regs); | 914 | PPC_WARN_ALIGNMENT(fp_pair, regs); |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 9d7dede2847c..c161ef3f28a1 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -726,12 +726,5 @@ int main(void) | |||
726 | arch.timing_last_enter.tv32.tbl)); | 726 | arch.timing_last_enter.tv32.tbl)); |
727 | #endif | 727 | #endif |
728 | 728 | ||
729 | #ifdef CONFIG_PPC_POWERNV | ||
730 | DEFINE(OPAL_MC_GPR3, offsetof(struct opal_machine_check_event, gpr3)); | ||
731 | DEFINE(OPAL_MC_SRR0, offsetof(struct opal_machine_check_event, srr0)); | ||
732 | DEFINE(OPAL_MC_SRR1, offsetof(struct opal_machine_check_event, srr1)); | ||
733 | DEFINE(PACA_OPAL_MC_EVT, offsetof(struct paca_struct, opal_mc_evt)); | ||
734 | #endif | ||
735 | |||
736 | return 0; | 729 | return 0; |
737 | } | 730 | } |
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index c78e6dac4d7d..cfa0f81a5bb0 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #undef DEBUG | 12 | #undef DEBUG |
13 | 13 | ||
14 | #include <linux/crash_dump.h> | 14 | #include <linux/crash_dump.h> |
15 | #include <linux/bootmem.h> | ||
16 | #include <linux/io.h> | 15 | #include <linux/io.h> |
17 | #include <linux/memblock.h> | 16 | #include <linux/memblock.h> |
18 | #include <asm/code-patching.h> | 17 | #include <asm/code-patching.h> |
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c index d55c76c571f3..f4217819cc31 100644 --- a/arch/powerpc/kernel/dbell.c +++ b/arch/powerpc/kernel/dbell.c | |||
@@ -41,7 +41,7 @@ void doorbell_exception(struct pt_regs *regs) | |||
41 | 41 | ||
42 | may_hard_irq_enable(); | 42 | may_hard_irq_enable(); |
43 | 43 | ||
44 | __get_cpu_var(irq_stat).doorbell_irqs++; | 44 | __this_cpu_inc(irq_stat.doorbell_irqs); |
45 | 45 | ||
46 | smp_ipi_demux(); | 46 | smp_ipi_demux(); |
47 | 47 | ||
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 2248a1999c64..e1b6d8e17289 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
@@ -143,6 +143,8 @@ static int __init eeh_setup(char *str) | |||
143 | { | 143 | { |
144 | if (!strcmp(str, "off")) | 144 | if (!strcmp(str, "off")) |
145 | eeh_add_flag(EEH_FORCE_DISABLED); | 145 | eeh_add_flag(EEH_FORCE_DISABLED); |
146 | else if (!strcmp(str, "early_log")) | ||
147 | eeh_add_flag(EEH_EARLY_DUMP_LOG); | ||
146 | 148 | ||
147 | return 1; | 149 | return 1; |
148 | } | 150 | } |
@@ -758,30 +760,41 @@ static void eeh_reset_pe_once(struct eeh_pe *pe) | |||
758 | int eeh_reset_pe(struct eeh_pe *pe) | 760 | int eeh_reset_pe(struct eeh_pe *pe) |
759 | { | 761 | { |
760 | int flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE); | 762 | int flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE); |
761 | int i, rc; | 763 | int i, state, ret; |
764 | |||
765 | /* Mark as reset and block config space */ | ||
766 | eeh_pe_state_mark(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED); | ||
762 | 767 | ||
763 | /* Take three shots at resetting the bus */ | 768 | /* Take three shots at resetting the bus */ |
764 | for (i=0; i<3; i++) { | 769 | for (i = 0; i < 3; i++) { |
765 | eeh_reset_pe_once(pe); | 770 | eeh_reset_pe_once(pe); |
766 | 771 | ||
767 | /* | 772 | /* |
768 | * EEH_PE_ISOLATED is expected to be removed after | 773 | * EEH_PE_ISOLATED is expected to be removed after |
769 | * BAR restore. | 774 | * BAR restore. |
770 | */ | 775 | */ |
771 | rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); | 776 | state = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); |
772 | if ((rc & flags) == flags) | 777 | if ((state & flags) == flags) { |
773 | return 0; | 778 | ret = 0; |
779 | goto out; | ||
780 | } | ||
774 | 781 | ||
775 | if (rc < 0) { | 782 | if (state < 0) { |
776 | pr_err("%s: Unrecoverable slot failure on PHB#%d-PE#%x", | 783 | pr_warn("%s: Unrecoverable slot failure on PHB#%d-PE#%x", |
777 | __func__, pe->phb->global_number, pe->addr); | 784 | __func__, pe->phb->global_number, pe->addr); |
778 | return -1; | 785 | ret = -ENOTRECOVERABLE; |
786 | goto out; | ||
779 | } | 787 | } |
780 | pr_err("EEH: bus reset %d failed on PHB#%d-PE#%x, rc=%d\n", | 788 | |
781 | i+1, pe->phb->global_number, pe->addr, rc); | 789 | /* We might run out of credits */ |
790 | ret = -EIO; | ||
791 | pr_warn("%s: Failure %d resetting PHB#%x-PE#%x\n (%d)\n", | ||
792 | __func__, state, pe->phb->global_number, pe->addr, (i + 1)); | ||
782 | } | 793 | } |
783 | 794 | ||
784 | return -1; | 795 | out: |
796 | eeh_pe_state_clear(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED); | ||
797 | return ret; | ||
785 | } | 798 | } |
786 | 799 | ||
787 | /** | 800 | /** |
@@ -920,11 +933,8 @@ int eeh_init(void) | |||
920 | pr_warn("%s: Platform EEH operation not found\n", | 933 | pr_warn("%s: Platform EEH operation not found\n", |
921 | __func__); | 934 | __func__); |
922 | return -EEXIST; | 935 | return -EEXIST; |
923 | } else if ((ret = eeh_ops->init())) { | 936 | } else if ((ret = eeh_ops->init())) |
924 | pr_warn("%s: Failed to call platform init function (%d)\n", | ||
925 | __func__, ret); | ||
926 | return ret; | 937 | return ret; |
927 | } | ||
928 | 938 | ||
929 | /* Initialize EEH event */ | 939 | /* Initialize EEH event */ |
930 | ret = eeh_event_init(); | 940 | ret = eeh_event_init(); |
@@ -1209,6 +1219,7 @@ int eeh_unfreeze_pe(struct eeh_pe *pe, bool sw_state) | |||
1209 | static struct pci_device_id eeh_reset_ids[] = { | 1219 | static struct pci_device_id eeh_reset_ids[] = { |
1210 | { PCI_DEVICE(0x19a2, 0x0710) }, /* Emulex, BE */ | 1220 | { PCI_DEVICE(0x19a2, 0x0710) }, /* Emulex, BE */ |
1211 | { PCI_DEVICE(0x10df, 0xe220) }, /* Emulex, Lancer */ | 1221 | { PCI_DEVICE(0x10df, 0xe220) }, /* Emulex, Lancer */ |
1222 | { PCI_DEVICE(0x14e4, 0x1657) }, /* Broadcom BCM5719 */ | ||
1212 | { 0 } | 1223 | { 0 } |
1213 | }; | 1224 | }; |
1214 | 1225 | ||
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 6535936bdf27..b17e793ba67e 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
@@ -528,13 +528,11 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe) | |||
528 | eeh_pe_dev_traverse(pe, eeh_report_error, &result); | 528 | eeh_pe_dev_traverse(pe, eeh_report_error, &result); |
529 | 529 | ||
530 | /* Issue reset */ | 530 | /* Issue reset */ |
531 | eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED); | ||
532 | ret = eeh_reset_pe(pe); | 531 | ret = eeh_reset_pe(pe); |
533 | if (ret) { | 532 | if (ret) { |
534 | eeh_pe_state_clear(pe, EEH_PE_RECOVERING | EEH_PE_CFG_BLOCKED); | 533 | eeh_pe_state_clear(pe, EEH_PE_RECOVERING); |
535 | return ret; | 534 | return ret; |
536 | } | 535 | } |
537 | eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED); | ||
538 | 536 | ||
539 | /* Unfreeze the PE */ | 537 | /* Unfreeze the PE */ |
540 | ret = eeh_clear_pe_frozen_state(pe, true); | 538 | ret = eeh_clear_pe_frozen_state(pe, true); |
@@ -601,19 +599,15 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) | |||
601 | * config accesses. So we prefer to block them. However, controlled | 599 | * config accesses. So we prefer to block them. However, controlled |
602 | * PCI config accesses initiated from EEH itself are allowed. | 600 | * PCI config accesses initiated from EEH itself are allowed. |
603 | */ | 601 | */ |
604 | eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED); | ||
605 | rc = eeh_reset_pe(pe); | 602 | rc = eeh_reset_pe(pe); |
606 | if (rc) { | 603 | if (rc) |
607 | eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED); | ||
608 | return rc; | 604 | return rc; |
609 | } | ||
610 | 605 | ||
611 | pci_lock_rescan_remove(); | 606 | pci_lock_rescan_remove(); |
612 | 607 | ||
613 | /* Restore PE */ | 608 | /* Restore PE */ |
614 | eeh_ops->configure_bridge(pe); | 609 | eeh_ops->configure_bridge(pe); |
615 | eeh_pe_restore_bars(pe); | 610 | eeh_pe_restore_bars(pe); |
616 | eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED); | ||
617 | 611 | ||
618 | /* Clear frozen state */ | 612 | /* Clear frozen state */ |
619 | rc = eeh_clear_pe_frozen_state(pe, false); | 613 | rc = eeh_clear_pe_frozen_state(pe, false); |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 22b45a4955cd..10a093579191 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -1424,12 +1424,18 @@ _GLOBAL(ftrace_graph_caller) | |||
1424 | lwz r4, 44(r1) | 1424 | lwz r4, 44(r1) |
1425 | subi r4, r4, MCOUNT_INSN_SIZE | 1425 | subi r4, r4, MCOUNT_INSN_SIZE |
1426 | 1426 | ||
1427 | /* get the parent address */ | 1427 | /* Grab the LR out of the caller stack frame */ |
1428 | addi r3, r1, 52 | 1428 | lwz r3,52(r1) |
1429 | 1429 | ||
1430 | bl prepare_ftrace_return | 1430 | bl prepare_ftrace_return |
1431 | nop | 1431 | nop |
1432 | 1432 | ||
1433 | /* | ||
1434 | * prepare_ftrace_return gives us the address we divert to. | ||
1435 | * Change the LR in the callers stack frame to this. | ||
1436 | */ | ||
1437 | stw r3,52(r1) | ||
1438 | |||
1433 | MCOUNT_RESTORE_FRAME | 1439 | MCOUNT_RESTORE_FRAME |
1434 | /* old link register ends up in ctr reg */ | 1440 | /* old link register ends up in ctr reg */ |
1435 | bctr | 1441 | bctr |
@@ -1457,4 +1463,4 @@ _GLOBAL(return_to_handler) | |||
1457 | blr | 1463 | blr |
1458 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 1464 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
1459 | 1465 | ||
1460 | #endif /* CONFIG_MCOUNT */ | 1466 | #endif /* CONFIG_FUNCTION_TRACER */ |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 0905c8da90f1..194e46dcf08d 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -1227,13 +1227,20 @@ _GLOBAL(ftrace_graph_caller) | |||
1227 | ld r4, 128(r1) | 1227 | ld r4, 128(r1) |
1228 | subi r4, r4, MCOUNT_INSN_SIZE | 1228 | subi r4, r4, MCOUNT_INSN_SIZE |
1229 | 1229 | ||
1230 | /* get the parent address */ | 1230 | /* Grab the LR out of the caller stack frame */ |
1231 | ld r11, 112(r1) | 1231 | ld r11, 112(r1) |
1232 | addi r3, r11, 16 | 1232 | ld r3, 16(r11) |
1233 | 1233 | ||
1234 | bl prepare_ftrace_return | 1234 | bl prepare_ftrace_return |
1235 | nop | 1235 | nop |
1236 | 1236 | ||
1237 | /* | ||
1238 | * prepare_ftrace_return gives us the address we divert to. | ||
1239 | * Change the LR in the callers stack frame to this. | ||
1240 | */ | ||
1241 | ld r11, 112(r1) | ||
1242 | std r3, 16(r11) | ||
1243 | |||
1237 | ld r0, 128(r1) | 1244 | ld r0, 128(r1) |
1238 | mtlr r0 | 1245 | mtlr r0 |
1239 | addi r1, r1, 112 | 1246 | addi r1, r1, 112 |
@@ -1241,28 +1248,6 @@ _GLOBAL(ftrace_graph_caller) | |||
1241 | 1248 | ||
1242 | _GLOBAL(return_to_handler) | 1249 | _GLOBAL(return_to_handler) |
1243 | /* need to save return values */ | 1250 | /* need to save return values */ |
1244 | std r4, -24(r1) | ||
1245 | std r3, -16(r1) | ||
1246 | std r31, -8(r1) | ||
1247 | mr r31, r1 | ||
1248 | stdu r1, -112(r1) | ||
1249 | |||
1250 | bl ftrace_return_to_handler | ||
1251 | nop | ||
1252 | |||
1253 | /* return value has real return address */ | ||
1254 | mtlr r3 | ||
1255 | |||
1256 | ld r1, 0(r1) | ||
1257 | ld r4, -24(r1) | ||
1258 | ld r3, -16(r1) | ||
1259 | ld r31, -8(r1) | ||
1260 | |||
1261 | /* Jump back to real return address */ | ||
1262 | blr | ||
1263 | |||
1264 | _GLOBAL(mod_return_to_handler) | ||
1265 | /* need to save return values */ | ||
1266 | std r4, -32(r1) | 1251 | std r4, -32(r1) |
1267 | std r3, -24(r1) | 1252 | std r3, -24(r1) |
1268 | /* save TOC */ | 1253 | /* save TOC */ |
@@ -1272,7 +1257,7 @@ _GLOBAL(mod_return_to_handler) | |||
1272 | stdu r1, -112(r1) | 1257 | stdu r1, -112(r1) |
1273 | 1258 | ||
1274 | /* | 1259 | /* |
1275 | * We are in a module using the module's TOC. | 1260 | * We might be called from a module. |
1276 | * Switch to our TOC to run inside the core kernel. | 1261 | * Switch to our TOC to run inside the core kernel. |
1277 | */ | 1262 | */ |
1278 | ld r2, PACATOC(r13) | 1263 | ld r2, PACATOC(r13) |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 72e783ea0681..db08382e19f1 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -131,6 +131,8 @@ BEGIN_FTR_SECTION | |||
131 | 1: | 131 | 1: |
132 | #endif | 132 | #endif |
133 | 133 | ||
134 | /* Return SRR1 from power7_nap() */ | ||
135 | mfspr r3,SPRN_SRR1 | ||
134 | beq cr1,2f | 136 | beq cr1,2f |
135 | b power7_wakeup_noloss | 137 | b power7_wakeup_noloss |
136 | 2: b power7_wakeup_loss | 138 | 2: b power7_wakeup_loss |
@@ -292,15 +294,26 @@ decrementer_pSeries: | |||
292 | . = 0xc00 | 294 | . = 0xc00 |
293 | .globl system_call_pSeries | 295 | .globl system_call_pSeries |
294 | system_call_pSeries: | 296 | system_call_pSeries: |
295 | HMT_MEDIUM | 297 | /* |
298 | * If CONFIG_KVM_BOOK3S_64_HANDLER is set, save the PPR (on systems | ||
299 | * that support it) before changing to HMT_MEDIUM. That allows the KVM | ||
300 | * code to save that value into the guest state (it is the guest's PPR | ||
301 | * value). Otherwise just change to HMT_MEDIUM as userspace has | ||
302 | * already saved the PPR. | ||
303 | */ | ||
296 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | 304 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER |
297 | SET_SCRATCH0(r13) | 305 | SET_SCRATCH0(r13) |
298 | GET_PACA(r13) | 306 | GET_PACA(r13) |
299 | std r9,PACA_EXGEN+EX_R9(r13) | 307 | std r9,PACA_EXGEN+EX_R9(r13) |
308 | OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR); | ||
309 | HMT_MEDIUM; | ||
300 | std r10,PACA_EXGEN+EX_R10(r13) | 310 | std r10,PACA_EXGEN+EX_R10(r13) |
311 | OPT_SAVE_REG_TO_PACA(PACA_EXGEN+EX_PPR, r9, CPU_FTR_HAS_PPR); | ||
301 | mfcr r9 | 312 | mfcr r9 |
302 | KVMTEST(0xc00) | 313 | KVMTEST(0xc00) |
303 | GET_SCRATCH0(r13) | 314 | GET_SCRATCH0(r13) |
315 | #else | ||
316 | HMT_MEDIUM; | ||
304 | #endif | 317 | #endif |
305 | SYSCALL_PSERIES_1 | 318 | SYSCALL_PSERIES_1 |
306 | SYSCALL_PSERIES_2_RFID | 319 | SYSCALL_PSERIES_2_RFID |
@@ -1301,23 +1314,6 @@ hmi_exception_after_realmode: | |||
1301 | EXCEPTION_PROLOG_0(PACA_EXGEN) | 1314 | EXCEPTION_PROLOG_0(PACA_EXGEN) |
1302 | b hmi_exception_hv | 1315 | b hmi_exception_hv |
1303 | 1316 | ||
1304 | #ifdef CONFIG_PPC_POWERNV | ||
1305 | _GLOBAL(opal_mc_secondary_handler) | ||
1306 | HMT_MEDIUM_PPR_DISCARD | ||
1307 | SET_SCRATCH0(r13) | ||
1308 | GET_PACA(r13) | ||
1309 | clrldi r3,r3,2 | ||
1310 | tovirt(r3,r3) | ||
1311 | std r3,PACA_OPAL_MC_EVT(r13) | ||
1312 | ld r13,OPAL_MC_SRR0(r3) | ||
1313 | mtspr SPRN_SRR0,r13 | ||
1314 | ld r13,OPAL_MC_SRR1(r3) | ||
1315 | mtspr SPRN_SRR1,r13 | ||
1316 | ld r3,OPAL_MC_GPR3(r3) | ||
1317 | GET_SCRATCH0(r13) | ||
1318 | b machine_check_pSeries | ||
1319 | #endif /* CONFIG_PPC_POWERNV */ | ||
1320 | |||
1321 | 1317 | ||
1322 | #define MACHINE_CHECK_HANDLER_WINDUP \ | 1318 | #define MACHINE_CHECK_HANDLER_WINDUP \ |
1323 | /* Clear MSR_RI before setting SRR0 and SRR1. */\ | 1319 | /* Clear MSR_RI before setting SRR0 and SRR1. */\ |
@@ -1571,9 +1567,11 @@ do_hash_page: | |||
1571 | * r3 contains the faulting address | 1567 | * r3 contains the faulting address |
1572 | * r4 contains the required access permissions | 1568 | * r4 contains the required access permissions |
1573 | * r5 contains the trap number | 1569 | * r5 contains the trap number |
1570 | * r6 contains dsisr | ||
1574 | * | 1571 | * |
1575 | * at return r3 = 0 for success, 1 for page fault, negative for error | 1572 | * at return r3 = 0 for success, 1 for page fault, negative for error |
1576 | */ | 1573 | */ |
1574 | ld r6,_DSISR(r1) | ||
1577 | bl hash_page /* build HPTE if possible */ | 1575 | bl hash_page /* build HPTE if possible */ |
1578 | cmpdi r3,0 /* see if hash_page succeeded */ | 1576 | cmpdi r3,0 /* see if hash_page succeeded */ |
1579 | 1577 | ||
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index e66af6d265e8..44d4d8eb3c85 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c | |||
@@ -510,79 +510,36 @@ int ftrace_disable_ftrace_graph_caller(void) | |||
510 | } | 510 | } |
511 | #endif /* CONFIG_DYNAMIC_FTRACE */ | 511 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
512 | 512 | ||
513 | #ifdef CONFIG_PPC64 | ||
514 | extern void mod_return_to_handler(void); | ||
515 | #endif | ||
516 | |||
517 | /* | 513 | /* |
518 | * Hook the return address and push it in the stack of return addrs | 514 | * Hook the return address and push it in the stack of return addrs |
519 | * in current thread info. | 515 | * in current thread info. Return the address we want to divert to. |
520 | */ | 516 | */ |
521 | void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | 517 | unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip) |
522 | { | 518 | { |
523 | unsigned long old; | ||
524 | int faulted; | ||
525 | struct ftrace_graph_ent trace; | 519 | struct ftrace_graph_ent trace; |
526 | unsigned long return_hooker = (unsigned long)&return_to_handler; | 520 | unsigned long return_hooker; |
527 | 521 | ||
528 | if (unlikely(ftrace_graph_is_dead())) | 522 | if (unlikely(ftrace_graph_is_dead())) |
529 | return; | 523 | goto out; |
530 | 524 | ||
531 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | 525 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) |
532 | return; | 526 | goto out; |
533 | |||
534 | #ifdef CONFIG_PPC64 | ||
535 | /* non core kernel code needs to save and restore the TOC */ | ||
536 | if (REGION_ID(self_addr) != KERNEL_REGION_ID) | ||
537 | return_hooker = (unsigned long)&mod_return_to_handler; | ||
538 | #endif | ||
539 | |||
540 | return_hooker = ppc_function_entry((void *)return_hooker); | ||
541 | 527 | ||
542 | /* | 528 | return_hooker = ppc_function_entry(return_to_handler); |
543 | * Protect against fault, even if it shouldn't | ||
544 | * happen. This tool is too much intrusive to | ||
545 | * ignore such a protection. | ||
546 | */ | ||
547 | asm volatile( | ||
548 | "1: " PPC_LL "%[old], 0(%[parent])\n" | ||
549 | "2: " PPC_STL "%[return_hooker], 0(%[parent])\n" | ||
550 | " li %[faulted], 0\n" | ||
551 | "3:\n" | ||
552 | |||
553 | ".section .fixup, \"ax\"\n" | ||
554 | "4: li %[faulted], 1\n" | ||
555 | " b 3b\n" | ||
556 | ".previous\n" | ||
557 | |||
558 | ".section __ex_table,\"a\"\n" | ||
559 | PPC_LONG_ALIGN "\n" | ||
560 | PPC_LONG "1b,4b\n" | ||
561 | PPC_LONG "2b,4b\n" | ||
562 | ".previous" | ||
563 | |||
564 | : [old] "=&r" (old), [faulted] "=r" (faulted) | ||
565 | : [parent] "r" (parent), [return_hooker] "r" (return_hooker) | ||
566 | : "memory" | ||
567 | ); | ||
568 | |||
569 | if (unlikely(faulted)) { | ||
570 | ftrace_graph_stop(); | ||
571 | WARN_ON(1); | ||
572 | return; | ||
573 | } | ||
574 | 529 | ||
575 | trace.func = self_addr; | 530 | trace.func = ip; |
576 | trace.depth = current->curr_ret_stack + 1; | 531 | trace.depth = current->curr_ret_stack + 1; |
577 | 532 | ||
578 | /* Only trace if the calling function expects to */ | 533 | /* Only trace if the calling function expects to */ |
579 | if (!ftrace_graph_entry(&trace)) { | 534 | if (!ftrace_graph_entry(&trace)) |
580 | *parent = old; | 535 | goto out; |
581 | return; | 536 | |
582 | } | 537 | if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY) |
538 | goto out; | ||
583 | 539 | ||
584 | if (ftrace_push_return_trace(old, self_addr, &trace.depth, 0) == -EBUSY) | 540 | parent = return_hooker; |
585 | *parent = old; | 541 | out: |
542 | return parent; | ||
586 | } | 543 | } |
587 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 544 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
588 | 545 | ||
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index fafff8dbd5d9..d99aac0d69f1 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
@@ -33,13 +33,31 @@ | |||
33 | 33 | ||
34 | /* Macro to make the code more readable. */ | 34 | /* Macro to make the code more readable. */ |
35 | #ifdef CONFIG_8xx_CPU6 | 35 | #ifdef CONFIG_8xx_CPU6 |
36 | #define DO_8xx_CPU6(val, reg) \ | 36 | #define SPRN_MI_TWC_ADDR 0x2b80 |
37 | li reg, val; \ | 37 | #define SPRN_MI_RPN_ADDR 0x2d80 |
38 | stw reg, 12(r0); \ | 38 | #define SPRN_MD_TWC_ADDR 0x3b80 |
39 | lwz reg, 12(r0); | 39 | #define SPRN_MD_RPN_ADDR 0x3d80 |
40 | |||
41 | #define MTSPR_CPU6(spr, reg, treg) \ | ||
42 | li treg, spr##_ADDR; \ | ||
43 | stw treg, 12(r0); \ | ||
44 | lwz treg, 12(r0); \ | ||
45 | mtspr spr, reg | ||
40 | #else | 46 | #else |
41 | #define DO_8xx_CPU6(val, reg) | 47 | #define MTSPR_CPU6(spr, reg, treg) \ |
48 | mtspr spr, reg | ||
42 | #endif | 49 | #endif |
50 | |||
51 | /* | ||
52 | * Value for the bits that have fixed value in RPN entries. | ||
53 | * Also used for tagging DAR for DTLBerror. | ||
54 | */ | ||
55 | #ifdef CONFIG_PPC_16K_PAGES | ||
56 | #define RPN_PATTERN (0x00f0 | MD_SPS16K) | ||
57 | #else | ||
58 | #define RPN_PATTERN 0x00f0 | ||
59 | #endif | ||
60 | |||
43 | __HEAD | 61 | __HEAD |
44 | _ENTRY(_stext); | 62 | _ENTRY(_stext); |
45 | _ENTRY(_start); | 63 | _ENTRY(_start); |
@@ -65,13 +83,6 @@ _ENTRY(_start); | |||
65 | * 8M 1:1. I also mapped an additional I/O space 1:1 so we can get to | 83 | * 8M 1:1. I also mapped an additional I/O space 1:1 so we can get to |
66 | * the "internal" processor registers before MMU_init is called. | 84 | * the "internal" processor registers before MMU_init is called. |
67 | * | 85 | * |
68 | * The TLB code currently contains a major hack. Since I use the condition | ||
69 | * code register, I have to save and restore it. I am out of registers, so | ||
70 | * I just store it in memory location 0 (the TLB handlers are not reentrant). | ||
71 | * To avoid making any decisions, I need to use the "segment" valid bit | ||
72 | * in the first level table, but that would require many changes to the | ||
73 | * Linux page directory/table functions that I don't want to do right now. | ||
74 | * | ||
75 | * -- Dan | 86 | * -- Dan |
76 | */ | 87 | */ |
77 | .globl __start | 88 | .globl __start |
@@ -211,7 +222,7 @@ MachineCheck: | |||
211 | EXCEPTION_PROLOG | 222 | EXCEPTION_PROLOG |
212 | mfspr r4,SPRN_DAR | 223 | mfspr r4,SPRN_DAR |
213 | stw r4,_DAR(r11) | 224 | stw r4,_DAR(r11) |
214 | li r5,0x00f0 | 225 | li r5,RPN_PATTERN |
215 | mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ | 226 | mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ |
216 | mfspr r5,SPRN_DSISR | 227 | mfspr r5,SPRN_DSISR |
217 | stw r5,_DSISR(r11) | 228 | stw r5,_DSISR(r11) |
@@ -219,30 +230,16 @@ MachineCheck: | |||
219 | EXC_XFER_STD(0x200, machine_check_exception) | 230 | EXC_XFER_STD(0x200, machine_check_exception) |
220 | 231 | ||
221 | /* Data access exception. | 232 | /* Data access exception. |
222 | * This is "never generated" by the MPC8xx. We jump to it for other | 233 | * This is "never generated" by the MPC8xx. |
223 | * translation errors. | ||
224 | */ | 234 | */ |
225 | . = 0x300 | 235 | . = 0x300 |
226 | DataAccess: | 236 | DataAccess: |
227 | EXCEPTION_PROLOG | ||
228 | mfspr r10,SPRN_DSISR | ||
229 | stw r10,_DSISR(r11) | ||
230 | mr r5,r10 | ||
231 | mfspr r4,SPRN_DAR | ||
232 | li r10,0x00f0 | ||
233 | mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */ | ||
234 | EXC_XFER_LITE(0x300, handle_page_fault) | ||
235 | 237 | ||
236 | /* Instruction access exception. | 238 | /* Instruction access exception. |
237 | * This is "never generated" by the MPC8xx. We jump to it for other | 239 | * This is "never generated" by the MPC8xx. |
238 | * translation errors. | ||
239 | */ | 240 | */ |
240 | . = 0x400 | 241 | . = 0x400 |
241 | InstructionAccess: | 242 | InstructionAccess: |
242 | EXCEPTION_PROLOG | ||
243 | mr r4,r12 | ||
244 | mr r5,r9 | ||
245 | EXC_XFER_LITE(0x400, handle_page_fault) | ||
246 | 243 | ||
247 | /* External interrupt */ | 244 | /* External interrupt */ |
248 | EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE) | 245 | EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE) |
@@ -253,7 +250,7 @@ Alignment: | |||
253 | EXCEPTION_PROLOG | 250 | EXCEPTION_PROLOG |
254 | mfspr r4,SPRN_DAR | 251 | mfspr r4,SPRN_DAR |
255 | stw r4,_DAR(r11) | 252 | stw r4,_DAR(r11) |
256 | li r5,0x00f0 | 253 | li r5,RPN_PATTERN |
257 | mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ | 254 | mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ |
258 | mfspr r5,SPRN_DSISR | 255 | mfspr r5,SPRN_DSISR |
259 | stw r5,_DSISR(r11) | 256 | stw r5,_DSISR(r11) |
@@ -292,8 +289,8 @@ SystemCall: | |||
292 | . = 0x1100 | 289 | . = 0x1100 |
293 | /* | 290 | /* |
294 | * For the MPC8xx, this is a software tablewalk to load the instruction | 291 | * For the MPC8xx, this is a software tablewalk to load the instruction |
295 | * TLB. It is modelled after the example in the Motorola manual. The task | 292 | * TLB. The task switch loads the M_TW register with the pointer to the first |
296 | * switch loads the M_TWB register with the pointer to the first level table. | 293 | * level table. |
297 | * If we discover there is no second level table (value is zero) or if there | 294 | * If we discover there is no second level table (value is zero) or if there |
298 | * is an invalid pte, we load that into the TLB, which causes another fault | 295 | * is an invalid pte, we load that into the TLB, which causes another fault |
299 | * into the TLB Error interrupt where we can handle such problems. | 296 | * into the TLB Error interrupt where we can handle such problems. |
@@ -302,20 +299,17 @@ SystemCall: | |||
302 | */ | 299 | */ |
303 | InstructionTLBMiss: | 300 | InstructionTLBMiss: |
304 | #ifdef CONFIG_8xx_CPU6 | 301 | #ifdef CONFIG_8xx_CPU6 |
305 | stw r3, 8(r0) | 302 | mtspr SPRN_DAR, r3 |
306 | #endif | 303 | #endif |
307 | EXCEPTION_PROLOG_0 | 304 | EXCEPTION_PROLOG_0 |
308 | mtspr SPRN_SPRG_SCRATCH2, r10 | 305 | mtspr SPRN_SPRG_SCRATCH2, r10 |
309 | mfspr r10, SPRN_SRR0 /* Get effective address of fault */ | 306 | mfspr r10, SPRN_SRR0 /* Get effective address of fault */ |
310 | #ifdef CONFIG_8xx_CPU15 | 307 | #ifdef CONFIG_8xx_CPU15 |
311 | addi r11, r10, 0x1000 | 308 | addi r11, r10, PAGE_SIZE |
312 | tlbie r11 | 309 | tlbie r11 |
313 | addi r11, r10, -0x1000 | 310 | addi r11, r10, -PAGE_SIZE |
314 | tlbie r11 | 311 | tlbie r11 |
315 | #endif | 312 | #endif |
316 | DO_8xx_CPU6(0x3780, r3) | ||
317 | mtspr SPRN_MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */ | ||
318 | mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ | ||
319 | 313 | ||
320 | /* If we are faulting a kernel address, we have to use the | 314 | /* If we are faulting a kernel address, we have to use the |
321 | * kernel page tables. | 315 | * kernel page tables. |
@@ -323,32 +317,37 @@ InstructionTLBMiss: | |||
323 | #ifdef CONFIG_MODULES | 317 | #ifdef CONFIG_MODULES |
324 | /* Only modules will cause ITLB Misses as we always | 318 | /* Only modules will cause ITLB Misses as we always |
325 | * pin the first 8MB of kernel memory */ | 319 | * pin the first 8MB of kernel memory */ |
326 | andi. r11, r10, 0x0800 /* Address >= 0x80000000 */ | 320 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ |
321 | #endif | ||
322 | mfspr r11, SPRN_M_TW /* Get level 1 table base address */ | ||
323 | #ifdef CONFIG_MODULES | ||
327 | beq 3f | 324 | beq 3f |
328 | lis r11, swapper_pg_dir@h | 325 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@h |
329 | ori r11, r11, swapper_pg_dir@l | 326 | ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l |
330 | rlwimi r10, r11, 0, 2, 19 | ||
331 | 3: | 327 | 3: |
332 | #endif | 328 | #endif |
333 | lwz r11, 0(r10) /* Get the level 1 entry */ | 329 | /* Extract level 1 index */ |
330 | rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 | ||
331 | lwzx r11, r10, r11 /* Get the level 1 entry */ | ||
334 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ | 332 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ |
335 | beq 2f /* If zero, don't try to find a pte */ | 333 | beq 2f /* If zero, don't try to find a pte */ |
336 | 334 | ||
337 | /* We have a pte table, so load the MI_TWC with the attributes | 335 | /* We have a pte table, so load the MI_TWC with the attributes |
338 | * for this "segment." | 336 | * for this "segment." |
339 | */ | 337 | */ |
340 | ori r11,r11,1 /* Set valid bit */ | 338 | MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */ |
341 | DO_8xx_CPU6(0x2b80, r3) | 339 | mfspr r11, SPRN_SRR0 /* Get effective address of fault */ |
342 | mtspr SPRN_MI_TWC, r11 /* Set segment attributes */ | 340 | /* Extract level 2 index */ |
343 | DO_8xx_CPU6(0x3b80, r3) | 341 | rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 |
344 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ | 342 | lwzx r10, r10, r11 /* Get the pte */ |
345 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ | ||
346 | lwz r10, 0(r11) /* Get the pte */ | ||
347 | 343 | ||
348 | #ifdef CONFIG_SWAP | 344 | #ifdef CONFIG_SWAP |
349 | andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT | 345 | andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT |
350 | cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT | 346 | cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT |
347 | li r11, RPN_PATTERN | ||
351 | bne- cr0, 2f | 348 | bne- cr0, 2f |
349 | #else | ||
350 | li r11, RPN_PATTERN | ||
352 | #endif | 351 | #endif |
353 | /* The Linux PTE won't go exactly into the MMU TLB. | 352 | /* The Linux PTE won't go exactly into the MMU TLB. |
354 | * Software indicator bits 21 and 28 must be clear. | 353 | * Software indicator bits 21 and 28 must be clear. |
@@ -356,62 +355,63 @@ InstructionTLBMiss: | |||
356 | * set. All other Linux PTE bits control the behavior | 355 | * set. All other Linux PTE bits control the behavior |
357 | * of the MMU. | 356 | * of the MMU. |
358 | */ | 357 | */ |
359 | li r11, 0x00f0 | ||
360 | rlwimi r10, r11, 0, 0x07f8 /* Set 24-27, clear 21-23,28 */ | 358 | rlwimi r10, r11, 0, 0x07f8 /* Set 24-27, clear 21-23,28 */ |
361 | DO_8xx_CPU6(0x2d80, r3) | 359 | MTSPR_CPU6(SPRN_MI_RPN, r10, r3) /* Update TLB entry */ |
362 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ | ||
363 | 360 | ||
364 | /* Restore registers */ | 361 | /* Restore registers */ |
365 | #ifdef CONFIG_8xx_CPU6 | 362 | #ifdef CONFIG_8xx_CPU6 |
366 | lwz r3, 8(r0) | 363 | mfspr r3, SPRN_DAR |
364 | mtspr SPRN_DAR, r11 /* Tag DAR */ | ||
367 | #endif | 365 | #endif |
368 | mfspr r10, SPRN_SPRG_SCRATCH2 | 366 | mfspr r10, SPRN_SPRG_SCRATCH2 |
369 | EXCEPTION_EPILOG_0 | 367 | EXCEPTION_EPILOG_0 |
370 | rfi | 368 | rfi |
371 | 2: | 369 | 2: |
372 | mfspr r11, SPRN_SRR1 | 370 | mfspr r10, SPRN_SRR1 |
373 | /* clear all error bits as TLB Miss | 371 | /* clear all error bits as TLB Miss |
374 | * sets a few unconditionally | 372 | * sets a few unconditionally |
375 | */ | 373 | */ |
376 | rlwinm r11, r11, 0, 0xffff | 374 | rlwinm r10, r10, 0, 0xffff |
377 | mtspr SPRN_SRR1, r11 | 375 | mtspr SPRN_SRR1, r10 |
378 | 376 | ||
379 | /* Restore registers */ | 377 | /* Restore registers */ |
380 | #ifdef CONFIG_8xx_CPU6 | 378 | #ifdef CONFIG_8xx_CPU6 |
381 | lwz r3, 8(r0) | 379 | mfspr r3, SPRN_DAR |
380 | mtspr SPRN_DAR, r11 /* Tag DAR */ | ||
382 | #endif | 381 | #endif |
383 | mfspr r10, SPRN_SPRG_SCRATCH2 | 382 | mfspr r10, SPRN_SPRG_SCRATCH2 |
384 | EXCEPTION_EPILOG_0 | 383 | b InstructionTLBError1 |
385 | b InstructionAccess | ||
386 | 384 | ||
387 | . = 0x1200 | 385 | . = 0x1200 |
388 | DataStoreTLBMiss: | 386 | DataStoreTLBMiss: |
389 | #ifdef CONFIG_8xx_CPU6 | 387 | #ifdef CONFIG_8xx_CPU6 |
390 | stw r3, 8(r0) | 388 | mtspr SPRN_DAR, r3 |
391 | #endif | 389 | #endif |
392 | EXCEPTION_PROLOG_0 | 390 | EXCEPTION_PROLOG_0 |
393 | mtspr SPRN_SPRG_SCRATCH2, r10 | 391 | mtspr SPRN_SPRG_SCRATCH2, r10 |
394 | mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ | 392 | mfspr r10, SPRN_MD_EPN |
395 | 393 | ||
396 | /* If we are faulting a kernel address, we have to use the | 394 | /* If we are faulting a kernel address, we have to use the |
397 | * kernel page tables. | 395 | * kernel page tables. |
398 | */ | 396 | */ |
399 | andi. r11, r10, 0x0800 | 397 | andis. r11, r10, 0x8000 |
398 | mfspr r11, SPRN_M_TW /* Get level 1 table base address */ | ||
400 | beq 3f | 399 | beq 3f |
401 | lis r11, swapper_pg_dir@h | 400 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@h |
402 | ori r11, r11, swapper_pg_dir@l | 401 | ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l |
403 | rlwimi r10, r11, 0, 2, 19 | ||
404 | 3: | 402 | 3: |
405 | lwz r11, 0(r10) /* Get the level 1 entry */ | 403 | /* Extract level 1 index */ |
404 | rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 | ||
405 | lwzx r11, r10, r11 /* Get the level 1 entry */ | ||
406 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ | 406 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ |
407 | beq 2f /* If zero, don't try to find a pte */ | 407 | beq 2f /* If zero, don't try to find a pte */ |
408 | 408 | ||
409 | /* We have a pte table, so load fetch the pte from the table. | 409 | /* We have a pte table, so load fetch the pte from the table. |
410 | */ | 410 | */ |
411 | ori r11, r11, 1 /* Set valid bit in physical L2 page */ | 411 | mfspr r10, SPRN_MD_EPN /* Get address of fault */ |
412 | DO_8xx_CPU6(0x3b80, r3) | 412 | /* Extract level 2 index */ |
413 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ | 413 | rlwinm r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 |
414 | mfspr r10, SPRN_MD_TWC /* ....and get the pte address */ | 414 | rlwimi r10, r11, 0, 0, 32 - PAGE_SHIFT - 1 /* Add level 2 base */ |
415 | lwz r10, 0(r10) /* Get the pte */ | 415 | lwz r10, 0(r10) /* Get the pte */ |
416 | 416 | ||
417 | /* Insert the Guarded flag into the TWC from the Linux PTE. | 417 | /* Insert the Guarded flag into the TWC from the Linux PTE. |
@@ -425,8 +425,7 @@ DataStoreTLBMiss: | |||
425 | * It is bit 25 in the Linux PTE and bit 30 in the TWC | 425 | * It is bit 25 in the Linux PTE and bit 30 in the TWC |
426 | */ | 426 | */ |
427 | rlwimi r11, r10, 32-5, 30, 30 | 427 | rlwimi r11, r10, 32-5, 30, 30 |
428 | DO_8xx_CPU6(0x3b80, r3) | 428 | MTSPR_CPU6(SPRN_MD_TWC, r11, r3) |
429 | mtspr SPRN_MD_TWC, r11 | ||
430 | 429 | ||
431 | /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set. | 430 | /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set. |
432 | * We also need to know if the insn is a load/store, so: | 431 | * We also need to know if the insn is a load/store, so: |
@@ -442,14 +441,8 @@ DataStoreTLBMiss: | |||
442 | and r11, r11, r10 | 441 | and r11, r11, r10 |
443 | rlwimi r10, r11, 0, _PAGE_PRESENT | 442 | rlwimi r10, r11, 0, _PAGE_PRESENT |
444 | #endif | 443 | #endif |
445 | /* Honour kernel RO, User NA */ | 444 | /* invert RW */ |
446 | /* 0x200 == Extended encoding, bit 22 */ | 445 | xori r10, r10, _PAGE_RW |
447 | rlwimi r10, r10, 32-2, 0x200 /* Copy USER to bit 22, 0x200 */ | ||
448 | /* r11 = (r10 & _PAGE_RW) >> 1 */ | ||
449 | rlwinm r11, r10, 32-1, 0x200 | ||
450 | or r10, r11, r10 | ||
451 | /* invert RW and 0x200 bits */ | ||
452 | xori r10, r10, _PAGE_RW | 0x200 | ||
453 | 446 | ||
454 | /* The Linux PTE won't go exactly into the MMU TLB. | 447 | /* The Linux PTE won't go exactly into the MMU TLB. |
455 | * Software indicator bits 22 and 28 must be clear. | 448 | * Software indicator bits 22 and 28 must be clear. |
@@ -457,14 +450,13 @@ DataStoreTLBMiss: | |||
457 | * set. All other Linux PTE bits control the behavior | 450 | * set. All other Linux PTE bits control the behavior |
458 | * of the MMU. | 451 | * of the MMU. |
459 | */ | 452 | */ |
460 | 2: li r11, 0x00f0 | 453 | 2: li r11, RPN_PATTERN |
461 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ | 454 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ |
462 | DO_8xx_CPU6(0x3d80, r3) | 455 | MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */ |
463 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ | ||
464 | 456 | ||
465 | /* Restore registers */ | 457 | /* Restore registers */ |
466 | #ifdef CONFIG_8xx_CPU6 | 458 | #ifdef CONFIG_8xx_CPU6 |
467 | lwz r3, 8(r0) | 459 | mfspr r3, SPRN_DAR |
468 | #endif | 460 | #endif |
469 | mtspr SPRN_DAR, r11 /* Tag DAR */ | 461 | mtspr SPRN_DAR, r11 /* Tag DAR */ |
470 | mfspr r10, SPRN_SPRG_SCRATCH2 | 462 | mfspr r10, SPRN_SPRG_SCRATCH2 |
@@ -477,7 +469,17 @@ DataStoreTLBMiss: | |||
477 | */ | 469 | */ |
478 | . = 0x1300 | 470 | . = 0x1300 |
479 | InstructionTLBError: | 471 | InstructionTLBError: |
480 | b InstructionAccess | 472 | EXCEPTION_PROLOG_0 |
473 | InstructionTLBError1: | ||
474 | EXCEPTION_PROLOG_1 | ||
475 | EXCEPTION_PROLOG_2 | ||
476 | mr r4,r12 | ||
477 | mr r5,r9 | ||
478 | andis. r10,r5,0x4000 | ||
479 | beq+ 1f | ||
480 | tlbie r4 | ||
481 | /* 0x400 is InstructionAccess exception, needed by bad_page_fault() */ | ||
482 | 1: EXC_XFER_LITE(0x400, handle_page_fault) | ||
481 | 483 | ||
482 | /* This is the data TLB error on the MPC8xx. This could be due to | 484 | /* This is the data TLB error on the MPC8xx. This could be due to |
483 | * many reasons, including a dirty update to a pte. We bail out to | 485 | * many reasons, including a dirty update to a pte. We bail out to |
@@ -488,11 +490,21 @@ DataTLBError: | |||
488 | EXCEPTION_PROLOG_0 | 490 | EXCEPTION_PROLOG_0 |
489 | 491 | ||
490 | mfspr r11, SPRN_DAR | 492 | mfspr r11, SPRN_DAR |
491 | cmpwi cr0, r11, 0x00f0 | 493 | cmpwi cr0, r11, RPN_PATTERN |
492 | beq- FixupDAR /* must be a buggy dcbX, icbi insn. */ | 494 | beq- FixupDAR /* must be a buggy dcbX, icbi insn. */ |
493 | DARFixed:/* Return from dcbx instruction bug workaround */ | 495 | DARFixed:/* Return from dcbx instruction bug workaround */ |
494 | EXCEPTION_EPILOG_0 | 496 | EXCEPTION_PROLOG_1 |
495 | b DataAccess | 497 | EXCEPTION_PROLOG_2 |
498 | mfspr r5,SPRN_DSISR | ||
499 | stw r5,_DSISR(r11) | ||
500 | mfspr r4,SPRN_DAR | ||
501 | andis. r10,r5,0x4000 | ||
502 | beq+ 1f | ||
503 | tlbie r4 | ||
504 | 1: li r10,RPN_PATTERN | ||
505 | mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */ | ||
506 | /* 0x300 is DataAccess exception, needed by bad_page_fault() */ | ||
507 | EXC_XFER_LITE(0x300, handle_page_fault) | ||
496 | 508 | ||
497 | EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE) | 509 | EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE) |
498 | EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE) | 510 | EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE) |
@@ -521,29 +533,30 @@ DARFixed:/* Return from dcbx instruction bug workaround */ | |||
521 | #define NO_SELF_MODIFYING_CODE | 533 | #define NO_SELF_MODIFYING_CODE |
522 | FixupDAR:/* Entry point for dcbx workaround. */ | 534 | FixupDAR:/* Entry point for dcbx workaround. */ |
523 | #ifdef CONFIG_8xx_CPU6 | 535 | #ifdef CONFIG_8xx_CPU6 |
524 | stw r3, 8(r0) | 536 | mtspr SPRN_DAR, r3 |
525 | #endif | 537 | #endif |
526 | mtspr SPRN_SPRG_SCRATCH2, r10 | 538 | mtspr SPRN_SPRG_SCRATCH2, r10 |
527 | /* fetch instruction from memory. */ | 539 | /* fetch instruction from memory. */ |
528 | mfspr r10, SPRN_SRR0 | 540 | mfspr r10, SPRN_SRR0 |
529 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ | 541 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ |
530 | DO_8xx_CPU6(0x3780, r3) | 542 | mfspr r11, SPRN_M_TW /* Get level 1 table base address */ |
531 | mtspr SPRN_MD_EPN, r10 | ||
532 | mfspr r11, SPRN_M_TWB /* Get level 1 table entry address */ | ||
533 | beq- 3f /* Branch if user space */ | 543 | beq- 3f /* Branch if user space */ |
534 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@h | 544 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@h |
535 | ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l | 545 | ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l |
536 | rlwimi r11, r10, 32-20, 0xffc /* r11 = r11&~0xffc|(r10>>20)&0xffc */ | 546 | /* Extract level 1 index */ |
537 | 3: lwz r11, 0(r11) /* Get the level 1 entry */ | 547 | 3: rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 |
538 | DO_8xx_CPU6(0x3b80, r3) | 548 | lwzx r11, r10, r11 /* Get the level 1 entry */ |
539 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ | 549 | rlwinm r10, r11,0,0,19 /* Extract page descriptor page address */ |
540 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ | 550 | mfspr r11, SPRN_SRR0 /* Get effective address of fault */ |
541 | lwz r11, 0(r11) /* Get the pte */ | 551 | /* Extract level 2 index */ |
552 | rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 | ||
553 | lwzx r11, r10, r11 /* Get the pte */ | ||
542 | #ifdef CONFIG_8xx_CPU6 | 554 | #ifdef CONFIG_8xx_CPU6 |
543 | lwz r3, 8(r0) /* restore r3 from memory */ | 555 | mfspr r3, SPRN_DAR |
544 | #endif | 556 | #endif |
545 | /* concat physical page address(r11) and page offset(r10) */ | 557 | /* concat physical page address(r11) and page offset(r10) */ |
546 | rlwimi r11, r10, 0, 20, 31 | 558 | mfspr r10, SPRN_SRR0 |
559 | rlwimi r11, r10, 0, 32 - PAGE_SHIFT, 31 | ||
547 | lwz r11,0(r11) | 560 | lwz r11,0(r11) |
548 | /* Check if it really is a dcbx instruction. */ | 561 | /* Check if it really is a dcbx instruction. */ |
549 | /* dcbt and dcbtst does not generate DTLB Misses/Errors, | 562 | /* dcbt and dcbtst does not generate DTLB Misses/Errors, |
@@ -698,11 +711,11 @@ start_here: | |||
698 | #ifdef CONFIG_8xx_CPU6 | 711 | #ifdef CONFIG_8xx_CPU6 |
699 | lis r4, cpu6_errata_word@h | 712 | lis r4, cpu6_errata_word@h |
700 | ori r4, r4, cpu6_errata_word@l | 713 | ori r4, r4, cpu6_errata_word@l |
701 | li r3, 0x3980 | 714 | li r3, 0x3f80 |
702 | stw r3, 12(r4) | 715 | stw r3, 12(r4) |
703 | lwz r3, 12(r4) | 716 | lwz r3, 12(r4) |
704 | #endif | 717 | #endif |
705 | mtspr SPRN_M_TWB, r6 | 718 | mtspr SPRN_M_TW, r6 |
706 | lis r4,2f@h | 719 | lis r4,2f@h |
707 | ori r4,r4,2f@l | 720 | ori r4,r4,2f@l |
708 | tophys(r4,r4) | 721 | tophys(r4,r4) |
@@ -876,10 +889,10 @@ _GLOBAL(set_context) | |||
876 | lis r6, cpu6_errata_word@h | 889 | lis r6, cpu6_errata_word@h |
877 | ori r6, r6, cpu6_errata_word@l | 890 | ori r6, r6, cpu6_errata_word@l |
878 | tophys (r4, r4) | 891 | tophys (r4, r4) |
879 | li r7, 0x3980 | 892 | li r7, 0x3f80 |
880 | stw r7, 12(r6) | 893 | stw r7, 12(r6) |
881 | lwz r7, 12(r6) | 894 | lwz r7, 12(r6) |
882 | mtspr SPRN_M_TWB, r4 /* Update MMU base address */ | 895 | mtspr SPRN_M_TW, r4 /* Update MMU base address */ |
883 | li r7, 0x3380 | 896 | li r7, 0x3380 |
884 | stw r7, 12(r6) | 897 | stw r7, 12(r6) |
885 | lwz r7, 12(r6) | 898 | lwz r7, 12(r6) |
@@ -887,7 +900,7 @@ _GLOBAL(set_context) | |||
887 | #else | 900 | #else |
888 | mtspr SPRN_M_CASID,r3 /* Update context */ | 901 | mtspr SPRN_M_CASID,r3 /* Update context */ |
889 | tophys (r4, r4) | 902 | tophys (r4, r4) |
890 | mtspr SPRN_M_TWB, r4 /* and pgd */ | 903 | mtspr SPRN_M_TW, r4 /* and pgd */ |
891 | #endif | 904 | #endif |
892 | SYNC | 905 | SYNC |
893 | blr | 906 | blr |
@@ -919,12 +932,13 @@ set_dec_cpu6: | |||
919 | .globl sdata | 932 | .globl sdata |
920 | sdata: | 933 | sdata: |
921 | .globl empty_zero_page | 934 | .globl empty_zero_page |
935 | .align PAGE_SHIFT | ||
922 | empty_zero_page: | 936 | empty_zero_page: |
923 | .space 4096 | 937 | .space PAGE_SIZE |
924 | 938 | ||
925 | .globl swapper_pg_dir | 939 | .globl swapper_pg_dir |
926 | swapper_pg_dir: | 940 | swapper_pg_dir: |
927 | .space 4096 | 941 | .space PGD_TABLE_SIZE |
928 | 942 | ||
929 | /* Room for two PTE table poiners, usually the kernel and current user | 943 | /* Room for two PTE table poiners, usually the kernel and current user |
930 | * pointer to their respective root page table (pgdir). | 944 | * pointer to their respective root page table (pgdir). |
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c index 1f7d84e2e8b2..05e804cdecaa 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c | |||
@@ -63,7 +63,7 @@ int hw_breakpoint_slots(int type) | |||
63 | int arch_install_hw_breakpoint(struct perf_event *bp) | 63 | int arch_install_hw_breakpoint(struct perf_event *bp) |
64 | { | 64 | { |
65 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | 65 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); |
66 | struct perf_event **slot = &__get_cpu_var(bp_per_reg); | 66 | struct perf_event **slot = this_cpu_ptr(&bp_per_reg); |
67 | 67 | ||
68 | *slot = bp; | 68 | *slot = bp; |
69 | 69 | ||
@@ -88,7 +88,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp) | |||
88 | */ | 88 | */ |
89 | void arch_uninstall_hw_breakpoint(struct perf_event *bp) | 89 | void arch_uninstall_hw_breakpoint(struct perf_event *bp) |
90 | { | 90 | { |
91 | struct perf_event **slot = &__get_cpu_var(bp_per_reg); | 91 | struct perf_event **slot = this_cpu_ptr(&bp_per_reg); |
92 | 92 | ||
93 | if (*slot != bp) { | 93 | if (*slot != bp) { |
94 | WARN_ONCE(1, "Can't find the breakpoint"); | 94 | WARN_ONCE(1, "Can't find the breakpoint"); |
@@ -226,7 +226,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args) | |||
226 | */ | 226 | */ |
227 | rcu_read_lock(); | 227 | rcu_read_lock(); |
228 | 228 | ||
229 | bp = __get_cpu_var(bp_per_reg); | 229 | bp = __this_cpu_read(bp_per_reg); |
230 | if (!bp) | 230 | if (!bp) |
231 | goto out; | 231 | goto out; |
232 | info = counter_arch_bp(bp); | 232 | info = counter_arch_bp(bp); |
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index c0754bbf8118..18c0687e5ab3 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S | |||
@@ -212,6 +212,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | |||
212 | mtspr SPRN_SRR0,r5 | 212 | mtspr SPRN_SRR0,r5 |
213 | rfid | 213 | rfid |
214 | 214 | ||
215 | /* | ||
216 | * R3 here contains the value that will be returned to the caller | ||
217 | * of power7_nap. | ||
218 | */ | ||
215 | _GLOBAL(power7_wakeup_loss) | 219 | _GLOBAL(power7_wakeup_loss) |
216 | ld r1,PACAR1(r13) | 220 | ld r1,PACAR1(r13) |
217 | BEGIN_FTR_SECTION | 221 | BEGIN_FTR_SECTION |
@@ -219,15 +223,19 @@ BEGIN_FTR_SECTION | |||
219 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | 223 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) |
220 | REST_NVGPRS(r1) | 224 | REST_NVGPRS(r1) |
221 | REST_GPR(2, r1) | 225 | REST_GPR(2, r1) |
222 | ld r3,_CCR(r1) | 226 | ld r6,_CCR(r1) |
223 | ld r4,_MSR(r1) | 227 | ld r4,_MSR(r1) |
224 | ld r5,_NIP(r1) | 228 | ld r5,_NIP(r1) |
225 | addi r1,r1,INT_FRAME_SIZE | 229 | addi r1,r1,INT_FRAME_SIZE |
226 | mtcr r3 | 230 | mtcr r6 |
227 | mtspr SPRN_SRR1,r4 | 231 | mtspr SPRN_SRR1,r4 |
228 | mtspr SPRN_SRR0,r5 | 232 | mtspr SPRN_SRR0,r5 |
229 | rfid | 233 | rfid |
230 | 234 | ||
235 | /* | ||
236 | * R3 here contains the value that will be returned to the caller | ||
237 | * of power7_nap. | ||
238 | */ | ||
231 | _GLOBAL(power7_wakeup_noloss) | 239 | _GLOBAL(power7_wakeup_noloss) |
232 | lbz r0,PACA_NAPSTATELOST(r13) | 240 | lbz r0,PACA_NAPSTATELOST(r13) |
233 | cmpwi r0,0 | 241 | cmpwi r0,0 |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index a83cf5ef6488..5d3968c4d799 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -208,7 +208,7 @@ static unsigned long iommu_range_alloc(struct device *dev, | |||
208 | * We don't need to disable preemption here because any CPU can | 208 | * We don't need to disable preemption here because any CPU can |
209 | * safely use any IOMMU pool. | 209 | * safely use any IOMMU pool. |
210 | */ | 210 | */ |
211 | pool_nr = __raw_get_cpu_var(iommu_pool_hash) & (tbl->nr_pools - 1); | 211 | pool_nr = __this_cpu_read(iommu_pool_hash) & (tbl->nr_pools - 1); |
212 | 212 | ||
213 | if (largealloc) | 213 | if (largealloc) |
214 | pool = &(tbl->large_pool); | 214 | pool = &(tbl->large_pool); |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index c14383575fe8..45096033d37b 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <linux/list.h> | 50 | #include <linux/list.h> |
51 | #include <linux/radix-tree.h> | 51 | #include <linux/radix-tree.h> |
52 | #include <linux/mutex.h> | 52 | #include <linux/mutex.h> |
53 | #include <linux/bootmem.h> | ||
54 | #include <linux/pci.h> | 53 | #include <linux/pci.h> |
55 | #include <linux/debugfs.h> | 54 | #include <linux/debugfs.h> |
56 | #include <linux/of.h> | 55 | #include <linux/of.h> |
@@ -114,7 +113,7 @@ static inline notrace void set_soft_enabled(unsigned long enable) | |||
114 | static inline notrace int decrementer_check_overflow(void) | 113 | static inline notrace int decrementer_check_overflow(void) |
115 | { | 114 | { |
116 | u64 now = get_tb_or_rtc(); | 115 | u64 now = get_tb_or_rtc(); |
117 | u64 *next_tb = &__get_cpu_var(decrementers_next_tb); | 116 | u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); |
118 | 117 | ||
119 | return now >= *next_tb; | 118 | return now >= *next_tb; |
120 | } | 119 | } |
@@ -499,7 +498,7 @@ void __do_irq(struct pt_regs *regs) | |||
499 | 498 | ||
500 | /* And finally process it */ | 499 | /* And finally process it */ |
501 | if (unlikely(irq == NO_IRQ)) | 500 | if (unlikely(irq == NO_IRQ)) |
502 | __get_cpu_var(irq_stat).spurious_irqs++; | 501 | __this_cpu_inc(irq_stat.spurious_irqs); |
503 | else | 502 | else |
504 | generic_handle_irq(irq); | 503 | generic_handle_irq(irq); |
505 | 504 | ||
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index 8504657379f1..e77c3ccf8dcf 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c | |||
@@ -155,7 +155,7 @@ static int kgdb_singlestep(struct pt_regs *regs) | |||
155 | { | 155 | { |
156 | struct thread_info *thread_info, *exception_thread_info; | 156 | struct thread_info *thread_info, *exception_thread_info; |
157 | struct thread_info *backup_current_thread_info = | 157 | struct thread_info *backup_current_thread_info = |
158 | &__get_cpu_var(kgdb_thread_info); | 158 | this_cpu_ptr(&kgdb_thread_info); |
159 | 159 | ||
160 | if (user_mode(regs)) | 160 | if (user_mode(regs)) |
161 | return 0; | 161 | return 0; |
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 2f72af82513c..7c053f281406 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
@@ -119,7 +119,7 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) | |||
119 | 119 | ||
120 | static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) | 120 | static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) |
121 | { | 121 | { |
122 | __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; | 122 | __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); |
123 | kcb->kprobe_status = kcb->prev_kprobe.status; | 123 | kcb->kprobe_status = kcb->prev_kprobe.status; |
124 | kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr; | 124 | kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr; |
125 | } | 125 | } |
@@ -127,7 +127,7 @@ static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) | |||
127 | static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, | 127 | static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, |
128 | struct kprobe_ctlblk *kcb) | 128 | struct kprobe_ctlblk *kcb) |
129 | { | 129 | { |
130 | __get_cpu_var(current_kprobe) = p; | 130 | __this_cpu_write(current_kprobe, p); |
131 | kcb->kprobe_saved_msr = regs->msr; | 131 | kcb->kprobe_saved_msr = regs->msr; |
132 | } | 132 | } |
133 | 133 | ||
@@ -192,7 +192,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
192 | ret = 1; | 192 | ret = 1; |
193 | goto no_kprobe; | 193 | goto no_kprobe; |
194 | } | 194 | } |
195 | p = __get_cpu_var(current_kprobe); | 195 | p = __this_cpu_read(current_kprobe); |
196 | if (p->break_handler && p->break_handler(p, regs)) { | 196 | if (p->break_handler && p->break_handler(p, regs)) { |
197 | goto ss_probe; | 197 | goto ss_probe; |
198 | } | 198 | } |
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index a7fd4cb78b78..15c99b649b04 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c | |||
@@ -73,8 +73,8 @@ void save_mce_event(struct pt_regs *regs, long handled, | |||
73 | uint64_t nip, uint64_t addr) | 73 | uint64_t nip, uint64_t addr) |
74 | { | 74 | { |
75 | uint64_t srr1; | 75 | uint64_t srr1; |
76 | int index = __get_cpu_var(mce_nest_count)++; | 76 | int index = __this_cpu_inc_return(mce_nest_count); |
77 | struct machine_check_event *mce = &__get_cpu_var(mce_event[index]); | 77 | struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]); |
78 | 78 | ||
79 | /* | 79 | /* |
80 | * Return if we don't have enough space to log mce event. | 80 | * Return if we don't have enough space to log mce event. |
@@ -143,7 +143,7 @@ void save_mce_event(struct pt_regs *regs, long handled, | |||
143 | */ | 143 | */ |
144 | int get_mce_event(struct machine_check_event *mce, bool release) | 144 | int get_mce_event(struct machine_check_event *mce, bool release) |
145 | { | 145 | { |
146 | int index = __get_cpu_var(mce_nest_count) - 1; | 146 | int index = __this_cpu_read(mce_nest_count) - 1; |
147 | struct machine_check_event *mc_evt; | 147 | struct machine_check_event *mc_evt; |
148 | int ret = 0; | 148 | int ret = 0; |
149 | 149 | ||
@@ -153,7 +153,7 @@ int get_mce_event(struct machine_check_event *mce, bool release) | |||
153 | 153 | ||
154 | /* Check if we have MCE info to process. */ | 154 | /* Check if we have MCE info to process. */ |
155 | if (index < MAX_MC_EVT) { | 155 | if (index < MAX_MC_EVT) { |
156 | mc_evt = &__get_cpu_var(mce_event[index]); | 156 | mc_evt = this_cpu_ptr(&mce_event[index]); |
157 | /* Copy the event structure and release the original */ | 157 | /* Copy the event structure and release the original */ |
158 | if (mce) | 158 | if (mce) |
159 | *mce = *mc_evt; | 159 | *mce = *mc_evt; |
@@ -163,7 +163,7 @@ int get_mce_event(struct machine_check_event *mce, bool release) | |||
163 | } | 163 | } |
164 | /* Decrement the count to free the slot. */ | 164 | /* Decrement the count to free the slot. */ |
165 | if (release) | 165 | if (release) |
166 | __get_cpu_var(mce_nest_count)--; | 166 | __this_cpu_dec(mce_nest_count); |
167 | 167 | ||
168 | return ret; | 168 | return ret; |
169 | } | 169 | } |
@@ -184,13 +184,13 @@ void machine_check_queue_event(void) | |||
184 | if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) | 184 | if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) |
185 | return; | 185 | return; |
186 | 186 | ||
187 | index = __get_cpu_var(mce_queue_count)++; | 187 | index = __this_cpu_inc_return(mce_queue_count); |
188 | /* If queue is full, just return for now. */ | 188 | /* If queue is full, just return for now. */ |
189 | if (index >= MAX_MC_EVT) { | 189 | if (index >= MAX_MC_EVT) { |
190 | __get_cpu_var(mce_queue_count)--; | 190 | __this_cpu_dec(mce_queue_count); |
191 | return; | 191 | return; |
192 | } | 192 | } |
193 | __get_cpu_var(mce_event_queue[index]) = evt; | 193 | memcpy(this_cpu_ptr(&mce_event_queue[index]), &evt, sizeof(evt)); |
194 | 194 | ||
195 | /* Queue irq work to process this event later. */ | 195 | /* Queue irq work to process this event later. */ |
196 | irq_work_queue(&mce_event_process_work); | 196 | irq_work_queue(&mce_event_process_work); |
@@ -208,11 +208,11 @@ static void machine_check_process_queued_event(struct irq_work *work) | |||
208 | * For now just print it to console. | 208 | * For now just print it to console. |
209 | * TODO: log this error event to FSP or nvram. | 209 | * TODO: log this error event to FSP or nvram. |
210 | */ | 210 | */ |
211 | while (__get_cpu_var(mce_queue_count) > 0) { | 211 | while (__this_cpu_read(mce_queue_count) > 0) { |
212 | index = __get_cpu_var(mce_queue_count) - 1; | 212 | index = __this_cpu_read(mce_queue_count) - 1; |
213 | machine_check_print_event_info( | 213 | machine_check_print_event_info( |
214 | &__get_cpu_var(mce_event_queue[index])); | 214 | this_cpu_ptr(&mce_event_queue[index])); |
215 | __get_cpu_var(mce_queue_count)--; | 215 | __this_cpu_dec(mce_queue_count); |
216 | } | 216 | } |
217 | } | 217 | } |
218 | 218 | ||
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index aa9aff3d6ad3..b6f123ab90ed 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c | |||
@@ -79,7 +79,7 @@ static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits) | |||
79 | } | 79 | } |
80 | if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) { | 80 | if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) { |
81 | if (cur_cpu_spec && cur_cpu_spec->flush_tlb) | 81 | if (cur_cpu_spec && cur_cpu_spec->flush_tlb) |
82 | cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE); | 82 | cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); |
83 | /* reset error bits */ | 83 | /* reset error bits */ |
84 | dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB; | 84 | dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB; |
85 | } | 85 | } |
@@ -110,7 +110,7 @@ static long mce_handle_common_ierror(uint64_t srr1) | |||
110 | break; | 110 | break; |
111 | case P7_SRR1_MC_IFETCH_TLB_MULTIHIT: | 111 | case P7_SRR1_MC_IFETCH_TLB_MULTIHIT: |
112 | if (cur_cpu_spec && cur_cpu_spec->flush_tlb) { | 112 | if (cur_cpu_spec && cur_cpu_spec->flush_tlb) { |
113 | cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE); | 113 | cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); |
114 | handled = 1; | 114 | handled = 1; |
115 | } | 115 | } |
116 | break; | 116 | break; |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index e5dad9a9edc0..37d512d35943 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/bootmem.h> | ||
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
25 | #include <linux/export.h> | 24 | #include <linux/export.h> |
26 | #include <linux/of_address.h> | 25 | #include <linux/of_address.h> |
@@ -1464,7 +1463,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose, | |||
1464 | res = &hose->io_resource; | 1463 | res = &hose->io_resource; |
1465 | 1464 | ||
1466 | if (!res->flags) { | 1465 | if (!res->flags) { |
1467 | printk(KERN_WARNING "PCI: I/O resource not set for host" | 1466 | pr_info("PCI: I/O resource not set for host" |
1468 | " bridge %s (domain %d)\n", | 1467 | " bridge %s (domain %d)\n", |
1469 | hose->dn->full_name, hose->global_number); | 1468 | hose->dn->full_name, hose->global_number); |
1470 | } else { | 1469 | } else { |
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 432459c817fa..1f7930037cb7 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -199,9 +199,7 @@ pci_create_OF_bus_map(void) | |||
199 | struct property* of_prop; | 199 | struct property* of_prop; |
200 | struct device_node *dn; | 200 | struct device_node *dn; |
201 | 201 | ||
202 | of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256); | 202 | of_prop = memblock_virt_alloc(sizeof(struct property) + 256, 0); |
203 | if (!of_prop) | ||
204 | return; | ||
205 | dn = of_find_node_by_path("/"); | 203 | dn = of_find_node_by_path("/"); |
206 | if (dn) { | 204 | if (dn) { |
207 | memset(of_prop, -1, sizeof(struct property) + 256); | 205 | memset(of_prop, -1, sizeof(struct property) + 256); |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index b15194e2c5fc..60bb187cb46a 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/bootmem.h> | ||
21 | #include <linux/export.h> | 20 | #include <linux/export.h> |
22 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
23 | #include <linux/list.h> | 22 | #include <linux/list.h> |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 923cd2daba89..b4cc7bef6b16 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -37,9 +37,9 @@ | |||
37 | #include <linux/personality.h> | 37 | #include <linux/personality.h> |
38 | #include <linux/random.h> | 38 | #include <linux/random.h> |
39 | #include <linux/hw_breakpoint.h> | 39 | #include <linux/hw_breakpoint.h> |
40 | #include <linux/uaccess.h> | ||
40 | 41 | ||
41 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
42 | #include <asm/uaccess.h> | ||
43 | #include <asm/io.h> | 43 | #include <asm/io.h> |
44 | #include <asm/processor.h> | 44 | #include <asm/processor.h> |
45 | #include <asm/mmu.h> | 45 | #include <asm/mmu.h> |
@@ -499,7 +499,7 @@ static inline int set_dawr(struct arch_hw_breakpoint *brk) | |||
499 | 499 | ||
500 | void __set_breakpoint(struct arch_hw_breakpoint *brk) | 500 | void __set_breakpoint(struct arch_hw_breakpoint *brk) |
501 | { | 501 | { |
502 | __get_cpu_var(current_brk) = *brk; | 502 | memcpy(this_cpu_ptr(¤t_brk), brk, sizeof(*brk)); |
503 | 503 | ||
504 | if (cpu_has_feature(CPU_FTR_DAWR)) | 504 | if (cpu_has_feature(CPU_FTR_DAWR)) |
505 | set_dawr(brk); | 505 | set_dawr(brk); |
@@ -842,7 +842,7 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
842 | * schedule DABR | 842 | * schedule DABR |
843 | */ | 843 | */ |
844 | #ifndef CONFIG_HAVE_HW_BREAKPOINT | 844 | #ifndef CONFIG_HAVE_HW_BREAKPOINT |
845 | if (unlikely(!hw_brk_match(&__get_cpu_var(current_brk), &new->thread.hw_brk))) | 845 | if (unlikely(!hw_brk_match(this_cpu_ptr(¤t_brk), &new->thread.hw_brk))) |
846 | __set_breakpoint(&new->thread.hw_brk); | 846 | __set_breakpoint(&new->thread.hw_brk); |
847 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | 847 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ |
848 | #endif | 848 | #endif |
@@ -856,7 +856,7 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
856 | * Collect processor utilization data per process | 856 | * Collect processor utilization data per process |
857 | */ | 857 | */ |
858 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | 858 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { |
859 | struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); | 859 | struct cpu_usage *cu = this_cpu_ptr(&cpu_usage_array); |
860 | long unsigned start_tb, current_tb; | 860 | long unsigned start_tb, current_tb; |
861 | start_tb = old_thread->start_tb; | 861 | start_tb = old_thread->start_tb; |
862 | cu->current_tb = current_tb = mfspr(SPRN_PURR); | 862 | cu->current_tb = current_tb = mfspr(SPRN_PURR); |
@@ -866,7 +866,7 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
866 | #endif /* CONFIG_PPC64 */ | 866 | #endif /* CONFIG_PPC64 */ |
867 | 867 | ||
868 | #ifdef CONFIG_PPC_BOOK3S_64 | 868 | #ifdef CONFIG_PPC_BOOK3S_64 |
869 | batch = &__get_cpu_var(ppc64_tlb_batch); | 869 | batch = this_cpu_ptr(&ppc64_tlb_batch); |
870 | if (batch->active) { | 870 | if (batch->active) { |
871 | current_thread_info()->local_flags |= _TLF_LAZY_MMU; | 871 | current_thread_info()->local_flags |= _TLF_LAZY_MMU; |
872 | if (batch->index) | 872 | if (batch->index) |
@@ -889,7 +889,7 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
889 | #ifdef CONFIG_PPC_BOOK3S_64 | 889 | #ifdef CONFIG_PPC_BOOK3S_64 |
890 | if (current_thread_info()->local_flags & _TLF_LAZY_MMU) { | 890 | if (current_thread_info()->local_flags & _TLF_LAZY_MMU) { |
891 | current_thread_info()->local_flags &= ~_TLF_LAZY_MMU; | 891 | current_thread_info()->local_flags &= ~_TLF_LAZY_MMU; |
892 | batch = &__get_cpu_var(ppc64_tlb_batch); | 892 | batch = this_cpu_ptr(&ppc64_tlb_batch); |
893 | batch->active = 1; | 893 | batch->active = 1; |
894 | } | 894 | } |
895 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 895 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
@@ -921,12 +921,8 @@ static void show_instructions(struct pt_regs *regs) | |||
921 | pc = (unsigned long)phys_to_virt(pc); | 921 | pc = (unsigned long)phys_to_virt(pc); |
922 | #endif | 922 | #endif |
923 | 923 | ||
924 | /* We use __get_user here *only* to avoid an OOPS on a | ||
925 | * bad address because the pc *should* only be a | ||
926 | * kernel address. | ||
927 | */ | ||
928 | if (!__kernel_text_address(pc) || | 924 | if (!__kernel_text_address(pc) || |
929 | __get_user(instr, (unsigned int __user *)pc)) { | 925 | probe_kernel_address((unsigned int __user *)pc, instr)) { |
930 | printk(KERN_CONT "XXXXXXXX "); | 926 | printk(KERN_CONT "XXXXXXXX "); |
931 | } else { | 927 | } else { |
932 | if (regs->nip == pc) | 928 | if (regs->nip == pc) |
@@ -1531,13 +1527,6 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
1531 | int curr_frame = current->curr_ret_stack; | 1527 | int curr_frame = current->curr_ret_stack; |
1532 | extern void return_to_handler(void); | 1528 | extern void return_to_handler(void); |
1533 | unsigned long rth = (unsigned long)return_to_handler; | 1529 | unsigned long rth = (unsigned long)return_to_handler; |
1534 | unsigned long mrth = -1; | ||
1535 | #ifdef CONFIG_PPC64 | ||
1536 | extern void mod_return_to_handler(void); | ||
1537 | rth = *(unsigned long *)rth; | ||
1538 | mrth = (unsigned long)mod_return_to_handler; | ||
1539 | mrth = *(unsigned long *)mrth; | ||
1540 | #endif | ||
1541 | #endif | 1530 | #endif |
1542 | 1531 | ||
1543 | sp = (unsigned long) stack; | 1532 | sp = (unsigned long) stack; |
@@ -1562,7 +1551,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
1562 | if (!firstframe || ip != lr) { | 1551 | if (!firstframe || ip != lr) { |
1563 | printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip); | 1552 | printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip); |
1564 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 1553 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1565 | if ((ip == rth || ip == mrth) && curr_frame >= 0) { | 1554 | if ((ip == rth) && curr_frame >= 0) { |
1566 | printk(" (%pS)", | 1555 | printk(" (%pS)", |
1567 | (void *)current->ret_stack[curr_frame].ret); | 1556 | (void *)current->ret_stack[curr_frame].ret); |
1568 | curr_frame--; | 1557 | curr_frame--; |
@@ -1665,12 +1654,3 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) | |||
1665 | return ret; | 1654 | return ret; |
1666 | } | 1655 | } |
1667 | 1656 | ||
1668 | unsigned long randomize_et_dyn(unsigned long base) | ||
1669 | { | ||
1670 | unsigned long ret = PAGE_ALIGN(base + brk_rnd()); | ||
1671 | |||
1672 | if (ret < base) | ||
1673 | return base; | ||
1674 | |||
1675 | return ret; | ||
1676 | } | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 099f27e6d1b0..6a799b3cc6b4 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -160,6 +160,12 @@ static struct ibm_pa_feature { | |||
160 | {CPU_FTR_NODSISRALIGN, 0, 0, 1, 1, 1}, | 160 | {CPU_FTR_NODSISRALIGN, 0, 0, 1, 1, 1}, |
161 | {0, MMU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, | 161 | {0, MMU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, |
162 | {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, | 162 | {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, |
163 | /* | ||
164 | * If the kernel doesn't support TM (ie. CONFIG_PPC_TRANSACTIONAL_MEM=n), | ||
165 | * we don't want to turn on CPU_FTR_TM here, so we use CPU_FTR_TM_COMP | ||
166 | * which is 0 if the kernel doesn't support TM. | ||
167 | */ | ||
168 | {CPU_FTR_TM_COMP, 0, 0, 22, 0, 0}, | ||
163 | }; | 169 | }; |
164 | 170 | ||
165 | static void __init scan_features(unsigned long node, const unsigned char *ftrs, | 171 | static void __init scan_features(unsigned long node, const unsigned char *ftrs, |
@@ -696,10 +702,7 @@ void __init early_init_devtree(void *params) | |||
696 | reserve_crashkernel(); | 702 | reserve_crashkernel(); |
697 | early_reserve_mem(); | 703 | early_reserve_mem(); |
698 | 704 | ||
699 | /* | 705 | /* Ensure that total memory size is page-aligned. */ |
700 | * Ensure that total memory size is page-aligned, because otherwise | ||
701 | * mark_bootmem() gets upset. | ||
702 | */ | ||
703 | limit = ALIGN(memory_limit ?: memblock_phys_mem_size(), PAGE_SIZE); | 706 | limit = ALIGN(memory_limit ?: memblock_phys_mem_size(), PAGE_SIZE); |
704 | memblock_enforce_memory_limit(limit); | 707 | memblock_enforce_memory_limit(limit); |
705 | 708 | ||
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 8777fb02349f..fb2fb3ea85e5 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c | |||
@@ -113,17 +113,6 @@ | |||
113 | #define SENSOR_PREFIX "ibm,sensor-" | 113 | #define SENSOR_PREFIX "ibm,sensor-" |
114 | #define cel_to_fahr(x) ((x*9/5)+32) | 114 | #define cel_to_fahr(x) ((x*9/5)+32) |
115 | 115 | ||
116 | |||
117 | /* Globals */ | ||
118 | static struct rtas_sensors sensors; | ||
119 | static struct device_node *rtas_node = NULL; | ||
120 | static unsigned long power_on_time = 0; /* Save the time the user set */ | ||
121 | static char progress_led[MAX_LINELENGTH]; | ||
122 | |||
123 | static unsigned long rtas_tone_frequency = 1000; | ||
124 | static unsigned long rtas_tone_volume = 0; | ||
125 | |||
126 | /* ****************STRUCTS******************************************* */ | ||
127 | struct individual_sensor { | 116 | struct individual_sensor { |
128 | unsigned int token; | 117 | unsigned int token; |
129 | unsigned int quant; | 118 | unsigned int quant; |
@@ -134,6 +123,15 @@ struct rtas_sensors { | |||
134 | unsigned int quant; | 123 | unsigned int quant; |
135 | }; | 124 | }; |
136 | 125 | ||
126 | /* Globals */ | ||
127 | static struct rtas_sensors sensors; | ||
128 | static struct device_node *rtas_node = NULL; | ||
129 | static unsigned long power_on_time = 0; /* Save the time the user set */ | ||
130 | static char progress_led[MAX_LINELENGTH]; | ||
131 | |||
132 | static unsigned long rtas_tone_frequency = 1000; | ||
133 | static unsigned long rtas_tone_volume = 0; | ||
134 | |||
137 | /* ****************************************************************** */ | 135 | /* ****************************************************************** */ |
138 | /* Declarations */ | 136 | /* Declarations */ |
139 | static int ppc_rtas_sensors_show(struct seq_file *m, void *v); | 137 | static int ppc_rtas_sensors_show(struct seq_file *m, void *v); |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 8b4c857c1421..4af905e81ab0 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -1091,8 +1091,8 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | /* | 1093 | /* |
1094 | * Call early during boot, before mem init or bootmem, to retrieve the RTAS | 1094 | * Call early during boot, before mem init, to retrieve the RTAS |
1095 | * informations from the device-tree and allocate the RMO buffer for userland | 1095 | * information from the device-tree and allocate the RMO buffer for userland |
1096 | * accesses. | 1096 | * accesses. |
1097 | */ | 1097 | */ |
1098 | void __init rtas_initialize(void) | 1098 | void __init rtas_initialize(void) |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 7c55b86206b3..ce230da2c015 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/string.h> | 27 | #include <linux/string.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/bootmem.h> | ||
30 | 29 | ||
31 | #include <asm/io.h> | 30 | #include <asm/io.h> |
32 | #include <asm/pgtable.h> | 31 | #include <asm/pgtable.h> |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 1362cd62b3fa..44c8d03558ac 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -139,8 +139,8 @@ void machine_restart(char *cmd) | |||
139 | void machine_power_off(void) | 139 | void machine_power_off(void) |
140 | { | 140 | { |
141 | machine_shutdown(); | 141 | machine_shutdown(); |
142 | if (ppc_md.power_off) | 142 | if (pm_power_off) |
143 | ppc_md.power_off(); | 143 | pm_power_off(); |
144 | #ifdef CONFIG_SMP | 144 | #ifdef CONFIG_SMP |
145 | smp_send_stop(); | 145 | smp_send_stop(); |
146 | #endif | 146 | #endif |
@@ -151,7 +151,7 @@ void machine_power_off(void) | |||
151 | /* Used by the G5 thermal driver */ | 151 | /* Used by the G5 thermal driver */ |
152 | EXPORT_SYMBOL_GPL(machine_power_off); | 152 | EXPORT_SYMBOL_GPL(machine_power_off); |
153 | 153 | ||
154 | void (*pm_power_off)(void) = machine_power_off; | 154 | void (*pm_power_off)(void); |
155 | EXPORT_SYMBOL_GPL(pm_power_off); | 155 | EXPORT_SYMBOL_GPL(pm_power_off); |
156 | 156 | ||
157 | void machine_halt(void) | 157 | void machine_halt(void) |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 07831ed0d9ef..bb02e9f6944e 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/initrd.h> | 12 | #include <linux/initrd.h> |
13 | #include <linux/tty.h> | 13 | #include <linux/tty.h> |
14 | #include <linux/bootmem.h> | ||
15 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
16 | #include <linux/root_dev.h> | 15 | #include <linux/root_dev.h> |
17 | #include <linux/cpu.h> | 16 | #include <linux/cpu.h> |
@@ -53,11 +52,6 @@ unsigned long ISA_DMA_THRESHOLD; | |||
53 | unsigned int DMA_MODE_READ; | 52 | unsigned int DMA_MODE_READ; |
54 | unsigned int DMA_MODE_WRITE; | 53 | unsigned int DMA_MODE_WRITE; |
55 | 54 | ||
56 | #ifdef CONFIG_VGA_CONSOLE | ||
57 | unsigned long vgacon_remap_base; | ||
58 | EXPORT_SYMBOL(vgacon_remap_base); | ||
59 | #endif | ||
60 | |||
61 | /* | 55 | /* |
62 | * These are used in binfmt_elf.c to put aux entries on the stack | 56 | * These are used in binfmt_elf.c to put aux entries on the stack |
63 | * for each elf executable being started. | 57 | * for each elf executable being started. |
@@ -311,9 +305,8 @@ void __init setup_arch(char **cmdline_p) | |||
311 | 305 | ||
312 | irqstack_early_init(); | 306 | irqstack_early_init(); |
313 | 307 | ||
314 | /* set up the bootmem stuff with available memory */ | 308 | initmem_init(); |
315 | do_init_bootmem(); | 309 | if ( ppc_md.progress ) ppc_md.progress("setup_arch: initmem", 0x3eab); |
316 | if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); | ||
317 | 310 | ||
318 | #ifdef CONFIG_DUMMY_CONSOLE | 311 | #ifdef CONFIG_DUMMY_CONSOLE |
319 | conswitchp = &dummy_con; | 312 | conswitchp = &dummy_con; |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4f3cfe1b6a33..49f553bbb360 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -660,13 +660,11 @@ static void __init emergency_stack_init(void) | |||
660 | } | 660 | } |
661 | 661 | ||
662 | /* | 662 | /* |
663 | * Called into from start_kernel this initializes bootmem, which is used | 663 | * Called into from start_kernel this initializes memblock, which is used |
664 | * to manage page allocation until mem_init is called. | 664 | * to manage page allocation until mem_init is called. |
665 | */ | 665 | */ |
666 | void __init setup_arch(char **cmdline_p) | 666 | void __init setup_arch(char **cmdline_p) |
667 | { | 667 | { |
668 | ppc64_boot_msg(0x12, "Setup Arch"); | ||
669 | |||
670 | *cmdline_p = boot_command_line; | 668 | *cmdline_p = boot_command_line; |
671 | 669 | ||
672 | /* | 670 | /* |
@@ -691,9 +689,7 @@ void __init setup_arch(char **cmdline_p) | |||
691 | exc_lvl_early_init(); | 689 | exc_lvl_early_init(); |
692 | emergency_stack_init(); | 690 | emergency_stack_init(); |
693 | 691 | ||
694 | /* set up the bootmem stuff with available memory */ | 692 | initmem_init(); |
695 | do_init_bootmem(); | ||
696 | sparse_init(); | ||
697 | 693 | ||
698 | #ifdef CONFIG_DUMMY_CONSOLE | 694 | #ifdef CONFIG_DUMMY_CONSOLE |
699 | conswitchp = &dummy_con; | 695 | conswitchp = &dummy_con; |
@@ -711,33 +707,6 @@ void __init setup_arch(char **cmdline_p) | |||
711 | if ((unsigned long)_stext & 0xffff) | 707 | if ((unsigned long)_stext & 0xffff) |
712 | panic("Kernelbase not 64K-aligned (0x%lx)!\n", | 708 | panic("Kernelbase not 64K-aligned (0x%lx)!\n", |
713 | (unsigned long)_stext); | 709 | (unsigned long)_stext); |
714 | |||
715 | ppc64_boot_msg(0x15, "Setup Done"); | ||
716 | } | ||
717 | |||
718 | |||
719 | /* ToDo: do something useful if ppc_md is not yet setup. */ | ||
720 | #define PPC64_LINUX_FUNCTION 0x0f000000 | ||
721 | #define PPC64_IPL_MESSAGE 0xc0000000 | ||
722 | #define PPC64_TERM_MESSAGE 0xb0000000 | ||
723 | |||
724 | static void ppc64_do_msg(unsigned int src, const char *msg) | ||
725 | { | ||
726 | if (ppc_md.progress) { | ||
727 | char buf[128]; | ||
728 | |||
729 | sprintf(buf, "%08X\n", src); | ||
730 | ppc_md.progress(buf, 0); | ||
731 | snprintf(buf, 128, "%s", msg); | ||
732 | ppc_md.progress(buf, 0); | ||
733 | } | ||
734 | } | ||
735 | |||
736 | /* Print a boot progress message. */ | ||
737 | void ppc64_boot_msg(unsigned int src, const char *msg) | ||
738 | { | ||
739 | ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg); | ||
740 | printk("[boot]%04x %s\n", src, msg); | ||
741 | } | 710 | } |
742 | 711 | ||
743 | #ifdef CONFIG_SMP | 712 | #ifdef CONFIG_SMP |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 71e186d5f331..8b2d2dc8ef10 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -243,7 +243,7 @@ void smp_muxed_ipi_message_pass(int cpu, int msg) | |||
243 | 243 | ||
244 | irqreturn_t smp_ipi_demux(void) | 244 | irqreturn_t smp_ipi_demux(void) |
245 | { | 245 | { |
246 | struct cpu_messages *info = &__get_cpu_var(ipi_message); | 246 | struct cpu_messages *info = this_cpu_ptr(&ipi_message); |
247 | unsigned int all; | 247 | unsigned int all; |
248 | 248 | ||
249 | mb(); /* order any irq clear */ | 249 | mb(); /* order any irq clear */ |
@@ -442,9 +442,9 @@ void generic_mach_cpu_die(void) | |||
442 | idle_task_exit(); | 442 | idle_task_exit(); |
443 | cpu = smp_processor_id(); | 443 | cpu = smp_processor_id(); |
444 | printk(KERN_DEBUG "CPU%d offline\n", cpu); | 444 | printk(KERN_DEBUG "CPU%d offline\n", cpu); |
445 | __get_cpu_var(cpu_state) = CPU_DEAD; | 445 | __this_cpu_write(cpu_state, CPU_DEAD); |
446 | smp_wmb(); | 446 | smp_wmb(); |
447 | while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) | 447 | while (__this_cpu_read(cpu_state) != CPU_UP_PREPARE) |
448 | cpu_relax(); | 448 | cpu_relax(); |
449 | } | 449 | } |
450 | 450 | ||
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 67fd2fd2620a..fa1fd8a0c867 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -394,10 +394,10 @@ void ppc_enable_pmcs(void) | |||
394 | ppc_set_pmu_inuse(1); | 394 | ppc_set_pmu_inuse(1); |
395 | 395 | ||
396 | /* Only need to enable them once */ | 396 | /* Only need to enable them once */ |
397 | if (__get_cpu_var(pmcs_enabled)) | 397 | if (__this_cpu_read(pmcs_enabled)) |
398 | return; | 398 | return; |
399 | 399 | ||
400 | __get_cpu_var(pmcs_enabled) = 1; | 400 | __this_cpu_write(pmcs_enabled, 1); |
401 | 401 | ||
402 | if (ppc_md.enable_pmcs) | 402 | if (ppc_md.enable_pmcs) |
403 | ppc_md.enable_pmcs(); | 403 | ppc_md.enable_pmcs(); |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 7505599c2593..fa7c4f12104f 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -458,9 +458,9 @@ static inline void clear_irq_work_pending(void) | |||
458 | 458 | ||
459 | DEFINE_PER_CPU(u8, irq_work_pending); | 459 | DEFINE_PER_CPU(u8, irq_work_pending); |
460 | 460 | ||
461 | #define set_irq_work_pending_flag() __get_cpu_var(irq_work_pending) = 1 | 461 | #define set_irq_work_pending_flag() __this_cpu_write(irq_work_pending, 1) |
462 | #define test_irq_work_pending() __get_cpu_var(irq_work_pending) | 462 | #define test_irq_work_pending() __this_cpu_read(irq_work_pending) |
463 | #define clear_irq_work_pending() __get_cpu_var(irq_work_pending) = 0 | 463 | #define clear_irq_work_pending() __this_cpu_write(irq_work_pending, 0) |
464 | 464 | ||
465 | #endif /* 32 vs 64 bit */ | 465 | #endif /* 32 vs 64 bit */ |
466 | 466 | ||
@@ -482,8 +482,8 @@ void arch_irq_work_raise(void) | |||
482 | static void __timer_interrupt(void) | 482 | static void __timer_interrupt(void) |
483 | { | 483 | { |
484 | struct pt_regs *regs = get_irq_regs(); | 484 | struct pt_regs *regs = get_irq_regs(); |
485 | u64 *next_tb = &__get_cpu_var(decrementers_next_tb); | 485 | u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); |
486 | struct clock_event_device *evt = &__get_cpu_var(decrementers); | 486 | struct clock_event_device *evt = this_cpu_ptr(&decrementers); |
487 | u64 now; | 487 | u64 now; |
488 | 488 | ||
489 | trace_timer_interrupt_entry(regs); | 489 | trace_timer_interrupt_entry(regs); |
@@ -498,7 +498,7 @@ static void __timer_interrupt(void) | |||
498 | *next_tb = ~(u64)0; | 498 | *next_tb = ~(u64)0; |
499 | if (evt->event_handler) | 499 | if (evt->event_handler) |
500 | evt->event_handler(evt); | 500 | evt->event_handler(evt); |
501 | __get_cpu_var(irq_stat).timer_irqs_event++; | 501 | __this_cpu_inc(irq_stat.timer_irqs_event); |
502 | } else { | 502 | } else { |
503 | now = *next_tb - now; | 503 | now = *next_tb - now; |
504 | if (now <= DECREMENTER_MAX) | 504 | if (now <= DECREMENTER_MAX) |
@@ -506,13 +506,13 @@ static void __timer_interrupt(void) | |||
506 | /* We may have raced with new irq work */ | 506 | /* We may have raced with new irq work */ |
507 | if (test_irq_work_pending()) | 507 | if (test_irq_work_pending()) |
508 | set_dec(1); | 508 | set_dec(1); |
509 | __get_cpu_var(irq_stat).timer_irqs_others++; | 509 | __this_cpu_inc(irq_stat.timer_irqs_others); |
510 | } | 510 | } |
511 | 511 | ||
512 | #ifdef CONFIG_PPC64 | 512 | #ifdef CONFIG_PPC64 |
513 | /* collect purr register values often, for accurate calculations */ | 513 | /* collect purr register values often, for accurate calculations */ |
514 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | 514 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { |
515 | struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); | 515 | struct cpu_usage *cu = this_cpu_ptr(&cpu_usage_array); |
516 | cu->current_tb = mfspr(SPRN_PURR); | 516 | cu->current_tb = mfspr(SPRN_PURR); |
517 | } | 517 | } |
518 | #endif | 518 | #endif |
@@ -527,7 +527,7 @@ static void __timer_interrupt(void) | |||
527 | void timer_interrupt(struct pt_regs * regs) | 527 | void timer_interrupt(struct pt_regs * regs) |
528 | { | 528 | { |
529 | struct pt_regs *old_regs; | 529 | struct pt_regs *old_regs; |
530 | u64 *next_tb = &__get_cpu_var(decrementers_next_tb); | 530 | u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); |
531 | 531 | ||
532 | /* Ensure a positive value is written to the decrementer, or else | 532 | /* Ensure a positive value is written to the decrementer, or else |
533 | * some CPUs will continue to take decrementer exceptions. | 533 | * some CPUs will continue to take decrementer exceptions. |
@@ -813,7 +813,7 @@ static void __init clocksource_init(void) | |||
813 | static int decrementer_set_next_event(unsigned long evt, | 813 | static int decrementer_set_next_event(unsigned long evt, |
814 | struct clock_event_device *dev) | 814 | struct clock_event_device *dev) |
815 | { | 815 | { |
816 | __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt; | 816 | __this_cpu_write(decrementers_next_tb, get_tb_or_rtc() + evt); |
817 | set_dec(evt); | 817 | set_dec(evt); |
818 | 818 | ||
819 | /* We may have raced with new irq work */ | 819 | /* We may have raced with new irq work */ |
@@ -833,7 +833,7 @@ static void decrementer_set_mode(enum clock_event_mode mode, | |||
833 | /* Interrupt handler for the timer broadcast IPI */ | 833 | /* Interrupt handler for the timer broadcast IPI */ |
834 | void tick_broadcast_ipi_handler(void) | 834 | void tick_broadcast_ipi_handler(void) |
835 | { | 835 | { |
836 | u64 *next_tb = &__get_cpu_var(decrementers_next_tb); | 836 | u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); |
837 | 837 | ||
838 | *next_tb = get_tb_or_rtc(); | 838 | *next_tb = get_tb_or_rtc(); |
839 | __timer_interrupt(); | 839 | __timer_interrupt(); |
@@ -989,6 +989,7 @@ void GregorianDay(struct rtc_time * tm) | |||
989 | 989 | ||
990 | tm->tm_wday = day % 7; | 990 | tm->tm_wday = day % 7; |
991 | } | 991 | } |
992 | EXPORT_SYMBOL_GPL(GregorianDay); | ||
992 | 993 | ||
993 | void to_tm(int tim, struct rtc_time * tm) | 994 | void to_tm(int tim, struct rtc_time * tm) |
994 | { | 995 | { |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 0dc43f9932cf..e6595b72269b 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -295,7 +295,7 @@ long machine_check_early(struct pt_regs *regs) | |||
295 | { | 295 | { |
296 | long handled = 0; | 296 | long handled = 0; |
297 | 297 | ||
298 | __get_cpu_var(irq_stat).mce_exceptions++; | 298 | __this_cpu_inc(irq_stat.mce_exceptions); |
299 | 299 | ||
300 | if (cur_cpu_spec && cur_cpu_spec->machine_check_early) | 300 | if (cur_cpu_spec && cur_cpu_spec->machine_check_early) |
301 | handled = cur_cpu_spec->machine_check_early(regs); | 301 | handled = cur_cpu_spec->machine_check_early(regs); |
@@ -304,7 +304,7 @@ long machine_check_early(struct pt_regs *regs) | |||
304 | 304 | ||
305 | long hmi_exception_realmode(struct pt_regs *regs) | 305 | long hmi_exception_realmode(struct pt_regs *regs) |
306 | { | 306 | { |
307 | __get_cpu_var(irq_stat).hmi_exceptions++; | 307 | __this_cpu_inc(irq_stat.hmi_exceptions); |
308 | 308 | ||
309 | if (ppc_md.hmi_exception_early) | 309 | if (ppc_md.hmi_exception_early) |
310 | ppc_md.hmi_exception_early(regs); | 310 | ppc_md.hmi_exception_early(regs); |
@@ -700,7 +700,7 @@ void machine_check_exception(struct pt_regs *regs) | |||
700 | enum ctx_state prev_state = exception_enter(); | 700 | enum ctx_state prev_state = exception_enter(); |
701 | int recover = 0; | 701 | int recover = 0; |
702 | 702 | ||
703 | __get_cpu_var(irq_stat).mce_exceptions++; | 703 | __this_cpu_inc(irq_stat.mce_exceptions); |
704 | 704 | ||
705 | /* See if any machine dependent calls. In theory, we would want | 705 | /* See if any machine dependent calls. In theory, we would want |
706 | * to call the CPU first, and call the ppc_md. one if the CPU | 706 | * to call the CPU first, and call the ppc_md. one if the CPU |
@@ -1519,7 +1519,7 @@ void vsx_unavailable_tm(struct pt_regs *regs) | |||
1519 | 1519 | ||
1520 | void performance_monitor_exception(struct pt_regs *regs) | 1520 | void performance_monitor_exception(struct pt_regs *regs) |
1521 | { | 1521 | { |
1522 | __get_cpu_var(irq_stat).pmu_irqs++; | 1522 | __this_cpu_inc(irq_stat.pmu_irqs); |
1523 | 1523 | ||
1524 | perf_irq(regs); | 1524 | perf_irq(regs); |
1525 | } | 1525 | } |
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 6e7c4923b5ea..411116c38da4 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c | |||
@@ -69,8 +69,12 @@ static void udbg_uart_putc(char c) | |||
69 | 69 | ||
70 | static int udbg_uart_getc_poll(void) | 70 | static int udbg_uart_getc_poll(void) |
71 | { | 71 | { |
72 | if (!udbg_uart_in || !(udbg_uart_in(UART_LSR) & LSR_DR)) | 72 | if (!udbg_uart_in) |
73 | return -1; | ||
74 | |||
75 | if (!(udbg_uart_in(UART_LSR) & LSR_DR)) | ||
73 | return udbg_uart_in(UART_RBR); | 76 | return udbg_uart_in(UART_RBR); |
77 | |||
74 | return -1; | 78 | return -1; |
75 | } | 79 | } |
76 | 80 | ||
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index f174351842cf..305eb0d9b768 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/user.h> | 20 | #include <linux/user.h> |
21 | #include <linux/elf.h> | 21 | #include <linux/elf.h> |
22 | #include <linux/security.h> | 22 | #include <linux/security.h> |
23 | #include <linux/bootmem.h> | ||
24 | #include <linux/memblock.h> | 23 | #include <linux/memblock.h> |
25 | 24 | ||
26 | #include <asm/pgtable.h> | 25 | #include <asm/pgtable.h> |
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 4fdc27c80f4c..3f1bb5a36c27 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/export.h> | 12 | #include <linux/export.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/bootmem.h> | ||
16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
17 | #include <linux/memblock.h> | 16 | #include <linux/memblock.h> |
18 | #include <linux/sizes.h> | 17 | #include <linux/sizes.h> |
@@ -154,7 +153,7 @@ EXPORT_SYMBOL_GPL(kvm_release_hpt); | |||
154 | * kvm_cma_reserve() - reserve area for kvm hash pagetable | 153 | * kvm_cma_reserve() - reserve area for kvm hash pagetable |
155 | * | 154 | * |
156 | * This function reserves memory from early allocator. It should be | 155 | * This function reserves memory from early allocator. It should be |
157 | * called by arch specific code once the early allocator (memblock or bootmem) | 156 | * called by arch specific code once the memblock allocator |
158 | * has been activated and all other subsystems have already allocated/reserved | 157 | * has been activated and all other subsystems have already allocated/reserved |
159 | * memory. | 158 | * memory. |
160 | */ | 159 | */ |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index edb2ccdbb2ba..65c105b17a25 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -201,8 +201,6 @@ kvmppc_primary_no_guest: | |||
201 | bge kvm_novcpu_exit /* another thread already exiting */ | 201 | bge kvm_novcpu_exit /* another thread already exiting */ |
202 | li r3, NAPPING_NOVCPU | 202 | li r3, NAPPING_NOVCPU |
203 | stb r3, HSTATE_NAPPING(r13) | 203 | stb r3, HSTATE_NAPPING(r13) |
204 | li r3, 1 | ||
205 | stb r3, HSTATE_HWTHREAD_REQ(r13) | ||
206 | 204 | ||
207 | b kvm_do_nap | 205 | b kvm_do_nap |
208 | 206 | ||
@@ -293,6 +291,8 @@ kvm_start_guest: | |||
293 | /* if we have no vcpu to run, go back to sleep */ | 291 | /* if we have no vcpu to run, go back to sleep */ |
294 | beq kvm_no_guest | 292 | beq kvm_no_guest |
295 | 293 | ||
294 | kvm_secondary_got_guest: | ||
295 | |||
296 | /* Set HSTATE_DSCR(r13) to something sensible */ | 296 | /* Set HSTATE_DSCR(r13) to something sensible */ |
297 | ld r6, PACA_DSCR(r13) | 297 | ld r6, PACA_DSCR(r13) |
298 | std r6, HSTATE_DSCR(r13) | 298 | std r6, HSTATE_DSCR(r13) |
@@ -318,27 +318,46 @@ kvm_start_guest: | |||
318 | stwcx. r3, 0, r4 | 318 | stwcx. r3, 0, r4 |
319 | bne 51b | 319 | bne 51b |
320 | 320 | ||
321 | /* | ||
322 | * At this point we have finished executing in the guest. | ||
323 | * We need to wait for hwthread_req to become zero, since | ||
324 | * we may not turn on the MMU while hwthread_req is non-zero. | ||
325 | * While waiting we also need to check if we get given a vcpu to run. | ||
326 | */ | ||
321 | kvm_no_guest: | 327 | kvm_no_guest: |
322 | li r0, KVM_HWTHREAD_IN_NAP | 328 | lbz r3, HSTATE_HWTHREAD_REQ(r13) |
329 | cmpwi r3, 0 | ||
330 | bne 53f | ||
331 | HMT_MEDIUM | ||
332 | li r0, KVM_HWTHREAD_IN_KERNEL | ||
323 | stb r0, HSTATE_HWTHREAD_STATE(r13) | 333 | stb r0, HSTATE_HWTHREAD_STATE(r13) |
324 | kvm_do_nap: | 334 | /* need to recheck hwthread_req after a barrier, to avoid race */ |
325 | /* Clear the runlatch bit before napping */ | 335 | sync |
326 | mfspr r2, SPRN_CTRLF | 336 | lbz r3, HSTATE_HWTHREAD_REQ(r13) |
327 | clrrdi r2, r2, 1 | 337 | cmpwi r3, 0 |
328 | mtspr SPRN_CTRLT, r2 | 338 | bne 54f |
329 | 339 | /* | |
340 | * We jump to power7_wakeup_loss, which will return to the caller | ||
341 | * of power7_nap in the powernv cpu offline loop. The value we | ||
342 | * put in r3 becomes the return value for power7_nap. | ||
343 | */ | ||
330 | li r3, LPCR_PECE0 | 344 | li r3, LPCR_PECE0 |
331 | mfspr r4, SPRN_LPCR | 345 | mfspr r4, SPRN_LPCR |
332 | rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1 | 346 | rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1 |
333 | mtspr SPRN_LPCR, r4 | 347 | mtspr SPRN_LPCR, r4 |
334 | isync | 348 | li r3, 0 |
335 | std r0, HSTATE_SCRATCH0(r13) | 349 | b power7_wakeup_loss |
336 | ptesync | 350 | |
337 | ld r0, HSTATE_SCRATCH0(r13) | 351 | 53: HMT_LOW |
338 | 1: cmpd r0, r0 | 352 | ld r4, HSTATE_KVM_VCPU(r13) |
339 | bne 1b | 353 | cmpdi r4, 0 |
340 | nap | 354 | beq kvm_no_guest |
341 | b . | 355 | HMT_MEDIUM |
356 | b kvm_secondary_got_guest | ||
357 | |||
358 | 54: li r0, KVM_HWTHREAD_IN_KVM | ||
359 | stb r0, HSTATE_HWTHREAD_STATE(r13) | ||
360 | b kvm_no_guest | ||
342 | 361 | ||
343 | /****************************************************************************** | 362 | /****************************************************************************** |
344 | * * | 363 | * * |
@@ -2172,6 +2191,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206) | |||
2172 | * occurs, with PECE1, PECE0 and PECEDP set in LPCR. Also clear the | 2191 | * occurs, with PECE1, PECE0 and PECEDP set in LPCR. Also clear the |
2173 | * runlatch bit before napping. | 2192 | * runlatch bit before napping. |
2174 | */ | 2193 | */ |
2194 | kvm_do_nap: | ||
2175 | mfspr r2, SPRN_CTRLF | 2195 | mfspr r2, SPRN_CTRLF |
2176 | clrrdi r2, r2, 1 | 2196 | clrrdi r2, r2, 1 |
2177 | mtspr SPRN_CTRLT, r2 | 2197 | mtspr SPRN_CTRLT, r2 |
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c index 2e02ed849f36..16095841afe1 100644 --- a/arch/powerpc/kvm/e500.c +++ b/arch/powerpc/kvm/e500.c | |||
@@ -76,11 +76,11 @@ static inline int local_sid_setup_one(struct id *entry) | |||
76 | unsigned long sid; | 76 | unsigned long sid; |
77 | int ret = -1; | 77 | int ret = -1; |
78 | 78 | ||
79 | sid = ++(__get_cpu_var(pcpu_last_used_sid)); | 79 | sid = __this_cpu_inc_return(pcpu_last_used_sid); |
80 | if (sid < NUM_TIDS) { | 80 | if (sid < NUM_TIDS) { |
81 | __get_cpu_var(pcpu_sids).entry[sid] = entry; | 81 | __this_cpu_write(pcpu_sids)entry[sid], entry); |
82 | entry->val = sid; | 82 | entry->val = sid; |
83 | entry->pentry = &__get_cpu_var(pcpu_sids).entry[sid]; | 83 | entry->pentry = this_cpu_ptr(&pcpu_sids.entry[sid]); |
84 | ret = sid; | 84 | ret = sid; |
85 | } | 85 | } |
86 | 86 | ||
@@ -108,8 +108,8 @@ static inline int local_sid_setup_one(struct id *entry) | |||
108 | static inline int local_sid_lookup(struct id *entry) | 108 | static inline int local_sid_lookup(struct id *entry) |
109 | { | 109 | { |
110 | if (entry && entry->val != 0 && | 110 | if (entry && entry->val != 0 && |
111 | __get_cpu_var(pcpu_sids).entry[entry->val] == entry && | 111 | __this_cpu_read(pcpu_sids.entry[entry->val]) == entry && |
112 | entry->pentry == &__get_cpu_var(pcpu_sids).entry[entry->val]) | 112 | entry->pentry == this_cpu_ptr(&pcpu_sids.entry[entry->val])) |
113 | return entry->val; | 113 | return entry->val; |
114 | return -1; | 114 | return -1; |
115 | } | 115 | } |
@@ -117,8 +117,8 @@ static inline int local_sid_lookup(struct id *entry) | |||
117 | /* Invalidate all id mappings on local core -- call with preempt disabled */ | 117 | /* Invalidate all id mappings on local core -- call with preempt disabled */ |
118 | static inline void local_sid_destroy_all(void) | 118 | static inline void local_sid_destroy_all(void) |
119 | { | 119 | { |
120 | __get_cpu_var(pcpu_last_used_sid) = 0; | 120 | __this_cpu_write(pcpu_last_used_sid, 0); |
121 | memset(&__get_cpu_var(pcpu_sids), 0, sizeof(__get_cpu_var(pcpu_sids))); | 121 | memset(this_cpu_ptr(&pcpu_sids), 0, sizeof(pcpu_sids)); |
122 | } | 122 | } |
123 | 123 | ||
124 | static void *kvmppc_e500_id_table_alloc(struct kvmppc_vcpu_e500 *vcpu_e500) | 124 | static void *kvmppc_e500_id_table_alloc(struct kvmppc_vcpu_e500 *vcpu_e500) |
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index 769778f855b0..cc536d4a75ef 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c | |||
@@ -661,7 +661,7 @@ int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type, | |||
661 | if (unlikely((pr && !(mas3 & MAS3_UX)) || | 661 | if (unlikely((pr && !(mas3 & MAS3_UX)) || |
662 | (!pr && !(mas3 & MAS3_SX)))) { | 662 | (!pr && !(mas3 & MAS3_SX)))) { |
663 | pr_err_ratelimited( | 663 | pr_err_ratelimited( |
664 | "%s: Instuction emulation from guest addres %08lx without execute permission\n", | 664 | "%s: Instruction emulation from guest address %08lx without execute permission\n", |
665 | __func__, geaddr); | 665 | __func__, geaddr); |
666 | return EMULATE_AGAIN; | 666 | return EMULATE_AGAIN; |
667 | } | 667 | } |
@@ -673,7 +673,7 @@ int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type, | |||
673 | if (has_feature(vcpu, VCPU_FTR_MMU_V2) && | 673 | if (has_feature(vcpu, VCPU_FTR_MMU_V2) && |
674 | unlikely((mas2 & MAS2_I) || (mas2 & MAS2_W) || !(mas2 & MAS2_M))) { | 674 | unlikely((mas2 & MAS2_I) || (mas2 & MAS2_W) || !(mas2 & MAS2_M))) { |
675 | pr_err_ratelimited( | 675 | pr_err_ratelimited( |
676 | "%s: Instuction emulation from guest addres %08lx mismatches storage attributes\n", | 676 | "%s: Instruction emulation from guest address %08lx mismatches storage attributes\n", |
677 | __func__, geaddr); | 677 | __func__, geaddr); |
678 | return EMULATE_AGAIN; | 678 | return EMULATE_AGAIN; |
679 | } | 679 | } |
@@ -686,7 +686,7 @@ int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type, | |||
686 | 686 | ||
687 | /* Guard against emulation from devices area */ | 687 | /* Guard against emulation from devices area */ |
688 | if (unlikely(!page_is_ram(pfn))) { | 688 | if (unlikely(!page_is_ram(pfn))) { |
689 | pr_err_ratelimited("%s: Instruction emulation from non-RAM host addres %08llx is not supported\n", | 689 | pr_err_ratelimited("%s: Instruction emulation from non-RAM host address %08llx is not supported\n", |
690 | __func__, addr); | 690 | __func__, addr); |
691 | return EMULATE_AGAIN; | 691 | return EMULATE_AGAIN; |
692 | } | 692 | } |
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c index 2fdc8722e324..cda695de8aa7 100644 --- a/arch/powerpc/kvm/e500mc.c +++ b/arch/powerpc/kvm/e500mc.c | |||
@@ -144,9 +144,9 @@ static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu) | |||
144 | mtspr(SPRN_GESR, vcpu->arch.shared->esr); | 144 | mtspr(SPRN_GESR, vcpu->arch.shared->esr); |
145 | 145 | ||
146 | if (vcpu->arch.oldpir != mfspr(SPRN_PIR) || | 146 | if (vcpu->arch.oldpir != mfspr(SPRN_PIR) || |
147 | __get_cpu_var(last_vcpu_of_lpid)[get_lpid(vcpu)] != vcpu) { | 147 | __this_cpu_read(last_vcpu_of_lpid[get_lpid(vcpu)]) != vcpu) { |
148 | kvmppc_e500_tlbil_all(vcpu_e500); | 148 | kvmppc_e500_tlbil_all(vcpu_e500); |
149 | __get_cpu_var(last_vcpu_of_lpid)[get_lpid(vcpu)] = vcpu; | 149 | __this_cpu_write(last_vcpu_of_lpid[get_lpid(vcpu)], vcpu); |
150 | } | 150 | } |
151 | } | 151 | } |
152 | 152 | ||
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 9f342f134ae4..597562f69b2d 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile | |||
@@ -12,7 +12,6 @@ CFLAGS_REMOVE_feature-fixups.o = -pg | |||
12 | obj-y := string.o alloc.o \ | 12 | obj-y := string.o alloc.o \ |
13 | crtsavres.o ppc_ksyms.o | 13 | crtsavres.o ppc_ksyms.o |
14 | obj-$(CONFIG_PPC32) += div64.o copy_32.o | 14 | obj-$(CONFIG_PPC32) += div64.o copy_32.o |
15 | obj-$(CONFIG_HAS_IOMEM) += devres.o | ||
16 | 15 | ||
17 | obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ | 16 | obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ |
18 | usercopy_64.o mem_64.o string.o \ | 17 | usercopy_64.o mem_64.o string.o \ |
diff --git a/arch/powerpc/lib/alloc.c b/arch/powerpc/lib/alloc.c index da22c84a8fed..4a6c2cf890d9 100644 --- a/arch/powerpc/lib/alloc.c +++ b/arch/powerpc/lib/alloc.c | |||
@@ -13,9 +13,7 @@ void * __init_refok zalloc_maybe_bootmem(size_t size, gfp_t mask) | |||
13 | if (mem_init_done) | 13 | if (mem_init_done) |
14 | p = kzalloc(size, mask); | 14 | p = kzalloc(size, mask); |
15 | else { | 15 | else { |
16 | p = alloc_bootmem(size); | 16 | p = memblock_virt_alloc(size, 0); |
17 | if (p) | ||
18 | memset(p, 0, size); | ||
19 | } | 17 | } |
20 | return p; | 18 | return p; |
21 | } | 19 | } |
diff --git a/arch/powerpc/lib/copyuser_power7.S b/arch/powerpc/lib/copyuser_power7.S index c46c876ac96a..92ee840529bc 100644 --- a/arch/powerpc/lib/copyuser_power7.S +++ b/arch/powerpc/lib/copyuser_power7.S | |||
@@ -718,4 +718,4 @@ err3; stb r0,0(r3) | |||
718 | 718 | ||
719 | 15: addi r1,r1,STACKFRAMESIZE | 719 | 15: addi r1,r1,STACKFRAMESIZE |
720 | b exit_vmx_usercopy /* tail call optimise */ | 720 | b exit_vmx_usercopy /* tail call optimise */ |
721 | #endif /* CONFiG_ALTIVEC */ | 721 | #endif /* CONFIG_ALTIVEC */ |
diff --git a/arch/powerpc/lib/devres.c b/arch/powerpc/lib/devres.c deleted file mode 100644 index 8df55fc3aad6..000000000000 --- a/arch/powerpc/lib/devres.c +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/device.h> /* devres_*(), devm_ioremap_release() */ | ||
11 | #include <linux/gfp.h> | ||
12 | #include <linux/io.h> /* ioremap_prot() */ | ||
13 | #include <linux/export.h> /* EXPORT_SYMBOL() */ | ||
14 | |||
15 | /** | ||
16 | * devm_ioremap_prot - Managed ioremap_prot() | ||
17 | * @dev: Generic device to remap IO address for | ||
18 | * @offset: BUS offset to map | ||
19 | * @size: Size of map | ||
20 | * @flags: Page flags | ||
21 | * | ||
22 | * Managed ioremap_prot(). Map is automatically unmapped on driver | ||
23 | * detach. | ||
24 | */ | ||
25 | void __iomem *devm_ioremap_prot(struct device *dev, resource_size_t offset, | ||
26 | size_t size, unsigned long flags) | ||
27 | { | ||
28 | void __iomem **ptr, *addr; | ||
29 | |||
30 | ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL); | ||
31 | if (!ptr) | ||
32 | return NULL; | ||
33 | |||
34 | addr = ioremap_prot(offset, size, flags); | ||
35 | if (addr) { | ||
36 | *ptr = addr; | ||
37 | devres_add(dev, ptr); | ||
38 | } else | ||
39 | devres_free(ptr); | ||
40 | |||
41 | return addr; | ||
42 | } | ||
43 | EXPORT_SYMBOL(devm_ioremap_prot); | ||
diff --git a/arch/powerpc/lib/memcpy_power7.S b/arch/powerpc/lib/memcpy_power7.S index 2ff5c142f87b..0830587df16e 100644 --- a/arch/powerpc/lib/memcpy_power7.S +++ b/arch/powerpc/lib/memcpy_power7.S | |||
@@ -653,4 +653,4 @@ _GLOBAL(memcpy_power7) | |||
653 | 15: addi r1,r1,STACKFRAMESIZE | 653 | 15: addi r1,r1,STACKFRAMESIZE |
654 | ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1) | 654 | ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1) |
655 | b exit_vmx_copy /* tail call optimise */ | 655 | b exit_vmx_copy /* tail call optimise */ |
656 | #endif /* CONFiG_ALTIVEC */ | 656 | #endif /* CONFIG_ALTIVEC */ |
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 54651fc2d412..dc885b30f7a6 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
@@ -1865,6 +1865,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1865 | } | 1865 | } |
1866 | goto ldst_done; | 1866 | goto ldst_done; |
1867 | 1867 | ||
1868 | #ifdef CONFIG_PPC_FPU | ||
1868 | case LOAD_FP: | 1869 | case LOAD_FP: |
1869 | if (regs->msr & MSR_LE) | 1870 | if (regs->msr & MSR_LE) |
1870 | return 0; | 1871 | return 0; |
@@ -1873,7 +1874,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1873 | else | 1874 | else |
1874 | err = do_fp_load(op.reg, do_lfd, op.ea, size, regs); | 1875 | err = do_fp_load(op.reg, do_lfd, op.ea, size, regs); |
1875 | goto ldst_done; | 1876 | goto ldst_done; |
1876 | 1877 | #endif | |
1877 | #ifdef CONFIG_ALTIVEC | 1878 | #ifdef CONFIG_ALTIVEC |
1878 | case LOAD_VMX: | 1879 | case LOAD_VMX: |
1879 | if (regs->msr & MSR_LE) | 1880 | if (regs->msr & MSR_LE) |
@@ -1919,6 +1920,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1919 | err = write_mem(op.val, op.ea, size, regs); | 1920 | err = write_mem(op.val, op.ea, size, regs); |
1920 | goto ldst_done; | 1921 | goto ldst_done; |
1921 | 1922 | ||
1923 | #ifdef CONFIG_PPC_FPU | ||
1922 | case STORE_FP: | 1924 | case STORE_FP: |
1923 | if (regs->msr & MSR_LE) | 1925 | if (regs->msr & MSR_LE) |
1924 | return 0; | 1926 | return 0; |
@@ -1927,7 +1929,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1927 | else | 1929 | else |
1928 | err = do_fp_store(op.reg, do_stfd, op.ea, size, regs); | 1930 | err = do_fp_store(op.reg, do_stfd, op.ea, size, regs); |
1929 | goto ldst_done; | 1931 | goto ldst_done; |
1930 | 1932 | #endif | |
1931 | #ifdef CONFIG_ALTIVEC | 1933 | #ifdef CONFIG_ALTIVEC |
1932 | case STORE_VMX: | 1934 | case STORE_VMX: |
1933 | if (regs->msr & MSR_LE) | 1935 | if (regs->msr & MSR_LE) |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 325e861616a1..438dcd3fd0d1 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
@@ -6,7 +6,7 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | |||
6 | 6 | ||
7 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) | 7 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) |
8 | 8 | ||
9 | obj-y := fault.o mem.o pgtable.o gup.o mmap.o \ | 9 | obj-y := fault.o mem.o pgtable.o mmap.o \ |
10 | init_$(CONFIG_WORD_SIZE).o \ | 10 | init_$(CONFIG_WORD_SIZE).o \ |
11 | pgtable_$(CONFIG_WORD_SIZE).o | 11 | pgtable_$(CONFIG_WORD_SIZE).o |
12 | obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \ | 12 | obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \ |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 08d659a9fcdb..eb79907f34fa 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <asm/tlbflush.h> | 43 | #include <asm/tlbflush.h> |
44 | #include <asm/siginfo.h> | 44 | #include <asm/siginfo.h> |
45 | #include <asm/debug.h> | 45 | #include <asm/debug.h> |
46 | #include <mm/mmu_decl.h> | ||
47 | 46 | ||
48 | #include "icswx.h" | 47 | #include "icswx.h" |
49 | 48 | ||
@@ -380,12 +379,6 @@ good_area: | |||
380 | goto bad_area; | 379 | goto bad_area; |
381 | #endif /* CONFIG_6xx */ | 380 | #endif /* CONFIG_6xx */ |
382 | #if defined(CONFIG_8xx) | 381 | #if defined(CONFIG_8xx) |
383 | /* 8xx sometimes need to load a invalid/non-present TLBs. | ||
384 | * These must be invalidated separately as linux mm don't. | ||
385 | */ | ||
386 | if (error_code & 0x40000000) /* no translation? */ | ||
387 | _tlbil_va(address, 0, 0, 0); | ||
388 | |||
389 | /* The MPC8xx seems to always set 0x80000000, which is | 382 | /* The MPC8xx seems to always set 0x80000000, which is |
390 | * "undefined". Of those that can be set, this is the only | 383 | * "undefined". Of those that can be set, this is the only |
391 | * one which seems bad. | 384 | * one which seems bad. |
diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c deleted file mode 100644 index d8746684f606..000000000000 --- a/arch/powerpc/mm/gup.c +++ /dev/null | |||
@@ -1,235 +0,0 @@ | |||
1 | /* | ||
2 | * Lockless get_user_pages_fast for powerpc | ||
3 | * | ||
4 | * Copyright (C) 2008 Nick Piggin | ||
5 | * Copyright (C) 2008 Novell Inc. | ||
6 | */ | ||
7 | #undef DEBUG | ||
8 | |||
9 | #include <linux/sched.h> | ||
10 | #include <linux/mm.h> | ||
11 | #include <linux/hugetlb.h> | ||
12 | #include <linux/vmstat.h> | ||
13 | #include <linux/pagemap.h> | ||
14 | #include <linux/rwsem.h> | ||
15 | #include <asm/pgtable.h> | ||
16 | |||
17 | #ifdef __HAVE_ARCH_PTE_SPECIAL | ||
18 | |||
19 | /* | ||
20 | * The performance critical leaf functions are made noinline otherwise gcc | ||
21 | * inlines everything into a single function which results in too much | ||
22 | * register pressure. | ||
23 | */ | ||
24 | static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, | ||
25 | unsigned long end, int write, struct page **pages, int *nr) | ||
26 | { | ||
27 | unsigned long mask, result; | ||
28 | pte_t *ptep; | ||
29 | |||
30 | result = _PAGE_PRESENT|_PAGE_USER; | ||
31 | if (write) | ||
32 | result |= _PAGE_RW; | ||
33 | mask = result | _PAGE_SPECIAL; | ||
34 | |||
35 | ptep = pte_offset_kernel(&pmd, addr); | ||
36 | do { | ||
37 | pte_t pte = ACCESS_ONCE(*ptep); | ||
38 | struct page *page; | ||
39 | /* | ||
40 | * Similar to the PMD case, NUMA hinting must take slow path | ||
41 | */ | ||
42 | if (pte_numa(pte)) | ||
43 | return 0; | ||
44 | |||
45 | if ((pte_val(pte) & mask) != result) | ||
46 | return 0; | ||
47 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | ||
48 | page = pte_page(pte); | ||
49 | if (!page_cache_get_speculative(page)) | ||
50 | return 0; | ||
51 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { | ||
52 | put_page(page); | ||
53 | return 0; | ||
54 | } | ||
55 | pages[*nr] = page; | ||
56 | (*nr)++; | ||
57 | |||
58 | } while (ptep++, addr += PAGE_SIZE, addr != end); | ||
59 | |||
60 | return 1; | ||
61 | } | ||
62 | |||
63 | static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, | ||
64 | int write, struct page **pages, int *nr) | ||
65 | { | ||
66 | unsigned long next; | ||
67 | pmd_t *pmdp; | ||
68 | |||
69 | pmdp = pmd_offset(&pud, addr); | ||
70 | do { | ||
71 | pmd_t pmd = ACCESS_ONCE(*pmdp); | ||
72 | |||
73 | next = pmd_addr_end(addr, end); | ||
74 | /* | ||
75 | * If we find a splitting transparent hugepage we | ||
76 | * return zero. That will result in taking the slow | ||
77 | * path which will call wait_split_huge_page() | ||
78 | * if the pmd is still in splitting state | ||
79 | */ | ||
80 | if (pmd_none(pmd) || pmd_trans_splitting(pmd)) | ||
81 | return 0; | ||
82 | if (pmd_huge(pmd) || pmd_large(pmd)) { | ||
83 | /* | ||
84 | * NUMA hinting faults need to be handled in the GUP | ||
85 | * slowpath for accounting purposes and so that they | ||
86 | * can be serialised against THP migration. | ||
87 | */ | ||
88 | if (pmd_numa(pmd)) | ||
89 | return 0; | ||
90 | |||
91 | if (!gup_hugepte((pte_t *)pmdp, PMD_SIZE, addr, next, | ||
92 | write, pages, nr)) | ||
93 | return 0; | ||
94 | } else if (is_hugepd(pmdp)) { | ||
95 | if (!gup_hugepd((hugepd_t *)pmdp, PMD_SHIFT, | ||
96 | addr, next, write, pages, nr)) | ||
97 | return 0; | ||
98 | } else if (!gup_pte_range(pmd, addr, next, write, pages, nr)) | ||
99 | return 0; | ||
100 | } while (pmdp++, addr = next, addr != end); | ||
101 | |||
102 | return 1; | ||
103 | } | ||
104 | |||
105 | static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, | ||
106 | int write, struct page **pages, int *nr) | ||
107 | { | ||
108 | unsigned long next; | ||
109 | pud_t *pudp; | ||
110 | |||
111 | pudp = pud_offset(&pgd, addr); | ||
112 | do { | ||
113 | pud_t pud = ACCESS_ONCE(*pudp); | ||
114 | |||
115 | next = pud_addr_end(addr, end); | ||
116 | if (pud_none(pud)) | ||
117 | return 0; | ||
118 | if (pud_huge(pud)) { | ||
119 | if (!gup_hugepte((pte_t *)pudp, PUD_SIZE, addr, next, | ||
120 | write, pages, nr)) | ||
121 | return 0; | ||
122 | } else if (is_hugepd(pudp)) { | ||
123 | if (!gup_hugepd((hugepd_t *)pudp, PUD_SHIFT, | ||
124 | addr, next, write, pages, nr)) | ||
125 | return 0; | ||
126 | } else if (!gup_pmd_range(pud, addr, next, write, pages, nr)) | ||
127 | return 0; | ||
128 | } while (pudp++, addr = next, addr != end); | ||
129 | |||
130 | return 1; | ||
131 | } | ||
132 | |||
133 | int __get_user_pages_fast(unsigned long start, int nr_pages, int write, | ||
134 | struct page **pages) | ||
135 | { | ||
136 | struct mm_struct *mm = current->mm; | ||
137 | unsigned long addr, len, end; | ||
138 | unsigned long next; | ||
139 | unsigned long flags; | ||
140 | pgd_t *pgdp; | ||
141 | int nr = 0; | ||
142 | |||
143 | pr_devel("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read"); | ||
144 | |||
145 | start &= PAGE_MASK; | ||
146 | addr = start; | ||
147 | len = (unsigned long) nr_pages << PAGE_SHIFT; | ||
148 | end = start + len; | ||
149 | |||
150 | if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ, | ||
151 | start, len))) | ||
152 | return 0; | ||
153 | |||
154 | pr_devel(" aligned: %lx .. %lx\n", start, end); | ||
155 | |||
156 | /* | ||
157 | * XXX: batch / limit 'nr', to avoid large irq off latency | ||
158 | * needs some instrumenting to determine the common sizes used by | ||
159 | * important workloads (eg. DB2), and whether limiting the batch size | ||
160 | * will decrease performance. | ||
161 | * | ||
162 | * It seems like we're in the clear for the moment. Direct-IO is | ||
163 | * the main guy that batches up lots of get_user_pages, and even | ||
164 | * they are limited to 64-at-a-time which is not so many. | ||
165 | */ | ||
166 | /* | ||
167 | * This doesn't prevent pagetable teardown, but does prevent | ||
168 | * the pagetables from being freed on powerpc. | ||
169 | * | ||
170 | * So long as we atomically load page table pointers versus teardown, | ||
171 | * we can follow the address down to the the page and take a ref on it. | ||
172 | */ | ||
173 | local_irq_save(flags); | ||
174 | |||
175 | pgdp = pgd_offset(mm, addr); | ||
176 | do { | ||
177 | pgd_t pgd = ACCESS_ONCE(*pgdp); | ||
178 | |||
179 | pr_devel(" %016lx: normal pgd %p\n", addr, | ||
180 | (void *)pgd_val(pgd)); | ||
181 | next = pgd_addr_end(addr, end); | ||
182 | if (pgd_none(pgd)) | ||
183 | break; | ||
184 | if (pgd_huge(pgd)) { | ||
185 | if (!gup_hugepte((pte_t *)pgdp, PGDIR_SIZE, addr, next, | ||
186 | write, pages, &nr)) | ||
187 | break; | ||
188 | } else if (is_hugepd(pgdp)) { | ||
189 | if (!gup_hugepd((hugepd_t *)pgdp, PGDIR_SHIFT, | ||
190 | addr, next, write, pages, &nr)) | ||
191 | break; | ||
192 | } else if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) | ||
193 | break; | ||
194 | } while (pgdp++, addr = next, addr != end); | ||
195 | |||
196 | local_irq_restore(flags); | ||
197 | |||
198 | return nr; | ||
199 | } | ||
200 | |||
201 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, | ||
202 | struct page **pages) | ||
203 | { | ||
204 | struct mm_struct *mm = current->mm; | ||
205 | int nr, ret; | ||
206 | |||
207 | start &= PAGE_MASK; | ||
208 | nr = __get_user_pages_fast(start, nr_pages, write, pages); | ||
209 | ret = nr; | ||
210 | |||
211 | if (nr < nr_pages) { | ||
212 | pr_devel(" slow path ! nr = %d\n", nr); | ||
213 | |||
214 | /* Try to get the remaining pages with get_user_pages */ | ||
215 | start += nr << PAGE_SHIFT; | ||
216 | pages += nr; | ||
217 | |||
218 | down_read(&mm->mmap_sem); | ||
219 | ret = get_user_pages(current, mm, start, | ||
220 | nr_pages - nr, write, 0, pages, NULL); | ||
221 | up_read(&mm->mmap_sem); | ||
222 | |||
223 | /* Have to be a bit careful with return values */ | ||
224 | if (nr > 0) { | ||
225 | if (ret < 0) | ||
226 | ret = nr; | ||
227 | else | ||
228 | ret += nr; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | #endif /* __HAVE_ARCH_PTE_SPECIAL */ | ||
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index 057cbbb4c576..463174a4a647 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S | |||
@@ -46,7 +46,8 @@ | |||
46 | 46 | ||
47 | /* | 47 | /* |
48 | * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, | 48 | * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, |
49 | * pte_t *ptep, unsigned long trap, int local, int ssize) | 49 | * pte_t *ptep, unsigned long trap, unsigned long flags, |
50 | * int ssize) | ||
50 | * | 51 | * |
51 | * Adds a 4K page to the hash table in a segment of 4K pages only | 52 | * Adds a 4K page to the hash table in a segment of 4K pages only |
52 | */ | 53 | */ |
@@ -298,7 +299,7 @@ htab_modify_pte: | |||
298 | li r6,MMU_PAGE_4K /* base page size */ | 299 | li r6,MMU_PAGE_4K /* base page size */ |
299 | li r7,MMU_PAGE_4K /* actual page size */ | 300 | li r7,MMU_PAGE_4K /* actual page size */ |
300 | ld r8,STK_PARAM(R9)(r1) /* segment size */ | 301 | ld r8,STK_PARAM(R9)(r1) /* segment size */ |
301 | ld r9,STK_PARAM(R8)(r1) /* get "local" param */ | 302 | ld r9,STK_PARAM(R8)(r1) /* get "flags" param */ |
302 | .globl htab_call_hpte_updatepp | 303 | .globl htab_call_hpte_updatepp |
303 | htab_call_hpte_updatepp: | 304 | htab_call_hpte_updatepp: |
304 | bl . /* Patched by htab_finish_init() */ | 305 | bl . /* Patched by htab_finish_init() */ |
@@ -338,8 +339,8 @@ htab_pte_insert_failure: | |||
338 | *****************************************************************************/ | 339 | *****************************************************************************/ |
339 | 340 | ||
340 | /* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, | 341 | /* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, |
341 | * pte_t *ptep, unsigned long trap, int local, int ssize, | 342 | * pte_t *ptep, unsigned long trap, unsigned local flags, |
342 | * int subpg_prot) | 343 | * int ssize, int subpg_prot) |
343 | */ | 344 | */ |
344 | 345 | ||
345 | /* | 346 | /* |
@@ -514,7 +515,7 @@ htab_insert_pte: | |||
514 | andis. r0,r31,_PAGE_4K_PFN@h | 515 | andis. r0,r31,_PAGE_4K_PFN@h |
515 | srdi r5,r31,PTE_RPN_SHIFT | 516 | srdi r5,r31,PTE_RPN_SHIFT |
516 | bne- htab_special_pfn | 517 | bne- htab_special_pfn |
517 | sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT | 518 | sldi r5,r5,PAGE_FACTOR |
518 | add r5,r5,r25 | 519 | add r5,r5,r25 |
519 | htab_special_pfn: | 520 | htab_special_pfn: |
520 | sldi r5,r5,HW_PAGE_SHIFT | 521 | sldi r5,r5,HW_PAGE_SHIFT |
@@ -544,7 +545,7 @@ htab_call_hpte_insert1: | |||
544 | andis. r0,r31,_PAGE_4K_PFN@h | 545 | andis. r0,r31,_PAGE_4K_PFN@h |
545 | srdi r5,r31,PTE_RPN_SHIFT | 546 | srdi r5,r31,PTE_RPN_SHIFT |
546 | bne- 3f | 547 | bne- 3f |
547 | sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT | 548 | sldi r5,r5,PAGE_FACTOR |
548 | add r5,r5,r25 | 549 | add r5,r5,r25 |
549 | 3: sldi r5,r5,HW_PAGE_SHIFT | 550 | 3: sldi r5,r5,HW_PAGE_SHIFT |
550 | 551 | ||
@@ -594,7 +595,7 @@ htab_inval_old_hpte: | |||
594 | li r5,0 /* PTE.hidx */ | 595 | li r5,0 /* PTE.hidx */ |
595 | li r6,MMU_PAGE_64K /* psize */ | 596 | li r6,MMU_PAGE_64K /* psize */ |
596 | ld r7,STK_PARAM(R9)(r1) /* ssize */ | 597 | ld r7,STK_PARAM(R9)(r1) /* ssize */ |
597 | ld r8,STK_PARAM(R8)(r1) /* local */ | 598 | ld r8,STK_PARAM(R8)(r1) /* flags */ |
598 | bl flush_hash_page | 599 | bl flush_hash_page |
599 | /* Clear out _PAGE_HPTE_SUB bits in the new linux PTE */ | 600 | /* Clear out _PAGE_HPTE_SUB bits in the new linux PTE */ |
600 | lis r0,_PAGE_HPTE_SUB@h | 601 | lis r0,_PAGE_HPTE_SUB@h |
@@ -666,7 +667,7 @@ htab_modify_pte: | |||
666 | li r6,MMU_PAGE_4K /* base page size */ | 667 | li r6,MMU_PAGE_4K /* base page size */ |
667 | li r7,MMU_PAGE_4K /* actual page size */ | 668 | li r7,MMU_PAGE_4K /* actual page size */ |
668 | ld r8,STK_PARAM(R9)(r1) /* segment size */ | 669 | ld r8,STK_PARAM(R9)(r1) /* segment size */ |
669 | ld r9,STK_PARAM(R8)(r1) /* get "local" param */ | 670 | ld r9,STK_PARAM(R8)(r1) /* get "flags" param */ |
670 | .globl htab_call_hpte_updatepp | 671 | .globl htab_call_hpte_updatepp |
671 | htab_call_hpte_updatepp: | 672 | htab_call_hpte_updatepp: |
672 | bl . /* patched by htab_finish_init() */ | 673 | bl . /* patched by htab_finish_init() */ |
@@ -962,7 +963,7 @@ ht64_modify_pte: | |||
962 | li r6,MMU_PAGE_64K /* base page size */ | 963 | li r6,MMU_PAGE_64K /* base page size */ |
963 | li r7,MMU_PAGE_64K /* actual page size */ | 964 | li r7,MMU_PAGE_64K /* actual page size */ |
964 | ld r8,STK_PARAM(R9)(r1) /* segment size */ | 965 | ld r8,STK_PARAM(R9)(r1) /* segment size */ |
965 | ld r9,STK_PARAM(R8)(r1) /* get "local" param */ | 966 | ld r9,STK_PARAM(R8)(r1) /* get "flags" param */ |
966 | .globl ht64_call_hpte_updatepp | 967 | .globl ht64_call_hpte_updatepp |
967 | ht64_call_hpte_updatepp: | 968 | ht64_call_hpte_updatepp: |
968 | bl . /* patched by htab_finish_init() */ | 969 | bl . /* patched by htab_finish_init() */ |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index ae4962a06476..9c4880ddecd6 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -283,19 +283,17 @@ static long native_hpte_remove(unsigned long hpte_group) | |||
283 | 283 | ||
284 | static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | 284 | static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, |
285 | unsigned long vpn, int bpsize, | 285 | unsigned long vpn, int bpsize, |
286 | int apsize, int ssize, int local) | 286 | int apsize, int ssize, unsigned long flags) |
287 | { | 287 | { |
288 | struct hash_pte *hptep = htab_address + slot; | 288 | struct hash_pte *hptep = htab_address + slot; |
289 | unsigned long hpte_v, want_v; | 289 | unsigned long hpte_v, want_v; |
290 | int ret = 0; | 290 | int ret = 0, local = 0; |
291 | 291 | ||
292 | want_v = hpte_encode_avpn(vpn, bpsize, ssize); | 292 | want_v = hpte_encode_avpn(vpn, bpsize, ssize); |
293 | 293 | ||
294 | DBG_LOW(" update(vpn=%016lx, avpnv=%016lx, group=%lx, newpp=%lx)", | 294 | DBG_LOW(" update(vpn=%016lx, avpnv=%016lx, group=%lx, newpp=%lx)", |
295 | vpn, want_v & HPTE_V_AVPN, slot, newpp); | 295 | vpn, want_v & HPTE_V_AVPN, slot, newpp); |
296 | 296 | ||
297 | native_lock_hpte(hptep); | ||
298 | |||
299 | hpte_v = be64_to_cpu(hptep->v); | 297 | hpte_v = be64_to_cpu(hptep->v); |
300 | /* | 298 | /* |
301 | * We need to invalidate the TLB always because hpte_remove doesn't do | 299 | * We need to invalidate the TLB always because hpte_remove doesn't do |
@@ -308,15 +306,30 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
308 | DBG_LOW(" -> miss\n"); | 306 | DBG_LOW(" -> miss\n"); |
309 | ret = -1; | 307 | ret = -1; |
310 | } else { | 308 | } else { |
311 | DBG_LOW(" -> hit\n"); | 309 | native_lock_hpte(hptep); |
312 | /* Update the HPTE */ | 310 | /* recheck with locks held */ |
313 | hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & ~(HPTE_R_PP | HPTE_R_N)) | | 311 | hpte_v = be64_to_cpu(hptep->v); |
314 | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C))); | 312 | if (unlikely(!HPTE_V_COMPARE(hpte_v, want_v) || |
313 | !(hpte_v & HPTE_V_VALID))) { | ||
314 | ret = -1; | ||
315 | } else { | ||
316 | DBG_LOW(" -> hit\n"); | ||
317 | /* Update the HPTE */ | ||
318 | hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & | ||
319 | ~(HPTE_R_PP | HPTE_R_N)) | | ||
320 | (newpp & (HPTE_R_PP | HPTE_R_N | | ||
321 | HPTE_R_C))); | ||
322 | } | ||
323 | native_unlock_hpte(hptep); | ||
315 | } | 324 | } |
316 | native_unlock_hpte(hptep); | ||
317 | 325 | ||
318 | /* Ensure it is out of the tlb too. */ | 326 | if (flags & HPTE_LOCAL_UPDATE) |
319 | tlbie(vpn, bpsize, apsize, ssize, local); | 327 | local = 1; |
328 | /* | ||
329 | * Ensure it is out of the tlb too if it is not a nohpte fault | ||
330 | */ | ||
331 | if (!(flags & HPTE_NOHPTE_UPDATE)) | ||
332 | tlbie(vpn, bpsize, apsize, ssize, local); | ||
320 | 333 | ||
321 | return ret; | 334 | return ret; |
322 | } | 335 | } |
@@ -419,7 +432,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn, | |||
419 | static void native_hugepage_invalidate(unsigned long vsid, | 432 | static void native_hugepage_invalidate(unsigned long vsid, |
420 | unsigned long addr, | 433 | unsigned long addr, |
421 | unsigned char *hpte_slot_array, | 434 | unsigned char *hpte_slot_array, |
422 | int psize, int ssize) | 435 | int psize, int ssize, int local) |
423 | { | 436 | { |
424 | int i; | 437 | int i; |
425 | struct hash_pte *hptep; | 438 | struct hash_pte *hptep; |
@@ -465,7 +478,7 @@ static void native_hugepage_invalidate(unsigned long vsid, | |||
465 | * instruction compares entry_VA in tlb with the VA specified | 478 | * instruction compares entry_VA in tlb with the VA specified |
466 | * here | 479 | * here |
467 | */ | 480 | */ |
468 | tlbie(vpn, psize, actual_psize, ssize, 0); | 481 | tlbie(vpn, psize, actual_psize, ssize, local); |
469 | } | 482 | } |
470 | local_irq_restore(flags); | 483 | local_irq_restore(flags); |
471 | } | 484 | } |
@@ -629,7 +642,7 @@ static void native_flush_hash_range(unsigned long number, int local) | |||
629 | unsigned long want_v; | 642 | unsigned long want_v; |
630 | unsigned long flags; | 643 | unsigned long flags; |
631 | real_pte_t pte; | 644 | real_pte_t pte; |
632 | struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); | 645 | struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); |
633 | unsigned long psize = batch->psize; | 646 | unsigned long psize = batch->psize; |
634 | int ssize = batch->ssize; | 647 | int ssize = batch->ssize; |
635 | int i; | 648 | int i; |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index d5339a3b9945..e56a307bc676 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -989,7 +989,9 @@ static void check_paca_psize(unsigned long ea, struct mm_struct *mm, | |||
989 | * -1 - critical hash insertion error | 989 | * -1 - critical hash insertion error |
990 | * -2 - access not permitted by subpage protection mechanism | 990 | * -2 - access not permitted by subpage protection mechanism |
991 | */ | 991 | */ |
992 | int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, unsigned long trap) | 992 | int hash_page_mm(struct mm_struct *mm, unsigned long ea, |
993 | unsigned long access, unsigned long trap, | ||
994 | unsigned long flags) | ||
993 | { | 995 | { |
994 | enum ctx_state prev_state = exception_enter(); | 996 | enum ctx_state prev_state = exception_enter(); |
995 | pgd_t *pgdir; | 997 | pgd_t *pgdir; |
@@ -997,7 +999,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u | |||
997 | pte_t *ptep; | 999 | pte_t *ptep; |
998 | unsigned hugeshift; | 1000 | unsigned hugeshift; |
999 | const struct cpumask *tmp; | 1001 | const struct cpumask *tmp; |
1000 | int rc, user_region = 0, local = 0; | 1002 | int rc, user_region = 0; |
1001 | int psize, ssize; | 1003 | int psize, ssize; |
1002 | 1004 | ||
1003 | DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n", | 1005 | DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n", |
@@ -1049,7 +1051,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u | |||
1049 | /* Check CPU locality */ | 1051 | /* Check CPU locality */ |
1050 | tmp = cpumask_of(smp_processor_id()); | 1052 | tmp = cpumask_of(smp_processor_id()); |
1051 | if (user_region && cpumask_equal(mm_cpumask(mm), tmp)) | 1053 | if (user_region && cpumask_equal(mm_cpumask(mm), tmp)) |
1052 | local = 1; | 1054 | flags |= HPTE_LOCAL_UPDATE; |
1053 | 1055 | ||
1054 | #ifndef CONFIG_PPC_64K_PAGES | 1056 | #ifndef CONFIG_PPC_64K_PAGES |
1055 | /* If we use 4K pages and our psize is not 4K, then we might | 1057 | /* If we use 4K pages and our psize is not 4K, then we might |
@@ -1086,11 +1088,11 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u | |||
1086 | if (hugeshift) { | 1088 | if (hugeshift) { |
1087 | if (pmd_trans_huge(*(pmd_t *)ptep)) | 1089 | if (pmd_trans_huge(*(pmd_t *)ptep)) |
1088 | rc = __hash_page_thp(ea, access, vsid, (pmd_t *)ptep, | 1090 | rc = __hash_page_thp(ea, access, vsid, (pmd_t *)ptep, |
1089 | trap, local, ssize, psize); | 1091 | trap, flags, ssize, psize); |
1090 | #ifdef CONFIG_HUGETLB_PAGE | 1092 | #ifdef CONFIG_HUGETLB_PAGE |
1091 | else | 1093 | else |
1092 | rc = __hash_page_huge(ea, access, vsid, ptep, trap, | 1094 | rc = __hash_page_huge(ea, access, vsid, ptep, trap, |
1093 | local, ssize, hugeshift, psize); | 1095 | flags, ssize, hugeshift, psize); |
1094 | #else | 1096 | #else |
1095 | else { | 1097 | else { |
1096 | /* | 1098 | /* |
@@ -1149,7 +1151,8 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u | |||
1149 | 1151 | ||
1150 | #ifdef CONFIG_PPC_HAS_HASH_64K | 1152 | #ifdef CONFIG_PPC_HAS_HASH_64K |
1151 | if (psize == MMU_PAGE_64K) | 1153 | if (psize == MMU_PAGE_64K) |
1152 | rc = __hash_page_64K(ea, access, vsid, ptep, trap, local, ssize); | 1154 | rc = __hash_page_64K(ea, access, vsid, ptep, trap, |
1155 | flags, ssize); | ||
1153 | else | 1156 | else |
1154 | #endif /* CONFIG_PPC_HAS_HASH_64K */ | 1157 | #endif /* CONFIG_PPC_HAS_HASH_64K */ |
1155 | { | 1158 | { |
@@ -1158,7 +1161,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, u | |||
1158 | rc = -2; | 1161 | rc = -2; |
1159 | else | 1162 | else |
1160 | rc = __hash_page_4K(ea, access, vsid, ptep, trap, | 1163 | rc = __hash_page_4K(ea, access, vsid, ptep, trap, |
1161 | local, ssize, spp); | 1164 | flags, ssize, spp); |
1162 | } | 1165 | } |
1163 | 1166 | ||
1164 | /* Dump some info in case of hash insertion failure, they should | 1167 | /* Dump some info in case of hash insertion failure, they should |
@@ -1181,14 +1184,19 @@ bail: | |||
1181 | } | 1184 | } |
1182 | EXPORT_SYMBOL_GPL(hash_page_mm); | 1185 | EXPORT_SYMBOL_GPL(hash_page_mm); |
1183 | 1186 | ||
1184 | int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | 1187 | int hash_page(unsigned long ea, unsigned long access, unsigned long trap, |
1188 | unsigned long dsisr) | ||
1185 | { | 1189 | { |
1190 | unsigned long flags = 0; | ||
1186 | struct mm_struct *mm = current->mm; | 1191 | struct mm_struct *mm = current->mm; |
1187 | 1192 | ||
1188 | if (REGION_ID(ea) == VMALLOC_REGION_ID) | 1193 | if (REGION_ID(ea) == VMALLOC_REGION_ID) |
1189 | mm = &init_mm; | 1194 | mm = &init_mm; |
1190 | 1195 | ||
1191 | return hash_page_mm(mm, ea, access, trap); | 1196 | if (dsisr & DSISR_NOHPTE) |
1197 | flags |= HPTE_NOHPTE_UPDATE; | ||
1198 | |||
1199 | return hash_page_mm(mm, ea, access, trap, flags); | ||
1192 | } | 1200 | } |
1193 | EXPORT_SYMBOL_GPL(hash_page); | 1201 | EXPORT_SYMBOL_GPL(hash_page); |
1194 | 1202 | ||
@@ -1200,7 +1208,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, | |||
1200 | pgd_t *pgdir; | 1208 | pgd_t *pgdir; |
1201 | pte_t *ptep; | 1209 | pte_t *ptep; |
1202 | unsigned long flags; | 1210 | unsigned long flags; |
1203 | int rc, ssize, local = 0; | 1211 | int rc, ssize, update_flags = 0; |
1204 | 1212 | ||
1205 | BUG_ON(REGION_ID(ea) != USER_REGION_ID); | 1213 | BUG_ON(REGION_ID(ea) != USER_REGION_ID); |
1206 | 1214 | ||
@@ -1251,16 +1259,17 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, | |||
1251 | 1259 | ||
1252 | /* Is that local to this CPU ? */ | 1260 | /* Is that local to this CPU ? */ |
1253 | if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) | 1261 | if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) |
1254 | local = 1; | 1262 | update_flags |= HPTE_LOCAL_UPDATE; |
1255 | 1263 | ||
1256 | /* Hash it in */ | 1264 | /* Hash it in */ |
1257 | #ifdef CONFIG_PPC_HAS_HASH_64K | 1265 | #ifdef CONFIG_PPC_HAS_HASH_64K |
1258 | if (mm->context.user_psize == MMU_PAGE_64K) | 1266 | if (mm->context.user_psize == MMU_PAGE_64K) |
1259 | rc = __hash_page_64K(ea, access, vsid, ptep, trap, local, ssize); | 1267 | rc = __hash_page_64K(ea, access, vsid, ptep, trap, |
1268 | update_flags, ssize); | ||
1260 | else | 1269 | else |
1261 | #endif /* CONFIG_PPC_HAS_HASH_64K */ | 1270 | #endif /* CONFIG_PPC_HAS_HASH_64K */ |
1262 | rc = __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize, | 1271 | rc = __hash_page_4K(ea, access, vsid, ptep, trap, update_flags, |
1263 | subpage_protection(mm, ea)); | 1272 | ssize, subpage_protection(mm, ea)); |
1264 | 1273 | ||
1265 | /* Dump some info in case of hash insertion failure, they should | 1274 | /* Dump some info in case of hash insertion failure, they should |
1266 | * never happen so it is really useful to know if/when they do | 1275 | * never happen so it is really useful to know if/when they do |
@@ -1278,9 +1287,10 @@ out_exit: | |||
1278 | * do not forget to update the assembly call site ! | 1287 | * do not forget to update the assembly call site ! |
1279 | */ | 1288 | */ |
1280 | void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, | 1289 | void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, |
1281 | int local) | 1290 | unsigned long flags) |
1282 | { | 1291 | { |
1283 | unsigned long hash, index, shift, hidx, slot; | 1292 | unsigned long hash, index, shift, hidx, slot; |
1293 | int local = flags & HPTE_LOCAL_UPDATE; | ||
1284 | 1294 | ||
1285 | DBG_LOW("flush_hash_page(vpn=%016lx)\n", vpn); | 1295 | DBG_LOW("flush_hash_page(vpn=%016lx)\n", vpn); |
1286 | pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) { | 1296 | pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) { |
@@ -1315,6 +1325,78 @@ void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, | |||
1315 | #endif | 1325 | #endif |
1316 | } | 1326 | } |
1317 | 1327 | ||
1328 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
1329 | void flush_hash_hugepage(unsigned long vsid, unsigned long addr, | ||
1330 | pmd_t *pmdp, unsigned int psize, int ssize, | ||
1331 | unsigned long flags) | ||
1332 | { | ||
1333 | int i, max_hpte_count, valid; | ||
1334 | unsigned long s_addr; | ||
1335 | unsigned char *hpte_slot_array; | ||
1336 | unsigned long hidx, shift, vpn, hash, slot; | ||
1337 | int local = flags & HPTE_LOCAL_UPDATE; | ||
1338 | |||
1339 | s_addr = addr & HPAGE_PMD_MASK; | ||
1340 | hpte_slot_array = get_hpte_slot_array(pmdp); | ||
1341 | /* | ||
1342 | * IF we try to do a HUGE PTE update after a withdraw is done. | ||
1343 | * we will find the below NULL. This happens when we do | ||
1344 | * split_huge_page_pmd | ||
1345 | */ | ||
1346 | if (!hpte_slot_array) | ||
1347 | return; | ||
1348 | |||
1349 | if (ppc_md.hugepage_invalidate) { | ||
1350 | ppc_md.hugepage_invalidate(vsid, s_addr, hpte_slot_array, | ||
1351 | psize, ssize, local); | ||
1352 | goto tm_abort; | ||
1353 | } | ||
1354 | /* | ||
1355 | * No bluk hpte removal support, invalidate each entry | ||
1356 | */ | ||
1357 | shift = mmu_psize_defs[psize].shift; | ||
1358 | max_hpte_count = HPAGE_PMD_SIZE >> shift; | ||
1359 | for (i = 0; i < max_hpte_count; i++) { | ||
1360 | /* | ||
1361 | * 8 bits per each hpte entries | ||
1362 | * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit] | ||
1363 | */ | ||
1364 | valid = hpte_valid(hpte_slot_array, i); | ||
1365 | if (!valid) | ||
1366 | continue; | ||
1367 | hidx = hpte_hash_index(hpte_slot_array, i); | ||
1368 | |||
1369 | /* get the vpn */ | ||
1370 | addr = s_addr + (i * (1ul << shift)); | ||
1371 | vpn = hpt_vpn(addr, vsid, ssize); | ||
1372 | hash = hpt_hash(vpn, shift, ssize); | ||
1373 | if (hidx & _PTEIDX_SECONDARY) | ||
1374 | hash = ~hash; | ||
1375 | |||
1376 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | ||
1377 | slot += hidx & _PTEIDX_GROUP_IX; | ||
1378 | ppc_md.hpte_invalidate(slot, vpn, psize, | ||
1379 | MMU_PAGE_16M, ssize, local); | ||
1380 | } | ||
1381 | tm_abort: | ||
1382 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1383 | /* Transactions are not aborted by tlbiel, only tlbie. | ||
1384 | * Without, syncing a page back to a block device w/ PIO could pick up | ||
1385 | * transactional data (bad!) so we force an abort here. Before the | ||
1386 | * sync the page will be made read-only, which will flush_hash_page. | ||
1387 | * BIG ISSUE here: if the kernel uses a page from userspace without | ||
1388 | * unmapping it first, it may see the speculated version. | ||
1389 | */ | ||
1390 | if (local && cpu_has_feature(CPU_FTR_TM) && | ||
1391 | current->thread.regs && | ||
1392 | MSR_TM_ACTIVE(current->thread.regs->msr)) { | ||
1393 | tm_enable(); | ||
1394 | tm_abort(TM_CAUSE_TLBI); | ||
1395 | } | ||
1396 | #endif | ||
1397 | } | ||
1398 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | ||
1399 | |||
1318 | void flush_hash_range(unsigned long number, int local) | 1400 | void flush_hash_range(unsigned long number, int local) |
1319 | { | 1401 | { |
1320 | if (ppc_md.flush_hash_range) | 1402 | if (ppc_md.flush_hash_range) |
@@ -1322,7 +1404,7 @@ void flush_hash_range(unsigned long number, int local) | |||
1322 | else { | 1404 | else { |
1323 | int i; | 1405 | int i; |
1324 | struct ppc64_tlb_batch *batch = | 1406 | struct ppc64_tlb_batch *batch = |
1325 | &__get_cpu_var(ppc64_tlb_batch); | 1407 | this_cpu_ptr(&ppc64_tlb_batch); |
1326 | 1408 | ||
1327 | for (i = 0; i < number; i++) | 1409 | for (i = 0; i < number; i++) |
1328 | flush_hash_page(batch->vpn[i], batch->pte[i], | 1410 | flush_hash_page(batch->vpn[i], batch->pte[i], |
diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c index 5f5e6328c21c..86686514ae13 100644 --- a/arch/powerpc/mm/hugepage-hash64.c +++ b/arch/powerpc/mm/hugepage-hash64.c | |||
@@ -18,60 +18,9 @@ | |||
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
20 | 20 | ||
21 | static void invalidate_old_hpte(unsigned long vsid, unsigned long addr, | ||
22 | pmd_t *pmdp, unsigned int psize, int ssize) | ||
23 | { | ||
24 | int i, max_hpte_count, valid; | ||
25 | unsigned long s_addr; | ||
26 | unsigned char *hpte_slot_array; | ||
27 | unsigned long hidx, shift, vpn, hash, slot; | ||
28 | |||
29 | s_addr = addr & HPAGE_PMD_MASK; | ||
30 | hpte_slot_array = get_hpte_slot_array(pmdp); | ||
31 | /* | ||
32 | * IF we try to do a HUGE PTE update after a withdraw is done. | ||
33 | * we will find the below NULL. This happens when we do | ||
34 | * split_huge_page_pmd | ||
35 | */ | ||
36 | if (!hpte_slot_array) | ||
37 | return; | ||
38 | |||
39 | if (ppc_md.hugepage_invalidate) | ||
40 | return ppc_md.hugepage_invalidate(vsid, s_addr, hpte_slot_array, | ||
41 | psize, ssize); | ||
42 | /* | ||
43 | * No bluk hpte removal support, invalidate each entry | ||
44 | */ | ||
45 | shift = mmu_psize_defs[psize].shift; | ||
46 | max_hpte_count = HPAGE_PMD_SIZE >> shift; | ||
47 | for (i = 0; i < max_hpte_count; i++) { | ||
48 | /* | ||
49 | * 8 bits per each hpte entries | ||
50 | * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit] | ||
51 | */ | ||
52 | valid = hpte_valid(hpte_slot_array, i); | ||
53 | if (!valid) | ||
54 | continue; | ||
55 | hidx = hpte_hash_index(hpte_slot_array, i); | ||
56 | |||
57 | /* get the vpn */ | ||
58 | addr = s_addr + (i * (1ul << shift)); | ||
59 | vpn = hpt_vpn(addr, vsid, ssize); | ||
60 | hash = hpt_hash(vpn, shift, ssize); | ||
61 | if (hidx & _PTEIDX_SECONDARY) | ||
62 | hash = ~hash; | ||
63 | |||
64 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | ||
65 | slot += hidx & _PTEIDX_GROUP_IX; | ||
66 | ppc_md.hpte_invalidate(slot, vpn, psize, | ||
67 | MMU_PAGE_16M, ssize, 0); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | |||
72 | int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | 21 | int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, |
73 | pmd_t *pmdp, unsigned long trap, int local, int ssize, | 22 | pmd_t *pmdp, unsigned long trap, unsigned long flags, |
74 | unsigned int psize) | 23 | int ssize, unsigned int psize) |
75 | { | 24 | { |
76 | unsigned int index, valid; | 25 | unsigned int index, valid; |
77 | unsigned char *hpte_slot_array; | 26 | unsigned char *hpte_slot_array; |
@@ -145,7 +94,8 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | |||
145 | * hash page table entries. | 94 | * hash page table entries. |
146 | */ | 95 | */ |
147 | if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) | 96 | if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) |
148 | invalidate_old_hpte(vsid, ea, pmdp, MMU_PAGE_64K, ssize); | 97 | flush_hash_hugepage(vsid, ea, pmdp, MMU_PAGE_64K, |
98 | ssize, flags); | ||
149 | } | 99 | } |
150 | 100 | ||
151 | valid = hpte_valid(hpte_slot_array, index); | 101 | valid = hpte_valid(hpte_slot_array, index); |
@@ -158,7 +108,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | |||
158 | slot += hidx & _PTEIDX_GROUP_IX; | 108 | slot += hidx & _PTEIDX_GROUP_IX; |
159 | 109 | ||
160 | ret = ppc_md.hpte_updatepp(slot, rflags, vpn, | 110 | ret = ppc_md.hpte_updatepp(slot, rflags, vpn, |
161 | psize, lpsize, ssize, local); | 111 | psize, lpsize, ssize, flags); |
162 | /* | 112 | /* |
163 | * We failed to update, try to insert a new entry. | 113 | * We failed to update, try to insert a new entry. |
164 | */ | 114 | */ |
diff --git a/arch/powerpc/mm/hugetlbpage-book3e.c b/arch/powerpc/mm/hugetlbpage-book3e.c index 5e4ee2573903..ba47aaf33a4b 100644 --- a/arch/powerpc/mm/hugetlbpage-book3e.c +++ b/arch/powerpc/mm/hugetlbpage-book3e.c | |||
@@ -33,13 +33,13 @@ static inline int tlb1_next(void) | |||
33 | 33 | ||
34 | ncams = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY; | 34 | ncams = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY; |
35 | 35 | ||
36 | index = __get_cpu_var(next_tlbcam_idx); | 36 | index = this_cpu_read(next_tlbcam_idx); |
37 | 37 | ||
38 | /* Just round-robin the entries and wrap when we hit the end */ | 38 | /* Just round-robin the entries and wrap when we hit the end */ |
39 | if (unlikely(index == ncams - 1)) | 39 | if (unlikely(index == ncams - 1)) |
40 | __get_cpu_var(next_tlbcam_idx) = tlbcam_index; | 40 | __this_cpu_write(next_tlbcam_idx, tlbcam_index); |
41 | else | 41 | else |
42 | __get_cpu_var(next_tlbcam_idx)++; | 42 | __this_cpu_inc(next_tlbcam_idx); |
43 | 43 | ||
44 | return index; | 44 | return index; |
45 | } | 45 | } |
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c index a5bcf9301196..d94b1af53a93 100644 --- a/arch/powerpc/mm/hugetlbpage-hash64.c +++ b/arch/powerpc/mm/hugetlbpage-hash64.c | |||
@@ -19,8 +19,8 @@ extern long hpte_insert_repeating(unsigned long hash, unsigned long vpn, | |||
19 | unsigned long vflags, int psize, int ssize); | 19 | unsigned long vflags, int psize, int ssize); |
20 | 20 | ||
21 | int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, | 21 | int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, |
22 | pte_t *ptep, unsigned long trap, int local, int ssize, | 22 | pte_t *ptep, unsigned long trap, unsigned long flags, |
23 | unsigned int shift, unsigned int mmu_psize) | 23 | int ssize, unsigned int shift, unsigned int mmu_psize) |
24 | { | 24 | { |
25 | unsigned long vpn; | 25 | unsigned long vpn; |
26 | unsigned long old_pte, new_pte; | 26 | unsigned long old_pte, new_pte; |
@@ -81,7 +81,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, | |||
81 | slot += (old_pte & _PAGE_F_GIX) >> 12; | 81 | slot += (old_pte & _PAGE_F_GIX) >> 12; |
82 | 82 | ||
83 | if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize, | 83 | if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize, |
84 | mmu_psize, ssize, local) == -1) | 84 | mmu_psize, ssize, flags) == -1) |
85 | old_pte &= ~_PAGE_HPTEFLAGS; | 85 | old_pte &= ~_PAGE_HPTEFLAGS; |
86 | } | 86 | } |
87 | 87 | ||
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 6a4a5fcb9730..5ff4e07d920a 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -62,6 +62,9 @@ static unsigned nr_gpages; | |||
62 | /* | 62 | /* |
63 | * We have PGD_INDEX_SIZ = 12 and PTE_INDEX_SIZE = 8, so that we can have | 63 | * We have PGD_INDEX_SIZ = 12 and PTE_INDEX_SIZE = 8, so that we can have |
64 | * 16GB hugepage pte in PGD and 16MB hugepage pte at PMD; | 64 | * 16GB hugepage pte in PGD and 16MB hugepage pte at PMD; |
65 | * | ||
66 | * Defined in such a way that we can optimize away code block at build time | ||
67 | * if CONFIG_HUGETLB_PAGE=n. | ||
65 | */ | 68 | */ |
66 | int pmd_huge(pmd_t pmd) | 69 | int pmd_huge(pmd_t pmd) |
67 | { | 70 | { |
@@ -230,7 +233,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz | |||
230 | if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, pdshift, pshift)) | 233 | if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, pdshift, pshift)) |
231 | return NULL; | 234 | return NULL; |
232 | 235 | ||
233 | return hugepte_offset(hpdp, addr, pdshift); | 236 | return hugepte_offset(*hpdp, addr, pdshift); |
234 | } | 237 | } |
235 | 238 | ||
236 | #else | 239 | #else |
@@ -270,13 +273,13 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz | |||
270 | if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, pdshift, pshift)) | 273 | if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, pdshift, pshift)) |
271 | return NULL; | 274 | return NULL; |
272 | 275 | ||
273 | return hugepte_offset(hpdp, addr, pdshift); | 276 | return hugepte_offset(*hpdp, addr, pdshift); |
274 | } | 277 | } |
275 | #endif | 278 | #endif |
276 | 279 | ||
277 | #ifdef CONFIG_PPC_FSL_BOOK3E | 280 | #ifdef CONFIG_PPC_FSL_BOOK3E |
278 | /* Build list of addresses of gigantic pages. This function is used in early | 281 | /* Build list of addresses of gigantic pages. This function is used in early |
279 | * boot before the buddy or bootmem allocator is setup. | 282 | * boot before the buddy allocator is setup. |
280 | */ | 283 | */ |
281 | void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages) | 284 | void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages) |
282 | { | 285 | { |
@@ -312,7 +315,7 @@ int alloc_bootmem_huge_page(struct hstate *hstate) | |||
312 | * If gpages can be in highmem we can't use the trick of storing the | 315 | * If gpages can be in highmem we can't use the trick of storing the |
313 | * data structure in the page; allocate space for this | 316 | * data structure in the page; allocate space for this |
314 | */ | 317 | */ |
315 | m = alloc_bootmem(sizeof(struct huge_bootmem_page)); | 318 | m = memblock_virt_alloc(sizeof(struct huge_bootmem_page), 0); |
316 | m->phys = gpage_freearray[idx].gpage_list[--nr_gpages]; | 319 | m->phys = gpage_freearray[idx].gpage_list[--nr_gpages]; |
317 | #else | 320 | #else |
318 | m = phys_to_virt(gpage_freearray[idx].gpage_list[--nr_gpages]); | 321 | m = phys_to_virt(gpage_freearray[idx].gpage_list[--nr_gpages]); |
@@ -352,6 +355,13 @@ static int __init do_gpage_early_setup(char *param, char *val, | |||
352 | if (size != 0) { | 355 | if (size != 0) { |
353 | if (sscanf(val, "%lu", &npages) <= 0) | 356 | if (sscanf(val, "%lu", &npages) <= 0) |
354 | npages = 0; | 357 | npages = 0; |
358 | if (npages > MAX_NUMBER_GPAGES) { | ||
359 | pr_warn("MMU: %lu pages requested for page " | ||
360 | "size %llu KB, limiting to " | ||
361 | __stringify(MAX_NUMBER_GPAGES) "\n", | ||
362 | npages, size / 1024); | ||
363 | npages = MAX_NUMBER_GPAGES; | ||
364 | } | ||
355 | gpage_npages[shift_to_mmu_psize(__ffs(size))] = npages; | 365 | gpage_npages[shift_to_mmu_psize(__ffs(size))] = npages; |
356 | size = 0; | 366 | size = 0; |
357 | } | 367 | } |
@@ -399,7 +409,7 @@ void __init reserve_hugetlb_gpages(void) | |||
399 | #else /* !PPC_FSL_BOOK3E */ | 409 | #else /* !PPC_FSL_BOOK3E */ |
400 | 410 | ||
401 | /* Build list of addresses of gigantic pages. This function is used in early | 411 | /* Build list of addresses of gigantic pages. This function is used in early |
402 | * boot before the buddy or bootmem allocator is setup. | 412 | * boot before the buddy allocator is setup. |
403 | */ | 413 | */ |
404 | void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages) | 414 | void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages) |
405 | { | 415 | { |
@@ -462,7 +472,7 @@ static void hugepd_free(struct mmu_gather *tlb, void *hugepte) | |||
462 | { | 472 | { |
463 | struct hugepd_freelist **batchp; | 473 | struct hugepd_freelist **batchp; |
464 | 474 | ||
465 | batchp = &get_cpu_var(hugepd_freelist_cur); | 475 | batchp = this_cpu_ptr(&hugepd_freelist_cur); |
466 | 476 | ||
467 | if (atomic_read(&tlb->mm->mm_users) < 2 || | 477 | if (atomic_read(&tlb->mm->mm_users) < 2 || |
468 | cpumask_equal(mm_cpumask(tlb->mm), | 478 | cpumask_equal(mm_cpumask(tlb->mm), |
@@ -536,7 +546,7 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, | |||
536 | do { | 546 | do { |
537 | pmd = pmd_offset(pud, addr); | 547 | pmd = pmd_offset(pud, addr); |
538 | next = pmd_addr_end(addr, end); | 548 | next = pmd_addr_end(addr, end); |
539 | if (!is_hugepd(pmd)) { | 549 | if (!is_hugepd(__hugepd(pmd_val(*pmd)))) { |
540 | /* | 550 | /* |
541 | * if it is not hugepd pointer, we should already find | 551 | * if it is not hugepd pointer, we should already find |
542 | * it cleared. | 552 | * it cleared. |
@@ -585,7 +595,7 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, | |||
585 | do { | 595 | do { |
586 | pud = pud_offset(pgd, addr); | 596 | pud = pud_offset(pgd, addr); |
587 | next = pud_addr_end(addr, end); | 597 | next = pud_addr_end(addr, end); |
588 | if (!is_hugepd(pud)) { | 598 | if (!is_hugepd(__hugepd(pud_val(*pud)))) { |
589 | if (pud_none_or_clear_bad(pud)) | 599 | if (pud_none_or_clear_bad(pud)) |
590 | continue; | 600 | continue; |
591 | hugetlb_free_pmd_range(tlb, pud, addr, next, floor, | 601 | hugetlb_free_pmd_range(tlb, pud, addr, next, floor, |
@@ -651,7 +661,7 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, | |||
651 | do { | 661 | do { |
652 | next = pgd_addr_end(addr, end); | 662 | next = pgd_addr_end(addr, end); |
653 | pgd = pgd_offset(tlb->mm, addr); | 663 | pgd = pgd_offset(tlb->mm, addr); |
654 | if (!is_hugepd(pgd)) { | 664 | if (!is_hugepd(__hugepd(pgd_val(*pgd)))) { |
655 | if (pgd_none_or_clear_bad(pgd)) | 665 | if (pgd_none_or_clear_bad(pgd)) |
656 | continue; | 666 | continue; |
657 | hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling); | 667 | hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling); |
@@ -711,12 +721,11 @@ static unsigned long hugepte_addr_end(unsigned long addr, unsigned long end, | |||
711 | return (__boundary - 1 < end - 1) ? __boundary : end; | 721 | return (__boundary - 1 < end - 1) ? __boundary : end; |
712 | } | 722 | } |
713 | 723 | ||
714 | int gup_hugepd(hugepd_t *hugepd, unsigned pdshift, | 724 | int gup_huge_pd(hugepd_t hugepd, unsigned long addr, unsigned pdshift, |
715 | unsigned long addr, unsigned long end, | 725 | unsigned long end, int write, struct page **pages, int *nr) |
716 | int write, struct page **pages, int *nr) | ||
717 | { | 726 | { |
718 | pte_t *ptep; | 727 | pte_t *ptep; |
719 | unsigned long sz = 1UL << hugepd_shift(*hugepd); | 728 | unsigned long sz = 1UL << hugepd_shift(hugepd); |
720 | unsigned long next; | 729 | unsigned long next; |
721 | 730 | ||
722 | ptep = hugepte_offset(hugepd, addr, pdshift); | 731 | ptep = hugepte_offset(hugepd, addr, pdshift); |
@@ -959,7 +968,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift | |||
959 | else if (pgd_huge(pgd)) { | 968 | else if (pgd_huge(pgd)) { |
960 | ret_pte = (pte_t *) pgdp; | 969 | ret_pte = (pte_t *) pgdp; |
961 | goto out; | 970 | goto out; |
962 | } else if (is_hugepd(&pgd)) | 971 | } else if (is_hugepd(__hugepd(pgd_val(pgd)))) |
963 | hpdp = (hugepd_t *)&pgd; | 972 | hpdp = (hugepd_t *)&pgd; |
964 | else { | 973 | else { |
965 | /* | 974 | /* |
@@ -976,7 +985,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift | |||
976 | else if (pud_huge(pud)) { | 985 | else if (pud_huge(pud)) { |
977 | ret_pte = (pte_t *) pudp; | 986 | ret_pte = (pte_t *) pudp; |
978 | goto out; | 987 | goto out; |
979 | } else if (is_hugepd(&pud)) | 988 | } else if (is_hugepd(__hugepd(pud_val(pud)))) |
980 | hpdp = (hugepd_t *)&pud; | 989 | hpdp = (hugepd_t *)&pud; |
981 | else { | 990 | else { |
982 | pdshift = PMD_SHIFT; | 991 | pdshift = PMD_SHIFT; |
@@ -997,7 +1006,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift | |||
997 | if (pmd_huge(pmd) || pmd_large(pmd)) { | 1006 | if (pmd_huge(pmd) || pmd_large(pmd)) { |
998 | ret_pte = (pte_t *) pmdp; | 1007 | ret_pte = (pte_t *) pmdp; |
999 | goto out; | 1008 | goto out; |
1000 | } else if (is_hugepd(&pmd)) | 1009 | } else if (is_hugepd(__hugepd(pmd_val(pmd)))) |
1001 | hpdp = (hugepd_t *)&pmd; | 1010 | hpdp = (hugepd_t *)&pmd; |
1002 | else | 1011 | else |
1003 | return pte_offset_kernel(&pmd, ea); | 1012 | return pte_offset_kernel(&pmd, ea); |
@@ -1006,7 +1015,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift | |||
1006 | if (!hpdp) | 1015 | if (!hpdp) |
1007 | return NULL; | 1016 | return NULL; |
1008 | 1017 | ||
1009 | ret_pte = hugepte_offset(hpdp, ea, pdshift); | 1018 | ret_pte = hugepte_offset(*hpdp, ea, pdshift); |
1010 | pdshift = hugepd_shift(*hpdp); | 1019 | pdshift = hugepd_shift(*hpdp); |
1011 | out: | 1020 | out: |
1012 | if (shift) | 1021 | if (shift) |
@@ -1036,14 +1045,6 @@ int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, | |||
1036 | if ((pte_val(pte) & mask) != mask) | 1045 | if ((pte_val(pte) & mask) != mask) |
1037 | return 0; | 1046 | return 0; |
1038 | 1047 | ||
1039 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
1040 | /* | ||
1041 | * check for splitting here | ||
1042 | */ | ||
1043 | if (pmd_trans_splitting(pte_pmd(pte))) | ||
1044 | return 0; | ||
1045 | #endif | ||
1046 | |||
1047 | /* hugepages are never "special" */ | 1048 | /* hugepages are never "special" */ |
1048 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | 1049 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); |
1049 | 1050 | ||
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 415a51b028b9..a10be665b645 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
27 | #include <linux/stddef.h> | 27 | #include <linux/stddef.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/bootmem.h> | ||
30 | #include <linux/highmem.h> | 29 | #include <linux/highmem.h> |
31 | #include <linux/initrd.h> | 30 | #include <linux/initrd.h> |
32 | #include <linux/pagemap.h> | 31 | #include <linux/pagemap.h> |
@@ -195,15 +194,6 @@ void __init MMU_init(void) | |||
195 | memblock_set_current_limit(lowmem_end_addr); | 194 | memblock_set_current_limit(lowmem_end_addr); |
196 | } | 195 | } |
197 | 196 | ||
198 | /* This is only called until mem_init is done. */ | ||
199 | void __init *early_get_page(void) | ||
200 | { | ||
201 | if (init_bootmem_done) | ||
202 | return alloc_bootmem_pages(PAGE_SIZE); | ||
203 | else | ||
204 | return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE)); | ||
205 | } | ||
206 | |||
207 | #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */ | 197 | #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */ |
208 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | 198 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, |
209 | phys_addr_t first_memblock_size) | 199 | phys_addr_t first_memblock_size) |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 3481556a1880..10471f9bb63f 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/vmalloc.h> | 34 | #include <linux/vmalloc.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
37 | #include <linux/bootmem.h> | ||
38 | #include <linux/highmem.h> | 37 | #include <linux/highmem.h> |
39 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
40 | #include <linux/nodemask.h> | 39 | #include <linux/nodemask.h> |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 8ebaac75c940..b7285a5870f8 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/memblock.h> | 35 | #include <linux/memblock.h> |
36 | #include <linux/hugetlb.h> | 36 | #include <linux/hugetlb.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/vmalloc.h> | ||
38 | 39 | ||
39 | #include <asm/pgalloc.h> | 40 | #include <asm/pgalloc.h> |
40 | #include <asm/prom.h> | 41 | #include <asm/prom.h> |
@@ -60,7 +61,6 @@ | |||
60 | #define CPU_FTR_NOEXECUTE 0 | 61 | #define CPU_FTR_NOEXECUTE 0 |
61 | #endif | 62 | #endif |
62 | 63 | ||
63 | int init_bootmem_done; | ||
64 | int mem_init_done; | 64 | int mem_init_done; |
65 | unsigned long long memory_limit; | 65 | unsigned long long memory_limit; |
66 | 66 | ||
@@ -144,8 +144,17 @@ int arch_remove_memory(u64 start, u64 size) | |||
144 | 144 | ||
145 | zone = page_zone(pfn_to_page(start_pfn)); | 145 | zone = page_zone(pfn_to_page(start_pfn)); |
146 | ret = __remove_pages(zone, start_pfn, nr_pages); | 146 | ret = __remove_pages(zone, start_pfn, nr_pages); |
147 | if (!ret && (ppc_md.remove_memory)) | 147 | if (ret) |
148 | ret = ppc_md.remove_memory(start, size); | 148 | return ret; |
149 | |||
150 | /* Remove htab bolted mappings for this section of memory */ | ||
151 | start = (unsigned long)__va(start); | ||
152 | ret = remove_section_mapping(start, start + size); | ||
153 | |||
154 | /* Ensure all vmalloc mappings are flushed in case they also | ||
155 | * hit that section of memory | ||
156 | */ | ||
157 | vm_unmap_aliases(); | ||
149 | 158 | ||
150 | return ret; | 159 | return ret; |
151 | } | 160 | } |
@@ -180,70 +189,23 @@ walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | |||
180 | } | 189 | } |
181 | EXPORT_SYMBOL_GPL(walk_system_ram_range); | 190 | EXPORT_SYMBOL_GPL(walk_system_ram_range); |
182 | 191 | ||
183 | /* | ||
184 | * Initialize the bootmem system and give it all the memory we | ||
185 | * have available. If we are using highmem, we only put the | ||
186 | * lowmem into the bootmem system. | ||
187 | */ | ||
188 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 192 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
189 | void __init do_init_bootmem(void) | 193 | void __init initmem_init(void) |
190 | { | 194 | { |
191 | unsigned long start, bootmap_pages; | ||
192 | unsigned long total_pages; | ||
193 | struct memblock_region *reg; | ||
194 | int boot_mapsize; | ||
195 | |||
196 | max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; | 195 | max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; |
197 | total_pages = (memblock_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT; | 196 | min_low_pfn = MEMORY_START >> PAGE_SHIFT; |
198 | #ifdef CONFIG_HIGHMEM | 197 | #ifdef CONFIG_HIGHMEM |
199 | total_pages = total_lowmem >> PAGE_SHIFT; | ||
200 | max_low_pfn = lowmem_end_addr >> PAGE_SHIFT; | 198 | max_low_pfn = lowmem_end_addr >> PAGE_SHIFT; |
201 | #endif | 199 | #endif |
202 | 200 | ||
203 | /* | ||
204 | * Find an area to use for the bootmem bitmap. Calculate the size of | ||
205 | * bitmap required as (Total Memory) / PAGE_SIZE / BITS_PER_BYTE. | ||
206 | * Add 1 additional page in case the address isn't page-aligned. | ||
207 | */ | ||
208 | bootmap_pages = bootmem_bootmap_pages(total_pages); | ||
209 | |||
210 | start = memblock_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); | ||
211 | |||
212 | min_low_pfn = MEMORY_START >> PAGE_SHIFT; | ||
213 | boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn); | ||
214 | |||
215 | /* Place all memblock_regions in the same node and merge contiguous | 201 | /* Place all memblock_regions in the same node and merge contiguous |
216 | * memblock_regions | 202 | * memblock_regions |
217 | */ | 203 | */ |
218 | memblock_set_node(0, (phys_addr_t)ULLONG_MAX, &memblock.memory, 0); | 204 | memblock_set_node(0, (phys_addr_t)ULLONG_MAX, &memblock.memory, 0); |
219 | 205 | ||
220 | /* Add all physical memory to the bootmem map, mark each area | ||
221 | * present. | ||
222 | */ | ||
223 | #ifdef CONFIG_HIGHMEM | ||
224 | free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT); | ||
225 | |||
226 | /* reserve the sections we're already using */ | ||
227 | for_each_memblock(reserved, reg) { | ||
228 | unsigned long top = reg->base + reg->size - 1; | ||
229 | if (top < lowmem_end_addr) | ||
230 | reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); | ||
231 | else if (reg->base < lowmem_end_addr) { | ||
232 | unsigned long trunc_size = lowmem_end_addr - reg->base; | ||
233 | reserve_bootmem(reg->base, trunc_size, BOOTMEM_DEFAULT); | ||
234 | } | ||
235 | } | ||
236 | #else | ||
237 | free_bootmem_with_active_regions(0, max_pfn); | ||
238 | |||
239 | /* reserve the sections we're already using */ | ||
240 | for_each_memblock(reserved, reg) | ||
241 | reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); | ||
242 | #endif | ||
243 | /* XXX need to clip this if using highmem? */ | 206 | /* XXX need to clip this if using highmem? */ |
244 | sparse_memory_present_with_active_regions(0); | 207 | sparse_memory_present_with_active_regions(0); |
245 | 208 | sparse_init(); | |
246 | init_bootmem_done = 1; | ||
247 | } | 209 | } |
248 | 210 | ||
249 | /* mark pages that don't exist as nosave */ | 211 | /* mark pages that don't exist as nosave */ |
@@ -359,14 +321,6 @@ void __init paging_init(void) | |||
359 | mark_nonram_nosave(); | 321 | mark_nonram_nosave(); |
360 | } | 322 | } |
361 | 323 | ||
362 | static void __init register_page_bootmem_info(void) | ||
363 | { | ||
364 | int i; | ||
365 | |||
366 | for_each_online_node(i) | ||
367 | register_page_bootmem_info_node(NODE_DATA(i)); | ||
368 | } | ||
369 | |||
370 | void __init mem_init(void) | 324 | void __init mem_init(void) |
371 | { | 325 | { |
372 | /* | 326 | /* |
@@ -379,7 +333,6 @@ void __init mem_init(void) | |||
379 | swiotlb_init(0); | 333 | swiotlb_init(0); |
380 | #endif | 334 | #endif |
381 | 335 | ||
382 | register_page_bootmem_info(); | ||
383 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); | 336 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); |
384 | set_max_mapnr(max_pfn); | 337 | set_max_mapnr(max_pfn); |
385 | free_all_bootmem(); | 338 | free_all_bootmem(); |
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index 928ebe79668b..9cba6cba2e50 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c | |||
@@ -421,12 +421,12 @@ void __init mmu_context_init(void) | |||
421 | /* | 421 | /* |
422 | * Allocate the maps used by context management | 422 | * Allocate the maps used by context management |
423 | */ | 423 | */ |
424 | context_map = alloc_bootmem(CTX_MAP_SIZE); | 424 | context_map = memblock_virt_alloc(CTX_MAP_SIZE, 0); |
425 | context_mm = alloc_bootmem(sizeof(void *) * (last_context + 1)); | 425 | context_mm = memblock_virt_alloc(sizeof(void *) * (last_context + 1), 0); |
426 | #ifndef CONFIG_SMP | 426 | #ifndef CONFIG_SMP |
427 | stale_map[0] = alloc_bootmem(CTX_MAP_SIZE); | 427 | stale_map[0] = memblock_virt_alloc(CTX_MAP_SIZE, 0); |
428 | #else | 428 | #else |
429 | stale_map[boot_cpuid] = alloc_bootmem(CTX_MAP_SIZE); | 429 | stale_map[boot_cpuid] = memblock_virt_alloc(CTX_MAP_SIZE, 0); |
430 | 430 | ||
431 | register_cpu_notifier(&mmu_context_cpu_nb); | 431 | register_cpu_notifier(&mmu_context_cpu_nb); |
432 | #endif | 432 | #endif |
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 9615d82919b8..78c45f392f5b 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
@@ -67,7 +67,7 @@ static inline void _tlbil_va(unsigned long address, unsigned int pid, | |||
67 | { | 67 | { |
68 | __tlbil_va(address, pid); | 68 | __tlbil_va(address, pid); |
69 | } | 69 | } |
70 | #endif /* CONIFG_8xx */ | 70 | #endif /* CONFIG_8xx */ |
71 | 71 | ||
72 | #if defined(CONFIG_PPC_BOOK3E) || defined(CONFIG_PPC_47x) | 72 | #if defined(CONFIG_PPC_BOOK3E) || defined(CONFIG_PPC_47x) |
73 | extern void _tlbivax_bcast(unsigned long address, unsigned int pid, | 73 | extern void _tlbivax_bcast(unsigned long address, unsigned int pid, |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 9fe6002c1d5a..0257a7d659ef 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -134,28 +134,6 @@ static int __init fake_numa_create_new_node(unsigned long end_pfn, | |||
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
136 | 136 | ||
137 | /* | ||
138 | * get_node_active_region - Return active region containing pfn | ||
139 | * Active range returned is empty if none found. | ||
140 | * @pfn: The page to return the region for | ||
141 | * @node_ar: Returned set to the active region containing @pfn | ||
142 | */ | ||
143 | static void __init get_node_active_region(unsigned long pfn, | ||
144 | struct node_active_region *node_ar) | ||
145 | { | ||
146 | unsigned long start_pfn, end_pfn; | ||
147 | int i, nid; | ||
148 | |||
149 | for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) { | ||
150 | if (pfn >= start_pfn && pfn < end_pfn) { | ||
151 | node_ar->nid = nid; | ||
152 | node_ar->start_pfn = start_pfn; | ||
153 | node_ar->end_pfn = end_pfn; | ||
154 | break; | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | |||
159 | static void reset_numa_cpu_lookup_table(void) | 137 | static void reset_numa_cpu_lookup_table(void) |
160 | { | 138 | { |
161 | unsigned int cpu; | 139 | unsigned int cpu; |
@@ -928,134 +906,48 @@ static void __init dump_numa_memory_topology(void) | |||
928 | } | 906 | } |
929 | } | 907 | } |
930 | 908 | ||
931 | /* | ||
932 | * Allocate some memory, satisfying the memblock or bootmem allocator where | ||
933 | * required. nid is the preferred node and end is the physical address of | ||
934 | * the highest address in the node. | ||
935 | * | ||
936 | * Returns the virtual address of the memory. | ||
937 | */ | ||
938 | static void __init *careful_zallocation(int nid, unsigned long size, | ||
939 | unsigned long align, | ||
940 | unsigned long end_pfn) | ||
941 | { | ||
942 | void *ret; | ||
943 | int new_nid; | ||
944 | unsigned long ret_paddr; | ||
945 | |||
946 | ret_paddr = __memblock_alloc_base(size, align, end_pfn << PAGE_SHIFT); | ||
947 | |||
948 | /* retry over all memory */ | ||
949 | if (!ret_paddr) | ||
950 | ret_paddr = __memblock_alloc_base(size, align, memblock_end_of_DRAM()); | ||
951 | |||
952 | if (!ret_paddr) | ||
953 | panic("numa.c: cannot allocate %lu bytes for node %d", | ||
954 | size, nid); | ||
955 | |||
956 | ret = __va(ret_paddr); | ||
957 | |||
958 | /* | ||
959 | * We initialize the nodes in numeric order: 0, 1, 2... | ||
960 | * and hand over control from the MEMBLOCK allocator to the | ||
961 | * bootmem allocator. If this function is called for | ||
962 | * node 5, then we know that all nodes <5 are using the | ||
963 | * bootmem allocator instead of the MEMBLOCK allocator. | ||
964 | * | ||
965 | * So, check the nid from which this allocation came | ||
966 | * and double check to see if we need to use bootmem | ||
967 | * instead of the MEMBLOCK. We don't free the MEMBLOCK memory | ||
968 | * since it would be useless. | ||
969 | */ | ||
970 | new_nid = early_pfn_to_nid(ret_paddr >> PAGE_SHIFT); | ||
971 | if (new_nid < nid) { | ||
972 | ret = __alloc_bootmem_node(NODE_DATA(new_nid), | ||
973 | size, align, 0); | ||
974 | |||
975 | dbg("alloc_bootmem %p %lx\n", ret, size); | ||
976 | } | ||
977 | |||
978 | memset(ret, 0, size); | ||
979 | return ret; | ||
980 | } | ||
981 | |||
982 | static struct notifier_block ppc64_numa_nb = { | 909 | static struct notifier_block ppc64_numa_nb = { |
983 | .notifier_call = cpu_numa_callback, | 910 | .notifier_call = cpu_numa_callback, |
984 | .priority = 1 /* Must run before sched domains notifier. */ | 911 | .priority = 1 /* Must run before sched domains notifier. */ |
985 | }; | 912 | }; |
986 | 913 | ||
987 | static void __init mark_reserved_regions_for_nid(int nid) | 914 | /* Initialize NODE_DATA for a node on the local memory */ |
915 | static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) | ||
988 | { | 916 | { |
989 | struct pglist_data *node = NODE_DATA(nid); | 917 | u64 spanned_pages = end_pfn - start_pfn; |
990 | struct memblock_region *reg; | 918 | const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES); |
991 | 919 | u64 nd_pa; | |
992 | for_each_memblock(reserved, reg) { | 920 | void *nd; |
993 | unsigned long physbase = reg->base; | 921 | int tnid; |
994 | unsigned long size = reg->size; | 922 | |
995 | unsigned long start_pfn = physbase >> PAGE_SHIFT; | 923 | if (spanned_pages) |
996 | unsigned long end_pfn = PFN_UP(physbase + size); | 924 | pr_info("Initmem setup node %d [mem %#010Lx-%#010Lx]\n", |
997 | struct node_active_region node_ar; | 925 | nid, start_pfn << PAGE_SHIFT, |
998 | unsigned long node_end_pfn = pgdat_end_pfn(node); | 926 | (end_pfn << PAGE_SHIFT) - 1); |
999 | 927 | else | |
1000 | /* | 928 | pr_info("Initmem setup node %d\n", nid); |
1001 | * Check to make sure that this memblock.reserved area is | 929 | |
1002 | * within the bounds of the node that we care about. | 930 | nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); |
1003 | * Checking the nid of the start and end points is not | 931 | nd = __va(nd_pa); |
1004 | * sufficient because the reserved area could span the | 932 | |
1005 | * entire node. | 933 | /* report and initialize */ |
1006 | */ | 934 | pr_info(" NODE_DATA [mem %#010Lx-%#010Lx]\n", |
1007 | if (end_pfn <= node->node_start_pfn || | 935 | nd_pa, nd_pa + nd_size - 1); |
1008 | start_pfn >= node_end_pfn) | 936 | tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); |
1009 | continue; | 937 | if (tnid != nid) |
1010 | 938 | pr_info(" NODE_DATA(%d) on node %d\n", nid, tnid); | |
1011 | get_node_active_region(start_pfn, &node_ar); | 939 | |
1012 | while (start_pfn < end_pfn && | 940 | node_data[nid] = nd; |
1013 | node_ar.start_pfn < node_ar.end_pfn) { | 941 | memset(NODE_DATA(nid), 0, sizeof(pg_data_t)); |
1014 | unsigned long reserve_size = size; | 942 | NODE_DATA(nid)->node_id = nid; |
1015 | /* | 943 | NODE_DATA(nid)->node_start_pfn = start_pfn; |
1016 | * if reserved region extends past active region | 944 | NODE_DATA(nid)->node_spanned_pages = spanned_pages; |
1017 | * then trim size to active region | ||
1018 | */ | ||
1019 | if (end_pfn > node_ar.end_pfn) | ||
1020 | reserve_size = (node_ar.end_pfn << PAGE_SHIFT) | ||
1021 | - physbase; | ||
1022 | /* | ||
1023 | * Only worry about *this* node, others may not | ||
1024 | * yet have valid NODE_DATA(). | ||
1025 | */ | ||
1026 | if (node_ar.nid == nid) { | ||
1027 | dbg("reserve_bootmem %lx %lx nid=%d\n", | ||
1028 | physbase, reserve_size, node_ar.nid); | ||
1029 | reserve_bootmem_node(NODE_DATA(node_ar.nid), | ||
1030 | physbase, reserve_size, | ||
1031 | BOOTMEM_DEFAULT); | ||
1032 | } | ||
1033 | /* | ||
1034 | * if reserved region is contained in the active region | ||
1035 | * then done. | ||
1036 | */ | ||
1037 | if (end_pfn <= node_ar.end_pfn) | ||
1038 | break; | ||
1039 | |||
1040 | /* | ||
1041 | * reserved region extends past the active region | ||
1042 | * get next active region that contains this | ||
1043 | * reserved region | ||
1044 | */ | ||
1045 | start_pfn = node_ar.end_pfn; | ||
1046 | physbase = start_pfn << PAGE_SHIFT; | ||
1047 | size = size - reserve_size; | ||
1048 | get_node_active_region(start_pfn, &node_ar); | ||
1049 | } | ||
1050 | } | ||
1051 | } | 945 | } |
1052 | 946 | ||
1053 | 947 | void __init initmem_init(void) | |
1054 | void __init do_init_bootmem(void) | ||
1055 | { | 948 | { |
1056 | int nid, cpu; | 949 | int nid, cpu; |
1057 | 950 | ||
1058 | min_low_pfn = 0; | ||
1059 | max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; | 951 | max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; |
1060 | max_pfn = max_low_pfn; | 952 | max_pfn = max_low_pfn; |
1061 | 953 | ||
@@ -1064,64 +956,18 @@ void __init do_init_bootmem(void) | |||
1064 | else | 956 | else |
1065 | dump_numa_memory_topology(); | 957 | dump_numa_memory_topology(); |
1066 | 958 | ||
959 | memblock_dump_all(); | ||
960 | |||
1067 | for_each_online_node(nid) { | 961 | for_each_online_node(nid) { |
1068 | unsigned long start_pfn, end_pfn; | 962 | unsigned long start_pfn, end_pfn; |
1069 | void *bootmem_vaddr; | ||
1070 | unsigned long bootmap_pages; | ||
1071 | 963 | ||
1072 | get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); | 964 | get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); |
1073 | 965 | setup_node_data(nid, start_pfn, end_pfn); | |
1074 | /* | ||
1075 | * Allocate the node structure node local if possible | ||
1076 | * | ||
1077 | * Be careful moving this around, as it relies on all | ||
1078 | * previous nodes' bootmem to be initialized and have | ||
1079 | * all reserved areas marked. | ||
1080 | */ | ||
1081 | NODE_DATA(nid) = careful_zallocation(nid, | ||
1082 | sizeof(struct pglist_data), | ||
1083 | SMP_CACHE_BYTES, end_pfn); | ||
1084 | |||
1085 | dbg("node %d\n", nid); | ||
1086 | dbg("NODE_DATA() = %p\n", NODE_DATA(nid)); | ||
1087 | |||
1088 | NODE_DATA(nid)->bdata = &bootmem_node_data[nid]; | ||
1089 | NODE_DATA(nid)->node_start_pfn = start_pfn; | ||
1090 | NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn; | ||
1091 | |||
1092 | if (NODE_DATA(nid)->node_spanned_pages == 0) | ||
1093 | continue; | ||
1094 | |||
1095 | dbg("start_paddr = %lx\n", start_pfn << PAGE_SHIFT); | ||
1096 | dbg("end_paddr = %lx\n", end_pfn << PAGE_SHIFT); | ||
1097 | |||
1098 | bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); | ||
1099 | bootmem_vaddr = careful_zallocation(nid, | ||
1100 | bootmap_pages << PAGE_SHIFT, | ||
1101 | PAGE_SIZE, end_pfn); | ||
1102 | |||
1103 | dbg("bootmap_vaddr = %p\n", bootmem_vaddr); | ||
1104 | |||
1105 | init_bootmem_node(NODE_DATA(nid), | ||
1106 | __pa(bootmem_vaddr) >> PAGE_SHIFT, | ||
1107 | start_pfn, end_pfn); | ||
1108 | |||
1109 | free_bootmem_with_active_regions(nid, end_pfn); | ||
1110 | /* | ||
1111 | * Be very careful about moving this around. Future | ||
1112 | * calls to careful_zallocation() depend on this getting | ||
1113 | * done correctly. | ||
1114 | */ | ||
1115 | mark_reserved_regions_for_nid(nid); | ||
1116 | sparse_memory_present_with_active_regions(nid); | 966 | sparse_memory_present_with_active_regions(nid); |
1117 | } | 967 | } |
1118 | 968 | ||
1119 | init_bootmem_done = 1; | 969 | sparse_init(); |
1120 | 970 | ||
1121 | /* | ||
1122 | * Now bootmem is initialised we can create the node to cpumask | ||
1123 | * lookup tables and setup the cpu callback to populate them. | ||
1124 | */ | ||
1125 | setup_node_to_cpumask_map(); | 971 | setup_node_to_cpumask_map(); |
1126 | 972 | ||
1127 | reset_numa_cpu_lookup_table(); | 973 | reset_numa_cpu_lookup_table(); |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index cf11342bf519..d545b1231594 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -100,12 +100,11 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add | |||
100 | { | 100 | { |
101 | pte_t *pte; | 101 | pte_t *pte; |
102 | extern int mem_init_done; | 102 | extern int mem_init_done; |
103 | extern void *early_get_page(void); | ||
104 | 103 | ||
105 | if (mem_init_done) { | 104 | if (mem_init_done) { |
106 | pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); | 105 | pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); |
107 | } else { | 106 | } else { |
108 | pte = (pte_t *)early_get_page(); | 107 | pte = __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE)); |
109 | if (pte) | 108 | if (pte) |
110 | clear_page(pte); | 109 | clear_page(pte); |
111 | } | 110 | } |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index c8d709ab489d..4fe5f64cc179 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -33,9 +33,9 @@ | |||
33 | #include <linux/swap.h> | 33 | #include <linux/swap.h> |
34 | #include <linux/stddef.h> | 34 | #include <linux/stddef.h> |
35 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
36 | #include <linux/bootmem.h> | ||
37 | #include <linux/memblock.h> | 36 | #include <linux/memblock.h> |
38 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/hugetlb.h> | ||
39 | 39 | ||
40 | #include <asm/pgalloc.h> | 40 | #include <asm/pgalloc.h> |
41 | #include <asm/page.h> | 41 | #include <asm/page.h> |
@@ -51,6 +51,7 @@ | |||
51 | #include <asm/cputable.h> | 51 | #include <asm/cputable.h> |
52 | #include <asm/sections.h> | 52 | #include <asm/sections.h> |
53 | #include <asm/firmware.h> | 53 | #include <asm/firmware.h> |
54 | #include <asm/dma.h> | ||
54 | 55 | ||
55 | #include "mmu_decl.h" | 56 | #include "mmu_decl.h" |
56 | 57 | ||
@@ -75,11 +76,7 @@ static __ref void *early_alloc_pgtable(unsigned long size) | |||
75 | { | 76 | { |
76 | void *pt; | 77 | void *pt; |
77 | 78 | ||
78 | if (init_bootmem_done) | 79 | pt = __va(memblock_alloc_base(size, size, __pa(MAX_DMA_ADDRESS))); |
79 | pt = __alloc_bootmem(size, size, __pa(MAX_DMA_ADDRESS)); | ||
80 | else | ||
81 | pt = __va(memblock_alloc_base(size, size, | ||
82 | __pa(MAX_DMA_ADDRESS))); | ||
83 | memset(pt, 0, size); | 80 | memset(pt, 0, size); |
84 | 81 | ||
85 | return pt; | 82 | return pt; |
@@ -113,10 +110,6 @@ int map_kernel_page(unsigned long ea, unsigned long pa, int flags) | |||
113 | __pgprot(flags))); | 110 | __pgprot(flags))); |
114 | } else { | 111 | } else { |
115 | #ifdef CONFIG_PPC_MMU_NOHASH | 112 | #ifdef CONFIG_PPC_MMU_NOHASH |
116 | /* Warning ! This will blow up if bootmem is not initialized | ||
117 | * which our ppc64 code is keen to do that, we'll need to | ||
118 | * fix it and/or be more careful | ||
119 | */ | ||
120 | pgdp = pgd_offset_k(ea); | 113 | pgdp = pgd_offset_k(ea); |
121 | #ifdef PUD_TABLE_SIZE | 114 | #ifdef PUD_TABLE_SIZE |
122 | if (pgd_none(*pgdp)) { | 115 | if (pgd_none(*pgdp)) { |
@@ -352,16 +345,31 @@ EXPORT_SYMBOL(iounmap); | |||
352 | EXPORT_SYMBOL(__iounmap); | 345 | EXPORT_SYMBOL(__iounmap); |
353 | EXPORT_SYMBOL(__iounmap_at); | 346 | EXPORT_SYMBOL(__iounmap_at); |
354 | 347 | ||
348 | #ifndef __PAGETABLE_PUD_FOLDED | ||
349 | /* 4 level page table */ | ||
350 | struct page *pgd_page(pgd_t pgd) | ||
351 | { | ||
352 | if (pgd_huge(pgd)) | ||
353 | return pte_page(pgd_pte(pgd)); | ||
354 | return virt_to_page(pgd_page_vaddr(pgd)); | ||
355 | } | ||
356 | #endif | ||
357 | |||
358 | struct page *pud_page(pud_t pud) | ||
359 | { | ||
360 | if (pud_huge(pud)) | ||
361 | return pte_page(pud_pte(pud)); | ||
362 | return virt_to_page(pud_page_vaddr(pud)); | ||
363 | } | ||
364 | |||
355 | /* | 365 | /* |
356 | * For hugepage we have pfn in the pmd, we use PTE_RPN_SHIFT bits for flags | 366 | * For hugepage we have pfn in the pmd, we use PTE_RPN_SHIFT bits for flags |
357 | * For PTE page, we have a PTE_FRAG_SIZE (4K) aligned virtual address. | 367 | * For PTE page, we have a PTE_FRAG_SIZE (4K) aligned virtual address. |
358 | */ | 368 | */ |
359 | struct page *pmd_page(pmd_t pmd) | 369 | struct page *pmd_page(pmd_t pmd) |
360 | { | 370 | { |
361 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 371 | if (pmd_trans_huge(pmd) || pmd_huge(pmd)) |
362 | if (pmd_trans_huge(pmd)) | ||
363 | return pfn_to_page(pmd_pfn(pmd)); | 372 | return pfn_to_page(pmd_pfn(pmd)); |
364 | #endif | ||
365 | return virt_to_page(pmd_page_vaddr(pmd)); | 373 | return virt_to_page(pmd_page_vaddr(pmd)); |
366 | } | 374 | } |
367 | 375 | ||
@@ -731,29 +739,15 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, | |||
731 | void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, | 739 | void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, |
732 | pmd_t *pmdp, unsigned long old_pmd) | 740 | pmd_t *pmdp, unsigned long old_pmd) |
733 | { | 741 | { |
734 | int ssize, i; | 742 | int ssize; |
735 | unsigned long s_addr; | 743 | unsigned int psize; |
736 | int max_hpte_count; | 744 | unsigned long vsid; |
737 | unsigned int psize, valid; | 745 | unsigned long flags = 0; |
738 | unsigned char *hpte_slot_array; | 746 | const struct cpumask *tmp; |
739 | unsigned long hidx, vpn, vsid, hash, shift, slot; | ||
740 | |||
741 | /* | ||
742 | * Flush all the hptes mapping this hugepage | ||
743 | */ | ||
744 | s_addr = addr & HPAGE_PMD_MASK; | ||
745 | hpte_slot_array = get_hpte_slot_array(pmdp); | ||
746 | /* | ||
747 | * IF we try to do a HUGE PTE update after a withdraw is done. | ||
748 | * we will find the below NULL. This happens when we do | ||
749 | * split_huge_page_pmd | ||
750 | */ | ||
751 | if (!hpte_slot_array) | ||
752 | return; | ||
753 | 747 | ||
754 | /* get the base page size,vsid and segment size */ | 748 | /* get the base page size,vsid and segment size */ |
755 | #ifdef CONFIG_DEBUG_VM | 749 | #ifdef CONFIG_DEBUG_VM |
756 | psize = get_slice_psize(mm, s_addr); | 750 | psize = get_slice_psize(mm, addr); |
757 | BUG_ON(psize == MMU_PAGE_16M); | 751 | BUG_ON(psize == MMU_PAGE_16M); |
758 | #endif | 752 | #endif |
759 | if (old_pmd & _PAGE_COMBO) | 753 | if (old_pmd & _PAGE_COMBO) |
@@ -761,46 +755,20 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, | |||
761 | else | 755 | else |
762 | psize = MMU_PAGE_64K; | 756 | psize = MMU_PAGE_64K; |
763 | 757 | ||
764 | if (!is_kernel_addr(s_addr)) { | 758 | if (!is_kernel_addr(addr)) { |
765 | ssize = user_segment_size(s_addr); | 759 | ssize = user_segment_size(addr); |
766 | vsid = get_vsid(mm->context.id, s_addr, ssize); | 760 | vsid = get_vsid(mm->context.id, addr, ssize); |
767 | WARN_ON(vsid == 0); | 761 | WARN_ON(vsid == 0); |
768 | } else { | 762 | } else { |
769 | vsid = get_kernel_vsid(s_addr, mmu_kernel_ssize); | 763 | vsid = get_kernel_vsid(addr, mmu_kernel_ssize); |
770 | ssize = mmu_kernel_ssize; | 764 | ssize = mmu_kernel_ssize; |
771 | } | 765 | } |
772 | 766 | ||
773 | if (ppc_md.hugepage_invalidate) | 767 | tmp = cpumask_of(smp_processor_id()); |
774 | return ppc_md.hugepage_invalidate(vsid, s_addr, | 768 | if (cpumask_equal(mm_cpumask(mm), tmp)) |
775 | hpte_slot_array, | 769 | flags |= HPTE_LOCAL_UPDATE; |
776 | psize, ssize); | 770 | |
777 | /* | 771 | return flush_hash_hugepage(vsid, addr, pmdp, psize, ssize, flags); |
778 | * No bluk hpte removal support, invalidate each entry | ||
779 | */ | ||
780 | shift = mmu_psize_defs[psize].shift; | ||
781 | max_hpte_count = HPAGE_PMD_SIZE >> shift; | ||
782 | for (i = 0; i < max_hpte_count; i++) { | ||
783 | /* | ||
784 | * 8 bits per each hpte entries | ||
785 | * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit] | ||
786 | */ | ||
787 | valid = hpte_valid(hpte_slot_array, i); | ||
788 | if (!valid) | ||
789 | continue; | ||
790 | hidx = hpte_hash_index(hpte_slot_array, i); | ||
791 | |||
792 | /* get the vpn */ | ||
793 | addr = s_addr + (i * (1ul << shift)); | ||
794 | vpn = hpt_vpn(addr, vsid, ssize); | ||
795 | hash = hpt_hash(vpn, shift, ssize); | ||
796 | if (hidx & _PTEIDX_SECONDARY) | ||
797 | hash = ~hash; | ||
798 | |||
799 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | ||
800 | slot += hidx & _PTEIDX_GROUP_IX; | ||
801 | ppc_md.hpte_invalidate(slot, vpn, psize, | ||
802 | MMU_PAGE_16M, ssize, 0); | ||
803 | } | ||
804 | } | 772 | } |
805 | 773 | ||
806 | static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot) | 774 | static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot) |
diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c index 6adf55fa5d88..ecc66d5f02c9 100644 --- a/arch/powerpc/oprofile/backtrace.c +++ b/arch/powerpc/oprofile/backtrace.c | |||
@@ -10,7 +10,7 @@ | |||
10 | #include <linux/oprofile.h> | 10 | #include <linux/oprofile.h> |
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <asm/processor.h> | 12 | #include <asm/processor.h> |
13 | #include <asm/uaccess.h> | 13 | #include <linux/uaccess.h> |
14 | #include <asm/compat.h> | 14 | #include <asm/compat.h> |
15 | #include <asm/oprofile_impl.h> | 15 | #include <asm/oprofile_impl.h> |
16 | 16 | ||
@@ -105,6 +105,7 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth) | |||
105 | first_frame = 0; | 105 | first_frame = 0; |
106 | } | 106 | } |
107 | } else { | 107 | } else { |
108 | pagefault_disable(); | ||
108 | #ifdef CONFIG_PPC64 | 109 | #ifdef CONFIG_PPC64 |
109 | if (!is_32bit_task()) { | 110 | if (!is_32bit_task()) { |
110 | while (depth--) { | 111 | while (depth--) { |
@@ -113,7 +114,7 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth) | |||
113 | break; | 114 | break; |
114 | first_frame = 0; | 115 | first_frame = 0; |
115 | } | 116 | } |
116 | 117 | pagefault_enable(); | |
117 | return; | 118 | return; |
118 | } | 119 | } |
119 | #endif | 120 | #endif |
@@ -124,5 +125,6 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth) | |||
124 | break; | 125 | break; |
125 | first_frame = 0; | 126 | first_frame = 0; |
126 | } | 127 | } |
128 | pagefault_enable(); | ||
127 | } | 129 | } |
128 | } | 130 | } |
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index a6995d4e93d4..7c4f6690533a 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c | |||
@@ -339,7 +339,7 @@ static void power_pmu_bhrb_reset(void) | |||
339 | 339 | ||
340 | static void power_pmu_bhrb_enable(struct perf_event *event) | 340 | static void power_pmu_bhrb_enable(struct perf_event *event) |
341 | { | 341 | { |
342 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 342 | struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); |
343 | 343 | ||
344 | if (!ppmu->bhrb_nr) | 344 | if (!ppmu->bhrb_nr) |
345 | return; | 345 | return; |
@@ -354,7 +354,7 @@ static void power_pmu_bhrb_enable(struct perf_event *event) | |||
354 | 354 | ||
355 | static void power_pmu_bhrb_disable(struct perf_event *event) | 355 | static void power_pmu_bhrb_disable(struct perf_event *event) |
356 | { | 356 | { |
357 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 357 | struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); |
358 | 358 | ||
359 | if (!ppmu->bhrb_nr) | 359 | if (!ppmu->bhrb_nr) |
360 | return; | 360 | return; |
@@ -1144,7 +1144,7 @@ static void power_pmu_disable(struct pmu *pmu) | |||
1144 | if (!ppmu) | 1144 | if (!ppmu) |
1145 | return; | 1145 | return; |
1146 | local_irq_save(flags); | 1146 | local_irq_save(flags); |
1147 | cpuhw = &__get_cpu_var(cpu_hw_events); | 1147 | cpuhw = this_cpu_ptr(&cpu_hw_events); |
1148 | 1148 | ||
1149 | if (!cpuhw->disabled) { | 1149 | if (!cpuhw->disabled) { |
1150 | /* | 1150 | /* |
@@ -1211,7 +1211,7 @@ static void power_pmu_enable(struct pmu *pmu) | |||
1211 | return; | 1211 | return; |
1212 | local_irq_save(flags); | 1212 | local_irq_save(flags); |
1213 | 1213 | ||
1214 | cpuhw = &__get_cpu_var(cpu_hw_events); | 1214 | cpuhw = this_cpu_ptr(&cpu_hw_events); |
1215 | if (!cpuhw->disabled) | 1215 | if (!cpuhw->disabled) |
1216 | goto out; | 1216 | goto out; |
1217 | 1217 | ||
@@ -1403,7 +1403,7 @@ static int power_pmu_add(struct perf_event *event, int ef_flags) | |||
1403 | * Add the event to the list (if there is room) | 1403 | * Add the event to the list (if there is room) |
1404 | * and check whether the total set is still feasible. | 1404 | * and check whether the total set is still feasible. |
1405 | */ | 1405 | */ |
1406 | cpuhw = &__get_cpu_var(cpu_hw_events); | 1406 | cpuhw = this_cpu_ptr(&cpu_hw_events); |
1407 | n0 = cpuhw->n_events; | 1407 | n0 = cpuhw->n_events; |
1408 | if (n0 >= ppmu->n_counter) | 1408 | if (n0 >= ppmu->n_counter) |
1409 | goto out; | 1409 | goto out; |
@@ -1469,7 +1469,7 @@ static void power_pmu_del(struct perf_event *event, int ef_flags) | |||
1469 | 1469 | ||
1470 | power_pmu_read(event); | 1470 | power_pmu_read(event); |
1471 | 1471 | ||
1472 | cpuhw = &__get_cpu_var(cpu_hw_events); | 1472 | cpuhw = this_cpu_ptr(&cpu_hw_events); |
1473 | for (i = 0; i < cpuhw->n_events; ++i) { | 1473 | for (i = 0; i < cpuhw->n_events; ++i) { |
1474 | if (event == cpuhw->event[i]) { | 1474 | if (event == cpuhw->event[i]) { |
1475 | while (++i < cpuhw->n_events) { | 1475 | while (++i < cpuhw->n_events) { |
@@ -1575,7 +1575,7 @@ static void power_pmu_stop(struct perf_event *event, int ef_flags) | |||
1575 | */ | 1575 | */ |
1576 | static void power_pmu_start_txn(struct pmu *pmu) | 1576 | static void power_pmu_start_txn(struct pmu *pmu) |
1577 | { | 1577 | { |
1578 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 1578 | struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); |
1579 | 1579 | ||
1580 | perf_pmu_disable(pmu); | 1580 | perf_pmu_disable(pmu); |
1581 | cpuhw->group_flag |= PERF_EVENT_TXN; | 1581 | cpuhw->group_flag |= PERF_EVENT_TXN; |
@@ -1589,7 +1589,7 @@ static void power_pmu_start_txn(struct pmu *pmu) | |||
1589 | */ | 1589 | */ |
1590 | static void power_pmu_cancel_txn(struct pmu *pmu) | 1590 | static void power_pmu_cancel_txn(struct pmu *pmu) |
1591 | { | 1591 | { |
1592 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 1592 | struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); |
1593 | 1593 | ||
1594 | cpuhw->group_flag &= ~PERF_EVENT_TXN; | 1594 | cpuhw->group_flag &= ~PERF_EVENT_TXN; |
1595 | perf_pmu_enable(pmu); | 1595 | perf_pmu_enable(pmu); |
@@ -1607,7 +1607,7 @@ static int power_pmu_commit_txn(struct pmu *pmu) | |||
1607 | 1607 | ||
1608 | if (!ppmu) | 1608 | if (!ppmu) |
1609 | return -EAGAIN; | 1609 | return -EAGAIN; |
1610 | cpuhw = &__get_cpu_var(cpu_hw_events); | 1610 | cpuhw = this_cpu_ptr(&cpu_hw_events); |
1611 | n = cpuhw->n_events; | 1611 | n = cpuhw->n_events; |
1612 | if (check_excludes(cpuhw->event, cpuhw->flags, 0, n)) | 1612 | if (check_excludes(cpuhw->event, cpuhw->flags, 0, n)) |
1613 | return -EAGAIN; | 1613 | return -EAGAIN; |
@@ -1964,7 +1964,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val, | |||
1964 | 1964 | ||
1965 | if (event->attr.sample_type & PERF_SAMPLE_BRANCH_STACK) { | 1965 | if (event->attr.sample_type & PERF_SAMPLE_BRANCH_STACK) { |
1966 | struct cpu_hw_events *cpuhw; | 1966 | struct cpu_hw_events *cpuhw; |
1967 | cpuhw = &__get_cpu_var(cpu_hw_events); | 1967 | cpuhw = this_cpu_ptr(&cpu_hw_events); |
1968 | power_pmu_bhrb_read(cpuhw); | 1968 | power_pmu_bhrb_read(cpuhw); |
1969 | data.br_stack = &cpuhw->bhrb_stack; | 1969 | data.br_stack = &cpuhw->bhrb_stack; |
1970 | } | 1970 | } |
@@ -2037,7 +2037,7 @@ static bool pmc_overflow(unsigned long val) | |||
2037 | static void perf_event_interrupt(struct pt_regs *regs) | 2037 | static void perf_event_interrupt(struct pt_regs *regs) |
2038 | { | 2038 | { |
2039 | int i, j; | 2039 | int i, j; |
2040 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 2040 | struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); |
2041 | struct perf_event *event; | 2041 | struct perf_event *event; |
2042 | unsigned long val[8]; | 2042 | unsigned long val[8]; |
2043 | int found, active; | 2043 | int found, active; |
diff --git a/arch/powerpc/perf/core-fsl-emb.c b/arch/powerpc/perf/core-fsl-emb.c index d35ae52c69dc..4acaea01fe03 100644 --- a/arch/powerpc/perf/core-fsl-emb.c +++ b/arch/powerpc/perf/core-fsl-emb.c | |||
@@ -210,7 +210,7 @@ static void fsl_emb_pmu_disable(struct pmu *pmu) | |||
210 | unsigned long flags; | 210 | unsigned long flags; |
211 | 211 | ||
212 | local_irq_save(flags); | 212 | local_irq_save(flags); |
213 | cpuhw = &__get_cpu_var(cpu_hw_events); | 213 | cpuhw = this_cpu_ptr(&cpu_hw_events); |
214 | 214 | ||
215 | if (!cpuhw->disabled) { | 215 | if (!cpuhw->disabled) { |
216 | cpuhw->disabled = 1; | 216 | cpuhw->disabled = 1; |
@@ -249,7 +249,7 @@ static void fsl_emb_pmu_enable(struct pmu *pmu) | |||
249 | unsigned long flags; | 249 | unsigned long flags; |
250 | 250 | ||
251 | local_irq_save(flags); | 251 | local_irq_save(flags); |
252 | cpuhw = &__get_cpu_var(cpu_hw_events); | 252 | cpuhw = this_cpu_ptr(&cpu_hw_events); |
253 | if (!cpuhw->disabled) | 253 | if (!cpuhw->disabled) |
254 | goto out; | 254 | goto out; |
255 | 255 | ||
@@ -653,7 +653,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val, | |||
653 | static void perf_event_interrupt(struct pt_regs *regs) | 653 | static void perf_event_interrupt(struct pt_regs *regs) |
654 | { | 654 | { |
655 | int i; | 655 | int i; |
656 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 656 | struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); |
657 | struct perf_event *event; | 657 | struct perf_event *event; |
658 | unsigned long val; | 658 | unsigned long val; |
659 | int found = 0; | 659 | int found = 0; |
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 82f2da28cd27..d2ac1c116454 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig | |||
@@ -220,7 +220,6 @@ config AKEBONO | |||
220 | select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD | 220 | select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD |
221 | select MMC_SDHCI | 221 | select MMC_SDHCI |
222 | select MMC_SDHCI_PLTFM | 222 | select MMC_SDHCI_PLTFM |
223 | select MMC_SDHCI_OF_476GTR | ||
224 | select ATA | 223 | select ATA |
225 | select SATA_AHCI_PLATFORM | 224 | select SATA_AHCI_PLATFORM |
226 | help | 225 | help |
diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c index 58db9d083969..c11ce6516c8f 100644 --- a/arch/powerpc/platforms/44x/ppc476.c +++ b/arch/powerpc/platforms/44x/ppc476.c | |||
@@ -94,7 +94,7 @@ static int avr_probe(struct i2c_client *client, | |||
94 | { | 94 | { |
95 | avr_i2c_client = client; | 95 | avr_i2c_client = client; |
96 | ppc_md.restart = avr_reset_system; | 96 | ppc_md.restart = avr_reset_system; |
97 | ppc_md.power_off = avr_power_off_system; | 97 | pm_power_off = avr_power_off_system; |
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c index e996e007bc44..711f3d352af7 100644 --- a/arch/powerpc/platforms/512x/mpc512x_shared.c +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/of_platform.h> | 19 | #include <linux/of_platform.h> |
20 | #include <linux/fsl-diu-fb.h> | 20 | #include <linux/fsl-diu-fb.h> |
21 | #include <linux/bootmem.h> | 21 | #include <linux/memblock.h> |
22 | #include <sysdev/fsl_soc.h> | 22 | #include <sysdev/fsl_soc.h> |
23 | 23 | ||
24 | #include <asm/cacheflush.h> | 24 | #include <asm/cacheflush.h> |
@@ -297,14 +297,13 @@ static void __init mpc512x_setup_diu(void) | |||
297 | * and so negatively affect boot time. Instead we reserve the | 297 | * and so negatively affect boot time. Instead we reserve the |
298 | * already configured frame buffer area so that it won't be | 298 | * already configured frame buffer area so that it won't be |
299 | * destroyed. The starting address of the area to reserve and | 299 | * destroyed. The starting address of the area to reserve and |
300 | * also it's length is passed to reserve_bootmem(). It will be | 300 | * also it's length is passed to memblock_reserve(). It will be |
301 | * freed later on first open of fbdev, when splash image is not | 301 | * freed later on first open of fbdev, when splash image is not |
302 | * needed any more. | 302 | * needed any more. |
303 | */ | 303 | */ |
304 | if (diu_shared_fb.in_use) { | 304 | if (diu_shared_fb.in_use) { |
305 | ret = reserve_bootmem(diu_shared_fb.fb_phys, | 305 | ret = memblock_reserve(diu_shared_fb.fb_phys, |
306 | diu_shared_fb.fb_len, | 306 | diu_shared_fb.fb_len); |
307 | BOOTMEM_EXCLUSIVE); | ||
308 | if (ret) { | 307 | if (ret) { |
309 | pr_err("%s: reserve bootmem failed\n", __func__); | 308 | pr_err("%s: reserve bootmem failed\n", __func__); |
310 | diu_shared_fb.in_use = false; | 309 | diu_shared_fb.in_use = false; |
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 3feffde9128d..6af651e69129 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
@@ -212,6 +212,8 @@ static int __init efika_probe(void) | |||
212 | DMA_MODE_READ = 0x44; | 212 | DMA_MODE_READ = 0x44; |
213 | DMA_MODE_WRITE = 0x48; | 213 | DMA_MODE_WRITE = 0x48; |
214 | 214 | ||
215 | pm_power_off = rtas_power_off; | ||
216 | |||
215 | return 1; | 217 | return 1; |
216 | } | 218 | } |
217 | 219 | ||
@@ -225,7 +227,6 @@ define_machine(efika) | |||
225 | .init_IRQ = mpc52xx_init_irq, | 227 | .init_IRQ = mpc52xx_init_irq, |
226 | .get_irq = mpc52xx_get_irq, | 228 | .get_irq = mpc52xx_get_irq, |
227 | .restart = rtas_restart, | 229 | .restart = rtas_restart, |
228 | .power_off = rtas_power_off, | ||
229 | .halt = rtas_halt, | 230 | .halt = rtas_halt, |
230 | .set_rtc_time = rtas_set_rtc_time, | 231 | .set_rtc_time = rtas_set_rtc_time, |
231 | .get_rtc_time = rtas_get_rtc_time, | 232 | .get_rtc_time = rtas_get_rtc_time, |
diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c index 463fa91ee5b6..15e8021ddef9 100644 --- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c +++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c | |||
@@ -167,10 +167,10 @@ static int mcu_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
167 | if (ret) | 167 | if (ret) |
168 | goto err; | 168 | goto err; |
169 | 169 | ||
170 | /* XXX: this is potentially racy, but there is no lock for ppc_md */ | 170 | /* XXX: this is potentially racy, but there is no lock for pm_power_off */ |
171 | if (!ppc_md.power_off) { | 171 | if (!pm_power_off) { |
172 | glob_mcu = mcu; | 172 | glob_mcu = mcu; |
173 | ppc_md.power_off = mcu_power_off; | 173 | pm_power_off = mcu_power_off; |
174 | dev_info(&client->dev, "will provide power-off service\n"); | 174 | dev_info(&client->dev, "will provide power-off service\n"); |
175 | } | 175 | } |
176 | 176 | ||
@@ -197,7 +197,7 @@ static int mcu_remove(struct i2c_client *client) | |||
197 | device_remove_file(&client->dev, &dev_attr_status); | 197 | device_remove_file(&client->dev, &dev_attr_status); |
198 | 198 | ||
199 | if (glob_mcu == mcu) { | 199 | if (glob_mcu == mcu) { |
200 | ppc_md.power_off = NULL; | 200 | pm_power_off = NULL; |
201 | glob_mcu = NULL; | 201 | glob_mcu = NULL; |
202 | } | 202 | } |
203 | 203 | ||
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c index e56b89a792ed..1f309ccb096e 100644 --- a/arch/powerpc/platforms/85xx/corenet_generic.c +++ b/arch/powerpc/platforms/85xx/corenet_generic.c | |||
@@ -170,7 +170,7 @@ static int __init corenet_generic_probe(void) | |||
170 | 170 | ||
171 | ppc_md.get_irq = ehv_pic_get_irq; | 171 | ppc_md.get_irq = ehv_pic_get_irq; |
172 | ppc_md.restart = fsl_hv_restart; | 172 | ppc_md.restart = fsl_hv_restart; |
173 | ppc_md.power_off = fsl_hv_halt; | 173 | pm_power_off = fsl_hv_halt; |
174 | ppc_md.halt = fsl_hv_halt; | 174 | ppc_md.halt = fsl_hv_halt; |
175 | #ifdef CONFIG_SMP | 175 | #ifdef CONFIG_SMP |
176 | /* | 176 | /* |
diff --git a/arch/powerpc/platforms/85xx/sgy_cts1000.c b/arch/powerpc/platforms/85xx/sgy_cts1000.c index 8162b0412117..e149c9ec26ae 100644 --- a/arch/powerpc/platforms/85xx/sgy_cts1000.c +++ b/arch/powerpc/platforms/85xx/sgy_cts1000.c | |||
@@ -120,7 +120,7 @@ static int gpio_halt_probe(struct platform_device *pdev) | |||
120 | 120 | ||
121 | /* Register our halt function */ | 121 | /* Register our halt function */ |
122 | ppc_md.halt = gpio_halt_cb; | 122 | ppc_md.halt = gpio_halt_cb; |
123 | ppc_md.power_off = gpio_halt_cb; | 123 | pm_power_off = gpio_halt_cb; |
124 | 124 | ||
125 | printk(KERN_INFO "gpio-halt: registered GPIO %d (%d trigger, %d" | 125 | printk(KERN_INFO "gpio-halt: registered GPIO %d (%d trigger, %d" |
126 | " irq).\n", gpio, trigger, irq); | 126 | " irq).\n", gpio, trigger, irq); |
@@ -137,7 +137,7 @@ static int gpio_halt_remove(struct platform_device *pdev) | |||
137 | free_irq(irq, halt_node); | 137 | free_irq(irq, halt_node); |
138 | 138 | ||
139 | ppc_md.halt = NULL; | 139 | ppc_md.halt = NULL; |
140 | ppc_md.power_off = NULL; | 140 | pm_power_off = NULL; |
141 | 141 | ||
142 | gpio_free(gpio); | 142 | gpio_free(gpio); |
143 | 143 | ||
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index bd6f1a1cf922..157250426b56 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig | |||
@@ -1,6 +1,3 @@ | |||
1 | config FADS | ||
2 | bool | ||
3 | |||
4 | config CPM1 | 1 | config CPM1 |
5 | bool | 2 | bool |
6 | select CPM | 3 | select CPM |
@@ -13,7 +10,6 @@ choice | |||
13 | 10 | ||
14 | config MPC8XXFADS | 11 | config MPC8XXFADS |
15 | bool "FADS" | 12 | bool "FADS" |
16 | select FADS | ||
17 | 13 | ||
18 | config MPC86XADS | 14 | config MPC86XADS |
19 | bool "MPC86XADS" | 15 | bool "MPC86XADS" |
diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c index d4d245c0d787..bee9232fe619 100644 --- a/arch/powerpc/platforms/cell/beat_htab.c +++ b/arch/powerpc/platforms/cell/beat_htab.c | |||
@@ -186,7 +186,7 @@ static long beat_lpar_hpte_updatepp(unsigned long slot, | |||
186 | unsigned long newpp, | 186 | unsigned long newpp, |
187 | unsigned long vpn, | 187 | unsigned long vpn, |
188 | int psize, int apsize, | 188 | int psize, int apsize, |
189 | int ssize, int local) | 189 | int ssize, unsigned long flags) |
190 | { | 190 | { |
191 | unsigned long lpar_rc; | 191 | unsigned long lpar_rc; |
192 | u64 dummy0, dummy1; | 192 | u64 dummy0, dummy1; |
@@ -369,7 +369,7 @@ static long beat_lpar_hpte_updatepp_v3(unsigned long slot, | |||
369 | unsigned long newpp, | 369 | unsigned long newpp, |
370 | unsigned long vpn, | 370 | unsigned long vpn, |
371 | int psize, int apsize, | 371 | int psize, int apsize, |
372 | int ssize, int local) | 372 | int ssize, unsigned long flags) |
373 | { | 373 | { |
374 | unsigned long lpar_rc; | 374 | unsigned long lpar_rc; |
375 | unsigned long want_v; | 375 | unsigned long want_v; |
diff --git a/arch/powerpc/platforms/cell/celleb_pci.c b/arch/powerpc/platforms/cell/celleb_pci.c index 2b98a36ef8fb..3ce70ded2d6a 100644 --- a/arch/powerpc/platforms/cell/celleb_pci.c +++ b/arch/powerpc/platforms/cell/celleb_pci.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <linux/string.h> | 30 | #include <linux/string.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/bootmem.h> | 32 | #include <linux/memblock.h> |
33 | #include <linux/pci_regs.h> | 33 | #include <linux/pci_regs.h> |
34 | #include <linux/of.h> | 34 | #include <linux/of.h> |
35 | #include <linux/of_device.h> | 35 | #include <linux/of_device.h> |
@@ -401,11 +401,11 @@ error: | |||
401 | } else { | 401 | } else { |
402 | if (config && *config) { | 402 | if (config && *config) { |
403 | size = 256; | 403 | size = 256; |
404 | free_bootmem(__pa(*config), size); | 404 | memblock_free(__pa(*config), size); |
405 | } | 405 | } |
406 | if (res && *res) { | 406 | if (res && *res) { |
407 | size = sizeof(struct celleb_pci_resource); | 407 | size = sizeof(struct celleb_pci_resource); |
408 | free_bootmem(__pa(*res), size); | 408 | memblock_free(__pa(*res), size); |
409 | } | 409 | } |
410 | } | 410 | } |
411 | 411 | ||
diff --git a/arch/powerpc/platforms/cell/celleb_scc_epci.c b/arch/powerpc/platforms/cell/celleb_scc_epci.c index 844c0facb4f7..9438bbed402f 100644 --- a/arch/powerpc/platforms/cell/celleb_scc_epci.c +++ b/arch/powerpc/platforms/cell/celleb_scc_epci.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/pci_regs.h> | 27 | #include <linux/pci_regs.h> |
28 | #include <linux/bootmem.h> | ||
29 | 28 | ||
30 | #include <asm/io.h> | 29 | #include <asm/io.h> |
31 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c index 4278acfa2ede..f22387598040 100644 --- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c +++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/bootmem.h> | ||
29 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
30 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
31 | 30 | ||
diff --git a/arch/powerpc/platforms/cell/celleb_setup.c b/arch/powerpc/platforms/cell/celleb_setup.c index 34e8ce2976aa..90be8ec51686 100644 --- a/arch/powerpc/platforms/cell/celleb_setup.c +++ b/arch/powerpc/platforms/cell/celleb_setup.c | |||
@@ -142,6 +142,7 @@ static int __init celleb_probe_beat(void) | |||
142 | powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS | 142 | powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS |
143 | | FW_FEATURE_BEAT | FW_FEATURE_LPAR; | 143 | | FW_FEATURE_BEAT | FW_FEATURE_LPAR; |
144 | hpte_init_beat_v3(); | 144 | hpte_init_beat_v3(); |
145 | pm_power_off = beat_power_off; | ||
145 | 146 | ||
146 | return 1; | 147 | return 1; |
147 | } | 148 | } |
@@ -190,6 +191,7 @@ static int __init celleb_probe_native(void) | |||
190 | 191 | ||
191 | powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS; | 192 | powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS; |
192 | hpte_init_native(); | 193 | hpte_init_native(); |
194 | pm_power_off = rtas_power_off; | ||
193 | 195 | ||
194 | return 1; | 196 | return 1; |
195 | } | 197 | } |
@@ -204,7 +206,6 @@ define_machine(celleb_beat) { | |||
204 | .setup_arch = celleb_setup_arch_beat, | 206 | .setup_arch = celleb_setup_arch_beat, |
205 | .show_cpuinfo = celleb_show_cpuinfo, | 207 | .show_cpuinfo = celleb_show_cpuinfo, |
206 | .restart = beat_restart, | 208 | .restart = beat_restart, |
207 | .power_off = beat_power_off, | ||
208 | .halt = beat_halt, | 209 | .halt = beat_halt, |
209 | .get_rtc_time = beat_get_rtc_time, | 210 | .get_rtc_time = beat_get_rtc_time, |
210 | .set_rtc_time = beat_set_rtc_time, | 211 | .set_rtc_time = beat_set_rtc_time, |
@@ -230,7 +231,6 @@ define_machine(celleb_native) { | |||
230 | .setup_arch = celleb_setup_arch_native, | 231 | .setup_arch = celleb_setup_arch_native, |
231 | .show_cpuinfo = celleb_show_cpuinfo, | 232 | .show_cpuinfo = celleb_show_cpuinfo, |
232 | .restart = rtas_restart, | 233 | .restart = rtas_restart, |
233 | .power_off = rtas_power_off, | ||
234 | .halt = rtas_halt, | 234 | .halt = rtas_halt, |
235 | .get_boot_time = rtas_get_boot_time, | 235 | .get_boot_time = rtas_get_boot_time, |
236 | .get_rtc_time = rtas_get_rtc_time, | 236 | .get_rtc_time = rtas_get_rtc_time, |
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 8a106b4172e0..4c11421847be 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c | |||
@@ -82,7 +82,7 @@ static void iic_unmask(struct irq_data *d) | |||
82 | 82 | ||
83 | static void iic_eoi(struct irq_data *d) | 83 | static void iic_eoi(struct irq_data *d) |
84 | { | 84 | { |
85 | struct iic *iic = &__get_cpu_var(cpu_iic); | 85 | struct iic *iic = this_cpu_ptr(&cpu_iic); |
86 | out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]); | 86 | out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]); |
87 | BUG_ON(iic->eoi_ptr < 0); | 87 | BUG_ON(iic->eoi_ptr < 0); |
88 | } | 88 | } |
@@ -148,7 +148,7 @@ static unsigned int iic_get_irq(void) | |||
148 | struct iic *iic; | 148 | struct iic *iic; |
149 | unsigned int virq; | 149 | unsigned int virq; |
150 | 150 | ||
151 | iic = &__get_cpu_var(cpu_iic); | 151 | iic = this_cpu_ptr(&cpu_iic); |
152 | *(unsigned long *) &pending = | 152 | *(unsigned long *) &pending = |
153 | in_be64((u64 __iomem *) &iic->regs->pending_destr); | 153 | in_be64((u64 __iomem *) &iic->regs->pending_destr); |
154 | if (!(pending.flags & CBE_IIC_IRQ_VALID)) | 154 | if (!(pending.flags & CBE_IIC_IRQ_VALID)) |
@@ -163,7 +163,7 @@ static unsigned int iic_get_irq(void) | |||
163 | 163 | ||
164 | void iic_setup_cpu(void) | 164 | void iic_setup_cpu(void) |
165 | { | 165 | { |
166 | out_be64(&__get_cpu_var(cpu_iic).regs->prio, 0xff); | 166 | out_be64(this_cpu_ptr(&cpu_iic.regs->prio), 0xff); |
167 | } | 167 | } |
168 | 168 | ||
169 | u8 iic_get_target_id(int cpu) | 169 | u8 iic_get_target_id(int cpu) |
diff --git a/arch/powerpc/platforms/cell/qpace_setup.c b/arch/powerpc/platforms/cell/qpace_setup.c index 6e3409d590ac..d328140dc6f5 100644 --- a/arch/powerpc/platforms/cell/qpace_setup.c +++ b/arch/powerpc/platforms/cell/qpace_setup.c | |||
@@ -127,6 +127,7 @@ static int __init qpace_probe(void) | |||
127 | return 0; | 127 | return 0; |
128 | 128 | ||
129 | hpte_init_native(); | 129 | hpte_init_native(); |
130 | pm_power_off = rtas_power_off; | ||
130 | 131 | ||
131 | return 1; | 132 | return 1; |
132 | } | 133 | } |
@@ -137,7 +138,6 @@ define_machine(qpace) { | |||
137 | .setup_arch = qpace_setup_arch, | 138 | .setup_arch = qpace_setup_arch, |
138 | .show_cpuinfo = qpace_show_cpuinfo, | 139 | .show_cpuinfo = qpace_show_cpuinfo, |
139 | .restart = rtas_restart, | 140 | .restart = rtas_restart, |
140 | .power_off = rtas_power_off, | ||
141 | .halt = rtas_halt, | 141 | .halt = rtas_halt, |
142 | .get_boot_time = rtas_get_boot_time, | 142 | .get_boot_time = rtas_get_boot_time, |
143 | .get_rtc_time = rtas_get_rtc_time, | 143 | .get_rtc_time = rtas_get_rtc_time, |
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 6ae25fb62015..d62aa982d530 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
@@ -259,6 +259,7 @@ static int __init cell_probe(void) | |||
259 | return 0; | 259 | return 0; |
260 | 260 | ||
261 | hpte_init_native(); | 261 | hpte_init_native(); |
262 | pm_power_off = rtas_power_off; | ||
262 | 263 | ||
263 | return 1; | 264 | return 1; |
264 | } | 265 | } |
@@ -269,7 +270,6 @@ define_machine(cell) { | |||
269 | .setup_arch = cell_setup_arch, | 270 | .setup_arch = cell_setup_arch, |
270 | .show_cpuinfo = cell_show_cpuinfo, | 271 | .show_cpuinfo = cell_show_cpuinfo, |
271 | .restart = rtas_restart, | 272 | .restart = rtas_restart, |
272 | .power_off = rtas_power_off, | ||
273 | .halt = rtas_halt, | 273 | .halt = rtas_halt, |
274 | .get_boot_time = rtas_get_boot_time, | 274 | .get_boot_time = rtas_get_boot_time, |
275 | .get_rtc_time = rtas_get_rtc_time, | 275 | .get_rtc_time = rtas_get_rtc_time, |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index ffcbd242e669..f7af74f83693 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -181,7 +181,8 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | 183 | ||
184 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX | 184 | extern int hash_page(unsigned long ea, unsigned long access, |
185 | unsigned long trap, unsigned long dsisr); //XXX | ||
185 | static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) | 186 | static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) |
186 | { | 187 | { |
187 | int ret; | 188 | int ret; |
@@ -196,7 +197,7 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) | |||
196 | (REGION_ID(ea) != USER_REGION_ID)) { | 197 | (REGION_ID(ea) != USER_REGION_ID)) { |
197 | 198 | ||
198 | spin_unlock(&spu->register_lock); | 199 | spin_unlock(&spu->register_lock); |
199 | ret = hash_page(ea, _PAGE_PRESENT, 0x300); | 200 | ret = hash_page(ea, _PAGE_PRESENT, 0x300, dsisr); |
200 | spin_lock(&spu->register_lock); | 201 | spin_lock(&spu->register_lock); |
201 | 202 | ||
202 | if (!ret) { | 203 | if (!ret) { |
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c index e45894a08118..d98f845ac777 100644 --- a/arch/powerpc/platforms/cell/spufs/fault.c +++ b/arch/powerpc/platforms/cell/spufs/fault.c | |||
@@ -144,7 +144,7 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
144 | access = (_PAGE_PRESENT | _PAGE_USER); | 144 | access = (_PAGE_PRESENT | _PAGE_USER); |
145 | access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; | 145 | access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; |
146 | local_irq_save(flags); | 146 | local_irq_save(flags); |
147 | ret = hash_page(ea, access, 0x300); | 147 | ret = hash_page(ea, access, 0x300, dsisr); |
148 | local_irq_restore(flags); | 148 | local_irq_restore(flags); |
149 | 149 | ||
150 | /* hashing failed, so try the actual fault handler */ | 150 | /* hashing failed, so try the actual fault handler */ |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 5b77b1919fd2..860a59eb8ea2 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -585,6 +585,8 @@ static int __init chrp_probe(void) | |||
585 | DMA_MODE_READ = 0x44; | 585 | DMA_MODE_READ = 0x44; |
586 | DMA_MODE_WRITE = 0x48; | 586 | DMA_MODE_WRITE = 0x48; |
587 | 587 | ||
588 | pm_power_off = rtas_power_off; | ||
589 | |||
588 | return 1; | 590 | return 1; |
589 | } | 591 | } |
590 | 592 | ||
@@ -597,7 +599,6 @@ define_machine(chrp) { | |||
597 | .show_cpuinfo = chrp_show_cpuinfo, | 599 | .show_cpuinfo = chrp_show_cpuinfo, |
598 | .init_IRQ = chrp_init_IRQ, | 600 | .init_IRQ = chrp_init_IRQ, |
599 | .restart = rtas_restart, | 601 | .restart = rtas_restart, |
600 | .power_off = rtas_power_off, | ||
601 | .halt = rtas_halt, | 602 | .halt = rtas_halt, |
602 | .time_init = chrp_time_init, | 603 | .time_init = chrp_time_init, |
603 | .set_rtc_time = chrp_set_rtc_time, | 604 | .set_rtc_time = chrp_set_rtc_time, |
diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c index bd4ba5d7d568..fe0ed6ee285e 100644 --- a/arch/powerpc/platforms/embedded6xx/gamecube.c +++ b/arch/powerpc/platforms/embedded6xx/gamecube.c | |||
@@ -67,6 +67,8 @@ static int __init gamecube_probe(void) | |||
67 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube")) | 67 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube")) |
68 | return 0; | 68 | return 0; |
69 | 69 | ||
70 | pm_power_off = gamecube_power_off; | ||
71 | |||
70 | return 1; | 72 | return 1; |
71 | } | 73 | } |
72 | 74 | ||
@@ -80,7 +82,6 @@ define_machine(gamecube) { | |||
80 | .probe = gamecube_probe, | 82 | .probe = gamecube_probe, |
81 | .init_early = gamecube_init_early, | 83 | .init_early = gamecube_init_early, |
82 | .restart = gamecube_restart, | 84 | .restart = gamecube_restart, |
83 | .power_off = gamecube_power_off, | ||
84 | .halt = gamecube_halt, | 85 | .halt = gamecube_halt, |
85 | .init_IRQ = flipper_pic_probe, | 86 | .init_IRQ = flipper_pic_probe, |
86 | .get_irq = flipper_pic_get_irq, | 87 | .get_irq = flipper_pic_get_irq, |
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index 168e1d80b2e5..540eeb58d3f0 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c | |||
@@ -147,6 +147,9 @@ static int __init linkstation_probe(void) | |||
147 | 147 | ||
148 | if (!of_flat_dt_is_compatible(root, "linkstation")) | 148 | if (!of_flat_dt_is_compatible(root, "linkstation")) |
149 | return 0; | 149 | return 0; |
150 | |||
151 | pm_power_off = linkstation_power_off; | ||
152 | |||
150 | return 1; | 153 | return 1; |
151 | } | 154 | } |
152 | 155 | ||
@@ -158,7 +161,6 @@ define_machine(linkstation){ | |||
158 | .show_cpuinfo = linkstation_show_cpuinfo, | 161 | .show_cpuinfo = linkstation_show_cpuinfo, |
159 | .get_irq = mpic_get_irq, | 162 | .get_irq = mpic_get_irq, |
160 | .restart = linkstation_restart, | 163 | .restart = linkstation_restart, |
161 | .power_off = linkstation_power_off, | ||
162 | .halt = linkstation_halt, | 164 | .halt = linkstation_halt, |
163 | .calibrate_decr = generic_calibrate_decr, | 165 | .calibrate_decr = generic_calibrate_decr, |
164 | }; | 166 | }; |
diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c index 20a8ed91962e..7feb325b636b 100644 --- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c +++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c | |||
@@ -247,7 +247,7 @@ void __init ug_udbg_init(void) | |||
247 | np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-exi"); | 247 | np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-exi"); |
248 | if (!np) { | 248 | if (!np) { |
249 | udbg_printf("%s: EXI node not found\n", __func__); | 249 | udbg_printf("%s: EXI node not found\n", __func__); |
250 | goto done; | 250 | goto out; |
251 | } | 251 | } |
252 | 252 | ||
253 | exi_io_base = ug_udbg_setup_exi_io_base(np); | 253 | exi_io_base = ug_udbg_setup_exi_io_base(np); |
@@ -267,8 +267,8 @@ void __init ug_udbg_init(void) | |||
267 | } | 267 | } |
268 | 268 | ||
269 | done: | 269 | done: |
270 | if (np) | 270 | of_node_put(np); |
271 | of_node_put(np); | 271 | out: |
272 | return; | 272 | return; |
273 | } | 273 | } |
274 | 274 | ||
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index 388e29bab8f6..352592d3e44e 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c | |||
@@ -211,6 +211,8 @@ static int __init wii_probe(void) | |||
211 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii")) | 211 | if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii")) |
212 | return 0; | 212 | return 0; |
213 | 213 | ||
214 | pm_power_off = wii_power_off; | ||
215 | |||
214 | return 1; | 216 | return 1; |
215 | } | 217 | } |
216 | 218 | ||
@@ -226,7 +228,6 @@ define_machine(wii) { | |||
226 | .init_early = wii_init_early, | 228 | .init_early = wii_init_early, |
227 | .setup_arch = wii_setup_arch, | 229 | .setup_arch = wii_setup_arch, |
228 | .restart = wii_restart, | 230 | .restart = wii_restart, |
229 | .power_off = wii_power_off, | ||
230 | .halt = wii_halt, | 231 | .halt = wii_halt, |
231 | .init_IRQ = wii_pic_probe, | 232 | .init_IRQ = wii_pic_probe, |
232 | .get_irq = flipper_pic_get_irq, | 233 | .get_irq = flipper_pic_get_irq, |
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index f7136aae8bbf..d3a13067ec42 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/bootmem.h> | ||
19 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
20 | 19 | ||
21 | #include <asm/sections.h> | 20 | #include <asm/sections.h> |
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index cb1b0b35a0c6..56b85cd61aaf 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c | |||
@@ -169,7 +169,7 @@ static void __init maple_use_rtas_reboot_and_halt_if_present(void) | |||
169 | if (rtas_service_present("system-reboot") && | 169 | if (rtas_service_present("system-reboot") && |
170 | rtas_service_present("power-off")) { | 170 | rtas_service_present("power-off")) { |
171 | ppc_md.restart = rtas_restart; | 171 | ppc_md.restart = rtas_restart; |
172 | ppc_md.power_off = rtas_power_off; | 172 | pm_power_off = rtas_power_off; |
173 | ppc_md.halt = rtas_halt; | 173 | ppc_md.halt = rtas_halt; |
174 | } | 174 | } |
175 | } | 175 | } |
@@ -312,6 +312,7 @@ static int __init maple_probe(void) | |||
312 | alloc_dart_table(); | 312 | alloc_dart_table(); |
313 | 313 | ||
314 | hpte_init_native(); | 314 | hpte_init_native(); |
315 | pm_power_off = maple_power_off; | ||
315 | 316 | ||
316 | return 1; | 317 | return 1; |
317 | } | 318 | } |
@@ -325,7 +326,6 @@ define_machine(maple) { | |||
325 | .pci_irq_fixup = maple_pci_irq_fixup, | 326 | .pci_irq_fixup = maple_pci_irq_fixup, |
326 | .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, | 327 | .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, |
327 | .restart = maple_restart, | 328 | .restart = maple_restart, |
328 | .power_off = maple_power_off, | ||
329 | .halt = maple_halt, | 329 | .halt = maple_halt, |
330 | .get_boot_time = maple_get_boot_time, | 330 | .get_boot_time = maple_get_boot_time, |
331 | .set_rtc_time = maple_set_rtc_time, | 331 | .set_rtc_time = maple_set_rtc_time, |
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 014d06e6d46b..60b03a1703d1 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c | |||
@@ -513,11 +513,7 @@ static int __init core99_nvram_setup(struct device_node *dp, unsigned long addr) | |||
513 | printk(KERN_ERR "nvram: no address\n"); | 513 | printk(KERN_ERR "nvram: no address\n"); |
514 | return -EINVAL; | 514 | return -EINVAL; |
515 | } | 515 | } |
516 | nvram_image = alloc_bootmem(NVRAM_SIZE); | 516 | nvram_image = memblock_virt_alloc(NVRAM_SIZE, 0); |
517 | if (nvram_image == NULL) { | ||
518 | printk(KERN_ERR "nvram: can't allocate ram image\n"); | ||
519 | return -ENOMEM; | ||
520 | } | ||
521 | nvram_data = ioremap(addr, NVRAM_SIZE*2); | 517 | nvram_data = ioremap(addr, NVRAM_SIZE*2); |
522 | nvram_naddrs = 1; /* Make sure we get the correct case */ | 518 | nvram_naddrs = 1; /* Make sure we get the correct case */ |
523 | 519 | ||
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 7e868ccf3b0d..04702db35d45 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/bootmem.h> | ||
19 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
20 | #include <linux/of_pci.h> | 19 | #include <linux/of_pci.h> |
21 | 20 | ||
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index b127a29ac526..713d36d45d1d 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -632,6 +632,8 @@ static int __init pmac_probe(void) | |||
632 | smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x80000000UL); | 632 | smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x80000000UL); |
633 | #endif /* CONFIG_PMAC_SMU */ | 633 | #endif /* CONFIG_PMAC_SMU */ |
634 | 634 | ||
635 | pm_power_off = pmac_power_off; | ||
636 | |||
635 | return 1; | 637 | return 1; |
636 | } | 638 | } |
637 | 639 | ||
@@ -663,7 +665,6 @@ define_machine(powermac) { | |||
663 | .get_irq = NULL, /* changed later */ | 665 | .get_irq = NULL, /* changed later */ |
664 | .pci_irq_fixup = pmac_pci_irq_fixup, | 666 | .pci_irq_fixup = pmac_pci_irq_fixup, |
665 | .restart = pmac_restart, | 667 | .restart = pmac_restart, |
666 | .power_off = pmac_power_off, | ||
667 | .halt = pmac_halt, | 668 | .halt = pmac_halt, |
668 | .time_init = pmac_time_init, | 669 | .time_init = pmac_time_init, |
669 | .get_boot_time = pmac_get_boot_time, | 670 | .get_boot_time = pmac_get_boot_time, |
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index eba9cb10619c..2809c9895288 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c | |||
@@ -11,7 +11,6 @@ | |||
11 | * (at your option) any later version. | 11 | * (at your option) any later version. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/bootmem.h> | ||
15 | #include <linux/debugfs.h> | 14 | #include <linux/debugfs.h> |
16 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
17 | #include <linux/io.h> | 16 | #include <linux/io.h> |
@@ -354,6 +353,9 @@ static int ioda_eeh_get_phb_state(struct eeh_pe *pe) | |||
354 | } else if (!(pe->state & EEH_PE_ISOLATED)) { | 353 | } else if (!(pe->state & EEH_PE_ISOLATED)) { |
355 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 354 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); |
356 | ioda_eeh_phb_diag(pe); | 355 | ioda_eeh_phb_diag(pe); |
356 | |||
357 | if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) | ||
358 | pnv_pci_dump_phb_diag_data(pe->phb, pe->data); | ||
357 | } | 359 | } |
358 | 360 | ||
359 | return result; | 361 | return result; |
@@ -373,7 +375,7 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe) | |||
373 | * moving forward, we have to return operational | 375 | * moving forward, we have to return operational |
374 | * state during PE reset. | 376 | * state during PE reset. |
375 | */ | 377 | */ |
376 | if (pe->state & EEH_PE_CFG_BLOCKED) { | 378 | if (pe->state & EEH_PE_RESET) { |
377 | result = (EEH_STATE_MMIO_ACTIVE | | 379 | result = (EEH_STATE_MMIO_ACTIVE | |
378 | EEH_STATE_DMA_ACTIVE | | 380 | EEH_STATE_DMA_ACTIVE | |
379 | EEH_STATE_MMIO_ENABLED | | 381 | EEH_STATE_MMIO_ENABLED | |
@@ -452,6 +454,9 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe) | |||
452 | 454 | ||
453 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 455 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); |
454 | ioda_eeh_phb_diag(pe); | 456 | ioda_eeh_phb_diag(pe); |
457 | |||
458 | if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) | ||
459 | pnv_pci_dump_phb_diag_data(pe->phb, pe->data); | ||
455 | } | 460 | } |
456 | 461 | ||
457 | return result; | 462 | return result; |
@@ -731,7 +736,8 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option) | |||
731 | static int ioda_eeh_get_log(struct eeh_pe *pe, int severity, | 736 | static int ioda_eeh_get_log(struct eeh_pe *pe, int severity, |
732 | char *drv_log, unsigned long len) | 737 | char *drv_log, unsigned long len) |
733 | { | 738 | { |
734 | pnv_pci_dump_phb_diag_data(pe->phb, pe->data); | 739 | if (!eeh_has_flag(EEH_EARLY_DUMP_LOG)) |
740 | pnv_pci_dump_phb_diag_data(pe->phb, pe->data); | ||
735 | 741 | ||
736 | return 0; | 742 | return 0; |
737 | } | 743 | } |
@@ -1087,6 +1093,10 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) | |||
1087 | !((*pe)->state & EEH_PE_ISOLATED)) { | 1093 | !((*pe)->state & EEH_PE_ISOLATED)) { |
1088 | eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); | 1094 | eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); |
1089 | ioda_eeh_phb_diag(*pe); | 1095 | ioda_eeh_phb_diag(*pe); |
1096 | |||
1097 | if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) | ||
1098 | pnv_pci_dump_phb_diag_data((*pe)->phb, | ||
1099 | (*pe)->data); | ||
1090 | } | 1100 | } |
1091 | 1101 | ||
1092 | /* | 1102 | /* |
diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c index e462ab947d16..693b6cdac691 100644 --- a/arch/powerpc/platforms/powernv/opal-async.c +++ b/arch/powerpc/platforms/powernv/opal-async.c | |||
@@ -71,6 +71,7 @@ int opal_async_get_token_interruptible(void) | |||
71 | 71 | ||
72 | return token; | 72 | return token; |
73 | } | 73 | } |
74 | EXPORT_SYMBOL_GPL(opal_async_get_token_interruptible); | ||
74 | 75 | ||
75 | int __opal_async_release_token(int token) | 76 | int __opal_async_release_token(int token) |
76 | { | 77 | { |
@@ -102,6 +103,7 @@ int opal_async_release_token(int token) | |||
102 | 103 | ||
103 | return 0; | 104 | return 0; |
104 | } | 105 | } |
106 | EXPORT_SYMBOL_GPL(opal_async_release_token); | ||
105 | 107 | ||
106 | int opal_async_wait_response(uint64_t token, struct opal_msg *msg) | 108 | int opal_async_wait_response(uint64_t token, struct opal_msg *msg) |
107 | { | 109 | { |
@@ -120,6 +122,7 @@ int opal_async_wait_response(uint64_t token, struct opal_msg *msg) | |||
120 | 122 | ||
121 | return 0; | 123 | return 0; |
122 | } | 124 | } |
125 | EXPORT_SYMBOL_GPL(opal_async_wait_response); | ||
123 | 126 | ||
124 | static int opal_async_comp_event(struct notifier_block *nb, | 127 | static int opal_async_comp_event(struct notifier_block *nb, |
125 | unsigned long msg_type, void *msg) | 128 | unsigned long msg_type, void *msg) |
diff --git a/arch/powerpc/platforms/powernv/opal-rtc.c b/arch/powerpc/platforms/powernv/opal-rtc.c index 499707ddaa9c..37dbee15769f 100644 --- a/arch/powerpc/platforms/powernv/opal-rtc.c +++ b/arch/powerpc/platforms/powernv/opal-rtc.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/rtc.h> | 16 | #include <linux/rtc.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/of_platform.h> | ||
18 | 20 | ||
19 | #include <asm/opal.h> | 21 | #include <asm/opal.h> |
20 | #include <asm/firmware.h> | 22 | #include <asm/firmware.h> |
@@ -43,7 +45,7 @@ unsigned long __init opal_get_boot_time(void) | |||
43 | long rc = OPAL_BUSY; | 45 | long rc = OPAL_BUSY; |
44 | 46 | ||
45 | if (!opal_check_token(OPAL_RTC_READ)) | 47 | if (!opal_check_token(OPAL_RTC_READ)) |
46 | goto out; | 48 | return 0; |
47 | 49 | ||
48 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { | 50 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { |
49 | rc = opal_rtc_read(&__y_m_d, &__h_m_s_ms); | 51 | rc = opal_rtc_read(&__y_m_d, &__h_m_s_ms); |
@@ -53,62 +55,33 @@ unsigned long __init opal_get_boot_time(void) | |||
53 | mdelay(10); | 55 | mdelay(10); |
54 | } | 56 | } |
55 | if (rc != OPAL_SUCCESS) | 57 | if (rc != OPAL_SUCCESS) |
56 | goto out; | 58 | return 0; |
57 | 59 | ||
58 | y_m_d = be32_to_cpu(__y_m_d); | 60 | y_m_d = be32_to_cpu(__y_m_d); |
59 | h_m_s_ms = be64_to_cpu(__h_m_s_ms); | 61 | h_m_s_ms = be64_to_cpu(__h_m_s_ms); |
60 | opal_to_tm(y_m_d, h_m_s_ms, &tm); | 62 | opal_to_tm(y_m_d, h_m_s_ms, &tm); |
61 | return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | 63 | return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, |
62 | tm.tm_hour, tm.tm_min, tm.tm_sec); | 64 | tm.tm_hour, tm.tm_min, tm.tm_sec); |
63 | out: | ||
64 | ppc_md.get_rtc_time = NULL; | ||
65 | ppc_md.set_rtc_time = NULL; | ||
66 | return 0; | ||
67 | } | 65 | } |
68 | 66 | ||
69 | void opal_get_rtc_time(struct rtc_time *tm) | 67 | static __init int opal_time_init(void) |
70 | { | 68 | { |
71 | long rc = OPAL_BUSY; | 69 | struct platform_device *pdev; |
72 | u32 y_m_d; | 70 | struct device_node *rtc; |
73 | u64 h_m_s_ms; | ||
74 | __be32 __y_m_d; | ||
75 | __be64 __h_m_s_ms; | ||
76 | 71 | ||
77 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { | 72 | rtc = of_find_node_by_path("/ibm,opal/rtc"); |
78 | rc = opal_rtc_read(&__y_m_d, &__h_m_s_ms); | 73 | if (rtc) { |
79 | if (rc == OPAL_BUSY_EVENT) | 74 | pdev = of_platform_device_create(rtc, "opal-rtc", NULL); |
80 | opal_poll_events(NULL); | 75 | of_node_put(rtc); |
76 | } else { | ||
77 | if (opal_check_token(OPAL_RTC_READ) || | ||
78 | opal_check_token(OPAL_READ_TPO)) | ||
79 | pdev = platform_device_register_simple("opal-rtc", -1, | ||
80 | NULL, 0); | ||
81 | else | 81 | else |
82 | mdelay(10); | 82 | return -ENODEV; |
83 | } | 83 | } |
84 | if (rc != OPAL_SUCCESS) | ||
85 | return; | ||
86 | y_m_d = be32_to_cpu(__y_m_d); | ||
87 | h_m_s_ms = be64_to_cpu(__h_m_s_ms); | ||
88 | opal_to_tm(y_m_d, h_m_s_ms, tm); | ||
89 | } | ||
90 | |||
91 | int opal_set_rtc_time(struct rtc_time *tm) | ||
92 | { | ||
93 | long rc = OPAL_BUSY; | ||
94 | u32 y_m_d = 0; | ||
95 | u64 h_m_s_ms = 0; | ||
96 | |||
97 | y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) / 100)) << 24; | ||
98 | y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) % 100)) << 16; | ||
99 | y_m_d |= ((u32)bin2bcd((tm->tm_mon + 1))) << 8; | ||
100 | y_m_d |= ((u32)bin2bcd(tm->tm_mday)); | ||
101 | |||
102 | h_m_s_ms |= ((u64)bin2bcd(tm->tm_hour)) << 56; | ||
103 | h_m_s_ms |= ((u64)bin2bcd(tm->tm_min)) << 48; | ||
104 | h_m_s_ms |= ((u64)bin2bcd(tm->tm_sec)) << 40; | ||
105 | 84 | ||
106 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { | 85 | return PTR_ERR_OR_ZERO(pdev); |
107 | rc = opal_rtc_write(y_m_d, h_m_s_ms); | ||
108 | if (rc == OPAL_BUSY_EVENT) | ||
109 | opal_poll_events(NULL); | ||
110 | else | ||
111 | mdelay(10); | ||
112 | } | ||
113 | return rc == OPAL_SUCCESS ? 0 : -EIO; | ||
114 | } | 86 | } |
87 | machine_subsys_initcall(powernv, opal_time_init); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-tracepoints.c b/arch/powerpc/platforms/powernv/opal-tracepoints.c index ae14c40b4b1c..e11273b2386d 100644 --- a/arch/powerpc/platforms/powernv/opal-tracepoints.c +++ b/arch/powerpc/platforms/powernv/opal-tracepoints.c | |||
@@ -48,7 +48,7 @@ void __trace_opal_entry(unsigned long opcode, unsigned long *args) | |||
48 | 48 | ||
49 | local_irq_save(flags); | 49 | local_irq_save(flags); |
50 | 50 | ||
51 | depth = &__get_cpu_var(opal_trace_depth); | 51 | depth = this_cpu_ptr(&opal_trace_depth); |
52 | 52 | ||
53 | if (*depth) | 53 | if (*depth) |
54 | goto out; | 54 | goto out; |
@@ -69,7 +69,7 @@ void __trace_opal_exit(long opcode, unsigned long retval) | |||
69 | 69 | ||
70 | local_irq_save(flags); | 70 | local_irq_save(flags); |
71 | 71 | ||
72 | depth = &__get_cpu_var(opal_trace_depth); | 72 | depth = this_cpu_ptr(&opal_trace_depth); |
73 | 73 | ||
74 | if (*depth) | 74 | if (*depth) |
75 | goto out; | 75 | goto out; |
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index feb549aa3eea..0a299be588af 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S | |||
@@ -18,7 +18,7 @@ | |||
18 | .section ".text" | 18 | .section ".text" |
19 | 19 | ||
20 | #ifdef CONFIG_TRACEPOINTS | 20 | #ifdef CONFIG_TRACEPOINTS |
21 | #ifdef CONFIG_JUMP_LABEL | 21 | #ifdef HAVE_JUMP_LABEL |
22 | #define OPAL_BRANCH(LABEL) \ | 22 | #define OPAL_BRANCH(LABEL) \ |
23 | ARCH_STATIC_BRANCH(LABEL, opal_tracepoint_key) | 23 | ARCH_STATIC_BRANCH(LABEL, opal_tracepoint_key) |
24 | #else | 24 | #else |
@@ -250,3 +250,7 @@ OPAL_CALL(opal_handle_hmi, OPAL_HANDLE_HMI); | |||
250 | OPAL_CALL(opal_register_dump_region, OPAL_REGISTER_DUMP_REGION); | 250 | OPAL_CALL(opal_register_dump_region, OPAL_REGISTER_DUMP_REGION); |
251 | OPAL_CALL(opal_unregister_dump_region, OPAL_UNREGISTER_DUMP_REGION); | 251 | OPAL_CALL(opal_unregister_dump_region, OPAL_UNREGISTER_DUMP_REGION); |
252 | OPAL_CALL(opal_pci_set_phb_cxl_mode, OPAL_PCI_SET_PHB_CXL_MODE); | 252 | OPAL_CALL(opal_pci_set_phb_cxl_mode, OPAL_PCI_SET_PHB_CXL_MODE); |
253 | OPAL_CALL(opal_tpo_write, OPAL_WRITE_TPO); | ||
254 | OPAL_CALL(opal_tpo_read, OPAL_READ_TPO); | ||
255 | OPAL_CALL(opal_ipmi_send, OPAL_IPMI_SEND); | ||
256 | OPAL_CALL(opal_ipmi_recv, OPAL_IPMI_RECV); | ||
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index d019b081df9d..cb0b6de79cd4 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -50,7 +50,6 @@ static int mc_recoverable_range_len; | |||
50 | 50 | ||
51 | struct device_node *opal_node; | 51 | struct device_node *opal_node; |
52 | static DEFINE_SPINLOCK(opal_write_lock); | 52 | static DEFINE_SPINLOCK(opal_write_lock); |
53 | extern u64 opal_mc_secondary_handler[]; | ||
54 | static unsigned int *opal_irqs; | 53 | static unsigned int *opal_irqs; |
55 | static unsigned int opal_irq_count; | 54 | static unsigned int opal_irq_count; |
56 | static ATOMIC_NOTIFIER_HEAD(opal_notifier_head); | 55 | static ATOMIC_NOTIFIER_HEAD(opal_notifier_head); |
@@ -644,6 +643,16 @@ static void __init opal_dump_region_init(void) | |||
644 | pr_warn("DUMP: Failed to register kernel log buffer. " | 643 | pr_warn("DUMP: Failed to register kernel log buffer. " |
645 | "rc = %d\n", rc); | 644 | "rc = %d\n", rc); |
646 | } | 645 | } |
646 | |||
647 | static void opal_ipmi_init(struct device_node *opal_node) | ||
648 | { | ||
649 | struct device_node *np; | ||
650 | |||
651 | for_each_child_of_node(opal_node, np) | ||
652 | if (of_device_is_compatible(np, "ibm,opal-ipmi")) | ||
653 | of_platform_device_create(np, NULL, NULL); | ||
654 | } | ||
655 | |||
647 | static int __init opal_init(void) | 656 | static int __init opal_init(void) |
648 | { | 657 | { |
649 | struct device_node *np, *consoles; | 658 | struct device_node *np, *consoles; |
@@ -707,6 +716,8 @@ static int __init opal_init(void) | |||
707 | opal_msglog_init(); | 716 | opal_msglog_init(); |
708 | } | 717 | } |
709 | 718 | ||
719 | opal_ipmi_init(opal_node); | ||
720 | |||
710 | return 0; | 721 | return 0; |
711 | } | 722 | } |
712 | machine_subsys_initcall(powernv, opal_init); | 723 | machine_subsys_initcall(powernv, opal_init); |
@@ -742,6 +753,8 @@ void opal_shutdown(void) | |||
742 | 753 | ||
743 | /* Export this so that test modules can use it */ | 754 | /* Export this so that test modules can use it */ |
744 | EXPORT_SYMBOL_GPL(opal_invalid_call); | 755 | EXPORT_SYMBOL_GPL(opal_invalid_call); |
756 | EXPORT_SYMBOL_GPL(opal_ipmi_send); | ||
757 | EXPORT_SYMBOL_GPL(opal_ipmi_recv); | ||
745 | 758 | ||
746 | /* Convert a region of vmalloc memory to an opal sg list */ | 759 | /* Convert a region of vmalloc memory to an opal sg list */ |
747 | struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr, | 760 | struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr, |
@@ -805,3 +818,9 @@ void opal_free_sg_list(struct opal_sg_list *sg) | |||
805 | sg = NULL; | 818 | sg = NULL; |
806 | } | 819 | } |
807 | } | 820 | } |
821 | |||
822 | EXPORT_SYMBOL_GPL(opal_poll_events); | ||
823 | EXPORT_SYMBOL_GPL(opal_rtc_read); | ||
824 | EXPORT_SYMBOL_GPL(opal_rtc_write); | ||
825 | EXPORT_SYMBOL_GPL(opal_tpo_read); | ||
826 | EXPORT_SYMBOL_GPL(opal_tpo_write); | ||
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 3ba435ec3dcd..fac88ed8a915 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -91,6 +91,24 @@ static inline bool pnv_pci_is_mem_pref_64(unsigned long flags) | |||
91 | (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)); | 91 | (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)); |
92 | } | 92 | } |
93 | 93 | ||
94 | static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no) | ||
95 | { | ||
96 | if (!(pe_no >= 0 && pe_no < phb->ioda.total_pe)) { | ||
97 | pr_warn("%s: Invalid PE %d on PHB#%x\n", | ||
98 | __func__, pe_no, phb->hose->global_number); | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | if (test_and_set_bit(pe_no, phb->ioda.pe_alloc)) { | ||
103 | pr_warn("%s: PE %d was assigned on PHB#%x\n", | ||
104 | __func__, pe_no, phb->hose->global_number); | ||
105 | return; | ||
106 | } | ||
107 | |||
108 | phb->ioda.pe_array[pe_no].phb = phb; | ||
109 | phb->ioda.pe_array[pe_no].pe_number = pe_no; | ||
110 | } | ||
111 | |||
94 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) | 112 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) |
95 | { | 113 | { |
96 | unsigned long pe; | 114 | unsigned long pe; |
@@ -172,7 +190,7 @@ fail: | |||
172 | return -EIO; | 190 | return -EIO; |
173 | } | 191 | } |
174 | 192 | ||
175 | static void pnv_ioda2_alloc_m64_pe(struct pnv_phb *phb) | 193 | static void pnv_ioda2_reserve_m64_pe(struct pnv_phb *phb) |
176 | { | 194 | { |
177 | resource_size_t sgsz = phb->ioda.m64_segsize; | 195 | resource_size_t sgsz = phb->ioda.m64_segsize; |
178 | struct pci_dev *pdev; | 196 | struct pci_dev *pdev; |
@@ -185,16 +203,15 @@ static void pnv_ioda2_alloc_m64_pe(struct pnv_phb *phb) | |||
185 | * instead of root bus. | 203 | * instead of root bus. |
186 | */ | 204 | */ |
187 | list_for_each_entry(pdev, &phb->hose->bus->devices, bus_list) { | 205 | list_for_each_entry(pdev, &phb->hose->bus->devices, bus_list) { |
188 | for (i = PCI_BRIDGE_RESOURCES; | 206 | for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) { |
189 | i <= PCI_BRIDGE_RESOURCE_END; i++) { | 207 | r = &pdev->resource[PCI_BRIDGE_RESOURCES + i]; |
190 | r = &pdev->resource[i]; | ||
191 | if (!r->parent || | 208 | if (!r->parent || |
192 | !pnv_pci_is_mem_pref_64(r->flags)) | 209 | !pnv_pci_is_mem_pref_64(r->flags)) |
193 | continue; | 210 | continue; |
194 | 211 | ||
195 | base = (r->start - phb->ioda.m64_base) / sgsz; | 212 | base = (r->start - phb->ioda.m64_base) / sgsz; |
196 | for (step = 0; step < resource_size(r) / sgsz; step++) | 213 | for (step = 0; step < resource_size(r) / sgsz; step++) |
197 | set_bit(base + step, phb->ioda.pe_alloc); | 214 | pnv_ioda_reserve_pe(phb, base + step); |
198 | } | 215 | } |
199 | } | 216 | } |
200 | } | 217 | } |
@@ -287,8 +304,6 @@ done: | |||
287 | while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) < | 304 | while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) < |
288 | phb->ioda.total_pe) { | 305 | phb->ioda.total_pe) { |
289 | pe = &phb->ioda.pe_array[i]; | 306 | pe = &phb->ioda.pe_array[i]; |
290 | pe->phb = phb; | ||
291 | pe->pe_number = i; | ||
292 | 307 | ||
293 | if (!master_pe) { | 308 | if (!master_pe) { |
294 | pe->flags |= PNV_IODA_PE_MASTER; | 309 | pe->flags |= PNV_IODA_PE_MASTER; |
@@ -313,6 +328,12 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) | |||
313 | const u32 *r; | 328 | const u32 *r; |
314 | u64 pci_addr; | 329 | u64 pci_addr; |
315 | 330 | ||
331 | /* FIXME: Support M64 for P7IOC */ | ||
332 | if (phb->type != PNV_PHB_IODA2) { | ||
333 | pr_info(" Not support M64 window\n"); | ||
334 | return; | ||
335 | } | ||
336 | |||
316 | if (!firmware_has_feature(FW_FEATURE_OPALv3)) { | 337 | if (!firmware_has_feature(FW_FEATURE_OPALv3)) { |
317 | pr_info(" Firmware too old to support M64 window\n"); | 338 | pr_info(" Firmware too old to support M64 window\n"); |
318 | return; | 339 | return; |
@@ -325,12 +346,6 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) | |||
325 | return; | 346 | return; |
326 | } | 347 | } |
327 | 348 | ||
328 | /* FIXME: Support M64 for P7IOC */ | ||
329 | if (phb->type != PNV_PHB_IODA2) { | ||
330 | pr_info(" Not support M64 window\n"); | ||
331 | return; | ||
332 | } | ||
333 | |||
334 | res = &hose->mem_resources[1]; | 349 | res = &hose->mem_resources[1]; |
335 | res->start = of_translate_address(dn, r + 2); | 350 | res->start = of_translate_address(dn, r + 2); |
336 | res->end = res->start + of_read_number(r + 4, 2) - 1; | 351 | res->end = res->start + of_read_number(r + 4, 2) - 1; |
@@ -345,7 +360,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) | |||
345 | /* Use last M64 BAR to cover M64 window */ | 360 | /* Use last M64 BAR to cover M64 window */ |
346 | phb->ioda.m64_bar_idx = 15; | 361 | phb->ioda.m64_bar_idx = 15; |
347 | phb->init_m64 = pnv_ioda2_init_m64; | 362 | phb->init_m64 = pnv_ioda2_init_m64; |
348 | phb->alloc_m64_pe = pnv_ioda2_alloc_m64_pe; | 363 | phb->reserve_m64_pe = pnv_ioda2_reserve_m64_pe; |
349 | phb->pick_m64_pe = pnv_ioda2_pick_m64_pe; | 364 | phb->pick_m64_pe = pnv_ioda2_pick_m64_pe; |
350 | } | 365 | } |
351 | 366 | ||
@@ -358,7 +373,9 @@ static void pnv_ioda_freeze_pe(struct pnv_phb *phb, int pe_no) | |||
358 | /* Fetch master PE */ | 373 | /* Fetch master PE */ |
359 | if (pe->flags & PNV_IODA_PE_SLAVE) { | 374 | if (pe->flags & PNV_IODA_PE_SLAVE) { |
360 | pe = pe->master; | 375 | pe = pe->master; |
361 | WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER)); | 376 | if (WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER))) |
377 | return; | ||
378 | |||
362 | pe_no = pe->pe_number; | 379 | pe_no = pe->pe_number; |
363 | } | 380 | } |
364 | 381 | ||
@@ -507,6 +524,106 @@ static struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev) | |||
507 | } | 524 | } |
508 | #endif /* CONFIG_PCI_MSI */ | 525 | #endif /* CONFIG_PCI_MSI */ |
509 | 526 | ||
527 | static int pnv_ioda_set_one_peltv(struct pnv_phb *phb, | ||
528 | struct pnv_ioda_pe *parent, | ||
529 | struct pnv_ioda_pe *child, | ||
530 | bool is_add) | ||
531 | { | ||
532 | const char *desc = is_add ? "adding" : "removing"; | ||
533 | uint8_t op = is_add ? OPAL_ADD_PE_TO_DOMAIN : | ||
534 | OPAL_REMOVE_PE_FROM_DOMAIN; | ||
535 | struct pnv_ioda_pe *slave; | ||
536 | long rc; | ||
537 | |||
538 | /* Parent PE affects child PE */ | ||
539 | rc = opal_pci_set_peltv(phb->opal_id, parent->pe_number, | ||
540 | child->pe_number, op); | ||
541 | if (rc != OPAL_SUCCESS) { | ||
542 | pe_warn(child, "OPAL error %ld %s to parent PELTV\n", | ||
543 | rc, desc); | ||
544 | return -ENXIO; | ||
545 | } | ||
546 | |||
547 | if (!(child->flags & PNV_IODA_PE_MASTER)) | ||
548 | return 0; | ||
549 | |||
550 | /* Compound case: parent PE affects slave PEs */ | ||
551 | list_for_each_entry(slave, &child->slaves, list) { | ||
552 | rc = opal_pci_set_peltv(phb->opal_id, parent->pe_number, | ||
553 | slave->pe_number, op); | ||
554 | if (rc != OPAL_SUCCESS) { | ||
555 | pe_warn(slave, "OPAL error %ld %s to parent PELTV\n", | ||
556 | rc, desc); | ||
557 | return -ENXIO; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | static int pnv_ioda_set_peltv(struct pnv_phb *phb, | ||
565 | struct pnv_ioda_pe *pe, | ||
566 | bool is_add) | ||
567 | { | ||
568 | struct pnv_ioda_pe *slave; | ||
569 | struct pci_dev *pdev; | ||
570 | int ret; | ||
571 | |||
572 | /* | ||
573 | * Clear PE frozen state. If it's master PE, we need | ||
574 | * clear slave PE frozen state as well. | ||
575 | */ | ||
576 | if (is_add) { | ||
577 | opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number, | ||
578 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); | ||
579 | if (pe->flags & PNV_IODA_PE_MASTER) { | ||
580 | list_for_each_entry(slave, &pe->slaves, list) | ||
581 | opal_pci_eeh_freeze_clear(phb->opal_id, | ||
582 | slave->pe_number, | ||
583 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); | ||
584 | } | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * Associate PE in PELT. We need add the PE into the | ||
589 | * corresponding PELT-V as well. Otherwise, the error | ||
590 | * originated from the PE might contribute to other | ||
591 | * PEs. | ||
592 | */ | ||
593 | ret = pnv_ioda_set_one_peltv(phb, pe, pe, is_add); | ||
594 | if (ret) | ||
595 | return ret; | ||
596 | |||
597 | /* For compound PEs, any one affects all of them */ | ||
598 | if (pe->flags & PNV_IODA_PE_MASTER) { | ||
599 | list_for_each_entry(slave, &pe->slaves, list) { | ||
600 | ret = pnv_ioda_set_one_peltv(phb, slave, pe, is_add); | ||
601 | if (ret) | ||
602 | return ret; | ||
603 | } | ||
604 | } | ||
605 | |||
606 | if (pe->flags & (PNV_IODA_PE_BUS_ALL | PNV_IODA_PE_BUS)) | ||
607 | pdev = pe->pbus->self; | ||
608 | else | ||
609 | pdev = pe->pdev->bus->self; | ||
610 | while (pdev) { | ||
611 | struct pci_dn *pdn = pci_get_pdn(pdev); | ||
612 | struct pnv_ioda_pe *parent; | ||
613 | |||
614 | if (pdn && pdn->pe_number != IODA_INVALID_PE) { | ||
615 | parent = &phb->ioda.pe_array[pdn->pe_number]; | ||
616 | ret = pnv_ioda_set_one_peltv(phb, parent, pe, is_add); | ||
617 | if (ret) | ||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | pdev = pdev->bus->self; | ||
622 | } | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
510 | static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) | 627 | static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) |
511 | { | 628 | { |
512 | struct pci_dev *parent; | 629 | struct pci_dev *parent; |
@@ -561,48 +678,36 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) | |||
561 | return -ENXIO; | 678 | return -ENXIO; |
562 | } | 679 | } |
563 | 680 | ||
564 | rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number, | 681 | /* Configure PELTV */ |
565 | pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); | 682 | pnv_ioda_set_peltv(phb, pe, true); |
566 | if (rc) | ||
567 | pe_warn(pe, "OPAL error %d adding self to PELTV\n", rc); | ||
568 | opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number, | ||
569 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); | ||
570 | 683 | ||
571 | /* Add to all parents PELT-V */ | ||
572 | while (parent) { | ||
573 | struct pci_dn *pdn = pci_get_pdn(parent); | ||
574 | if (pdn && pdn->pe_number != IODA_INVALID_PE) { | ||
575 | rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number, | ||
576 | pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); | ||
577 | /* XXX What to do in case of error ? */ | ||
578 | } | ||
579 | parent = parent->bus->self; | ||
580 | } | ||
581 | /* Setup reverse map */ | 684 | /* Setup reverse map */ |
582 | for (rid = pe->rid; rid < rid_end; rid++) | 685 | for (rid = pe->rid; rid < rid_end; rid++) |
583 | phb->ioda.pe_rmap[rid] = pe->pe_number; | 686 | phb->ioda.pe_rmap[rid] = pe->pe_number; |
584 | 687 | ||
585 | /* Setup one MVTs on IODA1 */ | 688 | /* Setup one MVTs on IODA1 */ |
586 | if (phb->type == PNV_PHB_IODA1) { | 689 | if (phb->type != PNV_PHB_IODA1) { |
587 | pe->mve_number = pe->pe_number; | 690 | pe->mve_number = 0; |
588 | rc = opal_pci_set_mve(phb->opal_id, pe->mve_number, | 691 | goto out; |
589 | pe->pe_number); | 692 | } |
693 | |||
694 | pe->mve_number = pe->pe_number; | ||
695 | rc = opal_pci_set_mve(phb->opal_id, pe->mve_number, pe->pe_number); | ||
696 | if (rc != OPAL_SUCCESS) { | ||
697 | pe_err(pe, "OPAL error %ld setting up MVE %d\n", | ||
698 | rc, pe->mve_number); | ||
699 | pe->mve_number = -1; | ||
700 | } else { | ||
701 | rc = opal_pci_set_mve_enable(phb->opal_id, | ||
702 | pe->mve_number, OPAL_ENABLE_MVE); | ||
590 | if (rc) { | 703 | if (rc) { |
591 | pe_err(pe, "OPAL error %ld setting up MVE %d\n", | 704 | pe_err(pe, "OPAL error %ld enabling MVE %d\n", |
592 | rc, pe->mve_number); | 705 | rc, pe->mve_number); |
593 | pe->mve_number = -1; | 706 | pe->mve_number = -1; |
594 | } else { | ||
595 | rc = opal_pci_set_mve_enable(phb->opal_id, | ||
596 | pe->mve_number, OPAL_ENABLE_MVE); | ||
597 | if (rc) { | ||
598 | pe_err(pe, "OPAL error %ld enabling MVE %d\n", | ||
599 | rc, pe->mve_number); | ||
600 | pe->mve_number = -1; | ||
601 | } | ||
602 | } | 707 | } |
603 | } else if (phb->type == PNV_PHB_IODA2) | 708 | } |
604 | pe->mve_number = 0; | ||
605 | 709 | ||
710 | out: | ||
606 | return 0; | 711 | return 0; |
607 | } | 712 | } |
608 | 713 | ||
@@ -837,8 +942,8 @@ static void pnv_pci_ioda_setup_PEs(void) | |||
837 | phb = hose->private_data; | 942 | phb = hose->private_data; |
838 | 943 | ||
839 | /* M64 layout might affect PE allocation */ | 944 | /* M64 layout might affect PE allocation */ |
840 | if (phb->alloc_m64_pe) | 945 | if (phb->reserve_m64_pe) |
841 | phb->alloc_m64_pe(phb); | 946 | phb->reserve_m64_pe(phb); |
842 | 947 | ||
843 | pnv_ioda_setup_PEs(hose->bus); | 948 | pnv_ioda_setup_PEs(hose->bus); |
844 | } | 949 | } |
@@ -1834,19 +1939,14 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1834 | phb_id = be64_to_cpup(prop64); | 1939 | phb_id = be64_to_cpup(prop64); |
1835 | pr_debug(" PHB-ID : 0x%016llx\n", phb_id); | 1940 | pr_debug(" PHB-ID : 0x%016llx\n", phb_id); |
1836 | 1941 | ||
1837 | phb = alloc_bootmem(sizeof(struct pnv_phb)); | 1942 | phb = memblock_virt_alloc(sizeof(struct pnv_phb), 0); |
1838 | if (!phb) { | ||
1839 | pr_err(" Out of memory !\n"); | ||
1840 | return; | ||
1841 | } | ||
1842 | 1943 | ||
1843 | /* Allocate PCI controller */ | 1944 | /* Allocate PCI controller */ |
1844 | memset(phb, 0, sizeof(struct pnv_phb)); | ||
1845 | phb->hose = hose = pcibios_alloc_controller(np); | 1945 | phb->hose = hose = pcibios_alloc_controller(np); |
1846 | if (!phb->hose) { | 1946 | if (!phb->hose) { |
1847 | pr_err(" Can't allocate PCI controller for %s\n", | 1947 | pr_err(" Can't allocate PCI controller for %s\n", |
1848 | np->full_name); | 1948 | np->full_name); |
1849 | free_bootmem((unsigned long)phb, sizeof(struct pnv_phb)); | 1949 | memblock_free(__pa(phb), sizeof(struct pnv_phb)); |
1850 | return; | 1950 | return; |
1851 | } | 1951 | } |
1852 | 1952 | ||
@@ -1913,8 +2013,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1913 | } | 2013 | } |
1914 | pemap_off = size; | 2014 | pemap_off = size; |
1915 | size += phb->ioda.total_pe * sizeof(struct pnv_ioda_pe); | 2015 | size += phb->ioda.total_pe * sizeof(struct pnv_ioda_pe); |
1916 | aux = alloc_bootmem(size); | 2016 | aux = memblock_virt_alloc(size, 0); |
1917 | memset(aux, 0, size); | ||
1918 | phb->ioda.pe_alloc = aux; | 2017 | phb->ioda.pe_alloc = aux; |
1919 | phb->ioda.m32_segmap = aux + m32map_off; | 2018 | phb->ioda.m32_segmap = aux + m32map_off; |
1920 | if (phb->type == PNV_PHB_IODA1) | 2019 | if (phb->type == PNV_PHB_IODA1) |
@@ -1999,8 +2098,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1999 | ioda_eeh_phb_reset(hose, EEH_RESET_DEACTIVATE); | 2098 | ioda_eeh_phb_reset(hose, EEH_RESET_DEACTIVATE); |
2000 | } | 2099 | } |
2001 | 2100 | ||
2002 | /* Configure M64 window */ | 2101 | /* Remove M64 resource if we can't configure it successfully */ |
2003 | if (phb->init_m64 && phb->init_m64(phb)) | 2102 | if (!phb->init_m64 || phb->init_m64(phb)) |
2004 | hose->mem_resources[1].flags = 0; | 2103 | hose->mem_resources[1].flags = 0; |
2005 | } | 2104 | } |
2006 | 2105 | ||
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c index 94ce3481490b..6ef6d4d8e7e2 100644 --- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c +++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c | |||
@@ -122,12 +122,9 @@ static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id, | |||
122 | return; | 122 | return; |
123 | } | 123 | } |
124 | 124 | ||
125 | phb = alloc_bootmem(sizeof(struct pnv_phb)); | 125 | phb = memblock_virt_alloc(sizeof(struct pnv_phb), 0); |
126 | if (phb) { | 126 | phb->hose = pcibios_alloc_controller(np); |
127 | memset(phb, 0, sizeof(struct pnv_phb)); | 127 | if (!phb->hose) { |
128 | phb->hose = pcibios_alloc_controller(np); | ||
129 | } | ||
130 | if (!phb || !phb->hose) { | ||
131 | pr_err(" Failed to allocate PCI controller\n"); | 128 | pr_err(" Failed to allocate PCI controller\n"); |
132 | return; | 129 | return; |
133 | } | 130 | } |
@@ -196,16 +193,27 @@ void __init pnv_pci_init_p5ioc2_hub(struct device_node *np) | |||
196 | hub_id = be64_to_cpup(prop64); | 193 | hub_id = be64_to_cpup(prop64); |
197 | pr_info(" HUB-ID : 0x%016llx\n", hub_id); | 194 | pr_info(" HUB-ID : 0x%016llx\n", hub_id); |
198 | 195 | ||
196 | /* Count child PHBs and calculate TCE space per PHB */ | ||
197 | for_each_child_of_node(np, phbn) { | ||
198 | if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") || | ||
199 | of_device_is_compatible(phbn, "ibm,p5ioc2-pciex")) | ||
200 | phb_count++; | ||
201 | } | ||
202 | |||
203 | if (phb_count <= 0) { | ||
204 | pr_info(" No PHBs for Hub %s\n", np->full_name); | ||
205 | return; | ||
206 | } | ||
207 | |||
208 | tce_per_phb = __rounddown_pow_of_two(P5IOC2_TCE_MEMORY / phb_count); | ||
209 | pr_info(" Allocating %lld MB of TCE memory per PHB\n", | ||
210 | tce_per_phb >> 20); | ||
211 | |||
199 | /* Currently allocate 16M of TCE memory for every Hub | 212 | /* Currently allocate 16M of TCE memory for every Hub |
200 | * | 213 | * |
201 | * XXX TODO: Make it chip local if possible | 214 | * XXX TODO: Make it chip local if possible |
202 | */ | 215 | */ |
203 | tce_mem = __alloc_bootmem(P5IOC2_TCE_MEMORY, P5IOC2_TCE_MEMORY, | 216 | tce_mem = memblock_virt_alloc(P5IOC2_TCE_MEMORY, P5IOC2_TCE_MEMORY); |
204 | __pa(MAX_DMA_ADDRESS)); | ||
205 | if (!tce_mem) { | ||
206 | pr_err(" Failed to allocate TCE Memory !\n"); | ||
207 | return; | ||
208 | } | ||
209 | pr_debug(" TCE : 0x%016lx..0x%016lx\n", | 217 | pr_debug(" TCE : 0x%016lx..0x%016lx\n", |
210 | __pa(tce_mem), __pa(tce_mem) + P5IOC2_TCE_MEMORY - 1); | 218 | __pa(tce_mem), __pa(tce_mem) + P5IOC2_TCE_MEMORY - 1); |
211 | rc = opal_pci_set_hub_tce_memory(hub_id, __pa(tce_mem), | 219 | rc = opal_pci_set_hub_tce_memory(hub_id, __pa(tce_mem), |
@@ -215,18 +223,6 @@ void __init pnv_pci_init_p5ioc2_hub(struct device_node *np) | |||
215 | return; | 223 | return; |
216 | } | 224 | } |
217 | 225 | ||
218 | /* Count child PHBs */ | ||
219 | for_each_child_of_node(np, phbn) { | ||
220 | if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") || | ||
221 | of_device_is_compatible(phbn, "ibm,p5ioc2-pciex")) | ||
222 | phb_count++; | ||
223 | } | ||
224 | |||
225 | /* Calculate how much TCE space we can give per PHB */ | ||
226 | tce_per_phb = __rounddown_pow_of_two(P5IOC2_TCE_MEMORY / phb_count); | ||
227 | pr_info(" Allocating %lld MB of TCE memory per PHB\n", | ||
228 | tce_per_phb >> 20); | ||
229 | |||
230 | /* Initialize PHBs */ | 226 | /* Initialize PHBs */ |
231 | for_each_child_of_node(np, phbn) { | 227 | for_each_child_of_node(np, phbn) { |
232 | if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") || | 228 | if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") || |
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 540fc6dd56b3..4945e87f12dc 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/bootmem.h> | ||
20 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
21 | #include <linux/io.h> | 20 | #include <linux/io.h> |
22 | #include <linux/msi.h> | 21 | #include <linux/msi.h> |
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 34d29eb2a4de..6c02ff8dd69f 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h | |||
@@ -130,7 +130,7 @@ struct pnv_phb { | |||
130 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); | 130 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); |
131 | void (*shutdown)(struct pnv_phb *phb); | 131 | void (*shutdown)(struct pnv_phb *phb); |
132 | int (*init_m64)(struct pnv_phb *phb); | 132 | int (*init_m64)(struct pnv_phb *phb); |
133 | void (*alloc_m64_pe)(struct pnv_phb *phb); | 133 | void (*reserve_m64_pe)(struct pnv_phb *phb); |
134 | int (*pick_m64_pe)(struct pnv_phb *phb, struct pci_bus *bus, int all); | 134 | int (*pick_m64_pe)(struct pnv_phb *phb, struct pci_bus *bus, int all); |
135 | int (*get_pe_state)(struct pnv_phb *phb, int pe_no); | 135 | int (*get_pe_state)(struct pnv_phb *phb, int pe_no); |
136 | void (*freeze_pe)(struct pnv_phb *phb, int pe_no); | 136 | void (*freeze_pe)(struct pnv_phb *phb, int pe_no); |
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index 3f9546d8a51f..30b1c3e298a6 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
@@ -265,10 +265,8 @@ static unsigned long pnv_memory_block_size(void) | |||
265 | static void __init pnv_setup_machdep_opal(void) | 265 | static void __init pnv_setup_machdep_opal(void) |
266 | { | 266 | { |
267 | ppc_md.get_boot_time = opal_get_boot_time; | 267 | ppc_md.get_boot_time = opal_get_boot_time; |
268 | ppc_md.get_rtc_time = opal_get_rtc_time; | ||
269 | ppc_md.set_rtc_time = opal_set_rtc_time; | ||
270 | ppc_md.restart = pnv_restart; | 268 | ppc_md.restart = pnv_restart; |
271 | ppc_md.power_off = pnv_power_off; | 269 | pm_power_off = pnv_power_off; |
272 | ppc_md.halt = pnv_halt; | 270 | ppc_md.halt = pnv_halt; |
273 | ppc_md.machine_check_exception = opal_machine_check; | 271 | ppc_md.machine_check_exception = opal_machine_check; |
274 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; | 272 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; |
@@ -285,7 +283,7 @@ static void __init pnv_setup_machdep_rtas(void) | |||
285 | ppc_md.set_rtc_time = rtas_set_rtc_time; | 283 | ppc_md.set_rtc_time = rtas_set_rtc_time; |
286 | } | 284 | } |
287 | ppc_md.restart = rtas_restart; | 285 | ppc_md.restart = rtas_restart; |
288 | ppc_md.power_off = rtas_power_off; | 286 | pm_power_off = rtas_power_off; |
289 | ppc_md.halt = rtas_halt; | 287 | ppc_md.halt = rtas_halt; |
290 | } | 288 | } |
291 | #endif /* CONFIG_PPC_POWERNV_RTAS */ | 289 | #endif /* CONFIG_PPC_POWERNV_RTAS */ |
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index 4753958cd509..b716f666e48a 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c | |||
@@ -149,6 +149,7 @@ static int pnv_smp_cpu_disable(void) | |||
149 | static void pnv_smp_cpu_kill_self(void) | 149 | static void pnv_smp_cpu_kill_self(void) |
150 | { | 150 | { |
151 | unsigned int cpu; | 151 | unsigned int cpu; |
152 | unsigned long srr1; | ||
152 | 153 | ||
153 | /* Standard hot unplug procedure */ | 154 | /* Standard hot unplug procedure */ |
154 | local_irq_disable(); | 155 | local_irq_disable(); |
@@ -165,13 +166,25 @@ static void pnv_smp_cpu_kill_self(void) | |||
165 | mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1); | 166 | mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1); |
166 | while (!generic_check_cpu_restart(cpu)) { | 167 | while (!generic_check_cpu_restart(cpu)) { |
167 | ppc64_runlatch_off(); | 168 | ppc64_runlatch_off(); |
168 | power7_nap(1); | 169 | srr1 = power7_nap(1); |
169 | ppc64_runlatch_on(); | 170 | ppc64_runlatch_on(); |
170 | 171 | ||
171 | /* Clear the IPI that woke us up */ | 172 | /* |
172 | icp_native_flush_interrupt(); | 173 | * If the SRR1 value indicates that we woke up due to |
173 | local_paca->irq_happened &= PACA_IRQ_HARD_DIS; | 174 | * an external interrupt, then clear the interrupt. |
174 | mb(); | 175 | * We clear the interrupt before checking for the |
176 | * reason, so as to avoid a race where we wake up for | ||
177 | * some other reason, find nothing and clear the interrupt | ||
178 | * just as some other cpu is sending us an interrupt. | ||
179 | * If we returned from power7_nap as a result of | ||
180 | * having finished executing in a KVM guest, then srr1 | ||
181 | * contains 0. | ||
182 | */ | ||
183 | if ((srr1 & SRR1_WAKEMASK) == SRR1_WAKEEE) { | ||
184 | icp_native_flush_interrupt(); | ||
185 | local_paca->irq_happened &= PACA_IRQ_HARD_DIS; | ||
186 | smp_mb(); | ||
187 | } | ||
175 | 188 | ||
176 | if (cpu_core_split_required()) | 189 | if (cpu_core_split_required()) |
177 | continue; | 190 | continue; |
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index 3e270e3412ae..2f95d33cf34a 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c | |||
@@ -110,7 +110,7 @@ static long ps3_hpte_remove(unsigned long hpte_group) | |||
110 | 110 | ||
111 | static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, | 111 | static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, |
112 | unsigned long vpn, int psize, int apsize, | 112 | unsigned long vpn, int psize, int apsize, |
113 | int ssize, int local) | 113 | int ssize, unsigned long inv_flags) |
114 | { | 114 | { |
115 | int result; | 115 | int result; |
116 | u64 hpte_v, want_v, hpte_rs; | 116 | u64 hpte_v, want_v, hpte_rs; |
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 5f3b23220b8e..a6c42f34303a 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c | |||
@@ -711,7 +711,7 @@ void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq) | |||
711 | 711 | ||
712 | static unsigned int ps3_get_irq(void) | 712 | static unsigned int ps3_get_irq(void) |
713 | { | 713 | { |
714 | struct ps3_private *pd = &__get_cpu_var(ps3_private); | 714 | struct ps3_private *pd = this_cpu_ptr(&ps3_private); |
715 | u64 x = (pd->bmp.status & pd->bmp.mask); | 715 | u64 x = (pd->bmp.status & pd->bmp.mask); |
716 | unsigned int plug; | 716 | unsigned int plug; |
717 | 717 | ||
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 3f509f86432c..799c8580ab09 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c | |||
@@ -125,12 +125,7 @@ static void __init prealloc(struct ps3_prealloc *p) | |||
125 | if (!p->size) | 125 | if (!p->size) |
126 | return; | 126 | return; |
127 | 127 | ||
128 | p->address = __alloc_bootmem(p->size, p->align, __pa(MAX_DMA_ADDRESS)); | 128 | p->address = memblock_virt_alloc(p->size, p->align); |
129 | if (!p->address) { | ||
130 | printk(KERN_ERR "%s: Cannot allocate %s\n", __func__, | ||
131 | p->name); | ||
132 | return; | ||
133 | } | ||
134 | 129 | ||
135 | printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size, | 130 | printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size, |
136 | p->address); | 131 | p->address); |
@@ -248,6 +243,7 @@ static int __init ps3_probe(void) | |||
248 | ps3_mm_init(); | 243 | ps3_mm_init(); |
249 | ps3_mm_vas_create(&htab_size); | 244 | ps3_mm_vas_create(&htab_size); |
250 | ps3_hpte_init(htab_size); | 245 | ps3_hpte_init(htab_size); |
246 | pm_power_off = ps3_power_off; | ||
251 | 247 | ||
252 | DBG(" <- %s:%d\n", __func__, __LINE__); | 248 | DBG(" <- %s:%d\n", __func__, __LINE__); |
253 | return 1; | 249 | return 1; |
@@ -278,7 +274,6 @@ define_machine(ps3) { | |||
278 | .calibrate_decr = ps3_calibrate_decr, | 274 | .calibrate_decr = ps3_calibrate_decr, |
279 | .progress = ps3_progress, | 275 | .progress = ps3_progress, |
280 | .restart = ps3_restart, | 276 | .restart = ps3_restart, |
281 | .power_off = ps3_power_off, | ||
282 | .halt = ps3_halt, | 277 | .halt = ps3_halt, |
283 | #if defined(CONFIG_KEXEC) | 278 | #if defined(CONFIG_KEXEC) |
284 | .kexec_cpu_down = ps3_kexec_cpu_down, | 279 | .kexec_cpu_down = ps3_kexec_cpu_down, |
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index 1062f71f5a85..39049e4884fb 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c | |||
@@ -75,7 +75,7 @@ static atomic_t dtl_count; | |||
75 | */ | 75 | */ |
76 | static void consume_dtle(struct dtl_entry *dtle, u64 index) | 76 | static void consume_dtle(struct dtl_entry *dtle, u64 index) |
77 | { | 77 | { |
78 | struct dtl_ring *dtlr = &__get_cpu_var(dtl_rings); | 78 | struct dtl_ring *dtlr = this_cpu_ptr(&dtl_rings); |
79 | struct dtl_entry *wp = dtlr->write_ptr; | 79 | struct dtl_entry *wp = dtlr->write_ptr; |
80 | struct lppaca *vpa = local_paca->lppaca_ptr; | 80 | struct lppaca *vpa = local_paca->lppaca_ptr; |
81 | 81 | ||
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 1bbb78fab530..fa41f0da5b6f 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/of.h> | 12 | #include <linux/of.h> |
13 | #include <linux/of_address.h> | 13 | #include <linux/of_address.h> |
14 | #include <linux/memblock.h> | 14 | #include <linux/memblock.h> |
15 | #include <linux/vmalloc.h> | ||
16 | #include <linux/memory.h> | 15 | #include <linux/memory.h> |
17 | #include <linux/memory_hotplug.h> | 16 | #include <linux/memory_hotplug.h> |
18 | 17 | ||
@@ -66,22 +65,6 @@ unsigned long pseries_memory_block_size(void) | |||
66 | } | 65 | } |
67 | 66 | ||
68 | #ifdef CONFIG_MEMORY_HOTREMOVE | 67 | #ifdef CONFIG_MEMORY_HOTREMOVE |
69 | static int pseries_remove_memory(u64 start, u64 size) | ||
70 | { | ||
71 | int ret; | ||
72 | |||
73 | /* Remove htab bolted mappings for this section of memory */ | ||
74 | start = (unsigned long)__va(start); | ||
75 | ret = remove_section_mapping(start, start + size); | ||
76 | |||
77 | /* Ensure all vmalloc mappings are flushed in case they also | ||
78 | * hit that section of memory | ||
79 | */ | ||
80 | vm_unmap_aliases(); | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size) | 68 | static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size) |
86 | { | 69 | { |
87 | unsigned long block_sz, start_pfn; | 70 | unsigned long block_sz, start_pfn; |
@@ -261,10 +244,6 @@ static int __init pseries_memory_hotplug_init(void) | |||
261 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 244 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
262 | of_reconfig_notifier_register(&pseries_mem_nb); | 245 | of_reconfig_notifier_register(&pseries_mem_nb); |
263 | 246 | ||
264 | #ifdef CONFIG_MEMORY_HOTREMOVE | ||
265 | ppc_md.remove_memory = pseries_remove_memory; | ||
266 | #endif | ||
267 | |||
268 | return 0; | 247 | return 0; |
269 | } | 248 | } |
270 | machine_device_initcall(pseries, pseries_memory_hotplug_init); | 249 | machine_device_initcall(pseries, pseries_memory_hotplug_init); |
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 3fda3f17b84e..ccd53f91e8aa 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S | |||
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | #ifdef CONFIG_TRACEPOINTS | 19 | #ifdef CONFIG_TRACEPOINTS |
20 | 20 | ||
21 | #ifndef CONFIG_JUMP_LABEL | 21 | #ifndef HAVE_JUMP_LABEL |
22 | .section ".toc","aw" | 22 | .section ".toc","aw" |
23 | 23 | ||
24 | .globl hcall_tracepoint_refcount | 24 | .globl hcall_tracepoint_refcount |
@@ -78,7 +78,7 @@ hcall_tracepoint_refcount: | |||
78 | mr r5,BUFREG; \ | 78 | mr r5,BUFREG; \ |
79 | __HCALL_INST_POSTCALL | 79 | __HCALL_INST_POSTCALL |
80 | 80 | ||
81 | #ifdef CONFIG_JUMP_LABEL | 81 | #ifdef HAVE_JUMP_LABEL |
82 | #define HCALL_BRANCH(LABEL) \ | 82 | #define HCALL_BRANCH(LABEL) \ |
83 | ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key) | 83 | ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key) |
84 | #else | 84 | #else |
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c index 4575f0c9e521..f02ec3ab428c 100644 --- a/arch/powerpc/platforms/pseries/hvCall_inst.c +++ b/arch/powerpc/platforms/pseries/hvCall_inst.c | |||
@@ -110,7 +110,7 @@ static void probe_hcall_entry(void *ignored, unsigned long opcode, unsigned long | |||
110 | if (opcode > MAX_HCALL_OPCODE) | 110 | if (opcode > MAX_HCALL_OPCODE) |
111 | return; | 111 | return; |
112 | 112 | ||
113 | h = &__get_cpu_var(hcall_stats)[opcode / 4]; | 113 | h = this_cpu_ptr(&hcall_stats[opcode / 4]); |
114 | h->tb_start = mftb(); | 114 | h->tb_start = mftb(); |
115 | h->purr_start = mfspr(SPRN_PURR); | 115 | h->purr_start = mfspr(SPRN_PURR); |
116 | } | 116 | } |
@@ -123,7 +123,7 @@ static void probe_hcall_exit(void *ignored, unsigned long opcode, unsigned long | |||
123 | if (opcode > MAX_HCALL_OPCODE) | 123 | if (opcode > MAX_HCALL_OPCODE) |
124 | return; | 124 | return; |
125 | 125 | ||
126 | h = &__get_cpu_var(hcall_stats)[opcode / 4]; | 126 | h = this_cpu_ptr(&hcall_stats[opcode / 4]); |
127 | h->num_calls++; | 127 | h->num_calls++; |
128 | h->tb_total += mftb() - h->tb_start; | 128 | h->tb_total += mftb() - h->tb_start; |
129 | h->purr_total += mfspr(SPRN_PURR) - h->purr_start; | 129 | h->purr_total += mfspr(SPRN_PURR) - h->purr_start; |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 3e5bfdafee63..1d3d52dc3ff3 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -199,7 +199,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
199 | 199 | ||
200 | local_irq_save(flags); /* to protect tcep and the page behind it */ | 200 | local_irq_save(flags); /* to protect tcep and the page behind it */ |
201 | 201 | ||
202 | tcep = __get_cpu_var(tce_page); | 202 | tcep = __this_cpu_read(tce_page); |
203 | 203 | ||
204 | /* This is safe to do since interrupts are off when we're called | 204 | /* This is safe to do since interrupts are off when we're called |
205 | * from iommu_alloc{,_sg}() | 205 | * from iommu_alloc{,_sg}() |
@@ -212,7 +212,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
212 | return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, | 212 | return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, |
213 | direction, attrs); | 213 | direction, attrs); |
214 | } | 214 | } |
215 | __get_cpu_var(tce_page) = tcep; | 215 | __this_cpu_write(tce_page, tcep); |
216 | } | 216 | } |
217 | 217 | ||
218 | rpn = __pa(uaddr) >> TCE_SHIFT; | 218 | rpn = __pa(uaddr) >> TCE_SHIFT; |
@@ -398,7 +398,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn, | |||
398 | long l, limit; | 398 | long l, limit; |
399 | 399 | ||
400 | local_irq_disable(); /* to protect tcep and the page behind it */ | 400 | local_irq_disable(); /* to protect tcep and the page behind it */ |
401 | tcep = __get_cpu_var(tce_page); | 401 | tcep = __this_cpu_read(tce_page); |
402 | 402 | ||
403 | if (!tcep) { | 403 | if (!tcep) { |
404 | tcep = (__be64 *)__get_free_page(GFP_ATOMIC); | 404 | tcep = (__be64 *)__get_free_page(GFP_ATOMIC); |
@@ -406,7 +406,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn, | |||
406 | local_irq_enable(); | 406 | local_irq_enable(); |
407 | return -ENOMEM; | 407 | return -ENOMEM; |
408 | } | 408 | } |
409 | __get_cpu_var(tce_page) = tcep; | 409 | __this_cpu_write(tce_page, tcep); |
410 | } | 410 | } |
411 | 411 | ||
412 | proto_tce = TCE_PCI_READ | TCE_PCI_WRITE; | 412 | proto_tce = TCE_PCI_READ | TCE_PCI_WRITE; |
@@ -574,8 +574,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) | |||
574 | while (isa_dn && isa_dn != dn) | 574 | while (isa_dn && isa_dn != dn) |
575 | isa_dn = isa_dn->parent; | 575 | isa_dn = isa_dn->parent; |
576 | 576 | ||
577 | if (isa_dn_orig) | 577 | of_node_put(isa_dn_orig); |
578 | of_node_put(isa_dn_orig); | ||
579 | 578 | ||
580 | /* Count number of direct PCI children of the PHB. */ | 579 | /* Count number of direct PCI children of the PHB. */ |
581 | for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) | 580 | for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index f6880d2a40fb..469751d92004 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -284,7 +284,7 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, | |||
284 | unsigned long newpp, | 284 | unsigned long newpp, |
285 | unsigned long vpn, | 285 | unsigned long vpn, |
286 | int psize, int apsize, | 286 | int psize, int apsize, |
287 | int ssize, int local) | 287 | int ssize, unsigned long inv_flags) |
288 | { | 288 | { |
289 | unsigned long lpar_rc; | 289 | unsigned long lpar_rc; |
290 | unsigned long flags = (newpp & 7) | H_AVPN; | 290 | unsigned long flags = (newpp & 7) | H_AVPN; |
@@ -442,7 +442,7 @@ static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, | |||
442 | static void pSeries_lpar_hugepage_invalidate(unsigned long vsid, | 442 | static void pSeries_lpar_hugepage_invalidate(unsigned long vsid, |
443 | unsigned long addr, | 443 | unsigned long addr, |
444 | unsigned char *hpte_slot_array, | 444 | unsigned char *hpte_slot_array, |
445 | int psize, int ssize) | 445 | int psize, int ssize, int local) |
446 | { | 446 | { |
447 | int i, index = 0; | 447 | int i, index = 0; |
448 | unsigned long s_addr = addr; | 448 | unsigned long s_addr = addr; |
@@ -515,7 +515,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | |||
515 | unsigned long vpn; | 515 | unsigned long vpn; |
516 | unsigned long i, pix, rc; | 516 | unsigned long i, pix, rc; |
517 | unsigned long flags = 0; | 517 | unsigned long flags = 0; |
518 | struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); | 518 | struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); |
519 | int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); | 519 | int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); |
520 | unsigned long param[9]; | 520 | unsigned long param[9]; |
521 | unsigned long hash, index, shift, hidx, slot; | 521 | unsigned long hash, index, shift, hidx, slot; |
@@ -705,7 +705,7 @@ void __trace_hcall_entry(unsigned long opcode, unsigned long *args) | |||
705 | 705 | ||
706 | local_irq_save(flags); | 706 | local_irq_save(flags); |
707 | 707 | ||
708 | depth = &__get_cpu_var(hcall_trace_depth); | 708 | depth = this_cpu_ptr(&hcall_trace_depth); |
709 | 709 | ||
710 | if (*depth) | 710 | if (*depth) |
711 | goto out; | 711 | goto out; |
@@ -730,7 +730,7 @@ void __trace_hcall_exit(long opcode, unsigned long retval, | |||
730 | 730 | ||
731 | local_irq_save(flags); | 731 | local_irq_save(flags); |
732 | 732 | ||
733 | depth = &__get_cpu_var(hcall_trace_depth); | 733 | depth = this_cpu_ptr(&hcall_trace_depth); |
734 | 734 | ||
735 | if (*depth) | 735 | if (*depth) |
736 | goto out; | 736 | goto out; |
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 11a3b617ef5d..054a0ed5c7ee 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c | |||
@@ -715,6 +715,8 @@ static int nvram_pstore_init(void) | |||
715 | nvram_pstore_info.buf = oops_data; | 715 | nvram_pstore_info.buf = oops_data; |
716 | nvram_pstore_info.bufsize = oops_data_sz; | 716 | nvram_pstore_info.bufsize = oops_data_sz; |
717 | 717 | ||
718 | spin_lock_init(&nvram_pstore_info.buf_lock); | ||
719 | |||
718 | rc = pstore_register(&nvram_pstore_info); | 720 | rc = pstore_register(&nvram_pstore_info); |
719 | if (rc != 0) | 721 | if (rc != 0) |
720 | pr_err("nvram: pstore_register() failed, defaults to " | 722 | pr_err("nvram: pstore_register() failed, defaults to " |
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 67e48594040c..fe16a50700de 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c | |||
@@ -134,7 +134,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) | |||
134 | of_node_put(pdn); | 134 | of_node_put(pdn); |
135 | 135 | ||
136 | if (rc) { | 136 | if (rc) { |
137 | pr_err("no ibm,pcie-link-speed-stats property\n"); | 137 | pr_debug("no ibm,pcie-link-speed-stats property\n"); |
138 | return 0; | 138 | return 0; |
139 | } | 139 | } |
140 | 140 | ||
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 5a4d0fc03b03..c3b2a7e81ddb 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
@@ -302,8 +302,8 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs) | |||
302 | /* If it isn't an extended log we can use the per cpu 64bit buffer */ | 302 | /* If it isn't an extended log we can use the per cpu 64bit buffer */ |
303 | h = (struct rtas_error_log *)&savep[1]; | 303 | h = (struct rtas_error_log *)&savep[1]; |
304 | if (!rtas_error_extended(h)) { | 304 | if (!rtas_error_extended(h)) { |
305 | memcpy(&__get_cpu_var(mce_data_buf), h, sizeof(__u64)); | 305 | memcpy(this_cpu_ptr(&mce_data_buf), h, sizeof(__u64)); |
306 | errhdr = (struct rtas_error_log *)&__get_cpu_var(mce_data_buf); | 306 | errhdr = (struct rtas_error_log *)this_cpu_ptr(&mce_data_buf); |
307 | } else { | 307 | } else { |
308 | int len, error_log_length; | 308 | int len, error_log_length; |
309 | 309 | ||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index ed8a90022a3d..e445b6701f50 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -500,7 +500,11 @@ static void __init pSeries_setup_arch(void) | |||
500 | 500 | ||
501 | if (firmware_has_feature(FW_FEATURE_SET_MODE)) { | 501 | if (firmware_has_feature(FW_FEATURE_SET_MODE)) { |
502 | long rc; | 502 | long rc; |
503 | if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) { | 503 | |
504 | rc = pSeries_enable_reloc_on_exc(); | ||
505 | if (rc == H_P2) { | ||
506 | pr_info("Relocation on exceptions not supported\n"); | ||
507 | } else if (rc != H_SUCCESS) { | ||
504 | pr_warn("Unable to enable relocation on exceptions: " | 508 | pr_warn("Unable to enable relocation on exceptions: " |
505 | "%ld\n", rc); | 509 | "%ld\n", rc); |
506 | } | 510 | } |
@@ -660,6 +664,34 @@ static void __init pSeries_init_early(void) | |||
660 | pr_debug(" <- pSeries_init_early()\n"); | 664 | pr_debug(" <- pSeries_init_early()\n"); |
661 | } | 665 | } |
662 | 666 | ||
667 | /** | ||
668 | * pseries_power_off - tell firmware about how to power off the system. | ||
669 | * | ||
670 | * This function calls either the power-off rtas token in normal cases | ||
671 | * or the ibm,power-off-ups token (if present & requested) in case of | ||
672 | * a power failure. If power-off token is used, power on will only be | ||
673 | * possible with power button press. If ibm,power-off-ups token is used | ||
674 | * it will allow auto poweron after power is restored. | ||
675 | */ | ||
676 | static void pseries_power_off(void) | ||
677 | { | ||
678 | int rc; | ||
679 | int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups"); | ||
680 | |||
681 | if (rtas_flash_term_hook) | ||
682 | rtas_flash_term_hook(SYS_POWER_OFF); | ||
683 | |||
684 | if (rtas_poweron_auto == 0 || | ||
685 | rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) { | ||
686 | rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1); | ||
687 | printk(KERN_INFO "RTAS power-off returned %d\n", rc); | ||
688 | } else { | ||
689 | rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL); | ||
690 | printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc); | ||
691 | } | ||
692 | for (;;); | ||
693 | } | ||
694 | |||
663 | /* | 695 | /* |
664 | * Called very early, MMU is off, device-tree isn't unflattened | 696 | * Called very early, MMU is off, device-tree isn't unflattened |
665 | */ | 697 | */ |
@@ -742,6 +774,8 @@ static int __init pSeries_probe(void) | |||
742 | else | 774 | else |
743 | hpte_init_native(); | 775 | hpte_init_native(); |
744 | 776 | ||
777 | pm_power_off = pseries_power_off; | ||
778 | |||
745 | pr_debug("Machine is%s LPAR !\n", | 779 | pr_debug("Machine is%s LPAR !\n", |
746 | (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); | 780 | (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); |
747 | 781 | ||
@@ -755,34 +789,6 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) | |||
755 | return PCI_PROBE_NORMAL; | 789 | return PCI_PROBE_NORMAL; |
756 | } | 790 | } |
757 | 791 | ||
758 | /** | ||
759 | * pSeries_power_off - tell firmware about how to power off the system. | ||
760 | * | ||
761 | * This function calls either the power-off rtas token in normal cases | ||
762 | * or the ibm,power-off-ups token (if present & requested) in case of | ||
763 | * a power failure. If power-off token is used, power on will only be | ||
764 | * possible with power button press. If ibm,power-off-ups token is used | ||
765 | * it will allow auto poweron after power is restored. | ||
766 | */ | ||
767 | static void pSeries_power_off(void) | ||
768 | { | ||
769 | int rc; | ||
770 | int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups"); | ||
771 | |||
772 | if (rtas_flash_term_hook) | ||
773 | rtas_flash_term_hook(SYS_POWER_OFF); | ||
774 | |||
775 | if (rtas_poweron_auto == 0 || | ||
776 | rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) { | ||
777 | rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1); | ||
778 | printk(KERN_INFO "RTAS power-off returned %d\n", rc); | ||
779 | } else { | ||
780 | rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL); | ||
781 | printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc); | ||
782 | } | ||
783 | for (;;); | ||
784 | } | ||
785 | |||
786 | #ifndef CONFIG_PCI | 792 | #ifndef CONFIG_PCI |
787 | void pSeries_final_fixup(void) { } | 793 | void pSeries_final_fixup(void) { } |
788 | #endif | 794 | #endif |
@@ -797,7 +803,6 @@ define_machine(pseries) { | |||
797 | .pcibios_fixup = pSeries_final_fixup, | 803 | .pcibios_fixup = pSeries_final_fixup, |
798 | .pci_probe_mode = pSeries_pci_probe_mode, | 804 | .pci_probe_mode = pSeries_pci_probe_mode, |
799 | .restart = rtas_restart, | 805 | .restart = rtas_restart, |
800 | .power_off = pSeries_power_off, | ||
801 | .halt = rtas_halt, | 806 | .halt = rtas_halt, |
802 | .panic = rtas_os_term, | 807 | .panic = rtas_os_term, |
803 | .get_boot_time = rtas_get_boot_time, | 808 | .get_boot_time = rtas_get_boot_time, |
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 7aed8d0876b7..d09f4fa2c3d1 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
@@ -13,7 +13,6 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/bootmem.h> | ||
17 | #include <linux/msi.h> | 16 | #include <linux/msi.h> |
18 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
19 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 65d2ed4549e6..6455c1eada1a 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/bootmem.h> | ||
27 | #include <linux/memblock.h> | 26 | #include <linux/memblock.h> |
28 | #include <linux/log2.h> | 27 | #include <linux/log2.h> |
29 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
@@ -152,7 +151,7 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci, | |||
152 | flags |= 0x10000000; /* enable relaxed ordering */ | 151 | flags |= 0x10000000; /* enable relaxed ordering */ |
153 | 152 | ||
154 | for (i = 0; size > 0; i++) { | 153 | for (i = 0; size > 0; i++) { |
155 | unsigned int bits = min(ilog2(size), | 154 | unsigned int bits = min_t(u32, ilog2(size), |
156 | __ffs(pci_addr | phys_addr)); | 155 | __ffs(pci_addr | phys_addr)); |
157 | 156 | ||
158 | if (index + i >= 5) | 157 | if (index + i >= 5) |
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index c04b718307c8..08d60f183dad 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
@@ -58,6 +58,19 @@ | |||
58 | #define RIO_ISR_AACR 0x10120 | 58 | #define RIO_ISR_AACR 0x10120 |
59 | #define RIO_ISR_AACR_AA 0x1 /* Accept All ID */ | 59 | #define RIO_ISR_AACR_AA 0x1 /* Accept All ID */ |
60 | 60 | ||
61 | #define RIWTAR_TRAD_VAL_SHIFT 12 | ||
62 | #define RIWTAR_TRAD_MASK 0x00FFFFFF | ||
63 | #define RIWBAR_BADD_VAL_SHIFT 12 | ||
64 | #define RIWBAR_BADD_MASK 0x003FFFFF | ||
65 | #define RIWAR_ENABLE 0x80000000 | ||
66 | #define RIWAR_TGINT_LOCAL 0x00F00000 | ||
67 | #define RIWAR_RDTYP_NO_SNOOP 0x00040000 | ||
68 | #define RIWAR_RDTYP_SNOOP 0x00050000 | ||
69 | #define RIWAR_WRTYP_NO_SNOOP 0x00004000 | ||
70 | #define RIWAR_WRTYP_SNOOP 0x00005000 | ||
71 | #define RIWAR_WRTYP_ALLOC 0x00006000 | ||
72 | #define RIWAR_SIZE_MASK 0x0000003F | ||
73 | |||
61 | #define __fsl_read_rio_config(x, addr, err, op) \ | 74 | #define __fsl_read_rio_config(x, addr, err, op) \ |
62 | __asm__ __volatile__( \ | 75 | __asm__ __volatile__( \ |
63 | "1: "op" %1,0(%2)\n" \ | 76 | "1: "op" %1,0(%2)\n" \ |
@@ -266,6 +279,89 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, | |||
266 | return 0; | 279 | return 0; |
267 | } | 280 | } |
268 | 281 | ||
282 | static void fsl_rio_inbound_mem_init(struct rio_priv *priv) | ||
283 | { | ||
284 | int i; | ||
285 | |||
286 | /* close inbound windows */ | ||
287 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) | ||
288 | out_be32(&priv->inb_atmu_regs[i].riwar, 0); | ||
289 | } | ||
290 | |||
291 | int fsl_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, | ||
292 | u64 rstart, u32 size, u32 flags) | ||
293 | { | ||
294 | struct rio_priv *priv = mport->priv; | ||
295 | u32 base_size; | ||
296 | unsigned int base_size_log; | ||
297 | u64 win_start, win_end; | ||
298 | u32 riwar; | ||
299 | int i; | ||
300 | |||
301 | if ((size & (size - 1)) != 0) | ||
302 | return -EINVAL; | ||
303 | |||
304 | base_size_log = ilog2(size); | ||
305 | base_size = 1 << base_size_log; | ||
306 | |||
307 | /* check if addresses are aligned with the window size */ | ||
308 | if (lstart & (base_size - 1)) | ||
309 | return -EINVAL; | ||
310 | if (rstart & (base_size - 1)) | ||
311 | return -EINVAL; | ||
312 | |||
313 | /* check for conflicting ranges */ | ||
314 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { | ||
315 | riwar = in_be32(&priv->inb_atmu_regs[i].riwar); | ||
316 | if ((riwar & RIWAR_ENABLE) == 0) | ||
317 | continue; | ||
318 | win_start = ((u64)(in_be32(&priv->inb_atmu_regs[i].riwbar) & RIWBAR_BADD_MASK)) | ||
319 | << RIWBAR_BADD_VAL_SHIFT; | ||
320 | win_end = win_start + ((1 << ((riwar & RIWAR_SIZE_MASK) + 1)) - 1); | ||
321 | if (rstart < win_end && (rstart + size) > win_start) | ||
322 | return -EINVAL; | ||
323 | } | ||
324 | |||
325 | /* find unused atmu */ | ||
326 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { | ||
327 | riwar = in_be32(&priv->inb_atmu_regs[i].riwar); | ||
328 | if ((riwar & RIWAR_ENABLE) == 0) | ||
329 | break; | ||
330 | } | ||
331 | if (i >= RIO_INB_ATMU_COUNT) | ||
332 | return -ENOMEM; | ||
333 | |||
334 | out_be32(&priv->inb_atmu_regs[i].riwtar, lstart >> RIWTAR_TRAD_VAL_SHIFT); | ||
335 | out_be32(&priv->inb_atmu_regs[i].riwbar, rstart >> RIWBAR_BADD_VAL_SHIFT); | ||
336 | out_be32(&priv->inb_atmu_regs[i].riwar, RIWAR_ENABLE | RIWAR_TGINT_LOCAL | | ||
337 | RIWAR_RDTYP_SNOOP | RIWAR_WRTYP_SNOOP | (base_size_log - 1)); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | void fsl_unmap_inb_mem(struct rio_mport *mport, dma_addr_t lstart) | ||
343 | { | ||
344 | u32 win_start_shift, base_start_shift; | ||
345 | struct rio_priv *priv = mport->priv; | ||
346 | u32 riwar, riwtar; | ||
347 | int i; | ||
348 | |||
349 | /* skip default window */ | ||
350 | base_start_shift = lstart >> RIWTAR_TRAD_VAL_SHIFT; | ||
351 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { | ||
352 | riwar = in_be32(&priv->inb_atmu_regs[i].riwar); | ||
353 | if ((riwar & RIWAR_ENABLE) == 0) | ||
354 | continue; | ||
355 | |||
356 | riwtar = in_be32(&priv->inb_atmu_regs[i].riwtar); | ||
357 | win_start_shift = riwtar & RIWTAR_TRAD_MASK; | ||
358 | if (win_start_shift == base_start_shift) { | ||
359 | out_be32(&priv->inb_atmu_regs[i].riwar, riwar & ~RIWAR_ENABLE); | ||
360 | return; | ||
361 | } | ||
362 | } | ||
363 | } | ||
364 | |||
269 | void fsl_rio_port_error_handler(int offset) | 365 | void fsl_rio_port_error_handler(int offset) |
270 | { | 366 | { |
271 | /*XXX: Error recovery is not implemented, we just clear errors */ | 367 | /*XXX: Error recovery is not implemented, we just clear errors */ |
@@ -389,6 +485,8 @@ int fsl_rio_setup(struct platform_device *dev) | |||
389 | ops->add_outb_message = fsl_add_outb_message; | 485 | ops->add_outb_message = fsl_add_outb_message; |
390 | ops->add_inb_buffer = fsl_add_inb_buffer; | 486 | ops->add_inb_buffer = fsl_add_inb_buffer; |
391 | ops->get_inb_message = fsl_get_inb_message; | 487 | ops->get_inb_message = fsl_get_inb_message; |
488 | ops->map_inb = fsl_map_inb_mem; | ||
489 | ops->unmap_inb = fsl_unmap_inb_mem; | ||
392 | 490 | ||
393 | rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0); | 491 | rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0); |
394 | if (!rmu_node) { | 492 | if (!rmu_node) { |
@@ -602,6 +700,11 @@ int fsl_rio_setup(struct platform_device *dev) | |||
602 | RIO_ATMU_REGS_PORT2_OFFSET)); | 700 | RIO_ATMU_REGS_PORT2_OFFSET)); |
603 | 701 | ||
604 | priv->maint_atmu_regs = priv->atmu_regs + 1; | 702 | priv->maint_atmu_regs = priv->atmu_regs + 1; |
703 | priv->inb_atmu_regs = (struct rio_inb_atmu_regs __iomem *) | ||
704 | (priv->regs_win + | ||
705 | ((i == 0) ? RIO_INB_ATMU_REGS_PORT1_OFFSET : | ||
706 | RIO_INB_ATMU_REGS_PORT2_OFFSET)); | ||
707 | |||
605 | 708 | ||
606 | /* Set to receive any dist ID for serial RapidIO controller. */ | 709 | /* Set to receive any dist ID for serial RapidIO controller. */ |
607 | if (port->phy_type == RIO_PHY_SERIAL) | 710 | if (port->phy_type == RIO_PHY_SERIAL) |
@@ -620,6 +723,7 @@ int fsl_rio_setup(struct platform_device *dev) | |||
620 | rio_law_start = range_start; | 723 | rio_law_start = range_start; |
621 | 724 | ||
622 | fsl_rio_setup_rmu(port, rmu_np[i]); | 725 | fsl_rio_setup_rmu(port, rmu_np[i]); |
726 | fsl_rio_inbound_mem_init(priv); | ||
623 | 727 | ||
624 | dbell->mport[i] = port; | 728 | dbell->mport[i] = port; |
625 | 729 | ||
diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h index ae8e27405a0d..d53407a34f32 100644 --- a/arch/powerpc/sysdev/fsl_rio.h +++ b/arch/powerpc/sysdev/fsl_rio.h | |||
@@ -50,9 +50,12 @@ | |||
50 | #define RIO_S_DBELL_REGS_OFFSET 0x13400 | 50 | #define RIO_S_DBELL_REGS_OFFSET 0x13400 |
51 | #define RIO_S_PW_REGS_OFFSET 0x134e0 | 51 | #define RIO_S_PW_REGS_OFFSET 0x134e0 |
52 | #define RIO_ATMU_REGS_DBELL_OFFSET 0x10C40 | 52 | #define RIO_ATMU_REGS_DBELL_OFFSET 0x10C40 |
53 | #define RIO_INB_ATMU_REGS_PORT1_OFFSET 0x10d60 | ||
54 | #define RIO_INB_ATMU_REGS_PORT2_OFFSET 0x10f60 | ||
53 | 55 | ||
54 | #define MAX_MSG_UNIT_NUM 2 | 56 | #define MAX_MSG_UNIT_NUM 2 |
55 | #define MAX_PORT_NUM 4 | 57 | #define MAX_PORT_NUM 4 |
58 | #define RIO_INB_ATMU_COUNT 4 | ||
56 | 59 | ||
57 | struct rio_atmu_regs { | 60 | struct rio_atmu_regs { |
58 | u32 rowtar; | 61 | u32 rowtar; |
@@ -63,6 +66,15 @@ struct rio_atmu_regs { | |||
63 | u32 pad2[3]; | 66 | u32 pad2[3]; |
64 | }; | 67 | }; |
65 | 68 | ||
69 | struct rio_inb_atmu_regs { | ||
70 | u32 riwtar; | ||
71 | u32 pad1; | ||
72 | u32 riwbar; | ||
73 | u32 pad2; | ||
74 | u32 riwar; | ||
75 | u32 pad3[3]; | ||
76 | }; | ||
77 | |||
66 | struct rio_dbell_ring { | 78 | struct rio_dbell_ring { |
67 | void *virt; | 79 | void *virt; |
68 | dma_addr_t phys; | 80 | dma_addr_t phys; |
@@ -99,6 +111,7 @@ struct rio_priv { | |||
99 | void __iomem *regs_win; | 111 | void __iomem *regs_win; |
100 | struct rio_atmu_regs __iomem *atmu_regs; | 112 | struct rio_atmu_regs __iomem *atmu_regs; |
101 | struct rio_atmu_regs __iomem *maint_atmu_regs; | 113 | struct rio_atmu_regs __iomem *maint_atmu_regs; |
114 | struct rio_inb_atmu_regs __iomem *inb_atmu_regs; | ||
102 | void __iomem *maint_win; | 115 | void __iomem *maint_win; |
103 | void *rmm_handle; /* RapidIO message manager(unit) Handle */ | 116 | void *rmm_handle; /* RapidIO message manager(unit) Handle */ |
104 | }; | 117 | }; |
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index ffd1169ebaab..99269c041615 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -197,8 +197,7 @@ static int __init setup_rstcr(void) | |||
197 | if (!rstcr && ppc_md.restart == fsl_rstcr_restart) | 197 | if (!rstcr && ppc_md.restart == fsl_rstcr_restart) |
198 | printk(KERN_ERR "No RSTCR register, warm reboot won't work\n"); | 198 | printk(KERN_ERR "No RSTCR register, warm reboot won't work\n"); |
199 | 199 | ||
200 | if (np) | 200 | of_node_put(np); |
201 | of_node_put(np); | ||
202 | 201 | ||
203 | return 0; | 202 | return 0; |
204 | } | 203 | } |
@@ -238,7 +237,7 @@ void fsl_hv_restart(char *cmd) | |||
238 | /* | 237 | /* |
239 | * Halt the current partition | 238 | * Halt the current partition |
240 | * | 239 | * |
241 | * This function should be assigned to the ppc_md.power_off and ppc_md.halt | 240 | * This function should be assigned to the pm_power_off and ppc_md.halt |
242 | * function pointers, to shut down the partition when we're running under | 241 | * function pointers, to shut down the partition when we're running under |
243 | * the Freescale hypervisor. | 242 | * the Freescale hypervisor. |
244 | */ | 243 | */ |
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index b50f97811c25..b28733727ed3 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/signal.h> | 20 | #include <linux/signal.h> |
21 | #include <linux/syscore_ops.h> | 21 | #include <linux/syscore_ops.h> |
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/bootmem.h> | ||
24 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
25 | #include <linux/fsl_devices.h> | 24 | #include <linux/fsl_devices.h> |
26 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
diff --git a/arch/powerpc/sysdev/mpc5xxx_clocks.c b/arch/powerpc/sysdev/mpc5xxx_clocks.c index 5492dc5f56f4..f4f0301b9a60 100644 --- a/arch/powerpc/sysdev/mpc5xxx_clocks.c +++ b/arch/powerpc/sysdev/mpc5xxx_clocks.c | |||
@@ -26,8 +26,7 @@ unsigned long mpc5xxx_get_bus_frequency(struct device_node *node) | |||
26 | of_node_put(node); | 26 | of_node_put(node); |
27 | node = np; | 27 | node = np; |
28 | } | 28 | } |
29 | if (node) | 29 | of_node_put(node); |
30 | of_node_put(node); | ||
31 | 30 | ||
32 | return p_bus_freq ? *p_bus_freq : 0; | 31 | return p_bus_freq ? *p_bus_freq : 0; |
33 | } | 32 | } |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 89cec0ed6a58..c4648ad5c1f3 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/smp.h> | 25 | #include <linux/smp.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/bootmem.h> | ||
28 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
29 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
30 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c index 45c114bc430b..a3f660eed6de 100644 --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #undef DEBUG | 16 | #undef DEBUG |
17 | 17 | ||
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/bootmem.h> | ||
20 | #include <linux/msi.h> | 19 | #include <linux/msi.h> |
21 | #include <asm/mpic.h> | 20 | #include <asm/mpic.h> |
22 | #include <asm/prom.h> | 21 | #include <asm/prom.h> |
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index 0dff1cd44481..b2cef1809389 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c | |||
@@ -10,7 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/irq.h> | 12 | #include <linux/irq.h> |
13 | #include <linux/bootmem.h> | ||
14 | #include <linux/msi.h> | 13 | #include <linux/msi.h> |
15 | #include <asm/mpic.h> | 14 | #include <asm/mpic.h> |
16 | #include <asm/prom.h> | 15 | #include <asm/prom.h> |
diff --git a/arch/powerpc/sysdev/ppc4xx_cpm.c b/arch/powerpc/sysdev/ppc4xx_cpm.c index 82e2cfe35c62..ba95adf81d8d 100644 --- a/arch/powerpc/sysdev/ppc4xx_cpm.c +++ b/arch/powerpc/sysdev/ppc4xx_cpm.c | |||
@@ -281,7 +281,7 @@ static int __init cpm_init(void) | |||
281 | printk(KERN_ERR "cpm: could not parse dcr property for %s\n", | 281 | printk(KERN_ERR "cpm: could not parse dcr property for %s\n", |
282 | np->full_name); | 282 | np->full_name); |
283 | ret = -EINVAL; | 283 | ret = -EINVAL; |
284 | goto out; | 284 | goto node_put; |
285 | } | 285 | } |
286 | 286 | ||
287 | cpm.dcr_host = dcr_map(np, dcr_base, dcr_len); | 287 | cpm.dcr_host = dcr_map(np, dcr_base, dcr_len); |
@@ -290,7 +290,7 @@ static int __init cpm_init(void) | |||
290 | printk(KERN_ERR "cpm: failed to map dcr property for %s\n", | 290 | printk(KERN_ERR "cpm: failed to map dcr property for %s\n", |
291 | np->full_name); | 291 | np->full_name); |
292 | ret = -EINVAL; | 292 | ret = -EINVAL; |
293 | goto out; | 293 | goto node_put; |
294 | } | 294 | } |
295 | 295 | ||
296 | /* All 4xx SoCs with a CPM controller have one of two | 296 | /* All 4xx SoCs with a CPM controller have one of two |
@@ -330,9 +330,9 @@ static int __init cpm_init(void) | |||
330 | 330 | ||
331 | if (cpm.standby || cpm.suspend) | 331 | if (cpm.standby || cpm.suspend) |
332 | suspend_set_ops(&cpm_suspend_ops); | 332 | suspend_set_ops(&cpm_suspend_ops); |
333 | node_put: | ||
334 | of_node_put(np); | ||
333 | out: | 335 | out: |
334 | if (np) | ||
335 | of_node_put(np); | ||
336 | return ret; | 336 | return ret; |
337 | } | 337 | } |
338 | 338 | ||
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c index 518eabbe0bdc..5e622c0544c4 100644 --- a/arch/powerpc/sysdev/ppc4xx_msi.c +++ b/arch/powerpc/sysdev/ppc4xx_msi.c | |||
@@ -22,7 +22,6 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/bootmem.h> | ||
26 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
27 | #include <linux/msi.h> | 26 | #include <linux/msi.h> |
28 | #include <linux/of_platform.h> | 27 | #include <linux/of_platform.h> |
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index df6e2fc4ff92..086aca69ecae 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/bootmem.h> | ||
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | 27 | ||
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 238a07b97f2c..b584debbcd9c 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/bootmem.h> | ||
26 | #include <linux/module.h> | 25 | #include <linux/module.h> |
27 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
28 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c index b2b87c30e266..543765e1ef14 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_ic.c +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include <linux/bootmem.h> | ||
27 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
28 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
29 | #include <asm/io.h> | 28 | #include <asm/io.h> |
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index 92033936a8f7..7c37157d4c24 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/signal.h> | 20 | #include <linux/signal.h> |
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/bootmem.h> | ||
23 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
24 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
25 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index fe0cca477164..365249cd346b 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c | |||
@@ -155,7 +155,7 @@ int __init xics_smp_probe(void) | |||
155 | 155 | ||
156 | void xics_teardown_cpu(void) | 156 | void xics_teardown_cpu(void) |
157 | { | 157 | { |
158 | struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr); | 158 | struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr); |
159 | 159 | ||
160 | /* | 160 | /* |
161 | * we have to reset the cppr index to 0 because we're | 161 | * we have to reset the cppr index to 0 because we're |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index c8efbb37d6e0..5b150f0c5df9 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -51,6 +51,12 @@ | |||
51 | #include <asm/paca.h> | 51 | #include <asm/paca.h> |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | #if defined(CONFIG_PPC_SPLPAR) | ||
55 | #include <asm/plpar_wrappers.h> | ||
56 | #else | ||
57 | static inline long plapr_set_ciabr(unsigned long ciabr) {return 0; }; | ||
58 | #endif | ||
59 | |||
54 | #include "nonstdio.h" | 60 | #include "nonstdio.h" |
55 | #include "dis-asm.h" | 61 | #include "dis-asm.h" |
56 | 62 | ||
@@ -88,10 +94,9 @@ struct bpt { | |||
88 | }; | 94 | }; |
89 | 95 | ||
90 | /* Bits in bpt.enabled */ | 96 | /* Bits in bpt.enabled */ |
91 | #define BP_IABR_TE 1 /* IABR translation enabled */ | 97 | #define BP_CIABR 1 |
92 | #define BP_IABR 2 | 98 | #define BP_TRAP 2 |
93 | #define BP_TRAP 8 | 99 | #define BP_DABR 4 |
94 | #define BP_DABR 0x10 | ||
95 | 100 | ||
96 | #define NBPTS 256 | 101 | #define NBPTS 256 |
97 | static struct bpt bpts[NBPTS]; | 102 | static struct bpt bpts[NBPTS]; |
@@ -270,6 +275,45 @@ static inline void cinval(void *p) | |||
270 | asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); | 275 | asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); |
271 | } | 276 | } |
272 | 277 | ||
278 | /** | ||
279 | * write_ciabr() - write the CIABR SPR | ||
280 | * @ciabr: The value to write. | ||
281 | * | ||
282 | * This function writes a value to the CIARB register either directly | ||
283 | * through mtspr instruction if the kernel is in HV privilege mode or | ||
284 | * call a hypervisor function to achieve the same in case the kernel | ||
285 | * is in supervisor privilege mode. | ||
286 | */ | ||
287 | static void write_ciabr(unsigned long ciabr) | ||
288 | { | ||
289 | if (!cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
290 | return; | ||
291 | |||
292 | if (cpu_has_feature(CPU_FTR_HVMODE)) { | ||
293 | mtspr(SPRN_CIABR, ciabr); | ||
294 | return; | ||
295 | } | ||
296 | plapr_set_ciabr(ciabr); | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * set_ciabr() - set the CIABR | ||
301 | * @addr: The value to set. | ||
302 | * | ||
303 | * This function sets the correct privilege value into the the HW | ||
304 | * breakpoint address before writing it up in the CIABR register. | ||
305 | */ | ||
306 | static void set_ciabr(unsigned long addr) | ||
307 | { | ||
308 | addr &= ~CIABR_PRIV; | ||
309 | |||
310 | if (cpu_has_feature(CPU_FTR_HVMODE)) | ||
311 | addr |= CIABR_PRIV_HYPER; | ||
312 | else | ||
313 | addr |= CIABR_PRIV_SUPER; | ||
314 | write_ciabr(addr); | ||
315 | } | ||
316 | |||
273 | /* | 317 | /* |
274 | * Disable surveillance (the service processor watchdog function) | 318 | * Disable surveillance (the service processor watchdog function) |
275 | * while we are in xmon. | 319 | * while we are in xmon. |
@@ -727,7 +771,7 @@ static void insert_bpts(void) | |||
727 | 771 | ||
728 | bp = bpts; | 772 | bp = bpts; |
729 | for (i = 0; i < NBPTS; ++i, ++bp) { | 773 | for (i = 0; i < NBPTS; ++i, ++bp) { |
730 | if ((bp->enabled & (BP_TRAP|BP_IABR)) == 0) | 774 | if ((bp->enabled & (BP_TRAP|BP_CIABR)) == 0) |
731 | continue; | 775 | continue; |
732 | if (mread(bp->address, &bp->instr[0], 4) != 4) { | 776 | if (mread(bp->address, &bp->instr[0], 4) != 4) { |
733 | printf("Couldn't read instruction at %lx, " | 777 | printf("Couldn't read instruction at %lx, " |
@@ -742,7 +786,7 @@ static void insert_bpts(void) | |||
742 | continue; | 786 | continue; |
743 | } | 787 | } |
744 | store_inst(&bp->instr[0]); | 788 | store_inst(&bp->instr[0]); |
745 | if (bp->enabled & BP_IABR) | 789 | if (bp->enabled & BP_CIABR) |
746 | continue; | 790 | continue; |
747 | if (mwrite(bp->address, &bpinstr, 4) != 4) { | 791 | if (mwrite(bp->address, &bpinstr, 4) != 4) { |
748 | printf("Couldn't write instruction at %lx, " | 792 | printf("Couldn't write instruction at %lx, " |
@@ -764,9 +808,9 @@ static void insert_cpu_bpts(void) | |||
764 | brk.len = 8; | 808 | brk.len = 8; |
765 | __set_breakpoint(&brk); | 809 | __set_breakpoint(&brk); |
766 | } | 810 | } |
767 | if (iabr && cpu_has_feature(CPU_FTR_IABR)) | 811 | |
768 | mtspr(SPRN_IABR, iabr->address | 812 | if (iabr) |
769 | | (iabr->enabled & (BP_IABR|BP_IABR_TE))); | 813 | set_ciabr(iabr->address); |
770 | } | 814 | } |
771 | 815 | ||
772 | static void remove_bpts(void) | 816 | static void remove_bpts(void) |
@@ -777,7 +821,7 @@ static void remove_bpts(void) | |||
777 | 821 | ||
778 | bp = bpts; | 822 | bp = bpts; |
779 | for (i = 0; i < NBPTS; ++i, ++bp) { | 823 | for (i = 0; i < NBPTS; ++i, ++bp) { |
780 | if ((bp->enabled & (BP_TRAP|BP_IABR)) != BP_TRAP) | 824 | if ((bp->enabled & (BP_TRAP|BP_CIABR)) != BP_TRAP) |
781 | continue; | 825 | continue; |
782 | if (mread(bp->address, &instr, 4) == 4 | 826 | if (mread(bp->address, &instr, 4) == 4 |
783 | && instr == bpinstr | 827 | && instr == bpinstr |
@@ -792,8 +836,7 @@ static void remove_bpts(void) | |||
792 | static void remove_cpu_bpts(void) | 836 | static void remove_cpu_bpts(void) |
793 | { | 837 | { |
794 | hw_breakpoint_disable(); | 838 | hw_breakpoint_disable(); |
795 | if (cpu_has_feature(CPU_FTR_IABR)) | 839 | write_ciabr(0); |
796 | mtspr(SPRN_IABR, 0); | ||
797 | } | 840 | } |
798 | 841 | ||
799 | /* Command interpreting routine */ | 842 | /* Command interpreting routine */ |
@@ -907,7 +950,7 @@ cmds(struct pt_regs *excp) | |||
907 | case 'u': | 950 | case 'u': |
908 | dump_segments(); | 951 | dump_segments(); |
909 | break; | 952 | break; |
910 | #elif defined(CONFIG_4xx) | 953 | #elif defined(CONFIG_44x) |
911 | case 'u': | 954 | case 'u': |
912 | dump_tlb_44x(); | 955 | dump_tlb_44x(); |
913 | break; | 956 | break; |
@@ -981,7 +1024,8 @@ static void bootcmds(void) | |||
981 | else if (cmd == 'h') | 1024 | else if (cmd == 'h') |
982 | ppc_md.halt(); | 1025 | ppc_md.halt(); |
983 | else if (cmd == 'p') | 1026 | else if (cmd == 'p') |
984 | ppc_md.power_off(); | 1027 | if (pm_power_off) |
1028 | pm_power_off(); | ||
985 | } | 1029 | } |
986 | 1030 | ||
987 | static int cpu_cmd(void) | 1031 | static int cpu_cmd(void) |
@@ -1127,7 +1171,7 @@ static char *breakpoint_help_string = | |||
1127 | "b <addr> [cnt] set breakpoint at given instr addr\n" | 1171 | "b <addr> [cnt] set breakpoint at given instr addr\n" |
1128 | "bc clear all breakpoints\n" | 1172 | "bc clear all breakpoints\n" |
1129 | "bc <n/addr> clear breakpoint number n or at addr\n" | 1173 | "bc <n/addr> clear breakpoint number n or at addr\n" |
1130 | "bi <addr> [cnt] set hardware instr breakpoint (POWER3/RS64 only)\n" | 1174 | "bi <addr> [cnt] set hardware instr breakpoint (POWER8 only)\n" |
1131 | "bd <addr> [cnt] set hardware data breakpoint\n" | 1175 | "bd <addr> [cnt] set hardware data breakpoint\n" |
1132 | ""; | 1176 | ""; |
1133 | 1177 | ||
@@ -1166,13 +1210,13 @@ bpt_cmds(void) | |||
1166 | break; | 1210 | break; |
1167 | 1211 | ||
1168 | case 'i': /* bi - hardware instr breakpoint */ | 1212 | case 'i': /* bi - hardware instr breakpoint */ |
1169 | if (!cpu_has_feature(CPU_FTR_IABR)) { | 1213 | if (!cpu_has_feature(CPU_FTR_ARCH_207S)) { |
1170 | printf("Hardware instruction breakpoint " | 1214 | printf("Hardware instruction breakpoint " |
1171 | "not supported on this cpu\n"); | 1215 | "not supported on this cpu\n"); |
1172 | break; | 1216 | break; |
1173 | } | 1217 | } |
1174 | if (iabr) { | 1218 | if (iabr) { |
1175 | iabr->enabled &= ~(BP_IABR | BP_IABR_TE); | 1219 | iabr->enabled &= ~BP_CIABR; |
1176 | iabr = NULL; | 1220 | iabr = NULL; |
1177 | } | 1221 | } |
1178 | if (!scanhex(&a)) | 1222 | if (!scanhex(&a)) |
@@ -1181,7 +1225,7 @@ bpt_cmds(void) | |||
1181 | break; | 1225 | break; |
1182 | bp = new_breakpoint(a); | 1226 | bp = new_breakpoint(a); |
1183 | if (bp != NULL) { | 1227 | if (bp != NULL) { |
1184 | bp->enabled |= BP_IABR | BP_IABR_TE; | 1228 | bp->enabled |= BP_CIABR; |
1185 | iabr = bp; | 1229 | iabr = bp; |
1186 | } | 1230 | } |
1187 | break; | 1231 | break; |
@@ -1238,7 +1282,7 @@ bpt_cmds(void) | |||
1238 | if (!bp->enabled) | 1282 | if (!bp->enabled) |
1239 | continue; | 1283 | continue; |
1240 | printf("%2x %s ", BP_NUM(bp), | 1284 | printf("%2x %s ", BP_NUM(bp), |
1241 | (bp->enabled & BP_IABR)? "inst": "trap"); | 1285 | (bp->enabled & BP_CIABR) ? "inst": "trap"); |
1242 | xmon_print_symbol(bp->address, " ", "\n"); | 1286 | xmon_print_symbol(bp->address, " ", "\n"); |
1243 | } | 1287 | } |
1244 | break; | 1288 | break; |
diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h index 4236408070e5..6259895fcd97 100644 --- a/arch/s390/include/asm/cmpxchg.h +++ b/arch/s390/include/asm/cmpxchg.h | |||
@@ -11,200 +11,28 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/bug.h> | 12 | #include <linux/bug.h> |
13 | 13 | ||
14 | extern void __xchg_called_with_bad_pointer(void); | 14 | #define cmpxchg(ptr, o, n) \ |
15 | 15 | ({ \ | |
16 | static inline unsigned long __xchg(unsigned long x, void *ptr, int size) | 16 | __typeof__(*(ptr)) __o = (o); \ |
17 | { | 17 | __typeof__(*(ptr)) __n = (n); \ |
18 | unsigned long addr, old; | 18 | (__typeof__(*(ptr))) __sync_val_compare_and_swap((ptr),__o,__n);\ |
19 | int shift; | ||
20 | |||
21 | switch (size) { | ||
22 | case 1: | ||
23 | addr = (unsigned long) ptr; | ||
24 | shift = (3 ^ (addr & 3)) << 3; | ||
25 | addr ^= addr & 3; | ||
26 | asm volatile( | ||
27 | " l %0,%4\n" | ||
28 | "0: lr 0,%0\n" | ||
29 | " nr 0,%3\n" | ||
30 | " or 0,%2\n" | ||
31 | " cs %0,0,%4\n" | ||
32 | " jl 0b\n" | ||
33 | : "=&d" (old), "=Q" (*(int *) addr) | ||
34 | : "d" ((x & 0xff) << shift), "d" (~(0xff << shift)), | ||
35 | "Q" (*(int *) addr) : "memory", "cc", "0"); | ||
36 | return old >> shift; | ||
37 | case 2: | ||
38 | addr = (unsigned long) ptr; | ||
39 | shift = (2 ^ (addr & 2)) << 3; | ||
40 | addr ^= addr & 2; | ||
41 | asm volatile( | ||
42 | " l %0,%4\n" | ||
43 | "0: lr 0,%0\n" | ||
44 | " nr 0,%3\n" | ||
45 | " or 0,%2\n" | ||
46 | " cs %0,0,%4\n" | ||
47 | " jl 0b\n" | ||
48 | : "=&d" (old), "=Q" (*(int *) addr) | ||
49 | : "d" ((x & 0xffff) << shift), "d" (~(0xffff << shift)), | ||
50 | "Q" (*(int *) addr) : "memory", "cc", "0"); | ||
51 | return old >> shift; | ||
52 | case 4: | ||
53 | asm volatile( | ||
54 | " l %0,%3\n" | ||
55 | "0: cs %0,%2,%3\n" | ||
56 | " jl 0b\n" | ||
57 | : "=&d" (old), "=Q" (*(int *) ptr) | ||
58 | : "d" (x), "Q" (*(int *) ptr) | ||
59 | : "memory", "cc"); | ||
60 | return old; | ||
61 | #ifdef CONFIG_64BIT | ||
62 | case 8: | ||
63 | asm volatile( | ||
64 | " lg %0,%3\n" | ||
65 | "0: csg %0,%2,%3\n" | ||
66 | " jl 0b\n" | ||
67 | : "=&d" (old), "=m" (*(long *) ptr) | ||
68 | : "d" (x), "Q" (*(long *) ptr) | ||
69 | : "memory", "cc"); | ||
70 | return old; | ||
71 | #endif /* CONFIG_64BIT */ | ||
72 | } | ||
73 | __xchg_called_with_bad_pointer(); | ||
74 | return x; | ||
75 | } | ||
76 | |||
77 | #define xchg(ptr, x) \ | ||
78 | ({ \ | ||
79 | __typeof__(*(ptr)) __ret; \ | ||
80 | __ret = (__typeof__(*(ptr))) \ | ||
81 | __xchg((unsigned long)(x), (void *)(ptr), sizeof(*(ptr)));\ | ||
82 | __ret; \ | ||
83 | }) | 19 | }) |
84 | 20 | ||
85 | /* | 21 | #define cmpxchg64 cmpxchg |
86 | * Atomic compare and exchange. Compare OLD with MEM, if identical, | 22 | #define cmpxchg_local cmpxchg |
87 | * store NEW in MEM. Return the initial value in MEM. Success is | 23 | #define cmpxchg64_local cmpxchg |
88 | * indicated by comparing RETURN with OLD. | ||
89 | */ | ||
90 | |||
91 | #define __HAVE_ARCH_CMPXCHG | ||
92 | |||
93 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
94 | |||
95 | static inline unsigned long __cmpxchg(void *ptr, unsigned long old, | ||
96 | unsigned long new, int size) | ||
97 | { | ||
98 | unsigned long addr, prev, tmp; | ||
99 | int shift; | ||
100 | |||
101 | switch (size) { | ||
102 | case 1: | ||
103 | addr = (unsigned long) ptr; | ||
104 | shift = (3 ^ (addr & 3)) << 3; | ||
105 | addr ^= addr & 3; | ||
106 | asm volatile( | ||
107 | " l %0,%2\n" | ||
108 | "0: nr %0,%5\n" | ||
109 | " lr %1,%0\n" | ||
110 | " or %0,%3\n" | ||
111 | " or %1,%4\n" | ||
112 | " cs %0,%1,%2\n" | ||
113 | " jnl 1f\n" | ||
114 | " xr %1,%0\n" | ||
115 | " nr %1,%5\n" | ||
116 | " jnz 0b\n" | ||
117 | "1:" | ||
118 | : "=&d" (prev), "=&d" (tmp), "+Q" (*(int *) addr) | ||
119 | : "d" ((old & 0xff) << shift), | ||
120 | "d" ((new & 0xff) << shift), | ||
121 | "d" (~(0xff << shift)) | ||
122 | : "memory", "cc"); | ||
123 | return prev >> shift; | ||
124 | case 2: | ||
125 | addr = (unsigned long) ptr; | ||
126 | shift = (2 ^ (addr & 2)) << 3; | ||
127 | addr ^= addr & 2; | ||
128 | asm volatile( | ||
129 | " l %0,%2\n" | ||
130 | "0: nr %0,%5\n" | ||
131 | " lr %1,%0\n" | ||
132 | " or %0,%3\n" | ||
133 | " or %1,%4\n" | ||
134 | " cs %0,%1,%2\n" | ||
135 | " jnl 1f\n" | ||
136 | " xr %1,%0\n" | ||
137 | " nr %1,%5\n" | ||
138 | " jnz 0b\n" | ||
139 | "1:" | ||
140 | : "=&d" (prev), "=&d" (tmp), "+Q" (*(int *) addr) | ||
141 | : "d" ((old & 0xffff) << shift), | ||
142 | "d" ((new & 0xffff) << shift), | ||
143 | "d" (~(0xffff << shift)) | ||
144 | : "memory", "cc"); | ||
145 | return prev >> shift; | ||
146 | case 4: | ||
147 | asm volatile( | ||
148 | " cs %0,%3,%1\n" | ||
149 | : "=&d" (prev), "=Q" (*(int *) ptr) | ||
150 | : "0" (old), "d" (new), "Q" (*(int *) ptr) | ||
151 | : "memory", "cc"); | ||
152 | return prev; | ||
153 | #ifdef CONFIG_64BIT | ||
154 | case 8: | ||
155 | asm volatile( | ||
156 | " csg %0,%3,%1\n" | ||
157 | : "=&d" (prev), "=Q" (*(long *) ptr) | ||
158 | : "0" (old), "d" (new), "Q" (*(long *) ptr) | ||
159 | : "memory", "cc"); | ||
160 | return prev; | ||
161 | #endif /* CONFIG_64BIT */ | ||
162 | } | ||
163 | __cmpxchg_called_with_bad_pointer(); | ||
164 | return old; | ||
165 | } | ||
166 | |||
167 | #define cmpxchg(ptr, o, n) \ | ||
168 | ({ \ | ||
169 | __typeof__(*(ptr)) __ret; \ | ||
170 | __ret = (__typeof__(*(ptr))) \ | ||
171 | __cmpxchg((ptr), (unsigned long)(o), (unsigned long)(n), \ | ||
172 | sizeof(*(ptr))); \ | ||
173 | __ret; \ | ||
174 | }) | ||
175 | 24 | ||
176 | #ifdef CONFIG_64BIT | 25 | #define xchg(ptr, x) \ |
177 | #define cmpxchg64(ptr, o, n) \ | ||
178 | ({ \ | 26 | ({ \ |
179 | cmpxchg((ptr), (o), (n)); \ | 27 | __typeof__(ptr) __ptr = (ptr); \ |
28 | __typeof__(*(ptr)) __old; \ | ||
29 | do { \ | ||
30 | __old = *__ptr; \ | ||
31 | } while (!__sync_bool_compare_and_swap(__ptr, __old, x)); \ | ||
32 | __old; \ | ||
180 | }) | 33 | }) |
181 | #else /* CONFIG_64BIT */ | ||
182 | static inline unsigned long long __cmpxchg64(void *ptr, | ||
183 | unsigned long long old, | ||
184 | unsigned long long new) | ||
185 | { | ||
186 | register_pair rp_old = {.pair = old}; | ||
187 | register_pair rp_new = {.pair = new}; | ||
188 | unsigned long long *ullptr = ptr; | ||
189 | 34 | ||
190 | asm volatile( | 35 | #define __HAVE_ARCH_CMPXCHG |
191 | " cds %0,%2,%1" | ||
192 | : "+d" (rp_old), "+Q" (*ullptr) | ||
193 | : "d" (rp_new) | ||
194 | : "memory", "cc"); | ||
195 | return rp_old.pair; | ||
196 | } | ||
197 | |||
198 | #define cmpxchg64(ptr, o, n) \ | ||
199 | ({ \ | ||
200 | __typeof__(*(ptr)) __ret; \ | ||
201 | __ret = (__typeof__(*(ptr))) \ | ||
202 | __cmpxchg64((ptr), \ | ||
203 | (unsigned long long)(o), \ | ||
204 | (unsigned long long)(n)); \ | ||
205 | __ret; \ | ||
206 | }) | ||
207 | #endif /* CONFIG_64BIT */ | ||
208 | 36 | ||
209 | #define __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, insn) \ | 37 | #define __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, insn) \ |
210 | ({ \ | 38 | ({ \ |
@@ -265,40 +93,4 @@ extern void __cmpxchg_double_called_with_bad_pointer(void); | |||
265 | 93 | ||
266 | #define system_has_cmpxchg_double() 1 | 94 | #define system_has_cmpxchg_double() 1 |
267 | 95 | ||
268 | #include <asm-generic/cmpxchg-local.h> | ||
269 | |||
270 | static inline unsigned long __cmpxchg_local(void *ptr, | ||
271 | unsigned long old, | ||
272 | unsigned long new, int size) | ||
273 | { | ||
274 | switch (size) { | ||
275 | case 1: | ||
276 | case 2: | ||
277 | case 4: | ||
278 | #ifdef CONFIG_64BIT | ||
279 | case 8: | ||
280 | #endif | ||
281 | return __cmpxchg(ptr, old, new, size); | ||
282 | default: | ||
283 | return __cmpxchg_local_generic(ptr, old, new, size); | ||
284 | } | ||
285 | |||
286 | return old; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make | ||
291 | * them available. | ||
292 | */ | ||
293 | #define cmpxchg_local(ptr, o, n) \ | ||
294 | ({ \ | ||
295 | __typeof__(*(ptr)) __ret; \ | ||
296 | __ret = (__typeof__(*(ptr))) \ | ||
297 | __cmpxchg_local((ptr), (unsigned long)(o), \ | ||
298 | (unsigned long)(n), sizeof(*(ptr))); \ | ||
299 | __ret; \ | ||
300 | }) | ||
301 | |||
302 | #define cmpxchg64_local(ptr, o, n) cmpxchg64((ptr), (o), (n)) | ||
303 | |||
304 | #endif /* __ASM_CMPXCHG_H */ | 96 | #endif /* __ASM_CMPXCHG_H */ |
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index f8c196984853..b91e960e4045 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h | |||
@@ -10,6 +10,8 @@ | |||
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <asm/div64.h> | 11 | #include <asm/div64.h> |
12 | 12 | ||
13 | #define CPUTIME_PER_USEC 4096ULL | ||
14 | #define CPUTIME_PER_SEC (CPUTIME_PER_USEC * USEC_PER_SEC) | ||
13 | 15 | ||
14 | /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ | 16 | /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ |
15 | 17 | ||
@@ -38,24 +40,24 @@ static inline unsigned long __div(unsigned long long n, unsigned long base) | |||
38 | */ | 40 | */ |
39 | static inline unsigned long cputime_to_jiffies(const cputime_t cputime) | 41 | static inline unsigned long cputime_to_jiffies(const cputime_t cputime) |
40 | { | 42 | { |
41 | return __div((__force unsigned long long) cputime, 4096000000ULL / HZ); | 43 | return __div((__force unsigned long long) cputime, CPUTIME_PER_SEC / HZ); |
42 | } | 44 | } |
43 | 45 | ||
44 | static inline cputime_t jiffies_to_cputime(const unsigned int jif) | 46 | static inline cputime_t jiffies_to_cputime(const unsigned int jif) |
45 | { | 47 | { |
46 | return (__force cputime_t)(jif * (4096000000ULL / HZ)); | 48 | return (__force cputime_t)(jif * (CPUTIME_PER_SEC / HZ)); |
47 | } | 49 | } |
48 | 50 | ||
49 | static inline u64 cputime64_to_jiffies64(cputime64_t cputime) | 51 | static inline u64 cputime64_to_jiffies64(cputime64_t cputime) |
50 | { | 52 | { |
51 | unsigned long long jif = (__force unsigned long long) cputime; | 53 | unsigned long long jif = (__force unsigned long long) cputime; |
52 | do_div(jif, 4096000000ULL / HZ); | 54 | do_div(jif, CPUTIME_PER_SEC / HZ); |
53 | return jif; | 55 | return jif; |
54 | } | 56 | } |
55 | 57 | ||
56 | static inline cputime64_t jiffies64_to_cputime64(const u64 jif) | 58 | static inline cputime64_t jiffies64_to_cputime64(const u64 jif) |
57 | { | 59 | { |
58 | return (__force cputime64_t)(jif * (4096000000ULL / HZ)); | 60 | return (__force cputime64_t)(jif * (CPUTIME_PER_SEC / HZ)); |
59 | } | 61 | } |
60 | 62 | ||
61 | /* | 63 | /* |
@@ -68,7 +70,7 @@ static inline unsigned int cputime_to_usecs(const cputime_t cputime) | |||
68 | 70 | ||
69 | static inline cputime_t usecs_to_cputime(const unsigned int m) | 71 | static inline cputime_t usecs_to_cputime(const unsigned int m) |
70 | { | 72 | { |
71 | return (__force cputime_t)(m * 4096ULL); | 73 | return (__force cputime_t)(m * CPUTIME_PER_USEC); |
72 | } | 74 | } |
73 | 75 | ||
74 | #define usecs_to_cputime64(m) usecs_to_cputime(m) | 76 | #define usecs_to_cputime64(m) usecs_to_cputime(m) |
@@ -78,12 +80,12 @@ static inline cputime_t usecs_to_cputime(const unsigned int m) | |||
78 | */ | 80 | */ |
79 | static inline unsigned int cputime_to_secs(const cputime_t cputime) | 81 | static inline unsigned int cputime_to_secs(const cputime_t cputime) |
80 | { | 82 | { |
81 | return __div((__force unsigned long long) cputime, 2048000000) >> 1; | 83 | return __div((__force unsigned long long) cputime, CPUTIME_PER_SEC / 2) >> 1; |
82 | } | 84 | } |
83 | 85 | ||
84 | static inline cputime_t secs_to_cputime(const unsigned int s) | 86 | static inline cputime_t secs_to_cputime(const unsigned int s) |
85 | { | 87 | { |
86 | return (__force cputime_t)(s * 4096000000ULL); | 88 | return (__force cputime_t)(s * CPUTIME_PER_SEC); |
87 | } | 89 | } |
88 | 90 | ||
89 | /* | 91 | /* |
@@ -91,8 +93,8 @@ static inline cputime_t secs_to_cputime(const unsigned int s) | |||
91 | */ | 93 | */ |
92 | static inline cputime_t timespec_to_cputime(const struct timespec *value) | 94 | static inline cputime_t timespec_to_cputime(const struct timespec *value) |
93 | { | 95 | { |
94 | unsigned long long ret = value->tv_sec * 4096000000ULL; | 96 | unsigned long long ret = value->tv_sec * CPUTIME_PER_SEC; |
95 | return (__force cputime_t)(ret + value->tv_nsec * 4096 / 1000); | 97 | return (__force cputime_t)(ret + __div(value->tv_nsec * CPUTIME_PER_USEC, NSEC_PER_USEC)); |
96 | } | 98 | } |
97 | 99 | ||
98 | static inline void cputime_to_timespec(const cputime_t cputime, | 100 | static inline void cputime_to_timespec(const cputime_t cputime, |
@@ -103,12 +105,12 @@ static inline void cputime_to_timespec(const cputime_t cputime, | |||
103 | register_pair rp; | 105 | register_pair rp; |
104 | 106 | ||
105 | rp.pair = __cputime >> 1; | 107 | rp.pair = __cputime >> 1; |
106 | asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL)); | 108 | asm ("dr %0,%1" : "+d" (rp) : "d" (CPUTIME_PER_SEC / 2)); |
107 | value->tv_nsec = rp.subreg.even * 1000 / 4096; | 109 | value->tv_nsec = rp.subreg.even * NSEC_PER_USEC / CPUTIME_PER_USEC; |
108 | value->tv_sec = rp.subreg.odd; | 110 | value->tv_sec = rp.subreg.odd; |
109 | #else | 111 | #else |
110 | value->tv_nsec = (__cputime % 4096000000ULL) * 1000 / 4096; | 112 | value->tv_nsec = (__cputime % CPUTIME_PER_SEC) * NSEC_PER_USEC / CPUTIME_PER_USEC; |
111 | value->tv_sec = __cputime / 4096000000ULL; | 113 | value->tv_sec = __cputime / CPUTIME_PER_SEC; |
112 | #endif | 114 | #endif |
113 | } | 115 | } |
114 | 116 | ||
@@ -119,8 +121,8 @@ static inline void cputime_to_timespec(const cputime_t cputime, | |||
119 | */ | 121 | */ |
120 | static inline cputime_t timeval_to_cputime(const struct timeval *value) | 122 | static inline cputime_t timeval_to_cputime(const struct timeval *value) |
121 | { | 123 | { |
122 | unsigned long long ret = value->tv_sec * 4096000000ULL; | 124 | unsigned long long ret = value->tv_sec * CPUTIME_PER_SEC; |
123 | return (__force cputime_t)(ret + value->tv_usec * 4096ULL); | 125 | return (__force cputime_t)(ret + value->tv_usec * CPUTIME_PER_USEC); |
124 | } | 126 | } |
125 | 127 | ||
126 | static inline void cputime_to_timeval(const cputime_t cputime, | 128 | static inline void cputime_to_timeval(const cputime_t cputime, |
@@ -131,12 +133,12 @@ static inline void cputime_to_timeval(const cputime_t cputime, | |||
131 | register_pair rp; | 133 | register_pair rp; |
132 | 134 | ||
133 | rp.pair = __cputime >> 1; | 135 | rp.pair = __cputime >> 1; |
134 | asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL)); | 136 | asm ("dr %0,%1" : "+d" (rp) : "d" (CPUTIME_PER_USEC / 2)); |
135 | value->tv_usec = rp.subreg.even / 4096; | 137 | value->tv_usec = rp.subreg.even / CPUTIME_PER_USEC; |
136 | value->tv_sec = rp.subreg.odd; | 138 | value->tv_sec = rp.subreg.odd; |
137 | #else | 139 | #else |
138 | value->tv_usec = (__cputime % 4096000000ULL) / 4096; | 140 | value->tv_usec = (__cputime % CPUTIME_PER_SEC) / CPUTIME_PER_USEC; |
139 | value->tv_sec = __cputime / 4096000000ULL; | 141 | value->tv_sec = __cputime / CPUTIME_PER_SEC; |
140 | #endif | 142 | #endif |
141 | } | 143 | } |
142 | 144 | ||
@@ -146,13 +148,13 @@ static inline void cputime_to_timeval(const cputime_t cputime, | |||
146 | static inline clock_t cputime_to_clock_t(cputime_t cputime) | 148 | static inline clock_t cputime_to_clock_t(cputime_t cputime) |
147 | { | 149 | { |
148 | unsigned long long clock = (__force unsigned long long) cputime; | 150 | unsigned long long clock = (__force unsigned long long) cputime; |
149 | do_div(clock, 4096000000ULL / USER_HZ); | 151 | do_div(clock, CPUTIME_PER_SEC / USER_HZ); |
150 | return clock; | 152 | return clock; |
151 | } | 153 | } |
152 | 154 | ||
153 | static inline cputime_t clock_t_to_cputime(unsigned long x) | 155 | static inline cputime_t clock_t_to_cputime(unsigned long x) |
154 | { | 156 | { |
155 | return (__force cputime_t)(x * (4096000000ULL / USER_HZ)); | 157 | return (__force cputime_t)(x * (CPUTIME_PER_SEC / USER_HZ)); |
156 | } | 158 | } |
157 | 159 | ||
158 | /* | 160 | /* |
@@ -161,7 +163,7 @@ static inline cputime_t clock_t_to_cputime(unsigned long x) | |||
161 | static inline clock_t cputime64_to_clock_t(cputime64_t cputime) | 163 | static inline clock_t cputime64_to_clock_t(cputime64_t cputime) |
162 | { | 164 | { |
163 | unsigned long long clock = (__force unsigned long long) cputime; | 165 | unsigned long long clock = (__force unsigned long long) cputime; |
164 | do_div(clock, 4096000000ULL / USER_HZ); | 166 | do_div(clock, CPUTIME_PER_SEC / USER_HZ); |
165 | return clock; | 167 | return clock; |
166 | } | 168 | } |
167 | 169 | ||
diff --git a/arch/s390/include/asm/debug.h b/arch/s390/include/asm/debug.h index 530c15eb01e9..0206c8052328 100644 --- a/arch/s390/include/asm/debug.h +++ b/arch/s390/include/asm/debug.h | |||
@@ -151,9 +151,21 @@ debug_text_event(debug_info_t* id, int level, const char* txt) | |||
151 | * stored in the s390dbf. See Documentation/s390/s390dbf.txt for more details! | 151 | * stored in the s390dbf. See Documentation/s390/s390dbf.txt for more details! |
152 | */ | 152 | */ |
153 | extern debug_entry_t * | 153 | extern debug_entry_t * |
154 | debug_sprintf_event(debug_info_t* id,int level,char *string,...) | 154 | __debug_sprintf_event(debug_info_t *id, int level, char *string, ...) |
155 | __attribute__ ((format(printf, 3, 4))); | 155 | __attribute__ ((format(printf, 3, 4))); |
156 | 156 | ||
157 | #define debug_sprintf_event(_id, _level, _fmt, ...) \ | ||
158 | ({ \ | ||
159 | debug_entry_t *__ret; \ | ||
160 | debug_info_t *__id = _id; \ | ||
161 | int __level = _level; \ | ||
162 | if ((!__id) || (__level > __id->level)) \ | ||
163 | __ret = NULL; \ | ||
164 | else \ | ||
165 | __ret = __debug_sprintf_event(__id, __level, \ | ||
166 | _fmt, ## __VA_ARGS__); \ | ||
167 | __ret; \ | ||
168 | }) | ||
157 | 169 | ||
158 | static inline debug_entry_t* | 170 | static inline debug_entry_t* |
159 | debug_exception(debug_info_t* id, int level, void* data, int length) | 171 | debug_exception(debug_info_t* id, int level, void* data, int length) |
@@ -194,9 +206,22 @@ debug_text_exception(debug_info_t* id, int level, const char* txt) | |||
194 | * stored in the s390dbf. See Documentation/s390/s390dbf.txt for more details! | 206 | * stored in the s390dbf. See Documentation/s390/s390dbf.txt for more details! |
195 | */ | 207 | */ |
196 | extern debug_entry_t * | 208 | extern debug_entry_t * |
197 | debug_sprintf_exception(debug_info_t* id,int level,char *string,...) | 209 | __debug_sprintf_exception(debug_info_t *id, int level, char *string, ...) |
198 | __attribute__ ((format(printf, 3, 4))); | 210 | __attribute__ ((format(printf, 3, 4))); |
199 | 211 | ||
212 | #define debug_sprintf_exception(_id, _level, _fmt, ...) \ | ||
213 | ({ \ | ||
214 | debug_entry_t *__ret; \ | ||
215 | debug_info_t *__id = _id; \ | ||
216 | int __level = _level; \ | ||
217 | if ((!__id) || (__level > __id->level)) \ | ||
218 | __ret = NULL; \ | ||
219 | else \ | ||
220 | __ret = __debug_sprintf_exception(__id, __level, \ | ||
221 | _fmt, ## __VA_ARGS__);\ | ||
222 | __ret; \ | ||
223 | }) | ||
224 | |||
200 | int debug_register_view(debug_info_t* id, struct debug_view* view); | 225 | int debug_register_view(debug_info_t* id, struct debug_view* view); |
201 | int debug_unregister_view(debug_info_t* id, struct debug_view* view); | 226 | int debug_unregister_view(debug_info_t* id, struct debug_view* view); |
202 | 227 | ||
diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h index 3aef8afec336..abb618f1ead2 100644 --- a/arch/s390/include/asm/ftrace.h +++ b/arch/s390/include/asm/ftrace.h | |||
@@ -1,25 +1,69 @@ | |||
1 | #ifndef _ASM_S390_FTRACE_H | 1 | #ifndef _ASM_S390_FTRACE_H |
2 | #define _ASM_S390_FTRACE_H | 2 | #define _ASM_S390_FTRACE_H |
3 | 3 | ||
4 | #define ARCH_SUPPORTS_FTRACE_OPS 1 | ||
5 | |||
6 | #define MCOUNT_INSN_SIZE 24 | ||
7 | #define MCOUNT_RETURN_FIXUP 18 | ||
8 | |||
4 | #ifndef __ASSEMBLY__ | 9 | #ifndef __ASSEMBLY__ |
5 | 10 | ||
6 | extern void _mcount(void); | 11 | #define ftrace_return_address(n) __builtin_return_address(n) |
12 | |||
13 | void _mcount(void); | ||
14 | void ftrace_caller(void); | ||
15 | |||
7 | extern char ftrace_graph_caller_end; | 16 | extern char ftrace_graph_caller_end; |
17 | extern unsigned long ftrace_plt; | ||
8 | 18 | ||
9 | struct dyn_arch_ftrace { }; | 19 | struct dyn_arch_ftrace { }; |
10 | 20 | ||
11 | #define MCOUNT_ADDR ((long)_mcount) | 21 | #define MCOUNT_ADDR ((unsigned long)_mcount) |
22 | #define FTRACE_ADDR ((unsigned long)ftrace_caller) | ||
12 | 23 | ||
24 | #define KPROBE_ON_FTRACE_NOP 0 | ||
25 | #define KPROBE_ON_FTRACE_CALL 1 | ||
13 | 26 | ||
14 | static inline unsigned long ftrace_call_adjust(unsigned long addr) | 27 | static inline unsigned long ftrace_call_adjust(unsigned long addr) |
15 | { | 28 | { |
16 | return addr; | 29 | return addr; |
17 | } | 30 | } |
18 | 31 | ||
19 | #endif /* __ASSEMBLY__ */ | 32 | struct ftrace_insn { |
33 | u16 opc; | ||
34 | s32 disp; | ||
35 | } __packed; | ||
36 | |||
37 | static inline void ftrace_generate_nop_insn(struct ftrace_insn *insn) | ||
38 | { | ||
39 | #ifdef CONFIG_FUNCTION_TRACER | ||
40 | /* jg .+24 */ | ||
41 | insn->opc = 0xc0f4; | ||
42 | insn->disp = MCOUNT_INSN_SIZE / 2; | ||
43 | #endif | ||
44 | } | ||
20 | 45 | ||
21 | #define MCOUNT_INSN_SIZE 18 | 46 | static inline int is_ftrace_nop(struct ftrace_insn *insn) |
47 | { | ||
48 | #ifdef CONFIG_FUNCTION_TRACER | ||
49 | if (insn->disp == MCOUNT_INSN_SIZE / 2) | ||
50 | return 1; | ||
51 | #endif | ||
52 | return 0; | ||
53 | } | ||
22 | 54 | ||
23 | #define ARCH_SUPPORTS_FTRACE_OPS 1 | 55 | static inline void ftrace_generate_call_insn(struct ftrace_insn *insn, |
56 | unsigned long ip) | ||
57 | { | ||
58 | #ifdef CONFIG_FUNCTION_TRACER | ||
59 | unsigned long target; | ||
60 | |||
61 | /* brasl r0,ftrace_caller */ | ||
62 | target = is_module_addr((void *) ip) ? ftrace_plt : FTRACE_ADDR; | ||
63 | insn->opc = 0xc005; | ||
64 | insn->disp = (target - ip) / 2; | ||
65 | #endif | ||
66 | } | ||
24 | 67 | ||
68 | #endif /* __ASSEMBLY__ */ | ||
25 | #endif /* _ASM_S390_FTRACE_H */ | 69 | #endif /* _ASM_S390_FTRACE_H */ |
diff --git a/arch/s390/include/asm/idle.h b/arch/s390/include/asm/idle.h index 6af037f574b8..113cd963dbbe 100644 --- a/arch/s390/include/asm/idle.h +++ b/arch/s390/include/asm/idle.h | |||
@@ -9,9 +9,10 @@ | |||
9 | 9 | ||
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/seqlock.h> | ||
12 | 13 | ||
13 | struct s390_idle_data { | 14 | struct s390_idle_data { |
14 | unsigned int sequence; | 15 | seqcount_t seqcount; |
15 | unsigned long long idle_count; | 16 | unsigned long long idle_count; |
16 | unsigned long long idle_time; | 17 | unsigned long long idle_time; |
17 | unsigned long long clock_idle_enter; | 18 | unsigned long long clock_idle_enter; |
diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h index 6ad9013c67e7..30fd5c84680e 100644 --- a/arch/s390/include/asm/io.h +++ b/arch/s390/include/asm/io.h | |||
@@ -39,6 +39,15 @@ static inline void iounmap(volatile void __iomem *addr) | |||
39 | { | 39 | { |
40 | } | 40 | } |
41 | 41 | ||
42 | static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) | ||
43 | { | ||
44 | return NULL; | ||
45 | } | ||
46 | |||
47 | static inline void ioport_unmap(void __iomem *p) | ||
48 | { | ||
49 | } | ||
50 | |||
42 | /* | 51 | /* |
43 | * s390 needs a private implementation of pci_iomap since ioremap with its | 52 | * s390 needs a private implementation of pci_iomap since ioremap with its |
44 | * offset parameter isn't sufficient. That's because BAR spaces are not | 53 | * offset parameter isn't sufficient. That's because BAR spaces are not |
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index b0d5f0a97a01..343ea7c987aa 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h | |||
@@ -1,11 +1,11 @@ | |||
1 | #ifndef _ASM_IRQ_H | 1 | #ifndef _ASM_IRQ_H |
2 | #define _ASM_IRQ_H | 2 | #define _ASM_IRQ_H |
3 | 3 | ||
4 | #define EXT_INTERRUPT 1 | 4 | #define EXT_INTERRUPT 0 |
5 | #define IO_INTERRUPT 2 | 5 | #define IO_INTERRUPT 1 |
6 | #define THIN_INTERRUPT 3 | 6 | #define THIN_INTERRUPT 2 |
7 | 7 | ||
8 | #define NR_IRQS_BASE 4 | 8 | #define NR_IRQS_BASE 3 |
9 | 9 | ||
10 | #ifdef CONFIG_PCI_NR_MSI | 10 | #ifdef CONFIG_PCI_NR_MSI |
11 | # define NR_IRQS (NR_IRQS_BASE + CONFIG_PCI_NR_MSI) | 11 | # define NR_IRQS (NR_IRQS_BASE + CONFIG_PCI_NR_MSI) |
@@ -13,9 +13,6 @@ | |||
13 | # define NR_IRQS NR_IRQS_BASE | 13 | # define NR_IRQS NR_IRQS_BASE |
14 | #endif | 14 | #endif |
15 | 15 | ||
16 | /* This number is used when no interrupt has been assigned */ | ||
17 | #define NO_IRQ 0 | ||
18 | |||
19 | /* External interruption codes */ | 16 | /* External interruption codes */ |
20 | #define EXT_IRQ_INTERRUPT_KEY 0x0040 | 17 | #define EXT_IRQ_INTERRUPT_KEY 0x0040 |
21 | #define EXT_IRQ_CLK_COMP 0x1004 | 18 | #define EXT_IRQ_CLK_COMP 0x1004 |
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h index 98629173ce3b..b47ad3b642cc 100644 --- a/arch/s390/include/asm/kprobes.h +++ b/arch/s390/include/asm/kprobes.h | |||
@@ -60,6 +60,7 @@ typedef u16 kprobe_opcode_t; | |||
60 | struct arch_specific_insn { | 60 | struct arch_specific_insn { |
61 | /* copy of original instruction */ | 61 | /* copy of original instruction */ |
62 | kprobe_opcode_t *insn; | 62 | kprobe_opcode_t *insn; |
63 | unsigned int is_ftrace_insn : 1; | ||
63 | }; | 64 | }; |
64 | 65 | ||
65 | struct prev_kprobe { | 66 | struct prev_kprobe { |
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 6cc51fe84410..34fbcac61133 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h | |||
@@ -147,7 +147,7 @@ struct _lowcore { | |||
147 | __u32 softirq_pending; /* 0x02ec */ | 147 | __u32 softirq_pending; /* 0x02ec */ |
148 | __u32 percpu_offset; /* 0x02f0 */ | 148 | __u32 percpu_offset; /* 0x02f0 */ |
149 | __u32 machine_flags; /* 0x02f4 */ | 149 | __u32 machine_flags; /* 0x02f4 */ |
150 | __u32 ftrace_func; /* 0x02f8 */ | 150 | __u8 pad_0x02f8[0x02fc-0x02f8]; /* 0x02f8 */ |
151 | __u32 spinlock_lockval; /* 0x02fc */ | 151 | __u32 spinlock_lockval; /* 0x02fc */ |
152 | 152 | ||
153 | __u8 pad_0x0300[0x0e00-0x0300]; /* 0x0300 */ | 153 | __u8 pad_0x0300[0x0e00-0x0300]; /* 0x0300 */ |
@@ -297,7 +297,7 @@ struct _lowcore { | |||
297 | __u64 percpu_offset; /* 0x0378 */ | 297 | __u64 percpu_offset; /* 0x0378 */ |
298 | __u64 vdso_per_cpu_data; /* 0x0380 */ | 298 | __u64 vdso_per_cpu_data; /* 0x0380 */ |
299 | __u64 machine_flags; /* 0x0388 */ | 299 | __u64 machine_flags; /* 0x0388 */ |
300 | __u64 ftrace_func; /* 0x0390 */ | 300 | __u8 pad_0x0390[0x0398-0x0390]; /* 0x0390 */ |
301 | __u64 gmap; /* 0x0398 */ | 301 | __u64 gmap; /* 0x0398 */ |
302 | __u32 spinlock_lockval; /* 0x03a0 */ | 302 | __u32 spinlock_lockval; /* 0x03a0 */ |
303 | __u8 pad_0x03a0[0x0400-0x03a4]; /* 0x03a4 */ | 303 | __u8 pad_0x03a0[0x0400-0x03a4]; /* 0x03a4 */ |
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index c030900320e0..ef803c202d42 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h | |||
@@ -50,10 +50,6 @@ struct zpci_fmb { | |||
50 | atomic64_t unmapped_pages; | 50 | atomic64_t unmapped_pages; |
51 | } __packed __aligned(16); | 51 | } __packed __aligned(16); |
52 | 52 | ||
53 | #define ZPCI_MSI_VEC_BITS 11 | ||
54 | #define ZPCI_MSI_VEC_MAX (1 << ZPCI_MSI_VEC_BITS) | ||
55 | #define ZPCI_MSI_VEC_MASK (ZPCI_MSI_VEC_MAX - 1) | ||
56 | |||
57 | enum zpci_state { | 53 | enum zpci_state { |
58 | ZPCI_FN_STATE_RESERVED, | 54 | ZPCI_FN_STATE_RESERVED, |
59 | ZPCI_FN_STATE_STANDBY, | 55 | ZPCI_FN_STATE_STANDBY, |
@@ -90,6 +86,7 @@ struct zpci_dev { | |||
90 | 86 | ||
91 | /* IRQ stuff */ | 87 | /* IRQ stuff */ |
92 | u64 msi_addr; /* MSI address */ | 88 | u64 msi_addr; /* MSI address */ |
89 | unsigned int max_msi; /* maximum number of MSI's */ | ||
93 | struct airq_iv *aibv; /* adapter interrupt bit vector */ | 90 | struct airq_iv *aibv; /* adapter interrupt bit vector */ |
94 | unsigned int aisb; /* number of the summary bit */ | 91 | unsigned int aisb; /* number of the summary bit */ |
95 | 92 | ||
diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h index d194d544d694..f664e96f48c7 100644 --- a/arch/s390/include/asm/pci_io.h +++ b/arch/s390/include/asm/pci_io.h | |||
@@ -139,7 +139,8 @@ static inline int zpci_memcpy_fromio(void *dst, | |||
139 | int size, rc = 0; | 139 | int size, rc = 0; |
140 | 140 | ||
141 | while (n > 0) { | 141 | while (n > 0) { |
142 | size = zpci_get_max_write_size((u64) src, (u64) dst, n, 8); | 142 | size = zpci_get_max_write_size((u64 __force) src, |
143 | (u64) dst, n, 8); | ||
143 | req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size); | 144 | req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size); |
144 | rc = zpci_read_single(req, dst, offset, size); | 145 | rc = zpci_read_single(req, dst, offset, size); |
145 | if (rc) | 146 | if (rc) |
@@ -162,7 +163,8 @@ static inline int zpci_memcpy_toio(volatile void __iomem *dst, | |||
162 | return -EINVAL; | 163 | return -EINVAL; |
163 | 164 | ||
164 | while (n > 0) { | 165 | while (n > 0) { |
165 | size = zpci_get_max_write_size((u64) dst, (u64) src, n, 128); | 166 | size = zpci_get_max_write_size((u64 __force) dst, |
167 | (u64) src, n, 128); | ||
166 | req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size); | 168 | req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size); |
167 | 169 | ||
168 | if (size > 8) /* main path */ | 170 | if (size > 8) /* main path */ |
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index d39a31c3cdf2..e510b9460efa 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h | |||
@@ -22,8 +22,6 @@ unsigned long *page_table_alloc(struct mm_struct *); | |||
22 | void page_table_free(struct mm_struct *, unsigned long *); | 22 | void page_table_free(struct mm_struct *, unsigned long *); |
23 | void page_table_free_rcu(struct mmu_gather *, unsigned long *, unsigned long); | 23 | void page_table_free_rcu(struct mmu_gather *, unsigned long *, unsigned long); |
24 | 24 | ||
25 | void page_table_reset_pgste(struct mm_struct *, unsigned long, unsigned long, | ||
26 | bool init_skey); | ||
27 | int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, | 25 | int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, |
28 | unsigned long key, bool nq); | 26 | unsigned long key, bool nq); |
29 | 27 | ||
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 57c882761dea..5e102422c9ab 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
@@ -133,6 +133,18 @@ extern unsigned long MODULES_END; | |||
133 | #define MODULES_LEN (1UL << 31) | 133 | #define MODULES_LEN (1UL << 31) |
134 | #endif | 134 | #endif |
135 | 135 | ||
136 | static inline int is_module_addr(void *addr) | ||
137 | { | ||
138 | #ifdef CONFIG_64BIT | ||
139 | BUILD_BUG_ON(MODULES_LEN > (1UL << 31)); | ||
140 | if (addr < (void *)MODULES_VADDR) | ||
141 | return 0; | ||
142 | if (addr > (void *)MODULES_END) | ||
143 | return 0; | ||
144 | #endif | ||
145 | return 1; | ||
146 | } | ||
147 | |||
136 | /* | 148 | /* |
137 | * A 31 bit pagetable entry of S390 has following format: | 149 | * A 31 bit pagetable entry of S390 has following format: |
138 | * | PFRA | | OS | | 150 | * | PFRA | | OS | |
@@ -479,6 +491,11 @@ static inline int mm_has_pgste(struct mm_struct *mm) | |||
479 | return 0; | 491 | return 0; |
480 | } | 492 | } |
481 | 493 | ||
494 | /* | ||
495 | * In the case that a guest uses storage keys | ||
496 | * faults should no longer be backed by zero pages | ||
497 | */ | ||
498 | #define mm_forbids_zeropage mm_use_skey | ||
482 | static inline int mm_use_skey(struct mm_struct *mm) | 499 | static inline int mm_use_skey(struct mm_struct *mm) |
483 | { | 500 | { |
484 | #ifdef CONFIG_PGSTE | 501 | #ifdef CONFIG_PGSTE |
@@ -1634,6 +1651,19 @@ static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, | |||
1634 | return pmd; | 1651 | return pmd; |
1635 | } | 1652 | } |
1636 | 1653 | ||
1654 | #define __HAVE_ARCH_PMDP_GET_AND_CLEAR_FULL | ||
1655 | static inline pmd_t pmdp_get_and_clear_full(struct mm_struct *mm, | ||
1656 | unsigned long address, | ||
1657 | pmd_t *pmdp, int full) | ||
1658 | { | ||
1659 | pmd_t pmd = *pmdp; | ||
1660 | |||
1661 | if (!full) | ||
1662 | pmdp_flush_lazy(mm, address, pmdp); | ||
1663 | pmd_clear(pmdp); | ||
1664 | return pmd; | ||
1665 | } | ||
1666 | |||
1637 | #define __HAVE_ARCH_PMDP_CLEAR_FLUSH | 1667 | #define __HAVE_ARCH_PMDP_CLEAR_FLUSH |
1638 | static inline pmd_t pmdp_clear_flush(struct vm_area_struct *vma, | 1668 | static inline pmd_t pmdp_clear_flush(struct vm_area_struct *vma, |
1639 | unsigned long address, pmd_t *pmdp) | 1669 | unsigned long address, pmd_t *pmdp) |
@@ -1746,7 +1776,8 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) | |||
1746 | extern int vmem_add_mapping(unsigned long start, unsigned long size); | 1776 | extern int vmem_add_mapping(unsigned long start, unsigned long size); |
1747 | extern int vmem_remove_mapping(unsigned long start, unsigned long size); | 1777 | extern int vmem_remove_mapping(unsigned long start, unsigned long size); |
1748 | extern int s390_enable_sie(void); | 1778 | extern int s390_enable_sie(void); |
1749 | extern void s390_enable_skey(void); | 1779 | extern int s390_enable_skey(void); |
1780 | extern void s390_reset_cmma(struct mm_struct *mm); | ||
1750 | 1781 | ||
1751 | /* | 1782 | /* |
1752 | * No page table caches to initialise | 1783 | * No page table caches to initialise |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index d559bdb03d18..bed05ea7ec27 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -217,8 +217,6 @@ static inline unsigned short stap(void) | |||
217 | */ | 217 | */ |
218 | static inline void cpu_relax(void) | 218 | static inline void cpu_relax(void) |
219 | { | 219 | { |
220 | if (MACHINE_HAS_DIAG44) | ||
221 | asm volatile("diag 0,0,68"); | ||
222 | barrier(); | 220 | barrier(); |
223 | } | 221 | } |
224 | 222 | ||
diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h index d6bdf906caa5..0e37cd041241 100644 --- a/arch/s390/include/asm/spinlock.h +++ b/arch/s390/include/asm/spinlock.h | |||
@@ -18,14 +18,7 @@ extern int spin_retry; | |||
18 | static inline int | 18 | static inline int |
19 | _raw_compare_and_swap(unsigned int *lock, unsigned int old, unsigned int new) | 19 | _raw_compare_and_swap(unsigned int *lock, unsigned int old, unsigned int new) |
20 | { | 20 | { |
21 | unsigned int old_expected = old; | 21 | return __sync_bool_compare_and_swap(lock, old, new); |
22 | |||
23 | asm volatile( | ||
24 | " cs %0,%3,%1" | ||
25 | : "=d" (old), "=Q" (*lock) | ||
26 | : "0" (old), "d" (new), "Q" (*lock) | ||
27 | : "cc", "memory" ); | ||
28 | return old == old_expected; | ||
29 | } | 22 | } |
30 | 23 | ||
31 | /* | 24 | /* |
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h index 572c59949004..06d8741ad6f4 100644 --- a/arch/s390/include/asm/tlb.h +++ b/arch/s390/include/asm/tlb.h | |||
@@ -121,6 +121,7 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, | |||
121 | #ifdef CONFIG_64BIT | 121 | #ifdef CONFIG_64BIT |
122 | if (tlb->mm->context.asce_limit <= (1UL << 31)) | 122 | if (tlb->mm->context.asce_limit <= (1UL << 31)) |
123 | return; | 123 | return; |
124 | pgtable_pmd_page_dtor(virt_to_page(pmd)); | ||
124 | tlb_remove_table(tlb, pmd); | 125 | tlb_remove_table(tlb, pmd); |
125 | #endif | 126 | #endif |
126 | } | 127 | } |
diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h index 4197c89c52d4..2b446cf0cc65 100644 --- a/arch/s390/include/uapi/asm/unistd.h +++ b/arch/s390/include/uapi/asm/unistd.h | |||
@@ -287,7 +287,9 @@ | |||
287 | #define __NR_getrandom 349 | 287 | #define __NR_getrandom 349 |
288 | #define __NR_memfd_create 350 | 288 | #define __NR_memfd_create 350 |
289 | #define __NR_bpf 351 | 289 | #define __NR_bpf 351 |
290 | #define NR_syscalls 352 | 290 | #define __NR_s390_pci_mmio_write 352 |
291 | #define __NR_s390_pci_mmio_read 353 | ||
292 | #define NR_syscalls 354 | ||
291 | 293 | ||
292 | /* | 294 | /* |
293 | * There are some system calls that are not present on 64 bit, some | 295 | * There are some system calls that are not present on 64 bit, some |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index ef279a136801..e07e91605353 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
@@ -17,8 +17,8 @@ | |||
17 | * Make sure that the compiler is new enough. We want a compiler that | 17 | * Make sure that the compiler is new enough. We want a compiler that |
18 | * is known to work with the "Q" assembler constraint. | 18 | * is known to work with the "Q" assembler constraint. |
19 | */ | 19 | */ |
20 | #if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) | 20 | #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) |
21 | #error Your compiler is too old; please use version 3.3.3 or newer | 21 | #error Your compiler is too old; please use version 4.3 or newer |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | int main(void) | 24 | int main(void) |
@@ -156,7 +156,6 @@ int main(void) | |||
156 | DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); | 156 | DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); |
157 | DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); | 157 | DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); |
158 | DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); | 158 | DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); |
159 | DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func)); | ||
160 | DEFINE(__LC_DUMP_REIPL, offsetof(struct _lowcore, ipib)); | 159 | DEFINE(__LC_DUMP_REIPL, offsetof(struct _lowcore, ipib)); |
161 | BLANK(); | 160 | BLANK(); |
162 | DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area)); | 161 | DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area)); |
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 009f5eb11125..34d5fa7b01b5 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c | |||
@@ -434,7 +434,7 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set, | |||
434 | ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE; | 434 | ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE; |
435 | } else { | 435 | } else { |
436 | /* Signal frames without vectors registers are short ! */ | 436 | /* Signal frames without vectors registers are short ! */ |
437 | __u16 __user *svc = (void *) frame + frame_size - 2; | 437 | __u16 __user *svc = (void __user *) frame + frame_size - 2; |
438 | if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc)) | 438 | if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc)) |
439 | return -EFAULT; | 439 | return -EFAULT; |
440 | restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE; | 440 | restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE; |
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c index c4f7a3d655b8..d7fa2f0f1425 100644 --- a/arch/s390/kernel/compat_wrapper.c +++ b/arch/s390/kernel/compat_wrapper.c | |||
@@ -218,3 +218,5 @@ COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char | |||
218 | COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags) | 218 | COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags) |
219 | COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags) | 219 | COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags) |
220 | COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size); | 220 | COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size); |
221 | COMPAT_SYSCALL_WRAP3(s390_pci_mmio_write, const unsigned long, mmio_addr, const void __user *, user_buffer, const size_t, length); | ||
222 | COMPAT_SYSCALL_WRAP3(s390_pci_mmio_read, const unsigned long, mmio_addr, void __user *, user_buffer, const size_t, length); | ||
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index ee8390da6ea7..c1f21aca76e7 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c | |||
@@ -1019,7 +1019,7 @@ debug_count_numargs(char *string) | |||
1019 | */ | 1019 | */ |
1020 | 1020 | ||
1021 | debug_entry_t* | 1021 | debug_entry_t* |
1022 | debug_sprintf_event(debug_info_t* id, int level,char *string,...) | 1022 | __debug_sprintf_event(debug_info_t *id, int level, char *string, ...) |
1023 | { | 1023 | { |
1024 | va_list ap; | 1024 | va_list ap; |
1025 | int numargs,idx; | 1025 | int numargs,idx; |
@@ -1027,8 +1027,6 @@ debug_sprintf_event(debug_info_t* id, int level,char *string,...) | |||
1027 | debug_sprintf_entry_t *curr_event; | 1027 | debug_sprintf_entry_t *curr_event; |
1028 | debug_entry_t *active; | 1028 | debug_entry_t *active; |
1029 | 1029 | ||
1030 | if((!id) || (level > id->level)) | ||
1031 | return NULL; | ||
1032 | if (!debug_active || !id->areas) | 1030 | if (!debug_active || !id->areas) |
1033 | return NULL; | 1031 | return NULL; |
1034 | numargs=debug_count_numargs(string); | 1032 | numargs=debug_count_numargs(string); |
@@ -1050,14 +1048,14 @@ debug_sprintf_event(debug_info_t* id, int level,char *string,...) | |||
1050 | 1048 | ||
1051 | return active; | 1049 | return active; |
1052 | } | 1050 | } |
1053 | EXPORT_SYMBOL(debug_sprintf_event); | 1051 | EXPORT_SYMBOL(__debug_sprintf_event); |
1054 | 1052 | ||
1055 | /* | 1053 | /* |
1056 | * debug_sprintf_exception: | 1054 | * debug_sprintf_exception: |
1057 | */ | 1055 | */ |
1058 | 1056 | ||
1059 | debug_entry_t* | 1057 | debug_entry_t* |
1060 | debug_sprintf_exception(debug_info_t* id, int level,char *string,...) | 1058 | __debug_sprintf_exception(debug_info_t *id, int level, char *string, ...) |
1061 | { | 1059 | { |
1062 | va_list ap; | 1060 | va_list ap; |
1063 | int numargs,idx; | 1061 | int numargs,idx; |
@@ -1065,8 +1063,6 @@ debug_sprintf_exception(debug_info_t* id, int level,char *string,...) | |||
1065 | debug_sprintf_entry_t *curr_event; | 1063 | debug_sprintf_entry_t *curr_event; |
1066 | debug_entry_t *active; | 1064 | debug_entry_t *active; |
1067 | 1065 | ||
1068 | if((!id) || (level > id->level)) | ||
1069 | return NULL; | ||
1070 | if (!debug_active || !id->areas) | 1066 | if (!debug_active || !id->areas) |
1071 | return NULL; | 1067 | return NULL; |
1072 | 1068 | ||
@@ -1089,7 +1085,7 @@ debug_sprintf_exception(debug_info_t* id, int level,char *string,...) | |||
1089 | 1085 | ||
1090 | return active; | 1086 | return active; |
1091 | } | 1087 | } |
1092 | EXPORT_SYMBOL(debug_sprintf_exception); | 1088 | EXPORT_SYMBOL(__debug_sprintf_exception); |
1093 | 1089 | ||
1094 | /* | 1090 | /* |
1095 | * debug_register_view: | 1091 | * debug_register_view: |
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c index acb412442e5e..a99852e96a77 100644 --- a/arch/s390/kernel/dumpstack.c +++ b/arch/s390/kernel/dumpstack.c | |||
@@ -191,7 +191,8 @@ void die(struct pt_regs *regs, const char *str) | |||
191 | console_verbose(); | 191 | console_verbose(); |
192 | spin_lock_irq(&die_lock); | 192 | spin_lock_irq(&die_lock); |
193 | bust_spinlocks(1); | 193 | bust_spinlocks(1); |
194 | printk("%s: %04x [#%d] ", str, regs->int_code & 0xffff, ++die_counter); | 194 | printk("%s: %04x ilc:%d [#%d] ", str, regs->int_code & 0xffff, |
195 | regs->int_code >> 17, ++die_counter); | ||
195 | #ifdef CONFIG_PREEMPT | 196 | #ifdef CONFIG_PREEMPT |
196 | printk("PREEMPT "); | 197 | printk("PREEMPT "); |
197 | #endif | 198 | #endif |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index cef2879edff3..302ac1f7f8e7 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
15 | #include <linux/ftrace.h> | ||
16 | #include <linux/lockdep.h> | 15 | #include <linux/lockdep.h> |
17 | #include <linux/module.h> | 16 | #include <linux/module.h> |
18 | #include <linux/pfn.h> | 17 | #include <linux/pfn.h> |
@@ -490,8 +489,5 @@ void __init startup_init(void) | |||
490 | detect_machine_facilities(); | 489 | detect_machine_facilities(); |
491 | setup_topology(); | 490 | setup_topology(); |
492 | sclp_early_detect(); | 491 | sclp_early_detect(); |
493 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
494 | S390_lowcore.ftrace_func = (unsigned long)ftrace_caller; | ||
495 | #endif | ||
496 | lockdep_on(); | 492 | lockdep_on(); |
497 | } | 493 | } |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 70203265196f..398329b2b518 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -53,7 +53,7 @@ _PIF_WORK = (_PIF_PER_TRAP) | |||
53 | .macro TRACE_IRQS_ON | 53 | .macro TRACE_IRQS_ON |
54 | #ifdef CONFIG_TRACE_IRQFLAGS | 54 | #ifdef CONFIG_TRACE_IRQFLAGS |
55 | basr %r2,%r0 | 55 | basr %r2,%r0 |
56 | l %r1,BASED(.Lhardirqs_on) | 56 | l %r1,BASED(.Lc_hardirqs_on) |
57 | basr %r14,%r1 # call trace_hardirqs_on_caller | 57 | basr %r14,%r1 # call trace_hardirqs_on_caller |
58 | #endif | 58 | #endif |
59 | .endm | 59 | .endm |
@@ -61,7 +61,7 @@ _PIF_WORK = (_PIF_PER_TRAP) | |||
61 | .macro TRACE_IRQS_OFF | 61 | .macro TRACE_IRQS_OFF |
62 | #ifdef CONFIG_TRACE_IRQFLAGS | 62 | #ifdef CONFIG_TRACE_IRQFLAGS |
63 | basr %r2,%r0 | 63 | basr %r2,%r0 |
64 | l %r1,BASED(.Lhardirqs_off) | 64 | l %r1,BASED(.Lc_hardirqs_off) |
65 | basr %r14,%r1 # call trace_hardirqs_off_caller | 65 | basr %r14,%r1 # call trace_hardirqs_off_caller |
66 | #endif | 66 | #endif |
67 | .endm | 67 | .endm |
@@ -70,7 +70,7 @@ _PIF_WORK = (_PIF_PER_TRAP) | |||
70 | #ifdef CONFIG_LOCKDEP | 70 | #ifdef CONFIG_LOCKDEP |
71 | tm __PT_PSW+1(%r11),0x01 # returning to user ? | 71 | tm __PT_PSW+1(%r11),0x01 # returning to user ? |
72 | jz .+10 | 72 | jz .+10 |
73 | l %r1,BASED(.Llockdep_sys_exit) | 73 | l %r1,BASED(.Lc_lockdep_sys_exit) |
74 | basr %r14,%r1 # call lockdep_sys_exit | 74 | basr %r14,%r1 # call lockdep_sys_exit |
75 | #endif | 75 | #endif |
76 | .endm | 76 | .endm |
@@ -87,8 +87,8 @@ _PIF_WORK = (_PIF_PER_TRAP) | |||
87 | tmh %r8,0x0001 # interrupting from user ? | 87 | tmh %r8,0x0001 # interrupting from user ? |
88 | jnz 1f | 88 | jnz 1f |
89 | lr %r14,%r9 | 89 | lr %r14,%r9 |
90 | sl %r14,BASED(.Lcritical_start) | 90 | sl %r14,BASED(.Lc_critical_start) |
91 | cl %r14,BASED(.Lcritical_length) | 91 | cl %r14,BASED(.Lc_critical_length) |
92 | jhe 0f | 92 | jhe 0f |
93 | la %r11,\savearea # inside critical section, do cleanup | 93 | la %r11,\savearea # inside critical section, do cleanup |
94 | bras %r14,cleanup_critical | 94 | bras %r14,cleanup_critical |
@@ -162,7 +162,7 @@ ENTRY(__switch_to) | |||
162 | lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task | 162 | lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task |
163 | br %r14 | 163 | br %r14 |
164 | 164 | ||
165 | __critical_start: | 165 | .L__critical_start: |
166 | /* | 166 | /* |
167 | * SVC interrupt handler routine. System calls are synchronous events and | 167 | * SVC interrupt handler routine. System calls are synchronous events and |
168 | * are executed with interrupts enabled. | 168 | * are executed with interrupts enabled. |
@@ -170,145 +170,145 @@ __critical_start: | |||
170 | 170 | ||
171 | ENTRY(system_call) | 171 | ENTRY(system_call) |
172 | stpt __LC_SYNC_ENTER_TIMER | 172 | stpt __LC_SYNC_ENTER_TIMER |
173 | sysc_stm: | 173 | .Lsysc_stm: |
174 | stm %r8,%r15,__LC_SAVE_AREA_SYNC | 174 | stm %r8,%r15,__LC_SAVE_AREA_SYNC |
175 | l %r12,__LC_THREAD_INFO | 175 | l %r12,__LC_THREAD_INFO |
176 | l %r13,__LC_SVC_NEW_PSW+4 | 176 | l %r13,__LC_SVC_NEW_PSW+4 |
177 | lhi %r14,_PIF_SYSCALL | 177 | lhi %r14,_PIF_SYSCALL |
178 | sysc_per: | 178 | .Lsysc_per: |
179 | l %r15,__LC_KERNEL_STACK | 179 | l %r15,__LC_KERNEL_STACK |
180 | la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs | 180 | la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs |
181 | sysc_vtime: | 181 | .Lsysc_vtime: |
182 | UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER | 182 | UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER |
183 | stm %r0,%r7,__PT_R0(%r11) | 183 | stm %r0,%r7,__PT_R0(%r11) |
184 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC | 184 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC |
185 | mvc __PT_PSW(8,%r11),__LC_SVC_OLD_PSW | 185 | mvc __PT_PSW(8,%r11),__LC_SVC_OLD_PSW |
186 | mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC | 186 | mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC |
187 | st %r14,__PT_FLAGS(%r11) | 187 | st %r14,__PT_FLAGS(%r11) |
188 | sysc_do_svc: | 188 | .Lsysc_do_svc: |
189 | l %r10,__TI_sysc_table(%r12) # 31 bit system call table | 189 | l %r10,__TI_sysc_table(%r12) # 31 bit system call table |
190 | lh %r8,__PT_INT_CODE+2(%r11) | 190 | lh %r8,__PT_INT_CODE+2(%r11) |
191 | sla %r8,2 # shift and test for svc0 | 191 | sla %r8,2 # shift and test for svc0 |
192 | jnz sysc_nr_ok | 192 | jnz .Lsysc_nr_ok |
193 | # svc 0: system call number in %r1 | 193 | # svc 0: system call number in %r1 |
194 | cl %r1,BASED(.Lnr_syscalls) | 194 | cl %r1,BASED(.Lnr_syscalls) |
195 | jnl sysc_nr_ok | 195 | jnl .Lsysc_nr_ok |
196 | sth %r1,__PT_INT_CODE+2(%r11) | 196 | sth %r1,__PT_INT_CODE+2(%r11) |
197 | lr %r8,%r1 | 197 | lr %r8,%r1 |
198 | sla %r8,2 | 198 | sla %r8,2 |
199 | sysc_nr_ok: | 199 | .Lsysc_nr_ok: |
200 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | 200 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
201 | st %r2,__PT_ORIG_GPR2(%r11) | 201 | st %r2,__PT_ORIG_GPR2(%r11) |
202 | st %r7,STACK_FRAME_OVERHEAD(%r15) | 202 | st %r7,STACK_FRAME_OVERHEAD(%r15) |
203 | l %r9,0(%r8,%r10) # get system call addr. | 203 | l %r9,0(%r8,%r10) # get system call addr. |
204 | tm __TI_flags+3(%r12),_TIF_TRACE | 204 | tm __TI_flags+3(%r12),_TIF_TRACE |
205 | jnz sysc_tracesys | 205 | jnz .Lsysc_tracesys |
206 | basr %r14,%r9 # call sys_xxxx | 206 | basr %r14,%r9 # call sys_xxxx |
207 | st %r2,__PT_R2(%r11) # store return value | 207 | st %r2,__PT_R2(%r11) # store return value |
208 | 208 | ||
209 | sysc_return: | 209 | .Lsysc_return: |
210 | LOCKDEP_SYS_EXIT | 210 | LOCKDEP_SYS_EXIT |
211 | sysc_tif: | 211 | .Lsysc_tif: |
212 | tm __PT_PSW+1(%r11),0x01 # returning to user ? | 212 | tm __PT_PSW+1(%r11),0x01 # returning to user ? |
213 | jno sysc_restore | 213 | jno .Lsysc_restore |
214 | tm __PT_FLAGS+3(%r11),_PIF_WORK | 214 | tm __PT_FLAGS+3(%r11),_PIF_WORK |
215 | jnz sysc_work | 215 | jnz .Lsysc_work |
216 | tm __TI_flags+3(%r12),_TIF_WORK | 216 | tm __TI_flags+3(%r12),_TIF_WORK |
217 | jnz sysc_work # check for thread work | 217 | jnz .Lsysc_work # check for thread work |
218 | tm __LC_CPU_FLAGS+3,_CIF_WORK | 218 | tm __LC_CPU_FLAGS+3,_CIF_WORK |
219 | jnz sysc_work | 219 | jnz .Lsysc_work |
220 | sysc_restore: | 220 | .Lsysc_restore: |
221 | mvc __LC_RETURN_PSW(8),__PT_PSW(%r11) | 221 | mvc __LC_RETURN_PSW(8),__PT_PSW(%r11) |
222 | stpt __LC_EXIT_TIMER | 222 | stpt __LC_EXIT_TIMER |
223 | lm %r0,%r15,__PT_R0(%r11) | 223 | lm %r0,%r15,__PT_R0(%r11) |
224 | lpsw __LC_RETURN_PSW | 224 | lpsw __LC_RETURN_PSW |
225 | sysc_done: | 225 | .Lsysc_done: |
226 | 226 | ||
227 | # | 227 | # |
228 | # One of the work bits is on. Find out which one. | 228 | # One of the work bits is on. Find out which one. |
229 | # | 229 | # |
230 | sysc_work: | 230 | .Lsysc_work: |
231 | tm __LC_CPU_FLAGS+3,_CIF_MCCK_PENDING | 231 | tm __LC_CPU_FLAGS+3,_CIF_MCCK_PENDING |
232 | jo sysc_mcck_pending | 232 | jo .Lsysc_mcck_pending |
233 | tm __TI_flags+3(%r12),_TIF_NEED_RESCHED | 233 | tm __TI_flags+3(%r12),_TIF_NEED_RESCHED |
234 | jo sysc_reschedule | 234 | jo .Lsysc_reschedule |
235 | tm __PT_FLAGS+3(%r11),_PIF_PER_TRAP | 235 | tm __PT_FLAGS+3(%r11),_PIF_PER_TRAP |
236 | jo sysc_singlestep | 236 | jo .Lsysc_singlestep |
237 | tm __TI_flags+3(%r12),_TIF_SIGPENDING | 237 | tm __TI_flags+3(%r12),_TIF_SIGPENDING |
238 | jo sysc_sigpending | 238 | jo .Lsysc_sigpending |
239 | tm __TI_flags+3(%r12),_TIF_NOTIFY_RESUME | 239 | tm __TI_flags+3(%r12),_TIF_NOTIFY_RESUME |
240 | jo sysc_notify_resume | 240 | jo .Lsysc_notify_resume |
241 | tm __LC_CPU_FLAGS+3,_CIF_ASCE | 241 | tm __LC_CPU_FLAGS+3,_CIF_ASCE |
242 | jo sysc_uaccess | 242 | jo .Lsysc_uaccess |
243 | j sysc_return # beware of critical section cleanup | 243 | j .Lsysc_return # beware of critical section cleanup |
244 | 244 | ||
245 | # | 245 | # |
246 | # _TIF_NEED_RESCHED is set, call schedule | 246 | # _TIF_NEED_RESCHED is set, call schedule |
247 | # | 247 | # |
248 | sysc_reschedule: | 248 | .Lsysc_reschedule: |
249 | l %r1,BASED(.Lschedule) | 249 | l %r1,BASED(.Lc_schedule) |
250 | la %r14,BASED(sysc_return) | 250 | la %r14,BASED(.Lsysc_return) |
251 | br %r1 # call schedule | 251 | br %r1 # call schedule |
252 | 252 | ||
253 | # | 253 | # |
254 | # _CIF_MCCK_PENDING is set, call handler | 254 | # _CIF_MCCK_PENDING is set, call handler |
255 | # | 255 | # |
256 | sysc_mcck_pending: | 256 | .Lsysc_mcck_pending: |
257 | l %r1,BASED(.Lhandle_mcck) | 257 | l %r1,BASED(.Lc_handle_mcck) |
258 | la %r14,BASED(sysc_return) | 258 | la %r14,BASED(.Lsysc_return) |
259 | br %r1 # TIF bit will be cleared by handler | 259 | br %r1 # TIF bit will be cleared by handler |
260 | 260 | ||
261 | # | 261 | # |
262 | # _CIF_ASCE is set, load user space asce | 262 | # _CIF_ASCE is set, load user space asce |
263 | # | 263 | # |
264 | sysc_uaccess: | 264 | .Lsysc_uaccess: |
265 | ni __LC_CPU_FLAGS+3,255-_CIF_ASCE | 265 | ni __LC_CPU_FLAGS+3,255-_CIF_ASCE |
266 | lctl %c1,%c1,__LC_USER_ASCE # load primary asce | 266 | lctl %c1,%c1,__LC_USER_ASCE # load primary asce |
267 | j sysc_return | 267 | j .Lsysc_return |
268 | 268 | ||
269 | # | 269 | # |
270 | # _TIF_SIGPENDING is set, call do_signal | 270 | # _TIF_SIGPENDING is set, call do_signal |
271 | # | 271 | # |
272 | sysc_sigpending: | 272 | .Lsysc_sigpending: |
273 | lr %r2,%r11 # pass pointer to pt_regs | 273 | lr %r2,%r11 # pass pointer to pt_regs |
274 | l %r1,BASED(.Ldo_signal) | 274 | l %r1,BASED(.Lc_do_signal) |
275 | basr %r14,%r1 # call do_signal | 275 | basr %r14,%r1 # call do_signal |
276 | tm __PT_FLAGS+3(%r11),_PIF_SYSCALL | 276 | tm __PT_FLAGS+3(%r11),_PIF_SYSCALL |
277 | jno sysc_return | 277 | jno .Lsysc_return |
278 | lm %r2,%r7,__PT_R2(%r11) # load svc arguments | 278 | lm %r2,%r7,__PT_R2(%r11) # load svc arguments |
279 | l %r10,__TI_sysc_table(%r12) # 31 bit system call table | 279 | l %r10,__TI_sysc_table(%r12) # 31 bit system call table |
280 | xr %r8,%r8 # svc 0 returns -ENOSYS | 280 | xr %r8,%r8 # svc 0 returns -ENOSYS |
281 | clc __PT_INT_CODE+2(2,%r11),BASED(.Lnr_syscalls+2) | 281 | clc __PT_INT_CODE+2(2,%r11),BASED(.Lnr_syscalls+2) |
282 | jnl sysc_nr_ok # invalid svc number -> do svc 0 | 282 | jnl .Lsysc_nr_ok # invalid svc number -> do svc 0 |
283 | lh %r8,__PT_INT_CODE+2(%r11) # load new svc number | 283 | lh %r8,__PT_INT_CODE+2(%r11) # load new svc number |
284 | sla %r8,2 | 284 | sla %r8,2 |
285 | j sysc_nr_ok # restart svc | 285 | j .Lsysc_nr_ok # restart svc |
286 | 286 | ||
287 | # | 287 | # |
288 | # _TIF_NOTIFY_RESUME is set, call do_notify_resume | 288 | # _TIF_NOTIFY_RESUME is set, call do_notify_resume |
289 | # | 289 | # |
290 | sysc_notify_resume: | 290 | .Lsysc_notify_resume: |
291 | lr %r2,%r11 # pass pointer to pt_regs | 291 | lr %r2,%r11 # pass pointer to pt_regs |
292 | l %r1,BASED(.Ldo_notify_resume) | 292 | l %r1,BASED(.Lc_do_notify_resume) |
293 | la %r14,BASED(sysc_return) | 293 | la %r14,BASED(.Lsysc_return) |
294 | br %r1 # call do_notify_resume | 294 | br %r1 # call do_notify_resume |
295 | 295 | ||
296 | # | 296 | # |
297 | # _PIF_PER_TRAP is set, call do_per_trap | 297 | # _PIF_PER_TRAP is set, call do_per_trap |
298 | # | 298 | # |
299 | sysc_singlestep: | 299 | .Lsysc_singlestep: |
300 | ni __PT_FLAGS+3(%r11),255-_PIF_PER_TRAP | 300 | ni __PT_FLAGS+3(%r11),255-_PIF_PER_TRAP |
301 | lr %r2,%r11 # pass pointer to pt_regs | 301 | lr %r2,%r11 # pass pointer to pt_regs |
302 | l %r1,BASED(.Ldo_per_trap) | 302 | l %r1,BASED(.Lc_do_per_trap) |
303 | la %r14,BASED(sysc_return) | 303 | la %r14,BASED(.Lsysc_return) |
304 | br %r1 # call do_per_trap | 304 | br %r1 # call do_per_trap |
305 | 305 | ||
306 | # | 306 | # |
307 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before | 307 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before |
308 | # and after the system call | 308 | # and after the system call |
309 | # | 309 | # |
310 | sysc_tracesys: | 310 | .Lsysc_tracesys: |
311 | l %r1,BASED(.Ltrace_enter) | 311 | l %r1,BASED(.Lc_trace_enter) |
312 | lr %r2,%r11 # pass pointer to pt_regs | 312 | lr %r2,%r11 # pass pointer to pt_regs |
313 | la %r3,0 | 313 | la %r3,0 |
314 | xr %r0,%r0 | 314 | xr %r0,%r0 |
@@ -316,22 +316,22 @@ sysc_tracesys: | |||
316 | st %r0,__PT_R2(%r11) | 316 | st %r0,__PT_R2(%r11) |
317 | basr %r14,%r1 # call do_syscall_trace_enter | 317 | basr %r14,%r1 # call do_syscall_trace_enter |
318 | cl %r2,BASED(.Lnr_syscalls) | 318 | cl %r2,BASED(.Lnr_syscalls) |
319 | jnl sysc_tracenogo | 319 | jnl .Lsysc_tracenogo |
320 | lr %r8,%r2 | 320 | lr %r8,%r2 |
321 | sll %r8,2 | 321 | sll %r8,2 |
322 | l %r9,0(%r8,%r10) | 322 | l %r9,0(%r8,%r10) |
323 | sysc_tracego: | 323 | .Lsysc_tracego: |
324 | lm %r3,%r7,__PT_R3(%r11) | 324 | lm %r3,%r7,__PT_R3(%r11) |
325 | st %r7,STACK_FRAME_OVERHEAD(%r15) | 325 | st %r7,STACK_FRAME_OVERHEAD(%r15) |
326 | l %r2,__PT_ORIG_GPR2(%r11) | 326 | l %r2,__PT_ORIG_GPR2(%r11) |
327 | basr %r14,%r9 # call sys_xxx | 327 | basr %r14,%r9 # call sys_xxx |
328 | st %r2,__PT_R2(%r11) # store return value | 328 | st %r2,__PT_R2(%r11) # store return value |
329 | sysc_tracenogo: | 329 | .Lsysc_tracenogo: |
330 | tm __TI_flags+3(%r12),_TIF_TRACE | 330 | tm __TI_flags+3(%r12),_TIF_TRACE |
331 | jz sysc_return | 331 | jz .Lsysc_return |
332 | l %r1,BASED(.Ltrace_exit) | 332 | l %r1,BASED(.Lc_trace_exit) |
333 | lr %r2,%r11 # pass pointer to pt_regs | 333 | lr %r2,%r11 # pass pointer to pt_regs |
334 | la %r14,BASED(sysc_return) | 334 | la %r14,BASED(.Lsysc_return) |
335 | br %r1 # call do_syscall_trace_exit | 335 | br %r1 # call do_syscall_trace_exit |
336 | 336 | ||
337 | # | 337 | # |
@@ -341,18 +341,18 @@ ENTRY(ret_from_fork) | |||
341 | la %r11,STACK_FRAME_OVERHEAD(%r15) | 341 | la %r11,STACK_FRAME_OVERHEAD(%r15) |
342 | l %r12,__LC_THREAD_INFO | 342 | l %r12,__LC_THREAD_INFO |
343 | l %r13,__LC_SVC_NEW_PSW+4 | 343 | l %r13,__LC_SVC_NEW_PSW+4 |
344 | l %r1,BASED(.Lschedule_tail) | 344 | l %r1,BASED(.Lc_schedule_tail) |
345 | basr %r14,%r1 # call schedule_tail | 345 | basr %r14,%r1 # call schedule_tail |
346 | TRACE_IRQS_ON | 346 | TRACE_IRQS_ON |
347 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 347 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
348 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? | 348 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? |
349 | jne sysc_tracenogo | 349 | jne .Lsysc_tracenogo |
350 | # it's a kernel thread | 350 | # it's a kernel thread |
351 | lm %r9,%r10,__PT_R9(%r11) # load gprs | 351 | lm %r9,%r10,__PT_R9(%r11) # load gprs |
352 | ENTRY(kernel_thread_starter) | 352 | ENTRY(kernel_thread_starter) |
353 | la %r2,0(%r10) | 353 | la %r2,0(%r10) |
354 | basr %r14,%r9 | 354 | basr %r14,%r9 |
355 | j sysc_tracenogo | 355 | j .Lsysc_tracenogo |
356 | 356 | ||
357 | /* | 357 | /* |
358 | * Program check handler routine | 358 | * Program check handler routine |
@@ -369,7 +369,7 @@ ENTRY(pgm_check_handler) | |||
369 | tmh %r8,0x4000 # PER bit set in old PSW ? | 369 | tmh %r8,0x4000 # PER bit set in old PSW ? |
370 | jnz 0f # -> enabled, can't be a double fault | 370 | jnz 0f # -> enabled, can't be a double fault |
371 | tm __LC_PGM_ILC+3,0x80 # check for per exception | 371 | tm __LC_PGM_ILC+3,0x80 # check for per exception |
372 | jnz pgm_svcper # -> single stepped svc | 372 | jnz .Lpgm_svcper # -> single stepped svc |
373 | 0: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC | 373 | 0: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC |
374 | ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 374 | ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
375 | j 2f | 375 | j 2f |
@@ -386,42 +386,42 @@ ENTRY(pgm_check_handler) | |||
386 | jz 0f | 386 | jz 0f |
387 | l %r1,__TI_task(%r12) | 387 | l %r1,__TI_task(%r12) |
388 | tmh %r8,0x0001 # kernel per event ? | 388 | tmh %r8,0x0001 # kernel per event ? |
389 | jz pgm_kprobe | 389 | jz .Lpgm_kprobe |
390 | oi __PT_FLAGS+3(%r11),_PIF_PER_TRAP | 390 | oi __PT_FLAGS+3(%r11),_PIF_PER_TRAP |
391 | mvc __THREAD_per_address(4,%r1),__LC_PER_ADDRESS | 391 | mvc __THREAD_per_address(4,%r1),__LC_PER_ADDRESS |
392 | mvc __THREAD_per_cause(2,%r1),__LC_PER_CODE | 392 | mvc __THREAD_per_cause(2,%r1),__LC_PER_CODE |
393 | mvc __THREAD_per_paid(1,%r1),__LC_PER_ACCESS_ID | 393 | mvc __THREAD_per_paid(1,%r1),__LC_PER_ACCESS_ID |
394 | 0: REENABLE_IRQS | 394 | 0: REENABLE_IRQS |
395 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | 395 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
396 | l %r1,BASED(.Ljump_table) | 396 | l %r1,BASED(.Lc_jump_table) |
397 | la %r10,0x7f | 397 | la %r10,0x7f |
398 | n %r10,__PT_INT_CODE(%r11) | 398 | n %r10,__PT_INT_CODE(%r11) |
399 | je sysc_return | 399 | je .Lsysc_return |
400 | sll %r10,2 | 400 | sll %r10,2 |
401 | l %r1,0(%r10,%r1) # load address of handler routine | 401 | l %r1,0(%r10,%r1) # load address of handler routine |
402 | lr %r2,%r11 # pass pointer to pt_regs | 402 | lr %r2,%r11 # pass pointer to pt_regs |
403 | basr %r14,%r1 # branch to interrupt-handler | 403 | basr %r14,%r1 # branch to interrupt-handler |
404 | j sysc_return | 404 | j .Lsysc_return |
405 | 405 | ||
406 | # | 406 | # |
407 | # PER event in supervisor state, must be kprobes | 407 | # PER event in supervisor state, must be kprobes |
408 | # | 408 | # |
409 | pgm_kprobe: | 409 | .Lpgm_kprobe: |
410 | REENABLE_IRQS | 410 | REENABLE_IRQS |
411 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | 411 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
412 | l %r1,BASED(.Ldo_per_trap) | 412 | l %r1,BASED(.Lc_do_per_trap) |
413 | lr %r2,%r11 # pass pointer to pt_regs | 413 | lr %r2,%r11 # pass pointer to pt_regs |
414 | basr %r14,%r1 # call do_per_trap | 414 | basr %r14,%r1 # call do_per_trap |
415 | j sysc_return | 415 | j .Lsysc_return |
416 | 416 | ||
417 | # | 417 | # |
418 | # single stepped system call | 418 | # single stepped system call |
419 | # | 419 | # |
420 | pgm_svcper: | 420 | .Lpgm_svcper: |
421 | mvc __LC_RETURN_PSW(4),__LC_SVC_NEW_PSW | 421 | mvc __LC_RETURN_PSW(4),__LC_SVC_NEW_PSW |
422 | mvc __LC_RETURN_PSW+4(4),BASED(.Lsysc_per) | 422 | mvc __LC_RETURN_PSW+4(4),BASED(.Lc_sysc_per) |
423 | lhi %r14,_PIF_SYSCALL | _PIF_PER_TRAP | 423 | lhi %r14,_PIF_SYSCALL | _PIF_PER_TRAP |
424 | lpsw __LC_RETURN_PSW # branch to sysc_per and enable irqs | 424 | lpsw __LC_RETURN_PSW # branch to .Lsysc_per and enable irqs |
425 | 425 | ||
426 | /* | 426 | /* |
427 | * IO interrupt handler routine | 427 | * IO interrupt handler routine |
@@ -435,9 +435,9 @@ ENTRY(io_int_handler) | |||
435 | l %r13,__LC_SVC_NEW_PSW+4 | 435 | l %r13,__LC_SVC_NEW_PSW+4 |
436 | lm %r8,%r9,__LC_IO_OLD_PSW | 436 | lm %r8,%r9,__LC_IO_OLD_PSW |
437 | tmh %r8,0x0001 # interrupting from user ? | 437 | tmh %r8,0x0001 # interrupting from user ? |
438 | jz io_skip | 438 | jz .Lio_skip |
439 | UPDATE_VTIME %r14,%r15,__LC_ASYNC_ENTER_TIMER | 439 | UPDATE_VTIME %r14,%r15,__LC_ASYNC_ENTER_TIMER |
440 | io_skip: | 440 | .Lio_skip: |
441 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT | 441 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT |
442 | stm %r0,%r7,__PT_R0(%r11) | 442 | stm %r0,%r7,__PT_R0(%r11) |
443 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC | 443 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC |
@@ -446,35 +446,35 @@ io_skip: | |||
446 | xc __PT_FLAGS(4,%r11),__PT_FLAGS(%r11) | 446 | xc __PT_FLAGS(4,%r11),__PT_FLAGS(%r11) |
447 | TRACE_IRQS_OFF | 447 | TRACE_IRQS_OFF |
448 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | 448 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
449 | io_loop: | 449 | .Lio_loop: |
450 | l %r1,BASED(.Ldo_IRQ) | 450 | l %r1,BASED(.Lc_do_IRQ) |
451 | lr %r2,%r11 # pass pointer to pt_regs | 451 | lr %r2,%r11 # pass pointer to pt_regs |
452 | lhi %r3,IO_INTERRUPT | 452 | lhi %r3,IO_INTERRUPT |
453 | tm __PT_INT_CODE+8(%r11),0x80 # adapter interrupt ? | 453 | tm __PT_INT_CODE+8(%r11),0x80 # adapter interrupt ? |
454 | jz io_call | 454 | jz .Lio_call |
455 | lhi %r3,THIN_INTERRUPT | 455 | lhi %r3,THIN_INTERRUPT |
456 | io_call: | 456 | .Lio_call: |
457 | basr %r14,%r1 # call do_IRQ | 457 | basr %r14,%r1 # call do_IRQ |
458 | tm __LC_MACHINE_FLAGS+2,0x10 # MACHINE_FLAG_LPAR | 458 | tm __LC_MACHINE_FLAGS+2,0x10 # MACHINE_FLAG_LPAR |
459 | jz io_return | 459 | jz .Lio_return |
460 | tpi 0 | 460 | tpi 0 |
461 | jz io_return | 461 | jz .Lio_return |
462 | mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID | 462 | mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID |
463 | j io_loop | 463 | j .Lio_loop |
464 | io_return: | 464 | .Lio_return: |
465 | LOCKDEP_SYS_EXIT | 465 | LOCKDEP_SYS_EXIT |
466 | TRACE_IRQS_ON | 466 | TRACE_IRQS_ON |
467 | io_tif: | 467 | .Lio_tif: |
468 | tm __TI_flags+3(%r12),_TIF_WORK | 468 | tm __TI_flags+3(%r12),_TIF_WORK |
469 | jnz io_work # there is work to do (signals etc.) | 469 | jnz .Lio_work # there is work to do (signals etc.) |
470 | tm __LC_CPU_FLAGS+3,_CIF_WORK | 470 | tm __LC_CPU_FLAGS+3,_CIF_WORK |
471 | jnz io_work | 471 | jnz .Lio_work |
472 | io_restore: | 472 | .Lio_restore: |
473 | mvc __LC_RETURN_PSW(8),__PT_PSW(%r11) | 473 | mvc __LC_RETURN_PSW(8),__PT_PSW(%r11) |
474 | stpt __LC_EXIT_TIMER | 474 | stpt __LC_EXIT_TIMER |
475 | lm %r0,%r15,__PT_R0(%r11) | 475 | lm %r0,%r15,__PT_R0(%r11) |
476 | lpsw __LC_RETURN_PSW | 476 | lpsw __LC_RETURN_PSW |
477 | io_done: | 477 | .Lio_done: |
478 | 478 | ||
479 | # | 479 | # |
480 | # There is work todo, find out in which context we have been interrupted: | 480 | # There is work todo, find out in which context we have been interrupted: |
@@ -483,15 +483,15 @@ io_done: | |||
483 | # the preemption counter and if it is zero call preempt_schedule_irq | 483 | # the preemption counter and if it is zero call preempt_schedule_irq |
484 | # Before any work can be done, a switch to the kernel stack is required. | 484 | # Before any work can be done, a switch to the kernel stack is required. |
485 | # | 485 | # |
486 | io_work: | 486 | .Lio_work: |
487 | tm __PT_PSW+1(%r11),0x01 # returning to user ? | 487 | tm __PT_PSW+1(%r11),0x01 # returning to user ? |
488 | jo io_work_user # yes -> do resched & signal | 488 | jo .Lio_work_user # yes -> do resched & signal |
489 | #ifdef CONFIG_PREEMPT | 489 | #ifdef CONFIG_PREEMPT |
490 | # check for preemptive scheduling | 490 | # check for preemptive scheduling |
491 | icm %r0,15,__TI_precount(%r12) | 491 | icm %r0,15,__TI_precount(%r12) |
492 | jnz io_restore # preemption disabled | 492 | jnz .Lio_restore # preemption disabled |
493 | tm __TI_flags+3(%r12),_TIF_NEED_RESCHED | 493 | tm __TI_flags+3(%r12),_TIF_NEED_RESCHED |
494 | jno io_restore | 494 | jno .Lio_restore |
495 | # switch to kernel stack | 495 | # switch to kernel stack |
496 | l %r1,__PT_R15(%r11) | 496 | l %r1,__PT_R15(%r11) |
497 | ahi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 497 | ahi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
@@ -499,20 +499,20 @@ io_work: | |||
499 | xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) | 499 | xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) |
500 | la %r11,STACK_FRAME_OVERHEAD(%r1) | 500 | la %r11,STACK_FRAME_OVERHEAD(%r1) |
501 | lr %r15,%r1 | 501 | lr %r15,%r1 |
502 | # TRACE_IRQS_ON already done at io_return, call | 502 | # TRACE_IRQS_ON already done at .Lio_return, call |
503 | # TRACE_IRQS_OFF to keep things symmetrical | 503 | # TRACE_IRQS_OFF to keep things symmetrical |
504 | TRACE_IRQS_OFF | 504 | TRACE_IRQS_OFF |
505 | l %r1,BASED(.Lpreempt_irq) | 505 | l %r1,BASED(.Lc_preempt_irq) |
506 | basr %r14,%r1 # call preempt_schedule_irq | 506 | basr %r14,%r1 # call preempt_schedule_irq |
507 | j io_return | 507 | j .Lio_return |
508 | #else | 508 | #else |
509 | j io_restore | 509 | j .Lio_restore |
510 | #endif | 510 | #endif |
511 | 511 | ||
512 | # | 512 | # |
513 | # Need to do work before returning to userspace, switch to kernel stack | 513 | # Need to do work before returning to userspace, switch to kernel stack |
514 | # | 514 | # |
515 | io_work_user: | 515 | .Lio_work_user: |
516 | l %r1,__LC_KERNEL_STACK | 516 | l %r1,__LC_KERNEL_STACK |
517 | mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) | 517 | mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) |
518 | xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) | 518 | xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) |
@@ -522,74 +522,74 @@ io_work_user: | |||
522 | # | 522 | # |
523 | # One of the work bits is on. Find out which one. | 523 | # One of the work bits is on. Find out which one. |
524 | # | 524 | # |
525 | io_work_tif: | 525 | .Lio_work_tif: |
526 | tm __LC_CPU_FLAGS+3(%r12),_CIF_MCCK_PENDING | 526 | tm __LC_CPU_FLAGS+3(%r12),_CIF_MCCK_PENDING |
527 | jo io_mcck_pending | 527 | jo .Lio_mcck_pending |
528 | tm __TI_flags+3(%r12),_TIF_NEED_RESCHED | 528 | tm __TI_flags+3(%r12),_TIF_NEED_RESCHED |
529 | jo io_reschedule | 529 | jo .Lio_reschedule |
530 | tm __TI_flags+3(%r12),_TIF_SIGPENDING | 530 | tm __TI_flags+3(%r12),_TIF_SIGPENDING |
531 | jo io_sigpending | 531 | jo .Lio_sigpending |
532 | tm __TI_flags+3(%r12),_TIF_NOTIFY_RESUME | 532 | tm __TI_flags+3(%r12),_TIF_NOTIFY_RESUME |
533 | jo io_notify_resume | 533 | jo .Lio_notify_resume |
534 | tm __LC_CPU_FLAGS+3,_CIF_ASCE | 534 | tm __LC_CPU_FLAGS+3,_CIF_ASCE |
535 | jo io_uaccess | 535 | jo .Lio_uaccess |
536 | j io_return # beware of critical section cleanup | 536 | j .Lio_return # beware of critical section cleanup |
537 | 537 | ||
538 | # | 538 | # |
539 | # _CIF_MCCK_PENDING is set, call handler | 539 | # _CIF_MCCK_PENDING is set, call handler |
540 | # | 540 | # |
541 | io_mcck_pending: | 541 | .Lio_mcck_pending: |
542 | # TRACE_IRQS_ON already done at io_return | 542 | # TRACE_IRQS_ON already done at .Lio_return |
543 | l %r1,BASED(.Lhandle_mcck) | 543 | l %r1,BASED(.Lc_handle_mcck) |
544 | basr %r14,%r1 # TIF bit will be cleared by handler | 544 | basr %r14,%r1 # TIF bit will be cleared by handler |
545 | TRACE_IRQS_OFF | 545 | TRACE_IRQS_OFF |
546 | j io_return | 546 | j .Lio_return |
547 | 547 | ||
548 | # | 548 | # |
549 | # _CIF_ASCE is set, load user space asce | 549 | # _CIF_ASCE is set, load user space asce |
550 | # | 550 | # |
551 | io_uaccess: | 551 | .Lio_uaccess: |
552 | ni __LC_CPU_FLAGS+3,255-_CIF_ASCE | 552 | ni __LC_CPU_FLAGS+3,255-_CIF_ASCE |
553 | lctl %c1,%c1,__LC_USER_ASCE # load primary asce | 553 | lctl %c1,%c1,__LC_USER_ASCE # load primary asce |
554 | j io_return | 554 | j .Lio_return |
555 | 555 | ||
556 | # | 556 | # |
557 | # _TIF_NEED_RESCHED is set, call schedule | 557 | # _TIF_NEED_RESCHED is set, call schedule |
558 | # | 558 | # |
559 | io_reschedule: | 559 | .Lio_reschedule: |
560 | # TRACE_IRQS_ON already done at io_return | 560 | # TRACE_IRQS_ON already done at .Lio_return |
561 | l %r1,BASED(.Lschedule) | 561 | l %r1,BASED(.Lc_schedule) |
562 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 562 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
563 | basr %r14,%r1 # call scheduler | 563 | basr %r14,%r1 # call scheduler |
564 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | 564 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
565 | TRACE_IRQS_OFF | 565 | TRACE_IRQS_OFF |
566 | j io_return | 566 | j .Lio_return |
567 | 567 | ||
568 | # | 568 | # |
569 | # _TIF_SIGPENDING is set, call do_signal | 569 | # _TIF_SIGPENDING is set, call do_signal |
570 | # | 570 | # |
571 | io_sigpending: | 571 | .Lio_sigpending: |
572 | # TRACE_IRQS_ON already done at io_return | 572 | # TRACE_IRQS_ON already done at .Lio_return |
573 | l %r1,BASED(.Ldo_signal) | 573 | l %r1,BASED(.Lc_do_signal) |
574 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 574 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
575 | lr %r2,%r11 # pass pointer to pt_regs | 575 | lr %r2,%r11 # pass pointer to pt_regs |
576 | basr %r14,%r1 # call do_signal | 576 | basr %r14,%r1 # call do_signal |
577 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | 577 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
578 | TRACE_IRQS_OFF | 578 | TRACE_IRQS_OFF |
579 | j io_return | 579 | j .Lio_return |
580 | 580 | ||
581 | # | 581 | # |
582 | # _TIF_SIGPENDING is set, call do_signal | 582 | # _TIF_SIGPENDING is set, call do_signal |
583 | # | 583 | # |
584 | io_notify_resume: | 584 | .Lio_notify_resume: |
585 | # TRACE_IRQS_ON already done at io_return | 585 | # TRACE_IRQS_ON already done at .Lio_return |
586 | l %r1,BASED(.Ldo_notify_resume) | 586 | l %r1,BASED(.Lc_do_notify_resume) |
587 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 587 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
588 | lr %r2,%r11 # pass pointer to pt_regs | 588 | lr %r2,%r11 # pass pointer to pt_regs |
589 | basr %r14,%r1 # call do_notify_resume | 589 | basr %r14,%r1 # call do_notify_resume |
590 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | 590 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
591 | TRACE_IRQS_OFF | 591 | TRACE_IRQS_OFF |
592 | j io_return | 592 | j .Lio_return |
593 | 593 | ||
594 | /* | 594 | /* |
595 | * External interrupt handler routine | 595 | * External interrupt handler routine |
@@ -603,9 +603,9 @@ ENTRY(ext_int_handler) | |||
603 | l %r13,__LC_SVC_NEW_PSW+4 | 603 | l %r13,__LC_SVC_NEW_PSW+4 |
604 | lm %r8,%r9,__LC_EXT_OLD_PSW | 604 | lm %r8,%r9,__LC_EXT_OLD_PSW |
605 | tmh %r8,0x0001 # interrupting from user ? | 605 | tmh %r8,0x0001 # interrupting from user ? |
606 | jz ext_skip | 606 | jz .Lext_skip |
607 | UPDATE_VTIME %r14,%r15,__LC_ASYNC_ENTER_TIMER | 607 | UPDATE_VTIME %r14,%r15,__LC_ASYNC_ENTER_TIMER |
608 | ext_skip: | 608 | .Lext_skip: |
609 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT | 609 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT |
610 | stm %r0,%r7,__PT_R0(%r11) | 610 | stm %r0,%r7,__PT_R0(%r11) |
611 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC | 611 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC |
@@ -614,29 +614,29 @@ ext_skip: | |||
614 | mvc __PT_INT_PARM(4,%r11),__LC_EXT_PARAMS | 614 | mvc __PT_INT_PARM(4,%r11),__LC_EXT_PARAMS |
615 | xc __PT_FLAGS(4,%r11),__PT_FLAGS(%r11) | 615 | xc __PT_FLAGS(4,%r11),__PT_FLAGS(%r11) |
616 | TRACE_IRQS_OFF | 616 | TRACE_IRQS_OFF |
617 | l %r1,BASED(.Ldo_IRQ) | 617 | l %r1,BASED(.Lc_do_IRQ) |
618 | lr %r2,%r11 # pass pointer to pt_regs | 618 | lr %r2,%r11 # pass pointer to pt_regs |
619 | lhi %r3,EXT_INTERRUPT | 619 | lhi %r3,EXT_INTERRUPT |
620 | basr %r14,%r1 # call do_IRQ | 620 | basr %r14,%r1 # call do_IRQ |
621 | j io_return | 621 | j .Lio_return |
622 | 622 | ||
623 | /* | 623 | /* |
624 | * Load idle PSW. The second "half" of this function is in cleanup_idle. | 624 | * Load idle PSW. The second "half" of this function is in .Lcleanup_idle. |
625 | */ | 625 | */ |
626 | ENTRY(psw_idle) | 626 | ENTRY(psw_idle) |
627 | st %r3,__SF_EMPTY(%r15) | 627 | st %r3,__SF_EMPTY(%r15) |
628 | basr %r1,0 | 628 | basr %r1,0 |
629 | la %r1,psw_idle_lpsw+4-.(%r1) | 629 | la %r1,.Lpsw_idle_lpsw+4-.(%r1) |
630 | st %r1,__SF_EMPTY+4(%r15) | 630 | st %r1,__SF_EMPTY+4(%r15) |
631 | oi __SF_EMPTY+4(%r15),0x80 | 631 | oi __SF_EMPTY+4(%r15),0x80 |
632 | stck __CLOCK_IDLE_ENTER(%r2) | 632 | stck __CLOCK_IDLE_ENTER(%r2) |
633 | stpt __TIMER_IDLE_ENTER(%r2) | 633 | stpt __TIMER_IDLE_ENTER(%r2) |
634 | psw_idle_lpsw: | 634 | .Lpsw_idle_lpsw: |
635 | lpsw __SF_EMPTY(%r15) | 635 | lpsw __SF_EMPTY(%r15) |
636 | br %r14 | 636 | br %r14 |
637 | psw_idle_end: | 637 | .Lpsw_idle_end: |
638 | 638 | ||
639 | __critical_end: | 639 | .L__critical_end: |
640 | 640 | ||
641 | /* | 641 | /* |
642 | * Machine check handler routines | 642 | * Machine check handler routines |
@@ -650,7 +650,7 @@ ENTRY(mcck_int_handler) | |||
650 | l %r13,__LC_SVC_NEW_PSW+4 | 650 | l %r13,__LC_SVC_NEW_PSW+4 |
651 | lm %r8,%r9,__LC_MCK_OLD_PSW | 651 | lm %r8,%r9,__LC_MCK_OLD_PSW |
652 | tm __LC_MCCK_CODE,0x80 # system damage? | 652 | tm __LC_MCCK_CODE,0x80 # system damage? |
653 | jo mcck_panic # yes -> rest of mcck code invalid | 653 | jo .Lmcck_panic # yes -> rest of mcck code invalid |
654 | la %r14,__LC_CPU_TIMER_SAVE_AREA | 654 | la %r14,__LC_CPU_TIMER_SAVE_AREA |
655 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) | 655 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) |
656 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | 656 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? |
@@ -668,22 +668,22 @@ ENTRY(mcck_int_handler) | |||
668 | 2: spt 0(%r14) | 668 | 2: spt 0(%r14) |
669 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) | 669 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) |
670 | 3: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | 670 | 3: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
671 | jno mcck_panic # no -> skip cleanup critical | 671 | jno .Lmcck_panic # no -> skip cleanup critical |
672 | tm %r8,0x0001 # interrupting from user ? | 672 | tm %r8,0x0001 # interrupting from user ? |
673 | jz mcck_skip | 673 | jz .Lmcck_skip |
674 | UPDATE_VTIME %r14,%r15,__LC_MCCK_ENTER_TIMER | 674 | UPDATE_VTIME %r14,%r15,__LC_MCCK_ENTER_TIMER |
675 | mcck_skip: | 675 | .Lmcck_skip: |
676 | SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+32,__LC_PANIC_STACK,PAGE_SHIFT | 676 | SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+32,__LC_PANIC_STACK,PAGE_SHIFT |
677 | stm %r0,%r7,__PT_R0(%r11) | 677 | stm %r0,%r7,__PT_R0(%r11) |
678 | mvc __PT_R8(32,%r11),__LC_GPREGS_SAVE_AREA+32 | 678 | mvc __PT_R8(32,%r11),__LC_GPREGS_SAVE_AREA+32 |
679 | stm %r8,%r9,__PT_PSW(%r11) | 679 | stm %r8,%r9,__PT_PSW(%r11) |
680 | xc __PT_FLAGS(4,%r11),__PT_FLAGS(%r11) | 680 | xc __PT_FLAGS(4,%r11),__PT_FLAGS(%r11) |
681 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | 681 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
682 | l %r1,BASED(.Ldo_machine_check) | 682 | l %r1,BASED(.Lc_do_machine_check) |
683 | lr %r2,%r11 # pass pointer to pt_regs | 683 | lr %r2,%r11 # pass pointer to pt_regs |
684 | basr %r14,%r1 # call s390_do_machine_check | 684 | basr %r14,%r1 # call s390_do_machine_check |
685 | tm __PT_PSW+1(%r11),0x01 # returning to user ? | 685 | tm __PT_PSW+1(%r11),0x01 # returning to user ? |
686 | jno mcck_return | 686 | jno .Lmcck_return |
687 | l %r1,__LC_KERNEL_STACK # switch to kernel stack | 687 | l %r1,__LC_KERNEL_STACK # switch to kernel stack |
688 | mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) | 688 | mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) |
689 | xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) | 689 | xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) |
@@ -691,12 +691,12 @@ mcck_skip: | |||
691 | lr %r15,%r1 | 691 | lr %r15,%r1 |
692 | ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off | 692 | ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off |
693 | tm __LC_CPU_FLAGS+3,_CIF_MCCK_PENDING | 693 | tm __LC_CPU_FLAGS+3,_CIF_MCCK_PENDING |
694 | jno mcck_return | 694 | jno .Lmcck_return |
695 | TRACE_IRQS_OFF | 695 | TRACE_IRQS_OFF |
696 | l %r1,BASED(.Lhandle_mcck) | 696 | l %r1,BASED(.Lc_handle_mcck) |
697 | basr %r14,%r1 # call s390_handle_mcck | 697 | basr %r14,%r1 # call s390_handle_mcck |
698 | TRACE_IRQS_ON | 698 | TRACE_IRQS_ON |
699 | mcck_return: | 699 | .Lmcck_return: |
700 | mvc __LC_RETURN_MCCK_PSW(8),__PT_PSW(%r11) # move return PSW | 700 | mvc __LC_RETURN_MCCK_PSW(8),__PT_PSW(%r11) # move return PSW |
701 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? | 701 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? |
702 | jno 0f | 702 | jno 0f |
@@ -706,15 +706,15 @@ mcck_return: | |||
706 | 0: lm %r0,%r15,__PT_R0(%r11) | 706 | 0: lm %r0,%r15,__PT_R0(%r11) |
707 | lpsw __LC_RETURN_MCCK_PSW | 707 | lpsw __LC_RETURN_MCCK_PSW |
708 | 708 | ||
709 | mcck_panic: | 709 | .Lmcck_panic: |
710 | l %r14,__LC_PANIC_STACK | 710 | l %r14,__LC_PANIC_STACK |
711 | slr %r14,%r15 | 711 | slr %r14,%r15 |
712 | sra %r14,PAGE_SHIFT | 712 | sra %r14,PAGE_SHIFT |
713 | jz 0f | 713 | jz 0f |
714 | l %r15,__LC_PANIC_STACK | 714 | l %r15,__LC_PANIC_STACK |
715 | j mcck_skip | 715 | j .Lmcck_skip |
716 | 0: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 716 | 0: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
717 | j mcck_skip | 717 | j .Lmcck_skip |
718 | 718 | ||
719 | # | 719 | # |
720 | # PSW restart interrupt handler | 720 | # PSW restart interrupt handler |
@@ -764,58 +764,58 @@ stack_overflow: | |||
764 | 1: .long kernel_stack_overflow | 764 | 1: .long kernel_stack_overflow |
765 | #endif | 765 | #endif |
766 | 766 | ||
767 | cleanup_table: | 767 | .Lcleanup_table: |
768 | .long system_call + 0x80000000 | 768 | .long system_call + 0x80000000 |
769 | .long sysc_do_svc + 0x80000000 | 769 | .long .Lsysc_do_svc + 0x80000000 |
770 | .long sysc_tif + 0x80000000 | 770 | .long .Lsysc_tif + 0x80000000 |
771 | .long sysc_restore + 0x80000000 | 771 | .long .Lsysc_restore + 0x80000000 |
772 | .long sysc_done + 0x80000000 | 772 | .long .Lsysc_done + 0x80000000 |
773 | .long io_tif + 0x80000000 | 773 | .long .Lio_tif + 0x80000000 |
774 | .long io_restore + 0x80000000 | 774 | .long .Lio_restore + 0x80000000 |
775 | .long io_done + 0x80000000 | 775 | .long .Lio_done + 0x80000000 |
776 | .long psw_idle + 0x80000000 | 776 | .long psw_idle + 0x80000000 |
777 | .long psw_idle_end + 0x80000000 | 777 | .long .Lpsw_idle_end + 0x80000000 |
778 | 778 | ||
779 | cleanup_critical: | 779 | cleanup_critical: |
780 | cl %r9,BASED(cleanup_table) # system_call | 780 | cl %r9,BASED(.Lcleanup_table) # system_call |
781 | jl 0f | 781 | jl 0f |
782 | cl %r9,BASED(cleanup_table+4) # sysc_do_svc | 782 | cl %r9,BASED(.Lcleanup_table+4) # .Lsysc_do_svc |
783 | jl cleanup_system_call | 783 | jl .Lcleanup_system_call |
784 | cl %r9,BASED(cleanup_table+8) # sysc_tif | 784 | cl %r9,BASED(.Lcleanup_table+8) # .Lsysc_tif |
785 | jl 0f | 785 | jl 0f |
786 | cl %r9,BASED(cleanup_table+12) # sysc_restore | 786 | cl %r9,BASED(.Lcleanup_table+12) # .Lsysc_restore |
787 | jl cleanup_sysc_tif | 787 | jl .Lcleanup_sysc_tif |
788 | cl %r9,BASED(cleanup_table+16) # sysc_done | 788 | cl %r9,BASED(.Lcleanup_table+16) # .Lsysc_done |
789 | jl cleanup_sysc_restore | 789 | jl .Lcleanup_sysc_restore |
790 | cl %r9,BASED(cleanup_table+20) # io_tif | 790 | cl %r9,BASED(.Lcleanup_table+20) # .Lio_tif |
791 | jl 0f | 791 | jl 0f |
792 | cl %r9,BASED(cleanup_table+24) # io_restore | 792 | cl %r9,BASED(.Lcleanup_table+24) # .Lio_restore |
793 | jl cleanup_io_tif | 793 | jl .Lcleanup_io_tif |
794 | cl %r9,BASED(cleanup_table+28) # io_done | 794 | cl %r9,BASED(.Lcleanup_table+28) # .Lio_done |
795 | jl cleanup_io_restore | 795 | jl .Lcleanup_io_restore |
796 | cl %r9,BASED(cleanup_table+32) # psw_idle | 796 | cl %r9,BASED(.Lcleanup_table+32) # psw_idle |
797 | jl 0f | 797 | jl 0f |
798 | cl %r9,BASED(cleanup_table+36) # psw_idle_end | 798 | cl %r9,BASED(.Lcleanup_table+36) # .Lpsw_idle_end |
799 | jl cleanup_idle | 799 | jl .Lcleanup_idle |
800 | 0: br %r14 | 800 | 0: br %r14 |
801 | 801 | ||
802 | cleanup_system_call: | 802 | .Lcleanup_system_call: |
803 | # check if stpt has been executed | 803 | # check if stpt has been executed |
804 | cl %r9,BASED(cleanup_system_call_insn) | 804 | cl %r9,BASED(.Lcleanup_system_call_insn) |
805 | jh 0f | 805 | jh 0f |
806 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER | 806 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER |
807 | chi %r11,__LC_SAVE_AREA_ASYNC | 807 | chi %r11,__LC_SAVE_AREA_ASYNC |
808 | je 0f | 808 | je 0f |
809 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER | 809 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER |
810 | 0: # check if stm has been executed | 810 | 0: # check if stm has been executed |
811 | cl %r9,BASED(cleanup_system_call_insn+4) | 811 | cl %r9,BASED(.Lcleanup_system_call_insn+4) |
812 | jh 0f | 812 | jh 0f |
813 | mvc __LC_SAVE_AREA_SYNC(32),0(%r11) | 813 | mvc __LC_SAVE_AREA_SYNC(32),0(%r11) |
814 | 0: # set up saved registers r12, and r13 | 814 | 0: # set up saved registers r12, and r13 |
815 | st %r12,16(%r11) # r12 thread-info pointer | 815 | st %r12,16(%r11) # r12 thread-info pointer |
816 | st %r13,20(%r11) # r13 literal-pool pointer | 816 | st %r13,20(%r11) # r13 literal-pool pointer |
817 | # check if the user time calculation has been done | 817 | # check if the user time calculation has been done |
818 | cl %r9,BASED(cleanup_system_call_insn+8) | 818 | cl %r9,BASED(.Lcleanup_system_call_insn+8) |
819 | jh 0f | 819 | jh 0f |
820 | l %r10,__LC_EXIT_TIMER | 820 | l %r10,__LC_EXIT_TIMER |
821 | l %r15,__LC_EXIT_TIMER+4 | 821 | l %r15,__LC_EXIT_TIMER+4 |
@@ -824,7 +824,7 @@ cleanup_system_call: | |||
824 | st %r10,__LC_USER_TIMER | 824 | st %r10,__LC_USER_TIMER |
825 | st %r15,__LC_USER_TIMER+4 | 825 | st %r15,__LC_USER_TIMER+4 |
826 | 0: # check if the system time calculation has been done | 826 | 0: # check if the system time calculation has been done |
827 | cl %r9,BASED(cleanup_system_call_insn+12) | 827 | cl %r9,BASED(.Lcleanup_system_call_insn+12) |
828 | jh 0f | 828 | jh 0f |
829 | l %r10,__LC_LAST_UPDATE_TIMER | 829 | l %r10,__LC_LAST_UPDATE_TIMER |
830 | l %r15,__LC_LAST_UPDATE_TIMER+4 | 830 | l %r15,__LC_LAST_UPDATE_TIMER+4 |
@@ -848,20 +848,20 @@ cleanup_system_call: | |||
848 | # setup saved register 15 | 848 | # setup saved register 15 |
849 | st %r15,28(%r11) # r15 stack pointer | 849 | st %r15,28(%r11) # r15 stack pointer |
850 | # set new psw address and exit | 850 | # set new psw address and exit |
851 | l %r9,BASED(cleanup_table+4) # sysc_do_svc + 0x80000000 | 851 | l %r9,BASED(.Lcleanup_table+4) # .Lsysc_do_svc + 0x80000000 |
852 | br %r14 | 852 | br %r14 |
853 | cleanup_system_call_insn: | 853 | .Lcleanup_system_call_insn: |
854 | .long system_call + 0x80000000 | 854 | .long system_call + 0x80000000 |
855 | .long sysc_stm + 0x80000000 | 855 | .long .Lsysc_stm + 0x80000000 |
856 | .long sysc_vtime + 0x80000000 + 36 | 856 | .long .Lsysc_vtime + 0x80000000 + 36 |
857 | .long sysc_vtime + 0x80000000 + 76 | 857 | .long .Lsysc_vtime + 0x80000000 + 76 |
858 | 858 | ||
859 | cleanup_sysc_tif: | 859 | .Lcleanup_sysc_tif: |
860 | l %r9,BASED(cleanup_table+8) # sysc_tif + 0x80000000 | 860 | l %r9,BASED(.Lcleanup_table+8) # .Lsysc_tif + 0x80000000 |
861 | br %r14 | 861 | br %r14 |
862 | 862 | ||
863 | cleanup_sysc_restore: | 863 | .Lcleanup_sysc_restore: |
864 | cl %r9,BASED(cleanup_sysc_restore_insn) | 864 | cl %r9,BASED(.Lcleanup_sysc_restore_insn) |
865 | jhe 0f | 865 | jhe 0f |
866 | l %r9,12(%r11) # get saved pointer to pt_regs | 866 | l %r9,12(%r11) # get saved pointer to pt_regs |
867 | mvc __LC_RETURN_PSW(8),__PT_PSW(%r9) | 867 | mvc __LC_RETURN_PSW(8),__PT_PSW(%r9) |
@@ -869,15 +869,15 @@ cleanup_sysc_restore: | |||
869 | lm %r0,%r7,__PT_R0(%r9) | 869 | lm %r0,%r7,__PT_R0(%r9) |
870 | 0: lm %r8,%r9,__LC_RETURN_PSW | 870 | 0: lm %r8,%r9,__LC_RETURN_PSW |
871 | br %r14 | 871 | br %r14 |
872 | cleanup_sysc_restore_insn: | 872 | .Lcleanup_sysc_restore_insn: |
873 | .long sysc_done - 4 + 0x80000000 | 873 | .long .Lsysc_done - 4 + 0x80000000 |
874 | 874 | ||
875 | cleanup_io_tif: | 875 | .Lcleanup_io_tif: |
876 | l %r9,BASED(cleanup_table+20) # io_tif + 0x80000000 | 876 | l %r9,BASED(.Lcleanup_table+20) # .Lio_tif + 0x80000000 |
877 | br %r14 | 877 | br %r14 |
878 | 878 | ||
879 | cleanup_io_restore: | 879 | .Lcleanup_io_restore: |
880 | cl %r9,BASED(cleanup_io_restore_insn) | 880 | cl %r9,BASED(.Lcleanup_io_restore_insn) |
881 | jhe 0f | 881 | jhe 0f |
882 | l %r9,12(%r11) # get saved r11 pointer to pt_regs | 882 | l %r9,12(%r11) # get saved r11 pointer to pt_regs |
883 | mvc __LC_RETURN_PSW(8),__PT_PSW(%r9) | 883 | mvc __LC_RETURN_PSW(8),__PT_PSW(%r9) |
@@ -885,10 +885,10 @@ cleanup_io_restore: | |||
885 | lm %r0,%r7,__PT_R0(%r9) | 885 | lm %r0,%r7,__PT_R0(%r9) |
886 | 0: lm %r8,%r9,__LC_RETURN_PSW | 886 | 0: lm %r8,%r9,__LC_RETURN_PSW |
887 | br %r14 | 887 | br %r14 |
888 | cleanup_io_restore_insn: | 888 | .Lcleanup_io_restore_insn: |
889 | .long io_done - 4 + 0x80000000 | 889 | .long .Lio_done - 4 + 0x80000000 |
890 | 890 | ||
891 | cleanup_idle: | 891 | .Lcleanup_idle: |
892 | # copy interrupt clock & cpu timer | 892 | # copy interrupt clock & cpu timer |
893 | mvc __CLOCK_IDLE_EXIT(8,%r2),__LC_INT_CLOCK | 893 | mvc __CLOCK_IDLE_EXIT(8,%r2),__LC_INT_CLOCK |
894 | mvc __TIMER_IDLE_EXIT(8,%r2),__LC_ASYNC_ENTER_TIMER | 894 | mvc __TIMER_IDLE_EXIT(8,%r2),__LC_ASYNC_ENTER_TIMER |
@@ -897,7 +897,7 @@ cleanup_idle: | |||
897 | mvc __CLOCK_IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK | 897 | mvc __CLOCK_IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK |
898 | mvc __TIMER_IDLE_EXIT(8,%r2),__LC_MCCK_ENTER_TIMER | 898 | mvc __TIMER_IDLE_EXIT(8,%r2),__LC_MCCK_ENTER_TIMER |
899 | 0: # check if stck has been executed | 899 | 0: # check if stck has been executed |
900 | cl %r9,BASED(cleanup_idle_insn) | 900 | cl %r9,BASED(.Lcleanup_idle_insn) |
901 | jhe 1f | 901 | jhe 1f |
902 | mvc __CLOCK_IDLE_ENTER(8,%r2),__CLOCK_IDLE_EXIT(%r2) | 902 | mvc __CLOCK_IDLE_ENTER(8,%r2),__CLOCK_IDLE_EXIT(%r2) |
903 | mvc __TIMER_IDLE_ENTER(8,%r2),__TIMER_IDLE_EXIT(%r3) | 903 | mvc __TIMER_IDLE_ENTER(8,%r2),__TIMER_IDLE_EXIT(%r3) |
@@ -913,12 +913,12 @@ cleanup_idle: | |||
913 | stm %r9,%r10,__LC_SYSTEM_TIMER | 913 | stm %r9,%r10,__LC_SYSTEM_TIMER |
914 | mvc __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2) | 914 | mvc __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2) |
915 | # prepare return psw | 915 | # prepare return psw |
916 | n %r8,BASED(cleanup_idle_wait) # clear irq & wait state bits | 916 | n %r8,BASED(.Lcleanup_idle_wait) # clear irq & wait state bits |
917 | l %r9,24(%r11) # return from psw_idle | 917 | l %r9,24(%r11) # return from psw_idle |
918 | br %r14 | 918 | br %r14 |
919 | cleanup_idle_insn: | 919 | .Lcleanup_idle_insn: |
920 | .long psw_idle_lpsw + 0x80000000 | 920 | .long .Lpsw_idle_lpsw + 0x80000000 |
921 | cleanup_idle_wait: | 921 | .Lcleanup_idle_wait: |
922 | .long 0xfcfdffff | 922 | .long 0xfcfdffff |
923 | 923 | ||
924 | /* | 924 | /* |
@@ -933,30 +933,30 @@ cleanup_idle_wait: | |||
933 | /* | 933 | /* |
934 | * Symbol constants | 934 | * Symbol constants |
935 | */ | 935 | */ |
936 | .Ldo_machine_check: .long s390_do_machine_check | 936 | .Lc_do_machine_check: .long s390_do_machine_check |
937 | .Lhandle_mcck: .long s390_handle_mcck | 937 | .Lc_handle_mcck: .long s390_handle_mcck |
938 | .Ldo_IRQ: .long do_IRQ | 938 | .Lc_do_IRQ: .long do_IRQ |
939 | .Ldo_signal: .long do_signal | 939 | .Lc_do_signal: .long do_signal |
940 | .Ldo_notify_resume: .long do_notify_resume | 940 | .Lc_do_notify_resume: .long do_notify_resume |
941 | .Ldo_per_trap: .long do_per_trap | 941 | .Lc_do_per_trap: .long do_per_trap |
942 | .Ljump_table: .long pgm_check_table | 942 | .Lc_jump_table: .long pgm_check_table |
943 | .Lschedule: .long schedule | 943 | .Lc_schedule: .long schedule |
944 | #ifdef CONFIG_PREEMPT | 944 | #ifdef CONFIG_PREEMPT |
945 | .Lpreempt_irq: .long preempt_schedule_irq | 945 | .Lc_preempt_irq: .long preempt_schedule_irq |
946 | #endif | 946 | #endif |
947 | .Ltrace_enter: .long do_syscall_trace_enter | 947 | .Lc_trace_enter: .long do_syscall_trace_enter |
948 | .Ltrace_exit: .long do_syscall_trace_exit | 948 | .Lc_trace_exit: .long do_syscall_trace_exit |
949 | .Lschedule_tail: .long schedule_tail | 949 | .Lc_schedule_tail: .long schedule_tail |
950 | .Lsysc_per: .long sysc_per + 0x80000000 | 950 | .Lc_sysc_per: .long .Lsysc_per + 0x80000000 |
951 | #ifdef CONFIG_TRACE_IRQFLAGS | 951 | #ifdef CONFIG_TRACE_IRQFLAGS |
952 | .Lhardirqs_on: .long trace_hardirqs_on_caller | 952 | .Lc_hardirqs_on: .long trace_hardirqs_on_caller |
953 | .Lhardirqs_off: .long trace_hardirqs_off_caller | 953 | .Lc_hardirqs_off: .long trace_hardirqs_off_caller |
954 | #endif | 954 | #endif |
955 | #ifdef CONFIG_LOCKDEP | 955 | #ifdef CONFIG_LOCKDEP |
956 | .Llockdep_sys_exit: .long lockdep_sys_exit | 956 | .Lc_lockdep_sys_exit: .long lockdep_sys_exit |
957 | #endif | 957 | #endif |
958 | .Lcritical_start: .long __critical_start + 0x80000000 | 958 | .Lc_critical_start: .long .L__critical_start + 0x80000000 |
959 | .Lcritical_length: .long __critical_end - __critical_start | 959 | .Lc_critical_length: .long .L__critical_end - .L__critical_start |
960 | 960 | ||
961 | .section .rodata, "a" | 961 | .section .rodata, "a" |
962 | #define SYSCALL(esa,esame,emu) .long esa | 962 | #define SYSCALL(esa,esame,emu) .long esa |
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index 0554b9771c9f..8e61393c8275 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
@@ -74,4 +74,6 @@ struct old_sigaction; | |||
74 | long sys_s390_personality(unsigned int personality); | 74 | long sys_s390_personality(unsigned int personality); |
75 | long sys_s390_runtime_instr(int command, int signum); | 75 | long sys_s390_runtime_instr(int command, int signum); |
76 | 76 | ||
77 | long sys_s390_pci_mmio_write(unsigned long, const void __user *, size_t); | ||
78 | long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t); | ||
77 | #endif /* _ENTRY_H */ | 79 | #endif /* _ENTRY_H */ |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 7b2e03afd017..c329446a951d 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -91,7 +91,7 @@ _PIF_WORK = (_PIF_PER_TRAP) | |||
91 | .if \reason==1 | 91 | .if \reason==1 |
92 | # Some program interrupts are suppressing (e.g. protection). | 92 | # Some program interrupts are suppressing (e.g. protection). |
93 | # We must also check the instruction after SIE in that case. | 93 | # We must also check the instruction after SIE in that case. |
94 | # do_protection_exception will rewind to rewind_pad | 94 | # do_protection_exception will rewind to .Lrewind_pad |
95 | jh .+42 | 95 | jh .+42 |
96 | .else | 96 | .else |
97 | jhe .+42 | 97 | jhe .+42 |
@@ -192,7 +192,7 @@ ENTRY(__switch_to) | |||
192 | lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task | 192 | lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task |
193 | br %r14 | 193 | br %r14 |
194 | 194 | ||
195 | __critical_start: | 195 | .L__critical_start: |
196 | /* | 196 | /* |
197 | * SVC interrupt handler routine. System calls are synchronous events and | 197 | * SVC interrupt handler routine. System calls are synchronous events and |
198 | * are executed with interrupts enabled. | 198 | * are executed with interrupts enabled. |
@@ -200,15 +200,15 @@ __critical_start: | |||
200 | 200 | ||
201 | ENTRY(system_call) | 201 | ENTRY(system_call) |
202 | stpt __LC_SYNC_ENTER_TIMER | 202 | stpt __LC_SYNC_ENTER_TIMER |
203 | sysc_stmg: | 203 | .Lsysc_stmg: |
204 | stmg %r8,%r15,__LC_SAVE_AREA_SYNC | 204 | stmg %r8,%r15,__LC_SAVE_AREA_SYNC |
205 | lg %r10,__LC_LAST_BREAK | 205 | lg %r10,__LC_LAST_BREAK |
206 | lg %r12,__LC_THREAD_INFO | 206 | lg %r12,__LC_THREAD_INFO |
207 | lghi %r14,_PIF_SYSCALL | 207 | lghi %r14,_PIF_SYSCALL |
208 | sysc_per: | 208 | .Lsysc_per: |
209 | lg %r15,__LC_KERNEL_STACK | 209 | lg %r15,__LC_KERNEL_STACK |
210 | la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs | 210 | la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs |
211 | sysc_vtime: | 211 | .Lsysc_vtime: |
212 | UPDATE_VTIME %r13,__LC_SYNC_ENTER_TIMER | 212 | UPDATE_VTIME %r13,__LC_SYNC_ENTER_TIMER |
213 | LAST_BREAK %r13 | 213 | LAST_BREAK %r13 |
214 | stmg %r0,%r7,__PT_R0(%r11) | 214 | stmg %r0,%r7,__PT_R0(%r11) |
@@ -216,39 +216,39 @@ sysc_vtime: | |||
216 | mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW | 216 | mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW |
217 | mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC | 217 | mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC |
218 | stg %r14,__PT_FLAGS(%r11) | 218 | stg %r14,__PT_FLAGS(%r11) |
219 | sysc_do_svc: | 219 | .Lsysc_do_svc: |
220 | lg %r10,__TI_sysc_table(%r12) # address of system call table | 220 | lg %r10,__TI_sysc_table(%r12) # address of system call table |
221 | llgh %r8,__PT_INT_CODE+2(%r11) | 221 | llgh %r8,__PT_INT_CODE+2(%r11) |
222 | slag %r8,%r8,2 # shift and test for svc 0 | 222 | slag %r8,%r8,2 # shift and test for svc 0 |
223 | jnz sysc_nr_ok | 223 | jnz .Lsysc_nr_ok |
224 | # svc 0: system call number in %r1 | 224 | # svc 0: system call number in %r1 |
225 | llgfr %r1,%r1 # clear high word in r1 | 225 | llgfr %r1,%r1 # clear high word in r1 |
226 | cghi %r1,NR_syscalls | 226 | cghi %r1,NR_syscalls |
227 | jnl sysc_nr_ok | 227 | jnl .Lsysc_nr_ok |
228 | sth %r1,__PT_INT_CODE+2(%r11) | 228 | sth %r1,__PT_INT_CODE+2(%r11) |
229 | slag %r8,%r1,2 | 229 | slag %r8,%r1,2 |
230 | sysc_nr_ok: | 230 | .Lsysc_nr_ok: |
231 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 231 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
232 | stg %r2,__PT_ORIG_GPR2(%r11) | 232 | stg %r2,__PT_ORIG_GPR2(%r11) |
233 | stg %r7,STACK_FRAME_OVERHEAD(%r15) | 233 | stg %r7,STACK_FRAME_OVERHEAD(%r15) |
234 | lgf %r9,0(%r8,%r10) # get system call add. | 234 | lgf %r9,0(%r8,%r10) # get system call add. |
235 | tm __TI_flags+7(%r12),_TIF_TRACE | 235 | tm __TI_flags+7(%r12),_TIF_TRACE |
236 | jnz sysc_tracesys | 236 | jnz .Lsysc_tracesys |
237 | basr %r14,%r9 # call sys_xxxx | 237 | basr %r14,%r9 # call sys_xxxx |
238 | stg %r2,__PT_R2(%r11) # store return value | 238 | stg %r2,__PT_R2(%r11) # store return value |
239 | 239 | ||
240 | sysc_return: | 240 | .Lsysc_return: |
241 | LOCKDEP_SYS_EXIT | 241 | LOCKDEP_SYS_EXIT |
242 | sysc_tif: | 242 | .Lsysc_tif: |
243 | tm __PT_PSW+1(%r11),0x01 # returning to user ? | 243 | tm __PT_PSW+1(%r11),0x01 # returning to user ? |
244 | jno sysc_restore | 244 | jno .Lsysc_restore |
245 | tm __PT_FLAGS+7(%r11),_PIF_WORK | 245 | tm __PT_FLAGS+7(%r11),_PIF_WORK |
246 | jnz sysc_work | 246 | jnz .Lsysc_work |
247 | tm __TI_flags+7(%r12),_TIF_WORK | 247 | tm __TI_flags+7(%r12),_TIF_WORK |
248 | jnz sysc_work # check for work | 248 | jnz .Lsysc_work # check for work |
249 | tm __LC_CPU_FLAGS+7,_CIF_WORK | 249 | tm __LC_CPU_FLAGS+7,_CIF_WORK |
250 | jnz sysc_work | 250 | jnz .Lsysc_work |
251 | sysc_restore: | 251 | .Lsysc_restore: |
252 | lg %r14,__LC_VDSO_PER_CPU | 252 | lg %r14,__LC_VDSO_PER_CPU |
253 | lmg %r0,%r10,__PT_R0(%r11) | 253 | lmg %r0,%r10,__PT_R0(%r11) |
254 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) | 254 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) |
@@ -256,101 +256,101 @@ sysc_restore: | |||
256 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER | 256 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER |
257 | lmg %r11,%r15,__PT_R11(%r11) | 257 | lmg %r11,%r15,__PT_R11(%r11) |
258 | lpswe __LC_RETURN_PSW | 258 | lpswe __LC_RETURN_PSW |
259 | sysc_done: | 259 | .Lsysc_done: |
260 | 260 | ||
261 | # | 261 | # |
262 | # One of the work bits is on. Find out which one. | 262 | # One of the work bits is on. Find out which one. |
263 | # | 263 | # |
264 | sysc_work: | 264 | .Lsysc_work: |
265 | tm __LC_CPU_FLAGS+7,_CIF_MCCK_PENDING | 265 | tm __LC_CPU_FLAGS+7,_CIF_MCCK_PENDING |
266 | jo sysc_mcck_pending | 266 | jo .Lsysc_mcck_pending |
267 | tm __TI_flags+7(%r12),_TIF_NEED_RESCHED | 267 | tm __TI_flags+7(%r12),_TIF_NEED_RESCHED |
268 | jo sysc_reschedule | 268 | jo .Lsysc_reschedule |
269 | #ifdef CONFIG_UPROBES | 269 | #ifdef CONFIG_UPROBES |
270 | tm __TI_flags+7(%r12),_TIF_UPROBE | 270 | tm __TI_flags+7(%r12),_TIF_UPROBE |
271 | jo sysc_uprobe_notify | 271 | jo .Lsysc_uprobe_notify |
272 | #endif | 272 | #endif |
273 | tm __PT_FLAGS+7(%r11),_PIF_PER_TRAP | 273 | tm __PT_FLAGS+7(%r11),_PIF_PER_TRAP |
274 | jo sysc_singlestep | 274 | jo .Lsysc_singlestep |
275 | tm __TI_flags+7(%r12),_TIF_SIGPENDING | 275 | tm __TI_flags+7(%r12),_TIF_SIGPENDING |
276 | jo sysc_sigpending | 276 | jo .Lsysc_sigpending |
277 | tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME | 277 | tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME |
278 | jo sysc_notify_resume | 278 | jo .Lsysc_notify_resume |
279 | tm __LC_CPU_FLAGS+7,_CIF_ASCE | 279 | tm __LC_CPU_FLAGS+7,_CIF_ASCE |
280 | jo sysc_uaccess | 280 | jo .Lsysc_uaccess |
281 | j sysc_return # beware of critical section cleanup | 281 | j .Lsysc_return # beware of critical section cleanup |
282 | 282 | ||
283 | # | 283 | # |
284 | # _TIF_NEED_RESCHED is set, call schedule | 284 | # _TIF_NEED_RESCHED is set, call schedule |
285 | # | 285 | # |
286 | sysc_reschedule: | 286 | .Lsysc_reschedule: |
287 | larl %r14,sysc_return | 287 | larl %r14,.Lsysc_return |
288 | jg schedule | 288 | jg schedule |
289 | 289 | ||
290 | # | 290 | # |
291 | # _CIF_MCCK_PENDING is set, call handler | 291 | # _CIF_MCCK_PENDING is set, call handler |
292 | # | 292 | # |
293 | sysc_mcck_pending: | 293 | .Lsysc_mcck_pending: |
294 | larl %r14,sysc_return | 294 | larl %r14,.Lsysc_return |
295 | jg s390_handle_mcck # TIF bit will be cleared by handler | 295 | jg s390_handle_mcck # TIF bit will be cleared by handler |
296 | 296 | ||
297 | # | 297 | # |
298 | # _CIF_ASCE is set, load user space asce | 298 | # _CIF_ASCE is set, load user space asce |
299 | # | 299 | # |
300 | sysc_uaccess: | 300 | .Lsysc_uaccess: |
301 | ni __LC_CPU_FLAGS+7,255-_CIF_ASCE | 301 | ni __LC_CPU_FLAGS+7,255-_CIF_ASCE |
302 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 302 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
303 | j sysc_return | 303 | j .Lsysc_return |
304 | 304 | ||
305 | # | 305 | # |
306 | # _TIF_SIGPENDING is set, call do_signal | 306 | # _TIF_SIGPENDING is set, call do_signal |
307 | # | 307 | # |
308 | sysc_sigpending: | 308 | .Lsysc_sigpending: |
309 | lgr %r2,%r11 # pass pointer to pt_regs | 309 | lgr %r2,%r11 # pass pointer to pt_regs |
310 | brasl %r14,do_signal | 310 | brasl %r14,do_signal |
311 | tm __PT_FLAGS+7(%r11),_PIF_SYSCALL | 311 | tm __PT_FLAGS+7(%r11),_PIF_SYSCALL |
312 | jno sysc_return | 312 | jno .Lsysc_return |
313 | lmg %r2,%r7,__PT_R2(%r11) # load svc arguments | 313 | lmg %r2,%r7,__PT_R2(%r11) # load svc arguments |
314 | lg %r10,__TI_sysc_table(%r12) # address of system call table | 314 | lg %r10,__TI_sysc_table(%r12) # address of system call table |
315 | lghi %r8,0 # svc 0 returns -ENOSYS | 315 | lghi %r8,0 # svc 0 returns -ENOSYS |
316 | llgh %r1,__PT_INT_CODE+2(%r11) # load new svc number | 316 | llgh %r1,__PT_INT_CODE+2(%r11) # load new svc number |
317 | cghi %r1,NR_syscalls | 317 | cghi %r1,NR_syscalls |
318 | jnl sysc_nr_ok # invalid svc number -> do svc 0 | 318 | jnl .Lsysc_nr_ok # invalid svc number -> do svc 0 |
319 | slag %r8,%r1,2 | 319 | slag %r8,%r1,2 |
320 | j sysc_nr_ok # restart svc | 320 | j .Lsysc_nr_ok # restart svc |
321 | 321 | ||
322 | # | 322 | # |
323 | # _TIF_NOTIFY_RESUME is set, call do_notify_resume | 323 | # _TIF_NOTIFY_RESUME is set, call do_notify_resume |
324 | # | 324 | # |
325 | sysc_notify_resume: | 325 | .Lsysc_notify_resume: |
326 | lgr %r2,%r11 # pass pointer to pt_regs | 326 | lgr %r2,%r11 # pass pointer to pt_regs |
327 | larl %r14,sysc_return | 327 | larl %r14,.Lsysc_return |
328 | jg do_notify_resume | 328 | jg do_notify_resume |
329 | 329 | ||
330 | # | 330 | # |
331 | # _TIF_UPROBE is set, call uprobe_notify_resume | 331 | # _TIF_UPROBE is set, call uprobe_notify_resume |
332 | # | 332 | # |
333 | #ifdef CONFIG_UPROBES | 333 | #ifdef CONFIG_UPROBES |
334 | sysc_uprobe_notify: | 334 | .Lsysc_uprobe_notify: |
335 | lgr %r2,%r11 # pass pointer to pt_regs | 335 | lgr %r2,%r11 # pass pointer to pt_regs |
336 | larl %r14,sysc_return | 336 | larl %r14,.Lsysc_return |
337 | jg uprobe_notify_resume | 337 | jg uprobe_notify_resume |
338 | #endif | 338 | #endif |
339 | 339 | ||
340 | # | 340 | # |
341 | # _PIF_PER_TRAP is set, call do_per_trap | 341 | # _PIF_PER_TRAP is set, call do_per_trap |
342 | # | 342 | # |
343 | sysc_singlestep: | 343 | .Lsysc_singlestep: |
344 | ni __PT_FLAGS+7(%r11),255-_PIF_PER_TRAP | 344 | ni __PT_FLAGS+7(%r11),255-_PIF_PER_TRAP |
345 | lgr %r2,%r11 # pass pointer to pt_regs | 345 | lgr %r2,%r11 # pass pointer to pt_regs |
346 | larl %r14,sysc_return | 346 | larl %r14,.Lsysc_return |
347 | jg do_per_trap | 347 | jg do_per_trap |
348 | 348 | ||
349 | # | 349 | # |
350 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before | 350 | # call tracehook_report_syscall_entry/tracehook_report_syscall_exit before |
351 | # and after the system call | 351 | # and after the system call |
352 | # | 352 | # |
353 | sysc_tracesys: | 353 | .Lsysc_tracesys: |
354 | lgr %r2,%r11 # pass pointer to pt_regs | 354 | lgr %r2,%r11 # pass pointer to pt_regs |
355 | la %r3,0 | 355 | la %r3,0 |
356 | llgh %r0,__PT_INT_CODE+2(%r11) | 356 | llgh %r0,__PT_INT_CODE+2(%r11) |
@@ -358,20 +358,20 @@ sysc_tracesys: | |||
358 | brasl %r14,do_syscall_trace_enter | 358 | brasl %r14,do_syscall_trace_enter |
359 | lghi %r0,NR_syscalls | 359 | lghi %r0,NR_syscalls |
360 | clgr %r0,%r2 | 360 | clgr %r0,%r2 |
361 | jnh sysc_tracenogo | 361 | jnh .Lsysc_tracenogo |
362 | sllg %r8,%r2,2 | 362 | sllg %r8,%r2,2 |
363 | lgf %r9,0(%r8,%r10) | 363 | lgf %r9,0(%r8,%r10) |
364 | sysc_tracego: | 364 | .Lsysc_tracego: |
365 | lmg %r3,%r7,__PT_R3(%r11) | 365 | lmg %r3,%r7,__PT_R3(%r11) |
366 | stg %r7,STACK_FRAME_OVERHEAD(%r15) | 366 | stg %r7,STACK_FRAME_OVERHEAD(%r15) |
367 | lg %r2,__PT_ORIG_GPR2(%r11) | 367 | lg %r2,__PT_ORIG_GPR2(%r11) |
368 | basr %r14,%r9 # call sys_xxx | 368 | basr %r14,%r9 # call sys_xxx |
369 | stg %r2,__PT_R2(%r11) # store return value | 369 | stg %r2,__PT_R2(%r11) # store return value |
370 | sysc_tracenogo: | 370 | .Lsysc_tracenogo: |
371 | tm __TI_flags+7(%r12),_TIF_TRACE | 371 | tm __TI_flags+7(%r12),_TIF_TRACE |
372 | jz sysc_return | 372 | jz .Lsysc_return |
373 | lgr %r2,%r11 # pass pointer to pt_regs | 373 | lgr %r2,%r11 # pass pointer to pt_regs |
374 | larl %r14,sysc_return | 374 | larl %r14,.Lsysc_return |
375 | jg do_syscall_trace_exit | 375 | jg do_syscall_trace_exit |
376 | 376 | ||
377 | # | 377 | # |
@@ -384,13 +384,13 @@ ENTRY(ret_from_fork) | |||
384 | TRACE_IRQS_ON | 384 | TRACE_IRQS_ON |
385 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 385 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
386 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? | 386 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? |
387 | jne sysc_tracenogo | 387 | jne .Lsysc_tracenogo |
388 | # it's a kernel thread | 388 | # it's a kernel thread |
389 | lmg %r9,%r10,__PT_R9(%r11) # load gprs | 389 | lmg %r9,%r10,__PT_R9(%r11) # load gprs |
390 | ENTRY(kernel_thread_starter) | 390 | ENTRY(kernel_thread_starter) |
391 | la %r2,0(%r10) | 391 | la %r2,0(%r10) |
392 | basr %r14,%r9 | 392 | basr %r14,%r9 |
393 | j sysc_tracenogo | 393 | j .Lsysc_tracenogo |
394 | 394 | ||
395 | /* | 395 | /* |
396 | * Program check handler routine | 396 | * Program check handler routine |
@@ -409,7 +409,7 @@ ENTRY(pgm_check_handler) | |||
409 | tmhh %r8,0x4000 # PER bit set in old PSW ? | 409 | tmhh %r8,0x4000 # PER bit set in old PSW ? |
410 | jnz 0f # -> enabled, can't be a double fault | 410 | jnz 0f # -> enabled, can't be a double fault |
411 | tm __LC_PGM_ILC+3,0x80 # check for per exception | 411 | tm __LC_PGM_ILC+3,0x80 # check for per exception |
412 | jnz pgm_svcper # -> single stepped svc | 412 | jnz .Lpgm_svcper # -> single stepped svc |
413 | 0: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC | 413 | 0: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC |
414 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 414 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
415 | j 2f | 415 | j 2f |
@@ -432,7 +432,7 @@ ENTRY(pgm_check_handler) | |||
432 | tm __LC_PGM_ILC+3,0x80 # check for per exception | 432 | tm __LC_PGM_ILC+3,0x80 # check for per exception |
433 | jz 0f | 433 | jz 0f |
434 | tmhh %r8,0x0001 # kernel per event ? | 434 | tmhh %r8,0x0001 # kernel per event ? |
435 | jz pgm_kprobe | 435 | jz .Lpgm_kprobe |
436 | oi __PT_FLAGS+7(%r11),_PIF_PER_TRAP | 436 | oi __PT_FLAGS+7(%r11),_PIF_PER_TRAP |
437 | mvc __THREAD_per_address(8,%r14),__LC_PER_ADDRESS | 437 | mvc __THREAD_per_address(8,%r14),__LC_PER_ADDRESS |
438 | mvc __THREAD_per_cause(2,%r14),__LC_PER_CODE | 438 | mvc __THREAD_per_cause(2,%r14),__LC_PER_CODE |
@@ -443,31 +443,31 @@ ENTRY(pgm_check_handler) | |||
443 | llgh %r10,__PT_INT_CODE+2(%r11) | 443 | llgh %r10,__PT_INT_CODE+2(%r11) |
444 | nill %r10,0x007f | 444 | nill %r10,0x007f |
445 | sll %r10,2 | 445 | sll %r10,2 |
446 | je sysc_return | 446 | je .Lsysc_return |
447 | lgf %r1,0(%r10,%r1) # load address of handler routine | 447 | lgf %r1,0(%r10,%r1) # load address of handler routine |
448 | lgr %r2,%r11 # pass pointer to pt_regs | 448 | lgr %r2,%r11 # pass pointer to pt_regs |
449 | basr %r14,%r1 # branch to interrupt-handler | 449 | basr %r14,%r1 # branch to interrupt-handler |
450 | j sysc_return | 450 | j .Lsysc_return |
451 | 451 | ||
452 | # | 452 | # |
453 | # PER event in supervisor state, must be kprobes | 453 | # PER event in supervisor state, must be kprobes |
454 | # | 454 | # |
455 | pgm_kprobe: | 455 | .Lpgm_kprobe: |
456 | REENABLE_IRQS | 456 | REENABLE_IRQS |
457 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 457 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
458 | lgr %r2,%r11 # pass pointer to pt_regs | 458 | lgr %r2,%r11 # pass pointer to pt_regs |
459 | brasl %r14,do_per_trap | 459 | brasl %r14,do_per_trap |
460 | j sysc_return | 460 | j .Lsysc_return |
461 | 461 | ||
462 | # | 462 | # |
463 | # single stepped system call | 463 | # single stepped system call |
464 | # | 464 | # |
465 | pgm_svcper: | 465 | .Lpgm_svcper: |
466 | mvc __LC_RETURN_PSW(8),__LC_SVC_NEW_PSW | 466 | mvc __LC_RETURN_PSW(8),__LC_SVC_NEW_PSW |
467 | larl %r14,sysc_per | 467 | larl %r14,.Lsysc_per |
468 | stg %r14,__LC_RETURN_PSW+8 | 468 | stg %r14,__LC_RETURN_PSW+8 |
469 | lghi %r14,_PIF_SYSCALL | _PIF_PER_TRAP | 469 | lghi %r14,_PIF_SYSCALL | _PIF_PER_TRAP |
470 | lpswe __LC_RETURN_PSW # branch to sysc_per and enable irqs | 470 | lpswe __LC_RETURN_PSW # branch to .Lsysc_per and enable irqs |
471 | 471 | ||
472 | /* | 472 | /* |
473 | * IO interrupt handler routine | 473 | * IO interrupt handler routine |
@@ -483,10 +483,10 @@ ENTRY(io_int_handler) | |||
483 | HANDLE_SIE_INTERCEPT %r14,2 | 483 | HANDLE_SIE_INTERCEPT %r14,2 |
484 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT | 484 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT |
485 | tmhh %r8,0x0001 # interrupting from user? | 485 | tmhh %r8,0x0001 # interrupting from user? |
486 | jz io_skip | 486 | jz .Lio_skip |
487 | UPDATE_VTIME %r14,__LC_ASYNC_ENTER_TIMER | 487 | UPDATE_VTIME %r14,__LC_ASYNC_ENTER_TIMER |
488 | LAST_BREAK %r14 | 488 | LAST_BREAK %r14 |
489 | io_skip: | 489 | .Lio_skip: |
490 | stmg %r0,%r7,__PT_R0(%r11) | 490 | stmg %r0,%r7,__PT_R0(%r11) |
491 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC | 491 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC |
492 | stmg %r8,%r9,__PT_PSW(%r11) | 492 | stmg %r8,%r9,__PT_PSW(%r11) |
@@ -494,29 +494,29 @@ io_skip: | |||
494 | xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) | 494 | xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) |
495 | TRACE_IRQS_OFF | 495 | TRACE_IRQS_OFF |
496 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 496 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
497 | io_loop: | 497 | .Lio_loop: |
498 | lgr %r2,%r11 # pass pointer to pt_regs | 498 | lgr %r2,%r11 # pass pointer to pt_regs |
499 | lghi %r3,IO_INTERRUPT | 499 | lghi %r3,IO_INTERRUPT |
500 | tm __PT_INT_CODE+8(%r11),0x80 # adapter interrupt ? | 500 | tm __PT_INT_CODE+8(%r11),0x80 # adapter interrupt ? |
501 | jz io_call | 501 | jz .Lio_call |
502 | lghi %r3,THIN_INTERRUPT | 502 | lghi %r3,THIN_INTERRUPT |
503 | io_call: | 503 | .Lio_call: |
504 | brasl %r14,do_IRQ | 504 | brasl %r14,do_IRQ |
505 | tm __LC_MACHINE_FLAGS+6,0x10 # MACHINE_FLAG_LPAR | 505 | tm __LC_MACHINE_FLAGS+6,0x10 # MACHINE_FLAG_LPAR |
506 | jz io_return | 506 | jz .Lio_return |
507 | tpi 0 | 507 | tpi 0 |
508 | jz io_return | 508 | jz .Lio_return |
509 | mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID | 509 | mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID |
510 | j io_loop | 510 | j .Lio_loop |
511 | io_return: | 511 | .Lio_return: |
512 | LOCKDEP_SYS_EXIT | 512 | LOCKDEP_SYS_EXIT |
513 | TRACE_IRQS_ON | 513 | TRACE_IRQS_ON |
514 | io_tif: | 514 | .Lio_tif: |
515 | tm __TI_flags+7(%r12),_TIF_WORK | 515 | tm __TI_flags+7(%r12),_TIF_WORK |
516 | jnz io_work # there is work to do (signals etc.) | 516 | jnz .Lio_work # there is work to do (signals etc.) |
517 | tm __LC_CPU_FLAGS+7,_CIF_WORK | 517 | tm __LC_CPU_FLAGS+7,_CIF_WORK |
518 | jnz io_work | 518 | jnz .Lio_work |
519 | io_restore: | 519 | .Lio_restore: |
520 | lg %r14,__LC_VDSO_PER_CPU | 520 | lg %r14,__LC_VDSO_PER_CPU |
521 | lmg %r0,%r10,__PT_R0(%r11) | 521 | lmg %r0,%r10,__PT_R0(%r11) |
522 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) | 522 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) |
@@ -524,7 +524,7 @@ io_restore: | |||
524 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER | 524 | mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER |
525 | lmg %r11,%r15,__PT_R11(%r11) | 525 | lmg %r11,%r15,__PT_R11(%r11) |
526 | lpswe __LC_RETURN_PSW | 526 | lpswe __LC_RETURN_PSW |
527 | io_done: | 527 | .Lio_done: |
528 | 528 | ||
529 | # | 529 | # |
530 | # There is work todo, find out in which context we have been interrupted: | 530 | # There is work todo, find out in which context we have been interrupted: |
@@ -535,15 +535,15 @@ io_done: | |||
535 | # the preemption counter and if it is zero call preempt_schedule_irq | 535 | # the preemption counter and if it is zero call preempt_schedule_irq |
536 | # Before any work can be done, a switch to the kernel stack is required. | 536 | # Before any work can be done, a switch to the kernel stack is required. |
537 | # | 537 | # |
538 | io_work: | 538 | .Lio_work: |
539 | tm __PT_PSW+1(%r11),0x01 # returning to user ? | 539 | tm __PT_PSW+1(%r11),0x01 # returning to user ? |
540 | jo io_work_user # yes -> do resched & signal | 540 | jo .Lio_work_user # yes -> do resched & signal |
541 | #ifdef CONFIG_PREEMPT | 541 | #ifdef CONFIG_PREEMPT |
542 | # check for preemptive scheduling | 542 | # check for preemptive scheduling |
543 | icm %r0,15,__TI_precount(%r12) | 543 | icm %r0,15,__TI_precount(%r12) |
544 | jnz io_restore # preemption is disabled | 544 | jnz .Lio_restore # preemption is disabled |
545 | tm __TI_flags+7(%r12),_TIF_NEED_RESCHED | 545 | tm __TI_flags+7(%r12),_TIF_NEED_RESCHED |
546 | jno io_restore | 546 | jno .Lio_restore |
547 | # switch to kernel stack | 547 | # switch to kernel stack |
548 | lg %r1,__PT_R15(%r11) | 548 | lg %r1,__PT_R15(%r11) |
549 | aghi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 549 | aghi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
@@ -551,19 +551,19 @@ io_work: | |||
551 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) | 551 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) |
552 | la %r11,STACK_FRAME_OVERHEAD(%r1) | 552 | la %r11,STACK_FRAME_OVERHEAD(%r1) |
553 | lgr %r15,%r1 | 553 | lgr %r15,%r1 |
554 | # TRACE_IRQS_ON already done at io_return, call | 554 | # TRACE_IRQS_ON already done at .Lio_return, call |
555 | # TRACE_IRQS_OFF to keep things symmetrical | 555 | # TRACE_IRQS_OFF to keep things symmetrical |
556 | TRACE_IRQS_OFF | 556 | TRACE_IRQS_OFF |
557 | brasl %r14,preempt_schedule_irq | 557 | brasl %r14,preempt_schedule_irq |
558 | j io_return | 558 | j .Lio_return |
559 | #else | 559 | #else |
560 | j io_restore | 560 | j .Lio_restore |
561 | #endif | 561 | #endif |
562 | 562 | ||
563 | # | 563 | # |
564 | # Need to do work before returning to userspace, switch to kernel stack | 564 | # Need to do work before returning to userspace, switch to kernel stack |
565 | # | 565 | # |
566 | io_work_user: | 566 | .Lio_work_user: |
567 | lg %r1,__LC_KERNEL_STACK | 567 | lg %r1,__LC_KERNEL_STACK |
568 | mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) | 568 | mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) |
569 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) | 569 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) |
@@ -573,70 +573,70 @@ io_work_user: | |||
573 | # | 573 | # |
574 | # One of the work bits is on. Find out which one. | 574 | # One of the work bits is on. Find out which one. |
575 | # | 575 | # |
576 | io_work_tif: | 576 | .Lio_work_tif: |
577 | tm __LC_CPU_FLAGS+7,_CIF_MCCK_PENDING | 577 | tm __LC_CPU_FLAGS+7,_CIF_MCCK_PENDING |
578 | jo io_mcck_pending | 578 | jo .Lio_mcck_pending |
579 | tm __TI_flags+7(%r12),_TIF_NEED_RESCHED | 579 | tm __TI_flags+7(%r12),_TIF_NEED_RESCHED |
580 | jo io_reschedule | 580 | jo .Lio_reschedule |
581 | tm __TI_flags+7(%r12),_TIF_SIGPENDING | 581 | tm __TI_flags+7(%r12),_TIF_SIGPENDING |
582 | jo io_sigpending | 582 | jo .Lio_sigpending |
583 | tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME | 583 | tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME |
584 | jo io_notify_resume | 584 | jo .Lio_notify_resume |
585 | tm __LC_CPU_FLAGS+7,_CIF_ASCE | 585 | tm __LC_CPU_FLAGS+7,_CIF_ASCE |
586 | jo io_uaccess | 586 | jo .Lio_uaccess |
587 | j io_return # beware of critical section cleanup | 587 | j .Lio_return # beware of critical section cleanup |
588 | 588 | ||
589 | # | 589 | # |
590 | # _CIF_MCCK_PENDING is set, call handler | 590 | # _CIF_MCCK_PENDING is set, call handler |
591 | # | 591 | # |
592 | io_mcck_pending: | 592 | .Lio_mcck_pending: |
593 | # TRACE_IRQS_ON already done at io_return | 593 | # TRACE_IRQS_ON already done at .Lio_return |
594 | brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler | 594 | brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler |
595 | TRACE_IRQS_OFF | 595 | TRACE_IRQS_OFF |
596 | j io_return | 596 | j .Lio_return |
597 | 597 | ||
598 | # | 598 | # |
599 | # _CIF_ASCE is set, load user space asce | 599 | # _CIF_ASCE is set, load user space asce |
600 | # | 600 | # |
601 | io_uaccess: | 601 | .Lio_uaccess: |
602 | ni __LC_CPU_FLAGS+7,255-_CIF_ASCE | 602 | ni __LC_CPU_FLAGS+7,255-_CIF_ASCE |
603 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 603 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
604 | j io_return | 604 | j .Lio_return |
605 | 605 | ||
606 | # | 606 | # |
607 | # _TIF_NEED_RESCHED is set, call schedule | 607 | # _TIF_NEED_RESCHED is set, call schedule |
608 | # | 608 | # |
609 | io_reschedule: | 609 | .Lio_reschedule: |
610 | # TRACE_IRQS_ON already done at io_return | 610 | # TRACE_IRQS_ON already done at .Lio_return |
611 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 611 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
612 | brasl %r14,schedule # call scheduler | 612 | brasl %r14,schedule # call scheduler |
613 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | 613 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
614 | TRACE_IRQS_OFF | 614 | TRACE_IRQS_OFF |
615 | j io_return | 615 | j .Lio_return |
616 | 616 | ||
617 | # | 617 | # |
618 | # _TIF_SIGPENDING or is set, call do_signal | 618 | # _TIF_SIGPENDING or is set, call do_signal |
619 | # | 619 | # |
620 | io_sigpending: | 620 | .Lio_sigpending: |
621 | # TRACE_IRQS_ON already done at io_return | 621 | # TRACE_IRQS_ON already done at .Lio_return |
622 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 622 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
623 | lgr %r2,%r11 # pass pointer to pt_regs | 623 | lgr %r2,%r11 # pass pointer to pt_regs |
624 | brasl %r14,do_signal | 624 | brasl %r14,do_signal |
625 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | 625 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
626 | TRACE_IRQS_OFF | 626 | TRACE_IRQS_OFF |
627 | j io_return | 627 | j .Lio_return |
628 | 628 | ||
629 | # | 629 | # |
630 | # _TIF_NOTIFY_RESUME or is set, call do_notify_resume | 630 | # _TIF_NOTIFY_RESUME or is set, call do_notify_resume |
631 | # | 631 | # |
632 | io_notify_resume: | 632 | .Lio_notify_resume: |
633 | # TRACE_IRQS_ON already done at io_return | 633 | # TRACE_IRQS_ON already done at .Lio_return |
634 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 634 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
635 | lgr %r2,%r11 # pass pointer to pt_regs | 635 | lgr %r2,%r11 # pass pointer to pt_regs |
636 | brasl %r14,do_notify_resume | 636 | brasl %r14,do_notify_resume |
637 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | 637 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
638 | TRACE_IRQS_OFF | 638 | TRACE_IRQS_OFF |
639 | j io_return | 639 | j .Lio_return |
640 | 640 | ||
641 | /* | 641 | /* |
642 | * External interrupt handler routine | 642 | * External interrupt handler routine |
@@ -652,10 +652,10 @@ ENTRY(ext_int_handler) | |||
652 | HANDLE_SIE_INTERCEPT %r14,3 | 652 | HANDLE_SIE_INTERCEPT %r14,3 |
653 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT | 653 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT |
654 | tmhh %r8,0x0001 # interrupting from user ? | 654 | tmhh %r8,0x0001 # interrupting from user ? |
655 | jz ext_skip | 655 | jz .Lext_skip |
656 | UPDATE_VTIME %r14,__LC_ASYNC_ENTER_TIMER | 656 | UPDATE_VTIME %r14,__LC_ASYNC_ENTER_TIMER |
657 | LAST_BREAK %r14 | 657 | LAST_BREAK %r14 |
658 | ext_skip: | 658 | .Lext_skip: |
659 | stmg %r0,%r7,__PT_R0(%r11) | 659 | stmg %r0,%r7,__PT_R0(%r11) |
660 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC | 660 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC |
661 | stmg %r8,%r9,__PT_PSW(%r11) | 661 | stmg %r8,%r9,__PT_PSW(%r11) |
@@ -669,23 +669,23 @@ ext_skip: | |||
669 | lgr %r2,%r11 # pass pointer to pt_regs | 669 | lgr %r2,%r11 # pass pointer to pt_regs |
670 | lghi %r3,EXT_INTERRUPT | 670 | lghi %r3,EXT_INTERRUPT |
671 | brasl %r14,do_IRQ | 671 | brasl %r14,do_IRQ |
672 | j io_return | 672 | j .Lio_return |
673 | 673 | ||
674 | /* | 674 | /* |
675 | * Load idle PSW. The second "half" of this function is in cleanup_idle. | 675 | * Load idle PSW. The second "half" of this function is in .Lcleanup_idle. |
676 | */ | 676 | */ |
677 | ENTRY(psw_idle) | 677 | ENTRY(psw_idle) |
678 | stg %r3,__SF_EMPTY(%r15) | 678 | stg %r3,__SF_EMPTY(%r15) |
679 | larl %r1,psw_idle_lpsw+4 | 679 | larl %r1,.Lpsw_idle_lpsw+4 |
680 | stg %r1,__SF_EMPTY+8(%r15) | 680 | stg %r1,__SF_EMPTY+8(%r15) |
681 | STCK __CLOCK_IDLE_ENTER(%r2) | 681 | STCK __CLOCK_IDLE_ENTER(%r2) |
682 | stpt __TIMER_IDLE_ENTER(%r2) | 682 | stpt __TIMER_IDLE_ENTER(%r2) |
683 | psw_idle_lpsw: | 683 | .Lpsw_idle_lpsw: |
684 | lpswe __SF_EMPTY(%r15) | 684 | lpswe __SF_EMPTY(%r15) |
685 | br %r14 | 685 | br %r14 |
686 | psw_idle_end: | 686 | .Lpsw_idle_end: |
687 | 687 | ||
688 | __critical_end: | 688 | .L__critical_end: |
689 | 689 | ||
690 | /* | 690 | /* |
691 | * Machine check handler routines | 691 | * Machine check handler routines |
@@ -701,7 +701,7 @@ ENTRY(mcck_int_handler) | |||
701 | lmg %r8,%r9,__LC_MCK_OLD_PSW | 701 | lmg %r8,%r9,__LC_MCK_OLD_PSW |
702 | HANDLE_SIE_INTERCEPT %r14,4 | 702 | HANDLE_SIE_INTERCEPT %r14,4 |
703 | tm __LC_MCCK_CODE,0x80 # system damage? | 703 | tm __LC_MCCK_CODE,0x80 # system damage? |
704 | jo mcck_panic # yes -> rest of mcck code invalid | 704 | jo .Lmcck_panic # yes -> rest of mcck code invalid |
705 | lghi %r14,__LC_CPU_TIMER_SAVE_AREA | 705 | lghi %r14,__LC_CPU_TIMER_SAVE_AREA |
706 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) | 706 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) |
707 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | 707 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? |
@@ -719,13 +719,13 @@ ENTRY(mcck_int_handler) | |||
719 | 2: spt 0(%r14) | 719 | 2: spt 0(%r14) |
720 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) | 720 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) |
721 | 3: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | 721 | 3: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
722 | jno mcck_panic # no -> skip cleanup critical | 722 | jno .Lmcck_panic # no -> skip cleanup critical |
723 | SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+64,__LC_PANIC_STACK,PAGE_SHIFT | 723 | SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+64,__LC_PANIC_STACK,PAGE_SHIFT |
724 | tm %r8,0x0001 # interrupting from user ? | 724 | tm %r8,0x0001 # interrupting from user ? |
725 | jz mcck_skip | 725 | jz .Lmcck_skip |
726 | UPDATE_VTIME %r14,__LC_MCCK_ENTER_TIMER | 726 | UPDATE_VTIME %r14,__LC_MCCK_ENTER_TIMER |
727 | LAST_BREAK %r14 | 727 | LAST_BREAK %r14 |
728 | mcck_skip: | 728 | .Lmcck_skip: |
729 | lghi %r14,__LC_GPREGS_SAVE_AREA+64 | 729 | lghi %r14,__LC_GPREGS_SAVE_AREA+64 |
730 | stmg %r0,%r7,__PT_R0(%r11) | 730 | stmg %r0,%r7,__PT_R0(%r11) |
731 | mvc __PT_R8(64,%r11),0(%r14) | 731 | mvc __PT_R8(64,%r11),0(%r14) |
@@ -735,7 +735,7 @@ mcck_skip: | |||
735 | lgr %r2,%r11 # pass pointer to pt_regs | 735 | lgr %r2,%r11 # pass pointer to pt_regs |
736 | brasl %r14,s390_do_machine_check | 736 | brasl %r14,s390_do_machine_check |
737 | tm __PT_PSW+1(%r11),0x01 # returning to user ? | 737 | tm __PT_PSW+1(%r11),0x01 # returning to user ? |
738 | jno mcck_return | 738 | jno .Lmcck_return |
739 | lg %r1,__LC_KERNEL_STACK # switch to kernel stack | 739 | lg %r1,__LC_KERNEL_STACK # switch to kernel stack |
740 | mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) | 740 | mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) |
741 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) | 741 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) |
@@ -743,11 +743,11 @@ mcck_skip: | |||
743 | lgr %r15,%r1 | 743 | lgr %r15,%r1 |
744 | ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off | 744 | ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off |
745 | tm __LC_CPU_FLAGS+7,_CIF_MCCK_PENDING | 745 | tm __LC_CPU_FLAGS+7,_CIF_MCCK_PENDING |
746 | jno mcck_return | 746 | jno .Lmcck_return |
747 | TRACE_IRQS_OFF | 747 | TRACE_IRQS_OFF |
748 | brasl %r14,s390_handle_mcck | 748 | brasl %r14,s390_handle_mcck |
749 | TRACE_IRQS_ON | 749 | TRACE_IRQS_ON |
750 | mcck_return: | 750 | .Lmcck_return: |
751 | lg %r14,__LC_VDSO_PER_CPU | 751 | lg %r14,__LC_VDSO_PER_CPU |
752 | lmg %r0,%r10,__PT_R0(%r11) | 752 | lmg %r0,%r10,__PT_R0(%r11) |
753 | mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW | 753 | mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW |
@@ -758,14 +758,14 @@ mcck_return: | |||
758 | 0: lmg %r11,%r15,__PT_R11(%r11) | 758 | 0: lmg %r11,%r15,__PT_R11(%r11) |
759 | lpswe __LC_RETURN_MCCK_PSW | 759 | lpswe __LC_RETURN_MCCK_PSW |
760 | 760 | ||
761 | mcck_panic: | 761 | .Lmcck_panic: |
762 | lg %r14,__LC_PANIC_STACK | 762 | lg %r14,__LC_PANIC_STACK |
763 | slgr %r14,%r15 | 763 | slgr %r14,%r15 |
764 | srag %r14,%r14,PAGE_SHIFT | 764 | srag %r14,%r14,PAGE_SHIFT |
765 | jz 0f | 765 | jz 0f |
766 | lg %r15,__LC_PANIC_STACK | 766 | lg %r15,__LC_PANIC_STACK |
767 | 0: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 767 | 0: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
768 | j mcck_skip | 768 | j .Lmcck_skip |
769 | 769 | ||
770 | # | 770 | # |
771 | # PSW restart interrupt handler | 771 | # PSW restart interrupt handler |
@@ -815,69 +815,69 @@ stack_overflow: | |||
815 | #endif | 815 | #endif |
816 | 816 | ||
817 | .align 8 | 817 | .align 8 |
818 | cleanup_table: | 818 | .Lcleanup_table: |
819 | .quad system_call | 819 | .quad system_call |
820 | .quad sysc_do_svc | 820 | .quad .Lsysc_do_svc |
821 | .quad sysc_tif | 821 | .quad .Lsysc_tif |
822 | .quad sysc_restore | 822 | .quad .Lsysc_restore |
823 | .quad sysc_done | 823 | .quad .Lsysc_done |
824 | .quad io_tif | 824 | .quad .Lio_tif |
825 | .quad io_restore | 825 | .quad .Lio_restore |
826 | .quad io_done | 826 | .quad .Lio_done |
827 | .quad psw_idle | 827 | .quad psw_idle |
828 | .quad psw_idle_end | 828 | .quad .Lpsw_idle_end |
829 | 829 | ||
830 | cleanup_critical: | 830 | cleanup_critical: |
831 | clg %r9,BASED(cleanup_table) # system_call | 831 | clg %r9,BASED(.Lcleanup_table) # system_call |
832 | jl 0f | 832 | jl 0f |
833 | clg %r9,BASED(cleanup_table+8) # sysc_do_svc | 833 | clg %r9,BASED(.Lcleanup_table+8) # .Lsysc_do_svc |
834 | jl cleanup_system_call | 834 | jl .Lcleanup_system_call |
835 | clg %r9,BASED(cleanup_table+16) # sysc_tif | 835 | clg %r9,BASED(.Lcleanup_table+16) # .Lsysc_tif |
836 | jl 0f | 836 | jl 0f |
837 | clg %r9,BASED(cleanup_table+24) # sysc_restore | 837 | clg %r9,BASED(.Lcleanup_table+24) # .Lsysc_restore |
838 | jl cleanup_sysc_tif | 838 | jl .Lcleanup_sysc_tif |
839 | clg %r9,BASED(cleanup_table+32) # sysc_done | 839 | clg %r9,BASED(.Lcleanup_table+32) # .Lsysc_done |
840 | jl cleanup_sysc_restore | 840 | jl .Lcleanup_sysc_restore |
841 | clg %r9,BASED(cleanup_table+40) # io_tif | 841 | clg %r9,BASED(.Lcleanup_table+40) # .Lio_tif |
842 | jl 0f | 842 | jl 0f |
843 | clg %r9,BASED(cleanup_table+48) # io_restore | 843 | clg %r9,BASED(.Lcleanup_table+48) # .Lio_restore |
844 | jl cleanup_io_tif | 844 | jl .Lcleanup_io_tif |
845 | clg %r9,BASED(cleanup_table+56) # io_done | 845 | clg %r9,BASED(.Lcleanup_table+56) # .Lio_done |
846 | jl cleanup_io_restore | 846 | jl .Lcleanup_io_restore |
847 | clg %r9,BASED(cleanup_table+64) # psw_idle | 847 | clg %r9,BASED(.Lcleanup_table+64) # psw_idle |
848 | jl 0f | 848 | jl 0f |
849 | clg %r9,BASED(cleanup_table+72) # psw_idle_end | 849 | clg %r9,BASED(.Lcleanup_table+72) # .Lpsw_idle_end |
850 | jl cleanup_idle | 850 | jl .Lcleanup_idle |
851 | 0: br %r14 | 851 | 0: br %r14 |
852 | 852 | ||
853 | 853 | ||
854 | cleanup_system_call: | 854 | .Lcleanup_system_call: |
855 | # check if stpt has been executed | 855 | # check if stpt has been executed |
856 | clg %r9,BASED(cleanup_system_call_insn) | 856 | clg %r9,BASED(.Lcleanup_system_call_insn) |
857 | jh 0f | 857 | jh 0f |
858 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER | 858 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER |
859 | cghi %r11,__LC_SAVE_AREA_ASYNC | 859 | cghi %r11,__LC_SAVE_AREA_ASYNC |
860 | je 0f | 860 | je 0f |
861 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER | 861 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER |
862 | 0: # check if stmg has been executed | 862 | 0: # check if stmg has been executed |
863 | clg %r9,BASED(cleanup_system_call_insn+8) | 863 | clg %r9,BASED(.Lcleanup_system_call_insn+8) |
864 | jh 0f | 864 | jh 0f |
865 | mvc __LC_SAVE_AREA_SYNC(64),0(%r11) | 865 | mvc __LC_SAVE_AREA_SYNC(64),0(%r11) |
866 | 0: # check if base register setup + TIF bit load has been done | 866 | 0: # check if base register setup + TIF bit load has been done |
867 | clg %r9,BASED(cleanup_system_call_insn+16) | 867 | clg %r9,BASED(.Lcleanup_system_call_insn+16) |
868 | jhe 0f | 868 | jhe 0f |
869 | # set up saved registers r10 and r12 | 869 | # set up saved registers r10 and r12 |
870 | stg %r10,16(%r11) # r10 last break | 870 | stg %r10,16(%r11) # r10 last break |
871 | stg %r12,32(%r11) # r12 thread-info pointer | 871 | stg %r12,32(%r11) # r12 thread-info pointer |
872 | 0: # check if the user time update has been done | 872 | 0: # check if the user time update has been done |
873 | clg %r9,BASED(cleanup_system_call_insn+24) | 873 | clg %r9,BASED(.Lcleanup_system_call_insn+24) |
874 | jh 0f | 874 | jh 0f |
875 | lg %r15,__LC_EXIT_TIMER | 875 | lg %r15,__LC_EXIT_TIMER |
876 | slg %r15,__LC_SYNC_ENTER_TIMER | 876 | slg %r15,__LC_SYNC_ENTER_TIMER |
877 | alg %r15,__LC_USER_TIMER | 877 | alg %r15,__LC_USER_TIMER |
878 | stg %r15,__LC_USER_TIMER | 878 | stg %r15,__LC_USER_TIMER |
879 | 0: # check if the system time update has been done | 879 | 0: # check if the system time update has been done |
880 | clg %r9,BASED(cleanup_system_call_insn+32) | 880 | clg %r9,BASED(.Lcleanup_system_call_insn+32) |
881 | jh 0f | 881 | jh 0f |
882 | lg %r15,__LC_LAST_UPDATE_TIMER | 882 | lg %r15,__LC_LAST_UPDATE_TIMER |
883 | slg %r15,__LC_EXIT_TIMER | 883 | slg %r15,__LC_EXIT_TIMER |
@@ -904,21 +904,21 @@ cleanup_system_call: | |||
904 | # setup saved register r15 | 904 | # setup saved register r15 |
905 | stg %r15,56(%r11) # r15 stack pointer | 905 | stg %r15,56(%r11) # r15 stack pointer |
906 | # set new psw address and exit | 906 | # set new psw address and exit |
907 | larl %r9,sysc_do_svc | 907 | larl %r9,.Lsysc_do_svc |
908 | br %r14 | 908 | br %r14 |
909 | cleanup_system_call_insn: | 909 | .Lcleanup_system_call_insn: |
910 | .quad system_call | 910 | .quad system_call |
911 | .quad sysc_stmg | 911 | .quad .Lsysc_stmg |
912 | .quad sysc_per | 912 | .quad .Lsysc_per |
913 | .quad sysc_vtime+18 | 913 | .quad .Lsysc_vtime+18 |
914 | .quad sysc_vtime+42 | 914 | .quad .Lsysc_vtime+42 |
915 | 915 | ||
916 | cleanup_sysc_tif: | 916 | .Lcleanup_sysc_tif: |
917 | larl %r9,sysc_tif | 917 | larl %r9,.Lsysc_tif |
918 | br %r14 | 918 | br %r14 |
919 | 919 | ||
920 | cleanup_sysc_restore: | 920 | .Lcleanup_sysc_restore: |
921 | clg %r9,BASED(cleanup_sysc_restore_insn) | 921 | clg %r9,BASED(.Lcleanup_sysc_restore_insn) |
922 | je 0f | 922 | je 0f |
923 | lg %r9,24(%r11) # get saved pointer to pt_regs | 923 | lg %r9,24(%r11) # get saved pointer to pt_regs |
924 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) | 924 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) |
@@ -926,15 +926,15 @@ cleanup_sysc_restore: | |||
926 | lmg %r0,%r7,__PT_R0(%r9) | 926 | lmg %r0,%r7,__PT_R0(%r9) |
927 | 0: lmg %r8,%r9,__LC_RETURN_PSW | 927 | 0: lmg %r8,%r9,__LC_RETURN_PSW |
928 | br %r14 | 928 | br %r14 |
929 | cleanup_sysc_restore_insn: | 929 | .Lcleanup_sysc_restore_insn: |
930 | .quad sysc_done - 4 | 930 | .quad .Lsysc_done - 4 |
931 | 931 | ||
932 | cleanup_io_tif: | 932 | .Lcleanup_io_tif: |
933 | larl %r9,io_tif | 933 | larl %r9,.Lio_tif |
934 | br %r14 | 934 | br %r14 |
935 | 935 | ||
936 | cleanup_io_restore: | 936 | .Lcleanup_io_restore: |
937 | clg %r9,BASED(cleanup_io_restore_insn) | 937 | clg %r9,BASED(.Lcleanup_io_restore_insn) |
938 | je 0f | 938 | je 0f |
939 | lg %r9,24(%r11) # get saved r11 pointer to pt_regs | 939 | lg %r9,24(%r11) # get saved r11 pointer to pt_regs |
940 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) | 940 | mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) |
@@ -942,10 +942,10 @@ cleanup_io_restore: | |||
942 | lmg %r0,%r7,__PT_R0(%r9) | 942 | lmg %r0,%r7,__PT_R0(%r9) |
943 | 0: lmg %r8,%r9,__LC_RETURN_PSW | 943 | 0: lmg %r8,%r9,__LC_RETURN_PSW |
944 | br %r14 | 944 | br %r14 |
945 | cleanup_io_restore_insn: | 945 | .Lcleanup_io_restore_insn: |
946 | .quad io_done - 4 | 946 | .quad .Lio_done - 4 |
947 | 947 | ||
948 | cleanup_idle: | 948 | .Lcleanup_idle: |
949 | # copy interrupt clock & cpu timer | 949 | # copy interrupt clock & cpu timer |
950 | mvc __CLOCK_IDLE_EXIT(8,%r2),__LC_INT_CLOCK | 950 | mvc __CLOCK_IDLE_EXIT(8,%r2),__LC_INT_CLOCK |
951 | mvc __TIMER_IDLE_EXIT(8,%r2),__LC_ASYNC_ENTER_TIMER | 951 | mvc __TIMER_IDLE_EXIT(8,%r2),__LC_ASYNC_ENTER_TIMER |
@@ -954,7 +954,7 @@ cleanup_idle: | |||
954 | mvc __CLOCK_IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK | 954 | mvc __CLOCK_IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK |
955 | mvc __TIMER_IDLE_EXIT(8,%r2),__LC_MCCK_ENTER_TIMER | 955 | mvc __TIMER_IDLE_EXIT(8,%r2),__LC_MCCK_ENTER_TIMER |
956 | 0: # check if stck & stpt have been executed | 956 | 0: # check if stck & stpt have been executed |
957 | clg %r9,BASED(cleanup_idle_insn) | 957 | clg %r9,BASED(.Lcleanup_idle_insn) |
958 | jhe 1f | 958 | jhe 1f |
959 | mvc __CLOCK_IDLE_ENTER(8,%r2),__CLOCK_IDLE_EXIT(%r2) | 959 | mvc __CLOCK_IDLE_ENTER(8,%r2),__CLOCK_IDLE_EXIT(%r2) |
960 | mvc __TIMER_IDLE_ENTER(8,%r2),__TIMER_IDLE_EXIT(%r2) | 960 | mvc __TIMER_IDLE_ENTER(8,%r2),__TIMER_IDLE_EXIT(%r2) |
@@ -973,17 +973,17 @@ cleanup_idle: | |||
973 | nihh %r8,0xfcfd # clear irq & wait state bits | 973 | nihh %r8,0xfcfd # clear irq & wait state bits |
974 | lg %r9,48(%r11) # return from psw_idle | 974 | lg %r9,48(%r11) # return from psw_idle |
975 | br %r14 | 975 | br %r14 |
976 | cleanup_idle_insn: | 976 | .Lcleanup_idle_insn: |
977 | .quad psw_idle_lpsw | 977 | .quad .Lpsw_idle_lpsw |
978 | 978 | ||
979 | /* | 979 | /* |
980 | * Integer constants | 980 | * Integer constants |
981 | */ | 981 | */ |
982 | .align 8 | 982 | .align 8 |
983 | .Lcritical_start: | 983 | .Lcritical_start: |
984 | .quad __critical_start | 984 | .quad .L__critical_start |
985 | .Lcritical_length: | 985 | .Lcritical_length: |
986 | .quad __critical_end - __critical_start | 986 | .quad .L__critical_end - .L__critical_start |
987 | 987 | ||
988 | 988 | ||
989 | #if IS_ENABLED(CONFIG_KVM) | 989 | #if IS_ENABLED(CONFIG_KVM) |
@@ -1000,25 +1000,25 @@ ENTRY(sie64a) | |||
1000 | lmg %r0,%r13,0(%r3) # load guest gprs 0-13 | 1000 | lmg %r0,%r13,0(%r3) # load guest gprs 0-13 |
1001 | lg %r14,__LC_GMAP # get gmap pointer | 1001 | lg %r14,__LC_GMAP # get gmap pointer |
1002 | ltgr %r14,%r14 | 1002 | ltgr %r14,%r14 |
1003 | jz sie_gmap | 1003 | jz .Lsie_gmap |
1004 | lctlg %c1,%c1,__GMAP_ASCE(%r14) # load primary asce | 1004 | lctlg %c1,%c1,__GMAP_ASCE(%r14) # load primary asce |
1005 | sie_gmap: | 1005 | .Lsie_gmap: |
1006 | lg %r14,__SF_EMPTY(%r15) # get control block pointer | 1006 | lg %r14,__SF_EMPTY(%r15) # get control block pointer |
1007 | oi __SIE_PROG0C+3(%r14),1 # we are going into SIE now | 1007 | oi __SIE_PROG0C+3(%r14),1 # we are going into SIE now |
1008 | tm __SIE_PROG20+3(%r14),1 # last exit... | 1008 | tm __SIE_PROG20+3(%r14),1 # last exit... |
1009 | jnz sie_done | 1009 | jnz .Lsie_done |
1010 | LPP __SF_EMPTY(%r15) # set guest id | 1010 | LPP __SF_EMPTY(%r15) # set guest id |
1011 | sie 0(%r14) | 1011 | sie 0(%r14) |
1012 | sie_done: | 1012 | .Lsie_done: |
1013 | LPP __SF_EMPTY+16(%r15) # set host id | 1013 | LPP __SF_EMPTY+16(%r15) # set host id |
1014 | ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE | 1014 | ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE |
1015 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 1015 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
1016 | # some program checks are suppressing. C code (e.g. do_protection_exception) | 1016 | # some program checks are suppressing. C code (e.g. do_protection_exception) |
1017 | # will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other | 1017 | # will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other |
1018 | # instructions between sie64a and sie_done should not cause program | 1018 | # instructions between sie64a and .Lsie_done should not cause program |
1019 | # interrupts. So lets use a nop (47 00 00 00) as a landing pad. | 1019 | # interrupts. So lets use a nop (47 00 00 00) as a landing pad. |
1020 | # See also HANDLE_SIE_INTERCEPT | 1020 | # See also HANDLE_SIE_INTERCEPT |
1021 | rewind_pad: | 1021 | .Lrewind_pad: |
1022 | nop 0 | 1022 | nop 0 |
1023 | .globl sie_exit | 1023 | .globl sie_exit |
1024 | sie_exit: | 1024 | sie_exit: |
@@ -1027,19 +1027,19 @@ sie_exit: | |||
1027 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers | 1027 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers |
1028 | lg %r2,__SF_EMPTY+24(%r15) # return exit reason code | 1028 | lg %r2,__SF_EMPTY+24(%r15) # return exit reason code |
1029 | br %r14 | 1029 | br %r14 |
1030 | sie_fault: | 1030 | .Lsie_fault: |
1031 | lghi %r14,-EFAULT | 1031 | lghi %r14,-EFAULT |
1032 | stg %r14,__SF_EMPTY+24(%r15) # set exit reason code | 1032 | stg %r14,__SF_EMPTY+24(%r15) # set exit reason code |
1033 | j sie_exit | 1033 | j sie_exit |
1034 | 1034 | ||
1035 | .align 8 | 1035 | .align 8 |
1036 | .Lsie_critical: | 1036 | .Lsie_critical: |
1037 | .quad sie_gmap | 1037 | .quad .Lsie_gmap |
1038 | .Lsie_critical_length: | 1038 | .Lsie_critical_length: |
1039 | .quad sie_done - sie_gmap | 1039 | .quad .Lsie_done - .Lsie_gmap |
1040 | 1040 | ||
1041 | EX_TABLE(rewind_pad,sie_fault) | 1041 | EX_TABLE(.Lrewind_pad,.Lsie_fault) |
1042 | EX_TABLE(sie_exit,sie_fault) | 1042 | EX_TABLE(sie_exit,.Lsie_fault) |
1043 | #endif | 1043 | #endif |
1044 | 1044 | ||
1045 | .section .rodata, "a" | 1045 | .section .rodata, "a" |
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index ca1cabb3a96c..b86bb8823f15 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/moduleloader.h> | ||
10 | #include <linux/hardirq.h> | 11 | #include <linux/hardirq.h> |
11 | #include <linux/uaccess.h> | 12 | #include <linux/uaccess.h> |
12 | #include <linux/ftrace.h> | 13 | #include <linux/ftrace.h> |
@@ -15,60 +16,39 @@ | |||
15 | #include <linux/kprobes.h> | 16 | #include <linux/kprobes.h> |
16 | #include <trace/syscall.h> | 17 | #include <trace/syscall.h> |
17 | #include <asm/asm-offsets.h> | 18 | #include <asm/asm-offsets.h> |
19 | #include <asm/cacheflush.h> | ||
18 | #include "entry.h" | 20 | #include "entry.h" |
19 | 21 | ||
20 | void mcount_replace_code(void); | ||
21 | void ftrace_disable_code(void); | ||
22 | void ftrace_enable_insn(void); | ||
23 | |||
24 | /* | 22 | /* |
25 | * The mcount code looks like this: | 23 | * The mcount code looks like this: |
26 | * stg %r14,8(%r15) # offset 0 | 24 | * stg %r14,8(%r15) # offset 0 |
27 | * larl %r1,<&counter> # offset 6 | 25 | * larl %r1,<&counter> # offset 6 |
28 | * brasl %r14,_mcount # offset 12 | 26 | * brasl %r14,_mcount # offset 12 |
29 | * lg %r14,8(%r15) # offset 18 | 27 | * lg %r14,8(%r15) # offset 18 |
30 | * Total length is 24 bytes. The complete mcount block initially gets replaced | 28 | * Total length is 24 bytes. Only the first instruction will be patched |
31 | * by ftrace_make_nop. Subsequent calls to ftrace_make_call / ftrace_make_nop | 29 | * by ftrace_make_call / ftrace_make_nop. |
32 | * only patch the jg/lg instruction within the block. | ||
33 | * Note: we do not patch the first instruction to an unconditional branch, | ||
34 | * since that would break kprobes/jprobes. It is easier to leave the larl | ||
35 | * instruction in and only modify the second instruction. | ||
36 | * The enabled ftrace code block looks like this: | 30 | * The enabled ftrace code block looks like this: |
37 | * larl %r0,.+24 # offset 0 | 31 | * > brasl %r0,ftrace_caller # offset 0 |
38 | * > lg %r1,__LC_FTRACE_FUNC # offset 6 | 32 | * larl %r1,<&counter> # offset 6 |
39 | * br %r1 # offset 12 | 33 | * brasl %r14,_mcount # offset 12 |
40 | * brcl 0,0 # offset 14 | 34 | * lg %r14,8(%r15) # offset 18 |
41 | * brc 0,0 # offset 20 | ||
42 | * The ftrace function gets called with a non-standard C function call ABI | 35 | * The ftrace function gets called with a non-standard C function call ABI |
43 | * where r0 contains the return address. It is also expected that the called | 36 | * where r0 contains the return address. It is also expected that the called |
44 | * function only clobbers r0 and r1, but restores r2-r15. | 37 | * function only clobbers r0 and r1, but restores r2-r15. |
38 | * For module code we can't directly jump to ftrace caller, but need a | ||
39 | * trampoline (ftrace_plt), which clobbers also r1. | ||
45 | * The return point of the ftrace function has offset 24, so execution | 40 | * The return point of the ftrace function has offset 24, so execution |
46 | * continues behind the mcount block. | 41 | * continues behind the mcount block. |
47 | * larl %r0,.+24 # offset 0 | 42 | * The disabled ftrace code block looks like this: |
48 | * > jg .+18 # offset 6 | 43 | * > jg .+24 # offset 0 |
49 | * br %r1 # offset 12 | 44 | * larl %r1,<&counter> # offset 6 |
50 | * brcl 0,0 # offset 14 | 45 | * brasl %r14,_mcount # offset 12 |
51 | * brc 0,0 # offset 20 | 46 | * lg %r14,8(%r15) # offset 18 |
52 | * The jg instruction branches to offset 24 to skip as many instructions | 47 | * The jg instruction branches to offset 24 to skip as many instructions |
53 | * as possible. | 48 | * as possible. |
54 | */ | 49 | */ |
55 | asm( | 50 | |
56 | " .align 4\n" | 51 | unsigned long ftrace_plt; |
57 | "mcount_replace_code:\n" | ||
58 | " larl %r0,0f\n" | ||
59 | "ftrace_disable_code:\n" | ||
60 | " jg 0f\n" | ||
61 | " br %r1\n" | ||
62 | " brcl 0,0\n" | ||
63 | " brc 0,0\n" | ||
64 | "0:\n" | ||
65 | " .align 4\n" | ||
66 | "ftrace_enable_insn:\n" | ||
67 | " lg %r1,"__stringify(__LC_FTRACE_FUNC)"\n"); | ||
68 | |||
69 | #define MCOUNT_BLOCK_SIZE 24 | ||
70 | #define MCOUNT_INSN_OFFSET 6 | ||
71 | #define FTRACE_INSN_SIZE 6 | ||
72 | 52 | ||
73 | int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, | 53 | int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, |
74 | unsigned long addr) | 54 | unsigned long addr) |
@@ -79,24 +59,62 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, | |||
79 | int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, | 59 | int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, |
80 | unsigned long addr) | 60 | unsigned long addr) |
81 | { | 61 | { |
82 | /* Initial replacement of the whole mcount block */ | 62 | struct ftrace_insn insn; |
83 | if (addr == MCOUNT_ADDR) { | 63 | unsigned short op; |
84 | if (probe_kernel_write((void *) rec->ip - MCOUNT_INSN_OFFSET, | 64 | void *from, *to; |
85 | mcount_replace_code, | 65 | size_t size; |
86 | MCOUNT_BLOCK_SIZE)) | 66 | |
87 | return -EPERM; | 67 | ftrace_generate_nop_insn(&insn); |
88 | return 0; | 68 | size = sizeof(insn); |
69 | from = &insn; | ||
70 | to = (void *) rec->ip; | ||
71 | if (probe_kernel_read(&op, (void *) rec->ip, sizeof(op))) | ||
72 | return -EFAULT; | ||
73 | /* | ||
74 | * If we find a breakpoint instruction, a kprobe has been placed | ||
75 | * at the beginning of the function. We write the constant | ||
76 | * KPROBE_ON_FTRACE_NOP into the remaining four bytes of the original | ||
77 | * instruction so that the kprobes handler can execute a nop, if it | ||
78 | * reaches this breakpoint. | ||
79 | */ | ||
80 | if (op == BREAKPOINT_INSTRUCTION) { | ||
81 | size -= 2; | ||
82 | from += 2; | ||
83 | to += 2; | ||
84 | insn.disp = KPROBE_ON_FTRACE_NOP; | ||
89 | } | 85 | } |
90 | if (probe_kernel_write((void *) rec->ip, ftrace_disable_code, | 86 | if (probe_kernel_write(to, from, size)) |
91 | MCOUNT_INSN_SIZE)) | ||
92 | return -EPERM; | 87 | return -EPERM; |
93 | return 0; | 88 | return 0; |
94 | } | 89 | } |
95 | 90 | ||
96 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | 91 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) |
97 | { | 92 | { |
98 | if (probe_kernel_write((void *) rec->ip, ftrace_enable_insn, | 93 | struct ftrace_insn insn; |
99 | FTRACE_INSN_SIZE)) | 94 | unsigned short op; |
95 | void *from, *to; | ||
96 | size_t size; | ||
97 | |||
98 | ftrace_generate_call_insn(&insn, rec->ip); | ||
99 | size = sizeof(insn); | ||
100 | from = &insn; | ||
101 | to = (void *) rec->ip; | ||
102 | if (probe_kernel_read(&op, (void *) rec->ip, sizeof(op))) | ||
103 | return -EFAULT; | ||
104 | /* | ||
105 | * If we find a breakpoint instruction, a kprobe has been placed | ||
106 | * at the beginning of the function. We write the constant | ||
107 | * KPROBE_ON_FTRACE_CALL into the remaining four bytes of the original | ||
108 | * instruction so that the kprobes handler can execute a brasl if it | ||
109 | * reaches this breakpoint. | ||
110 | */ | ||
111 | if (op == BREAKPOINT_INSTRUCTION) { | ||
112 | size -= 2; | ||
113 | from += 2; | ||
114 | to += 2; | ||
115 | insn.disp = KPROBE_ON_FTRACE_CALL; | ||
116 | } | ||
117 | if (probe_kernel_write(to, from, size)) | ||
100 | return -EPERM; | 118 | return -EPERM; |
101 | return 0; | 119 | return 0; |
102 | } | 120 | } |
@@ -111,13 +129,30 @@ int __init ftrace_dyn_arch_init(void) | |||
111 | return 0; | 129 | return 0; |
112 | } | 130 | } |
113 | 131 | ||
132 | static int __init ftrace_plt_init(void) | ||
133 | { | ||
134 | unsigned int *ip; | ||
135 | |||
136 | ftrace_plt = (unsigned long) module_alloc(PAGE_SIZE); | ||
137 | if (!ftrace_plt) | ||
138 | panic("cannot allocate ftrace plt\n"); | ||
139 | ip = (unsigned int *) ftrace_plt; | ||
140 | ip[0] = 0x0d10e310; /* basr 1,0; lg 1,10(1); br 1 */ | ||
141 | ip[1] = 0x100a0004; | ||
142 | ip[2] = 0x07f10000; | ||
143 | ip[3] = FTRACE_ADDR >> 32; | ||
144 | ip[4] = FTRACE_ADDR & 0xffffffff; | ||
145 | set_memory_ro(ftrace_plt, 1); | ||
146 | return 0; | ||
147 | } | ||
148 | device_initcall(ftrace_plt_init); | ||
149 | |||
114 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 150 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
115 | /* | 151 | /* |
116 | * Hook the return address and push it in the stack of return addresses | 152 | * Hook the return address and push it in the stack of return addresses |
117 | * in current thread info. | 153 | * in current thread info. |
118 | */ | 154 | */ |
119 | unsigned long __kprobes prepare_ftrace_return(unsigned long parent, | 155 | unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip) |
120 | unsigned long ip) | ||
121 | { | 156 | { |
122 | struct ftrace_graph_ent trace; | 157 | struct ftrace_graph_ent trace; |
123 | 158 | ||
@@ -137,6 +172,7 @@ unsigned long __kprobes prepare_ftrace_return(unsigned long parent, | |||
137 | out: | 172 | out: |
138 | return parent; | 173 | return parent; |
139 | } | 174 | } |
175 | NOKPROBE_SYMBOL(prepare_ftrace_return); | ||
140 | 176 | ||
141 | /* | 177 | /* |
142 | * Patch the kernel code at ftrace_graph_caller location. The instruction | 178 | * Patch the kernel code at ftrace_graph_caller location. The instruction |
diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c index 7559f1beab29..7a55c29b0b33 100644 --- a/arch/s390/kernel/idle.c +++ b/arch/s390/kernel/idle.c | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | static DEFINE_PER_CPU(struct s390_idle_data, s390_idle); | 20 | static DEFINE_PER_CPU(struct s390_idle_data, s390_idle); |
21 | 21 | ||
22 | void __kprobes enabled_wait(void) | 22 | void enabled_wait(void) |
23 | { | 23 | { |
24 | struct s390_idle_data *idle = this_cpu_ptr(&s390_idle); | 24 | struct s390_idle_data *idle = this_cpu_ptr(&s390_idle); |
25 | unsigned long long idle_time; | 25 | unsigned long long idle_time; |
@@ -35,31 +35,32 @@ void __kprobes enabled_wait(void) | |||
35 | /* Call the assembler magic in entry.S */ | 35 | /* Call the assembler magic in entry.S */ |
36 | psw_idle(idle, psw_mask); | 36 | psw_idle(idle, psw_mask); |
37 | 37 | ||
38 | trace_hardirqs_off(); | ||
39 | |||
38 | /* Account time spent with enabled wait psw loaded as idle time. */ | 40 | /* Account time spent with enabled wait psw loaded as idle time. */ |
39 | idle->sequence++; | 41 | write_seqcount_begin(&idle->seqcount); |
40 | smp_wmb(); | ||
41 | idle_time = idle->clock_idle_exit - idle->clock_idle_enter; | 42 | idle_time = idle->clock_idle_exit - idle->clock_idle_enter; |
42 | idle->clock_idle_enter = idle->clock_idle_exit = 0ULL; | 43 | idle->clock_idle_enter = idle->clock_idle_exit = 0ULL; |
43 | idle->idle_time += idle_time; | 44 | idle->idle_time += idle_time; |
44 | idle->idle_count++; | 45 | idle->idle_count++; |
45 | account_idle_time(idle_time); | 46 | account_idle_time(idle_time); |
46 | smp_wmb(); | 47 | write_seqcount_end(&idle->seqcount); |
47 | idle->sequence++; | ||
48 | } | 48 | } |
49 | NOKPROBE_SYMBOL(enabled_wait); | ||
49 | 50 | ||
50 | static ssize_t show_idle_count(struct device *dev, | 51 | static ssize_t show_idle_count(struct device *dev, |
51 | struct device_attribute *attr, char *buf) | 52 | struct device_attribute *attr, char *buf) |
52 | { | 53 | { |
53 | struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); | 54 | struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); |
54 | unsigned long long idle_count; | 55 | unsigned long long idle_count; |
55 | unsigned int sequence; | 56 | unsigned int seq; |
56 | 57 | ||
57 | do { | 58 | do { |
58 | sequence = ACCESS_ONCE(idle->sequence); | 59 | seq = read_seqcount_begin(&idle->seqcount); |
59 | idle_count = ACCESS_ONCE(idle->idle_count); | 60 | idle_count = ACCESS_ONCE(idle->idle_count); |
60 | if (ACCESS_ONCE(idle->clock_idle_enter)) | 61 | if (ACCESS_ONCE(idle->clock_idle_enter)) |
61 | idle_count++; | 62 | idle_count++; |
62 | } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); | 63 | } while (read_seqcount_retry(&idle->seqcount, seq)); |
63 | return sprintf(buf, "%llu\n", idle_count); | 64 | return sprintf(buf, "%llu\n", idle_count); |
64 | } | 65 | } |
65 | DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); | 66 | DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL); |
@@ -69,15 +70,15 @@ static ssize_t show_idle_time(struct device *dev, | |||
69 | { | 70 | { |
70 | struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); | 71 | struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id); |
71 | unsigned long long now, idle_time, idle_enter, idle_exit; | 72 | unsigned long long now, idle_time, idle_enter, idle_exit; |
72 | unsigned int sequence; | 73 | unsigned int seq; |
73 | 74 | ||
74 | do { | 75 | do { |
75 | now = get_tod_clock(); | 76 | now = get_tod_clock(); |
76 | sequence = ACCESS_ONCE(idle->sequence); | 77 | seq = read_seqcount_begin(&idle->seqcount); |
77 | idle_time = ACCESS_ONCE(idle->idle_time); | 78 | idle_time = ACCESS_ONCE(idle->idle_time); |
78 | idle_enter = ACCESS_ONCE(idle->clock_idle_enter); | 79 | idle_enter = ACCESS_ONCE(idle->clock_idle_enter); |
79 | idle_exit = ACCESS_ONCE(idle->clock_idle_exit); | 80 | idle_exit = ACCESS_ONCE(idle->clock_idle_exit); |
80 | } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); | 81 | } while (read_seqcount_retry(&idle->seqcount, seq)); |
81 | idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0; | 82 | idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0; |
82 | return sprintf(buf, "%llu\n", idle_time >> 12); | 83 | return sprintf(buf, "%llu\n", idle_time >> 12); |
83 | } | 84 | } |
@@ -87,14 +88,14 @@ cputime64_t arch_cpu_idle_time(int cpu) | |||
87 | { | 88 | { |
88 | struct s390_idle_data *idle = &per_cpu(s390_idle, cpu); | 89 | struct s390_idle_data *idle = &per_cpu(s390_idle, cpu); |
89 | unsigned long long now, idle_enter, idle_exit; | 90 | unsigned long long now, idle_enter, idle_exit; |
90 | unsigned int sequence; | 91 | unsigned int seq; |
91 | 92 | ||
92 | do { | 93 | do { |
93 | now = get_tod_clock(); | 94 | now = get_tod_clock(); |
94 | sequence = ACCESS_ONCE(idle->sequence); | 95 | seq = read_seqcount_begin(&idle->seqcount); |
95 | idle_enter = ACCESS_ONCE(idle->clock_idle_enter); | 96 | idle_enter = ACCESS_ONCE(idle->clock_idle_enter); |
96 | idle_exit = ACCESS_ONCE(idle->clock_idle_exit); | 97 | idle_exit = ACCESS_ONCE(idle->clock_idle_exit); |
97 | } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence)); | 98 | } while (read_seqcount_retry(&idle->seqcount, seq)); |
98 | return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0; | 99 | return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0; |
99 | } | 100 | } |
100 | 101 | ||
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 1b8a38ab7861..f238720690f3 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -127,13 +127,10 @@ int show_interrupts(struct seq_file *p, void *v) | |||
127 | for_each_online_cpu(cpu) | 127 | for_each_online_cpu(cpu) |
128 | seq_printf(p, "CPU%d ", cpu); | 128 | seq_printf(p, "CPU%d ", cpu); |
129 | seq_putc(p, '\n'); | 129 | seq_putc(p, '\n'); |
130 | goto out; | ||
131 | } | 130 | } |
132 | if (index < NR_IRQS) { | 131 | if (index < NR_IRQS) { |
133 | if (index >= NR_IRQS_BASE) | 132 | if (index >= NR_IRQS_BASE) |
134 | goto out; | 133 | goto out; |
135 | /* Adjust index to process irqclass_main_desc array entries */ | ||
136 | index--; | ||
137 | seq_printf(p, "%s: ", irqclass_main_desc[index].name); | 134 | seq_printf(p, "%s: ", irqclass_main_desc[index].name); |
138 | irq = irqclass_main_desc[index].irq; | 135 | irq = irqclass_main_desc[index].irq; |
139 | for_each_online_cpu(cpu) | 136 | for_each_online_cpu(cpu) |
@@ -158,7 +155,7 @@ out: | |||
158 | 155 | ||
159 | unsigned int arch_dynirq_lower_bound(unsigned int from) | 156 | unsigned int arch_dynirq_lower_bound(unsigned int from) |
160 | { | 157 | { |
161 | return from < THIN_INTERRUPT ? THIN_INTERRUPT : from; | 158 | return from < NR_IRQS_BASE ? NR_IRQS_BASE : from; |
162 | } | 159 | } |
163 | 160 | ||
164 | /* | 161 | /* |
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 014d4729b134..1e4c710dfb92 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/hardirq.h> | 31 | #include <linux/hardirq.h> |
32 | #include <linux/ftrace.h> | ||
32 | #include <asm/cacheflush.h> | 33 | #include <asm/cacheflush.h> |
33 | #include <asm/sections.h> | 34 | #include <asm/sections.h> |
34 | #include <asm/dis.h> | 35 | #include <asm/dis.h> |
@@ -58,12 +59,23 @@ struct kprobe_insn_cache kprobe_dmainsn_slots = { | |||
58 | .insn_size = MAX_INSN_SIZE, | 59 | .insn_size = MAX_INSN_SIZE, |
59 | }; | 60 | }; |
60 | 61 | ||
61 | static void __kprobes copy_instruction(struct kprobe *p) | 62 | static void copy_instruction(struct kprobe *p) |
62 | { | 63 | { |
64 | unsigned long ip = (unsigned long) p->addr; | ||
63 | s64 disp, new_disp; | 65 | s64 disp, new_disp; |
64 | u64 addr, new_addr; | 66 | u64 addr, new_addr; |
65 | 67 | ||
66 | memcpy(p->ainsn.insn, p->addr, insn_length(p->opcode >> 8)); | 68 | if (ftrace_location(ip) == ip) { |
69 | /* | ||
70 | * If kprobes patches the instruction that is morphed by | ||
71 | * ftrace make sure that kprobes always sees the branch | ||
72 | * "jg .+24" that skips the mcount block | ||
73 | */ | ||
74 | ftrace_generate_nop_insn((struct ftrace_insn *)p->ainsn.insn); | ||
75 | p->ainsn.is_ftrace_insn = 1; | ||
76 | } else | ||
77 | memcpy(p->ainsn.insn, p->addr, insn_length(*p->addr >> 8)); | ||
78 | p->opcode = p->ainsn.insn[0]; | ||
67 | if (!probe_is_insn_relative_long(p->ainsn.insn)) | 79 | if (!probe_is_insn_relative_long(p->ainsn.insn)) |
68 | return; | 80 | return; |
69 | /* | 81 | /* |
@@ -79,25 +91,14 @@ static void __kprobes copy_instruction(struct kprobe *p) | |||
79 | new_disp = ((addr + (disp * 2)) - new_addr) / 2; | 91 | new_disp = ((addr + (disp * 2)) - new_addr) / 2; |
80 | *(s32 *)&p->ainsn.insn[1] = new_disp; | 92 | *(s32 *)&p->ainsn.insn[1] = new_disp; |
81 | } | 93 | } |
94 | NOKPROBE_SYMBOL(copy_instruction); | ||
82 | 95 | ||
83 | static inline int is_kernel_addr(void *addr) | 96 | static inline int is_kernel_addr(void *addr) |
84 | { | 97 | { |
85 | return addr < (void *)_end; | 98 | return addr < (void *)_end; |
86 | } | 99 | } |
87 | 100 | ||
88 | static inline int is_module_addr(void *addr) | 101 | static int s390_get_insn_slot(struct kprobe *p) |
89 | { | ||
90 | #ifdef CONFIG_64BIT | ||
91 | BUILD_BUG_ON(MODULES_LEN > (1UL << 31)); | ||
92 | if (addr < (void *)MODULES_VADDR) | ||
93 | return 0; | ||
94 | if (addr > (void *)MODULES_END) | ||
95 | return 0; | ||
96 | #endif | ||
97 | return 1; | ||
98 | } | ||
99 | |||
100 | static int __kprobes s390_get_insn_slot(struct kprobe *p) | ||
101 | { | 102 | { |
102 | /* | 103 | /* |
103 | * Get an insn slot that is within the same 2GB area like the original | 104 | * Get an insn slot that is within the same 2GB area like the original |
@@ -111,8 +112,9 @@ static int __kprobes s390_get_insn_slot(struct kprobe *p) | |||
111 | p->ainsn.insn = get_insn_slot(); | 112 | p->ainsn.insn = get_insn_slot(); |
112 | return p->ainsn.insn ? 0 : -ENOMEM; | 113 | return p->ainsn.insn ? 0 : -ENOMEM; |
113 | } | 114 | } |
115 | NOKPROBE_SYMBOL(s390_get_insn_slot); | ||
114 | 116 | ||
115 | static void __kprobes s390_free_insn_slot(struct kprobe *p) | 117 | static void s390_free_insn_slot(struct kprobe *p) |
116 | { | 118 | { |
117 | if (!p->ainsn.insn) | 119 | if (!p->ainsn.insn) |
118 | return; | 120 | return; |
@@ -122,8 +124,9 @@ static void __kprobes s390_free_insn_slot(struct kprobe *p) | |||
122 | free_insn_slot(p->ainsn.insn, 0); | 124 | free_insn_slot(p->ainsn.insn, 0); |
123 | p->ainsn.insn = NULL; | 125 | p->ainsn.insn = NULL; |
124 | } | 126 | } |
127 | NOKPROBE_SYMBOL(s390_free_insn_slot); | ||
125 | 128 | ||
126 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 129 | int arch_prepare_kprobe(struct kprobe *p) |
127 | { | 130 | { |
128 | if ((unsigned long) p->addr & 0x01) | 131 | if ((unsigned long) p->addr & 0x01) |
129 | return -EINVAL; | 132 | return -EINVAL; |
@@ -132,54 +135,79 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
132 | return -EINVAL; | 135 | return -EINVAL; |
133 | if (s390_get_insn_slot(p)) | 136 | if (s390_get_insn_slot(p)) |
134 | return -ENOMEM; | 137 | return -ENOMEM; |
135 | p->opcode = *p->addr; | ||
136 | copy_instruction(p); | 138 | copy_instruction(p); |
137 | return 0; | 139 | return 0; |
138 | } | 140 | } |
141 | NOKPROBE_SYMBOL(arch_prepare_kprobe); | ||
139 | 142 | ||
140 | struct ins_replace_args { | 143 | int arch_check_ftrace_location(struct kprobe *p) |
141 | kprobe_opcode_t *ptr; | 144 | { |
142 | kprobe_opcode_t opcode; | 145 | return 0; |
146 | } | ||
147 | |||
148 | struct swap_insn_args { | ||
149 | struct kprobe *p; | ||
150 | unsigned int arm_kprobe : 1; | ||
143 | }; | 151 | }; |
144 | 152 | ||
145 | static int __kprobes swap_instruction(void *aref) | 153 | static int swap_instruction(void *data) |
146 | { | 154 | { |
147 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 155 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
148 | unsigned long status = kcb->kprobe_status; | 156 | unsigned long status = kcb->kprobe_status; |
149 | struct ins_replace_args *args = aref; | 157 | struct swap_insn_args *args = data; |
150 | 158 | struct ftrace_insn new_insn, *insn; | |
159 | struct kprobe *p = args->p; | ||
160 | size_t len; | ||
161 | |||
162 | new_insn.opc = args->arm_kprobe ? BREAKPOINT_INSTRUCTION : p->opcode; | ||
163 | len = sizeof(new_insn.opc); | ||
164 | if (!p->ainsn.is_ftrace_insn) | ||
165 | goto skip_ftrace; | ||
166 | len = sizeof(new_insn); | ||
167 | insn = (struct ftrace_insn *) p->addr; | ||
168 | if (args->arm_kprobe) { | ||
169 | if (is_ftrace_nop(insn)) | ||
170 | new_insn.disp = KPROBE_ON_FTRACE_NOP; | ||
171 | else | ||
172 | new_insn.disp = KPROBE_ON_FTRACE_CALL; | ||
173 | } else { | ||
174 | ftrace_generate_call_insn(&new_insn, (unsigned long)p->addr); | ||
175 | if (insn->disp == KPROBE_ON_FTRACE_NOP) | ||
176 | ftrace_generate_nop_insn(&new_insn); | ||
177 | } | ||
178 | skip_ftrace: | ||
151 | kcb->kprobe_status = KPROBE_SWAP_INST; | 179 | kcb->kprobe_status = KPROBE_SWAP_INST; |
152 | probe_kernel_write(args->ptr, &args->opcode, sizeof(args->opcode)); | 180 | probe_kernel_write(p->addr, &new_insn, len); |
153 | kcb->kprobe_status = status; | 181 | kcb->kprobe_status = status; |
154 | return 0; | 182 | return 0; |
155 | } | 183 | } |
184 | NOKPROBE_SYMBOL(swap_instruction); | ||
156 | 185 | ||
157 | void __kprobes arch_arm_kprobe(struct kprobe *p) | 186 | void arch_arm_kprobe(struct kprobe *p) |
158 | { | 187 | { |
159 | struct ins_replace_args args; | 188 | struct swap_insn_args args = {.p = p, .arm_kprobe = 1}; |
160 | 189 | ||
161 | args.ptr = p->addr; | ||
162 | args.opcode = BREAKPOINT_INSTRUCTION; | ||
163 | stop_machine(swap_instruction, &args, NULL); | 190 | stop_machine(swap_instruction, &args, NULL); |
164 | } | 191 | } |
192 | NOKPROBE_SYMBOL(arch_arm_kprobe); | ||
165 | 193 | ||
166 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 194 | void arch_disarm_kprobe(struct kprobe *p) |
167 | { | 195 | { |
168 | struct ins_replace_args args; | 196 | struct swap_insn_args args = {.p = p, .arm_kprobe = 0}; |
169 | 197 | ||
170 | args.ptr = p->addr; | ||
171 | args.opcode = p->opcode; | ||
172 | stop_machine(swap_instruction, &args, NULL); | 198 | stop_machine(swap_instruction, &args, NULL); |
173 | } | 199 | } |
200 | NOKPROBE_SYMBOL(arch_disarm_kprobe); | ||
174 | 201 | ||
175 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 202 | void arch_remove_kprobe(struct kprobe *p) |
176 | { | 203 | { |
177 | s390_free_insn_slot(p); | 204 | s390_free_insn_slot(p); |
178 | } | 205 | } |
206 | NOKPROBE_SYMBOL(arch_remove_kprobe); | ||
179 | 207 | ||
180 | static void __kprobes enable_singlestep(struct kprobe_ctlblk *kcb, | 208 | static void enable_singlestep(struct kprobe_ctlblk *kcb, |
181 | struct pt_regs *regs, | 209 | struct pt_regs *regs, |
182 | unsigned long ip) | 210 | unsigned long ip) |
183 | { | 211 | { |
184 | struct per_regs per_kprobe; | 212 | struct per_regs per_kprobe; |
185 | 213 | ||
@@ -199,10 +227,11 @@ static void __kprobes enable_singlestep(struct kprobe_ctlblk *kcb, | |||
199 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT); | 227 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT); |
200 | regs->psw.addr = ip | PSW_ADDR_AMODE; | 228 | regs->psw.addr = ip | PSW_ADDR_AMODE; |
201 | } | 229 | } |
230 | NOKPROBE_SYMBOL(enable_singlestep); | ||
202 | 231 | ||
203 | static void __kprobes disable_singlestep(struct kprobe_ctlblk *kcb, | 232 | static void disable_singlestep(struct kprobe_ctlblk *kcb, |
204 | struct pt_regs *regs, | 233 | struct pt_regs *regs, |
205 | unsigned long ip) | 234 | unsigned long ip) |
206 | { | 235 | { |
207 | /* Restore control regs and psw mask, set new psw address */ | 236 | /* Restore control regs and psw mask, set new psw address */ |
208 | __ctl_load(kcb->kprobe_saved_ctl, 9, 11); | 237 | __ctl_load(kcb->kprobe_saved_ctl, 9, 11); |
@@ -210,41 +239,43 @@ static void __kprobes disable_singlestep(struct kprobe_ctlblk *kcb, | |||
210 | regs->psw.mask |= kcb->kprobe_saved_imask; | 239 | regs->psw.mask |= kcb->kprobe_saved_imask; |
211 | regs->psw.addr = ip | PSW_ADDR_AMODE; | 240 | regs->psw.addr = ip | PSW_ADDR_AMODE; |
212 | } | 241 | } |
242 | NOKPROBE_SYMBOL(disable_singlestep); | ||
213 | 243 | ||
214 | /* | 244 | /* |
215 | * Activate a kprobe by storing its pointer to current_kprobe. The | 245 | * Activate a kprobe by storing its pointer to current_kprobe. The |
216 | * previous kprobe is stored in kcb->prev_kprobe. A stack of up to | 246 | * previous kprobe is stored in kcb->prev_kprobe. A stack of up to |
217 | * two kprobes can be active, see KPROBE_REENTER. | 247 | * two kprobes can be active, see KPROBE_REENTER. |
218 | */ | 248 | */ |
219 | static void __kprobes push_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p) | 249 | static void push_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p) |
220 | { | 250 | { |
221 | kcb->prev_kprobe.kp = __this_cpu_read(current_kprobe); | 251 | kcb->prev_kprobe.kp = __this_cpu_read(current_kprobe); |
222 | kcb->prev_kprobe.status = kcb->kprobe_status; | 252 | kcb->prev_kprobe.status = kcb->kprobe_status; |
223 | __this_cpu_write(current_kprobe, p); | 253 | __this_cpu_write(current_kprobe, p); |
224 | } | 254 | } |
255 | NOKPROBE_SYMBOL(push_kprobe); | ||
225 | 256 | ||
226 | /* | 257 | /* |
227 | * Deactivate a kprobe by backing up to the previous state. If the | 258 | * Deactivate a kprobe by backing up to the previous state. If the |
228 | * current state is KPROBE_REENTER prev_kprobe.kp will be non-NULL, | 259 | * current state is KPROBE_REENTER prev_kprobe.kp will be non-NULL, |
229 | * for any other state prev_kprobe.kp will be NULL. | 260 | * for any other state prev_kprobe.kp will be NULL. |
230 | */ | 261 | */ |
231 | static void __kprobes pop_kprobe(struct kprobe_ctlblk *kcb) | 262 | static void pop_kprobe(struct kprobe_ctlblk *kcb) |
232 | { | 263 | { |
233 | __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); | 264 | __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); |
234 | kcb->kprobe_status = kcb->prev_kprobe.status; | 265 | kcb->kprobe_status = kcb->prev_kprobe.status; |
235 | } | 266 | } |
267 | NOKPROBE_SYMBOL(pop_kprobe); | ||
236 | 268 | ||
237 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 269 | void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) |
238 | struct pt_regs *regs) | ||
239 | { | 270 | { |
240 | ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14]; | 271 | ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14]; |
241 | 272 | ||
242 | /* Replace the return addr with trampoline addr */ | 273 | /* Replace the return addr with trampoline addr */ |
243 | regs->gprs[14] = (unsigned long) &kretprobe_trampoline; | 274 | regs->gprs[14] = (unsigned long) &kretprobe_trampoline; |
244 | } | 275 | } |
276 | NOKPROBE_SYMBOL(arch_prepare_kretprobe); | ||
245 | 277 | ||
246 | static void __kprobes kprobe_reenter_check(struct kprobe_ctlblk *kcb, | 278 | static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p) |
247 | struct kprobe *p) | ||
248 | { | 279 | { |
249 | switch (kcb->kprobe_status) { | 280 | switch (kcb->kprobe_status) { |
250 | case KPROBE_HIT_SSDONE: | 281 | case KPROBE_HIT_SSDONE: |
@@ -264,8 +295,9 @@ static void __kprobes kprobe_reenter_check(struct kprobe_ctlblk *kcb, | |||
264 | BUG(); | 295 | BUG(); |
265 | } | 296 | } |
266 | } | 297 | } |
298 | NOKPROBE_SYMBOL(kprobe_reenter_check); | ||
267 | 299 | ||
268 | static int __kprobes kprobe_handler(struct pt_regs *regs) | 300 | static int kprobe_handler(struct pt_regs *regs) |
269 | { | 301 | { |
270 | struct kprobe_ctlblk *kcb; | 302 | struct kprobe_ctlblk *kcb; |
271 | struct kprobe *p; | 303 | struct kprobe *p; |
@@ -339,6 +371,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
339 | preempt_enable_no_resched(); | 371 | preempt_enable_no_resched(); |
340 | return 0; | 372 | return 0; |
341 | } | 373 | } |
374 | NOKPROBE_SYMBOL(kprobe_handler); | ||
342 | 375 | ||
343 | /* | 376 | /* |
344 | * Function return probe trampoline: | 377 | * Function return probe trampoline: |
@@ -355,8 +388,7 @@ static void __used kretprobe_trampoline_holder(void) | |||
355 | /* | 388 | /* |
356 | * Called when the probe at kretprobe trampoline is hit | 389 | * Called when the probe at kretprobe trampoline is hit |
357 | */ | 390 | */ |
358 | static int __kprobes trampoline_probe_handler(struct kprobe *p, | 391 | static int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
359 | struct pt_regs *regs) | ||
360 | { | 392 | { |
361 | struct kretprobe_instance *ri; | 393 | struct kretprobe_instance *ri; |
362 | struct hlist_head *head, empty_rp; | 394 | struct hlist_head *head, empty_rp; |
@@ -444,6 +476,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
444 | */ | 476 | */ |
445 | return 1; | 477 | return 1; |
446 | } | 478 | } |
479 | NOKPROBE_SYMBOL(trampoline_probe_handler); | ||
447 | 480 | ||
448 | /* | 481 | /* |
449 | * Called after single-stepping. p->addr is the address of the | 482 | * Called after single-stepping. p->addr is the address of the |
@@ -453,12 +486,30 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
453 | * single-stepped a copy of the instruction. The address of this | 486 | * single-stepped a copy of the instruction. The address of this |
454 | * copy is p->ainsn.insn. | 487 | * copy is p->ainsn.insn. |
455 | */ | 488 | */ |
456 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) | 489 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) |
457 | { | 490 | { |
458 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 491 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
459 | unsigned long ip = regs->psw.addr & PSW_ADDR_INSN; | 492 | unsigned long ip = regs->psw.addr & PSW_ADDR_INSN; |
460 | int fixup = probe_get_fixup_type(p->ainsn.insn); | 493 | int fixup = probe_get_fixup_type(p->ainsn.insn); |
461 | 494 | ||
495 | /* Check if the kprobes location is an enabled ftrace caller */ | ||
496 | if (p->ainsn.is_ftrace_insn) { | ||
497 | struct ftrace_insn *insn = (struct ftrace_insn *) p->addr; | ||
498 | struct ftrace_insn call_insn; | ||
499 | |||
500 | ftrace_generate_call_insn(&call_insn, (unsigned long) p->addr); | ||
501 | /* | ||
502 | * A kprobe on an enabled ftrace call site actually single | ||
503 | * stepped an unconditional branch (ftrace nop equivalent). | ||
504 | * Now we need to fixup things and pretend that a brasl r0,... | ||
505 | * was executed instead. | ||
506 | */ | ||
507 | if (insn->disp == KPROBE_ON_FTRACE_CALL) { | ||
508 | ip += call_insn.disp * 2 - MCOUNT_INSN_SIZE; | ||
509 | regs->gprs[0] = (unsigned long)p->addr + sizeof(*insn); | ||
510 | } | ||
511 | } | ||
512 | |||
462 | if (fixup & FIXUP_PSW_NORMAL) | 513 | if (fixup & FIXUP_PSW_NORMAL) |
463 | ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn; | 514 | ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn; |
464 | 515 | ||
@@ -476,8 +527,9 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) | |||
476 | 527 | ||
477 | disable_singlestep(kcb, regs, ip); | 528 | disable_singlestep(kcb, regs, ip); |
478 | } | 529 | } |
530 | NOKPROBE_SYMBOL(resume_execution); | ||
479 | 531 | ||
480 | static int __kprobes post_kprobe_handler(struct pt_regs *regs) | 532 | static int post_kprobe_handler(struct pt_regs *regs) |
481 | { | 533 | { |
482 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 534 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
483 | struct kprobe *p = kprobe_running(); | 535 | struct kprobe *p = kprobe_running(); |
@@ -504,8 +556,9 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) | |||
504 | 556 | ||
505 | return 1; | 557 | return 1; |
506 | } | 558 | } |
559 | NOKPROBE_SYMBOL(post_kprobe_handler); | ||
507 | 560 | ||
508 | static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr) | 561 | static int kprobe_trap_handler(struct pt_regs *regs, int trapnr) |
509 | { | 562 | { |
510 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 563 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
511 | struct kprobe *p = kprobe_running(); | 564 | struct kprobe *p = kprobe_running(); |
@@ -567,8 +620,9 @@ static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr) | |||
567 | } | 620 | } |
568 | return 0; | 621 | return 0; |
569 | } | 622 | } |
623 | NOKPROBE_SYMBOL(kprobe_trap_handler); | ||
570 | 624 | ||
571 | int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | 625 | int kprobe_fault_handler(struct pt_regs *regs, int trapnr) |
572 | { | 626 | { |
573 | int ret; | 627 | int ret; |
574 | 628 | ||
@@ -579,12 +633,13 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
579 | local_irq_restore(regs->psw.mask & ~PSW_MASK_PER); | 633 | local_irq_restore(regs->psw.mask & ~PSW_MASK_PER); |
580 | return ret; | 634 | return ret; |
581 | } | 635 | } |
636 | NOKPROBE_SYMBOL(kprobe_fault_handler); | ||
582 | 637 | ||
583 | /* | 638 | /* |
584 | * Wrapper routine to for handling exceptions. | 639 | * Wrapper routine to for handling exceptions. |
585 | */ | 640 | */ |
586 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | 641 | int kprobe_exceptions_notify(struct notifier_block *self, |
587 | unsigned long val, void *data) | 642 | unsigned long val, void *data) |
588 | { | 643 | { |
589 | struct die_args *args = (struct die_args *) data; | 644 | struct die_args *args = (struct die_args *) data; |
590 | struct pt_regs *regs = args->regs; | 645 | struct pt_regs *regs = args->regs; |
@@ -616,8 +671,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
616 | 671 | ||
617 | return ret; | 672 | return ret; |
618 | } | 673 | } |
674 | NOKPROBE_SYMBOL(kprobe_exceptions_notify); | ||
619 | 675 | ||
620 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 676 | int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
621 | { | 677 | { |
622 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 678 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
623 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 679 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
@@ -635,13 +691,15 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
635 | memcpy(kcb->jprobes_stack, (void *) stack, MIN_STACK_SIZE(stack)); | 691 | memcpy(kcb->jprobes_stack, (void *) stack, MIN_STACK_SIZE(stack)); |
636 | return 1; | 692 | return 1; |
637 | } | 693 | } |
694 | NOKPROBE_SYMBOL(setjmp_pre_handler); | ||
638 | 695 | ||
639 | void __kprobes jprobe_return(void) | 696 | void jprobe_return(void) |
640 | { | 697 | { |
641 | asm volatile(".word 0x0002"); | 698 | asm volatile(".word 0x0002"); |
642 | } | 699 | } |
700 | NOKPROBE_SYMBOL(jprobe_return); | ||
643 | 701 | ||
644 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 702 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
645 | { | 703 | { |
646 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 704 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
647 | unsigned long stack; | 705 | unsigned long stack; |
@@ -655,6 +713,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
655 | preempt_enable_no_resched(); | 713 | preempt_enable_no_resched(); |
656 | return 1; | 714 | return 1; |
657 | } | 715 | } |
716 | NOKPROBE_SYMBOL(longjmp_break_handler); | ||
658 | 717 | ||
659 | static struct kprobe trampoline = { | 718 | static struct kprobe trampoline = { |
660 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, | 719 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, |
@@ -666,7 +725,8 @@ int __init arch_init_kprobes(void) | |||
666 | return register_kprobe(&trampoline); | 725 | return register_kprobe(&trampoline); |
667 | } | 726 | } |
668 | 727 | ||
669 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | 728 | int arch_trampoline_kprobe(struct kprobe *p) |
670 | { | 729 | { |
671 | return p->addr == (kprobe_opcode_t *) &kretprobe_trampoline; | 730 | return p->addr == (kprobe_opcode_t *) &kretprobe_trampoline; |
672 | } | 731 | } |
732 | NOKPROBE_SYMBOL(arch_trampoline_kprobe); | ||
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index 4300ea374826..b6dfc5bfcb89 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S | |||
@@ -27,6 +27,7 @@ ENTRY(ftrace_caller) | |||
27 | .globl ftrace_regs_caller | 27 | .globl ftrace_regs_caller |
28 | .set ftrace_regs_caller,ftrace_caller | 28 | .set ftrace_regs_caller,ftrace_caller |
29 | lgr %r1,%r15 | 29 | lgr %r1,%r15 |
30 | aghi %r0,MCOUNT_RETURN_FIXUP | ||
30 | aghi %r15,-STACK_FRAME_SIZE | 31 | aghi %r15,-STACK_FRAME_SIZE |
31 | stg %r1,__SF_BACKCHAIN(%r15) | 32 | stg %r1,__SF_BACKCHAIN(%r15) |
32 | stg %r1,(STACK_PTREGS_GPRS+15*8)(%r15) | 33 | stg %r1,(STACK_PTREGS_GPRS+15*8)(%r15) |
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index b878f12a9597..c3f8d157cb0d 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c | |||
@@ -1383,7 +1383,6 @@ static int cpumsf_pmu_add(struct perf_event *event, int flags) | |||
1383 | cpuhw->lsctl.ed = 1; | 1383 | cpuhw->lsctl.ed = 1; |
1384 | 1384 | ||
1385 | /* Set in_use flag and store event */ | 1385 | /* Set in_use flag and store event */ |
1386 | event->hw.idx = 0; /* only one sampling event per CPU supported */ | ||
1387 | cpuhw->event = event; | 1386 | cpuhw->event = event; |
1388 | cpuhw->flags |= PMU_F_IN_USE; | 1387 | cpuhw->flags |= PMU_F_IN_USE; |
1389 | 1388 | ||
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index ed84cc224899..aa7a83948c7b 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -61,7 +61,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
61 | return sf->gprs[8]; | 61 | return sf->gprs[8]; |
62 | } | 62 | } |
63 | 63 | ||
64 | extern void __kprobes kernel_thread_starter(void); | 64 | extern void kernel_thread_starter(void); |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * Free current thread data structures etc.. | 67 | * Free current thread data structures etc.. |
@@ -153,6 +153,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
153 | save_fp_ctl(&p->thread.fp_regs.fpc); | 153 | save_fp_ctl(&p->thread.fp_regs.fpc); |
154 | save_fp_regs(p->thread.fp_regs.fprs); | 154 | save_fp_regs(p->thread.fp_regs.fprs); |
155 | p->thread.fp_regs.pad = 0; | 155 | p->thread.fp_regs.pad = 0; |
156 | p->thread.vxrs = NULL; | ||
156 | /* Set a new TLS ? */ | 157 | /* Set a new TLS ? */ |
157 | if (clone_flags & CLONE_SETTLS) { | 158 | if (clone_flags & CLONE_SETTLS) { |
158 | unsigned long tls = frame->childregs.gprs[6]; | 159 | unsigned long tls = frame->childregs.gprs[6]; |
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 99a567b70d16..eabfb4594517 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -248,14 +248,27 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr) | |||
248 | */ | 248 | */ |
249 | tmp = 0; | 249 | tmp = 0; |
250 | 250 | ||
251 | } else if (addr == (addr_t) &dummy->regs.fp_regs.fpc) { | ||
252 | /* | ||
253 | * floating point control reg. is in the thread structure | ||
254 | */ | ||
255 | tmp = child->thread.fp_regs.fpc; | ||
256 | tmp <<= BITS_PER_LONG - 32; | ||
257 | |||
251 | } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { | 258 | } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { |
252 | /* | 259 | /* |
253 | * floating point regs. are stored in the thread structure | 260 | * floating point regs. are either in child->thread.fp_regs |
261 | * or the child->thread.vxrs array | ||
254 | */ | 262 | */ |
255 | offset = addr - (addr_t) &dummy->regs.fp_regs; | 263 | offset = addr - (addr_t) &dummy->regs.fp_regs.fprs; |
256 | tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset); | 264 | #ifdef CONFIG_64BIT |
257 | if (addr == (addr_t) &dummy->regs.fp_regs.fpc) | 265 | if (child->thread.vxrs) |
258 | tmp <<= BITS_PER_LONG - 32; | 266 | tmp = *(addr_t *) |
267 | ((addr_t) child->thread.vxrs + 2*offset); | ||
268 | else | ||
269 | #endif | ||
270 | tmp = *(addr_t *) | ||
271 | ((addr_t) &child->thread.fp_regs.fprs + offset); | ||
259 | 272 | ||
260 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { | 273 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { |
261 | /* | 274 | /* |
@@ -383,16 +396,29 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) | |||
383 | */ | 396 | */ |
384 | return 0; | 397 | return 0; |
385 | 398 | ||
399 | } else if (addr == (addr_t) &dummy->regs.fp_regs.fpc) { | ||
400 | /* | ||
401 | * floating point control reg. is in the thread structure | ||
402 | */ | ||
403 | if ((unsigned int) data != 0 || | ||
404 | test_fp_ctl(data >> (BITS_PER_LONG - 32))) | ||
405 | return -EINVAL; | ||
406 | child->thread.fp_regs.fpc = data >> (BITS_PER_LONG - 32); | ||
407 | |||
386 | } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { | 408 | } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { |
387 | /* | 409 | /* |
388 | * floating point regs. are stored in the thread structure | 410 | * floating point regs. are either in child->thread.fp_regs |
411 | * or the child->thread.vxrs array | ||
389 | */ | 412 | */ |
390 | if (addr == (addr_t) &dummy->regs.fp_regs.fpc) | 413 | offset = addr - (addr_t) &dummy->regs.fp_regs.fprs; |
391 | if ((unsigned int) data != 0 || | 414 | #ifdef CONFIG_64BIT |
392 | test_fp_ctl(data >> (BITS_PER_LONG - 32))) | 415 | if (child->thread.vxrs) |
393 | return -EINVAL; | 416 | *(addr_t *)((addr_t) |
394 | offset = addr - (addr_t) &dummy->regs.fp_regs; | 417 | child->thread.vxrs + 2*offset) = data; |
395 | *(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data; | 418 | else |
419 | #endif | ||
420 | *(addr_t *)((addr_t) | ||
421 | &child->thread.fp_regs.fprs + offset) = data; | ||
396 | 422 | ||
397 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { | 423 | } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { |
398 | /* | 424 | /* |
@@ -611,12 +637,26 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr) | |||
611 | */ | 637 | */ |
612 | tmp = 0; | 638 | tmp = 0; |
613 | 639 | ||
640 | } else if (addr == (addr_t) &dummy32->regs.fp_regs.fpc) { | ||
641 | /* | ||
642 | * floating point control reg. is in the thread structure | ||
643 | */ | ||
644 | tmp = child->thread.fp_regs.fpc; | ||
645 | |||
614 | } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { | 646 | } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { |
615 | /* | 647 | /* |
616 | * floating point regs. are stored in the thread structure | 648 | * floating point regs. are either in child->thread.fp_regs |
649 | * or the child->thread.vxrs array | ||
617 | */ | 650 | */ |
618 | offset = addr - (addr_t) &dummy32->regs.fp_regs; | 651 | offset = addr - (addr_t) &dummy32->regs.fp_regs.fprs; |
619 | tmp = *(__u32 *)((addr_t) &child->thread.fp_regs + offset); | 652 | #ifdef CONFIG_64BIT |
653 | if (child->thread.vxrs) | ||
654 | tmp = *(__u32 *) | ||
655 | ((addr_t) child->thread.vxrs + 2*offset); | ||
656 | else | ||
657 | #endif | ||
658 | tmp = *(__u32 *) | ||
659 | ((addr_t) &child->thread.fp_regs.fprs + offset); | ||
620 | 660 | ||
621 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { | 661 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { |
622 | /* | 662 | /* |
@@ -722,15 +762,28 @@ static int __poke_user_compat(struct task_struct *child, | |||
722 | */ | 762 | */ |
723 | return 0; | 763 | return 0; |
724 | 764 | ||
725 | } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { | 765 | } else if (addr == (addr_t) &dummy32->regs.fp_regs.fpc) { |
726 | /* | 766 | /* |
727 | * floating point regs. are stored in the thread structure | 767 | * floating point control reg. is in the thread structure |
728 | */ | 768 | */ |
729 | if (addr == (addr_t) &dummy32->regs.fp_regs.fpc && | 769 | if (test_fp_ctl(tmp)) |
730 | test_fp_ctl(tmp)) | ||
731 | return -EINVAL; | 770 | return -EINVAL; |
732 | offset = addr - (addr_t) &dummy32->regs.fp_regs; | 771 | child->thread.fp_regs.fpc = data; |
733 | *(__u32 *)((addr_t) &child->thread.fp_regs + offset) = tmp; | 772 | |
773 | } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { | ||
774 | /* | ||
775 | * floating point regs. are either in child->thread.fp_regs | ||
776 | * or the child->thread.vxrs array | ||
777 | */ | ||
778 | offset = addr - (addr_t) &dummy32->regs.fp_regs.fprs; | ||
779 | #ifdef CONFIG_64BIT | ||
780 | if (child->thread.vxrs) | ||
781 | *(__u32 *)((addr_t) | ||
782 | child->thread.vxrs + 2*offset) = tmp; | ||
783 | else | ||
784 | #endif | ||
785 | *(__u32 *)((addr_t) | ||
786 | &child->thread.fp_regs.fprs + offset) = tmp; | ||
734 | 787 | ||
735 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { | 788 | } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { |
736 | /* | 789 | /* |
@@ -1038,12 +1091,6 @@ static int s390_tdb_set(struct task_struct *target, | |||
1038 | return 0; | 1091 | return 0; |
1039 | } | 1092 | } |
1040 | 1093 | ||
1041 | static int s390_vxrs_active(struct task_struct *target, | ||
1042 | const struct user_regset *regset) | ||
1043 | { | ||
1044 | return !!target->thread.vxrs; | ||
1045 | } | ||
1046 | |||
1047 | static int s390_vxrs_low_get(struct task_struct *target, | 1094 | static int s390_vxrs_low_get(struct task_struct *target, |
1048 | const struct user_regset *regset, | 1095 | const struct user_regset *regset, |
1049 | unsigned int pos, unsigned int count, | 1096 | unsigned int pos, unsigned int count, |
@@ -1052,6 +1099,8 @@ static int s390_vxrs_low_get(struct task_struct *target, | |||
1052 | __u64 vxrs[__NUM_VXRS_LOW]; | 1099 | __u64 vxrs[__NUM_VXRS_LOW]; |
1053 | int i; | 1100 | int i; |
1054 | 1101 | ||
1102 | if (!MACHINE_HAS_VX) | ||
1103 | return -ENODEV; | ||
1055 | if (target->thread.vxrs) { | 1104 | if (target->thread.vxrs) { |
1056 | if (target == current) | 1105 | if (target == current) |
1057 | save_vx_regs(target->thread.vxrs); | 1106 | save_vx_regs(target->thread.vxrs); |
@@ -1070,6 +1119,8 @@ static int s390_vxrs_low_set(struct task_struct *target, | |||
1070 | __u64 vxrs[__NUM_VXRS_LOW]; | 1119 | __u64 vxrs[__NUM_VXRS_LOW]; |
1071 | int i, rc; | 1120 | int i, rc; |
1072 | 1121 | ||
1122 | if (!MACHINE_HAS_VX) | ||
1123 | return -ENODEV; | ||
1073 | if (!target->thread.vxrs) { | 1124 | if (!target->thread.vxrs) { |
1074 | rc = alloc_vector_registers(target); | 1125 | rc = alloc_vector_registers(target); |
1075 | if (rc) | 1126 | if (rc) |
@@ -1095,6 +1146,8 @@ static int s390_vxrs_high_get(struct task_struct *target, | |||
1095 | { | 1146 | { |
1096 | __vector128 vxrs[__NUM_VXRS_HIGH]; | 1147 | __vector128 vxrs[__NUM_VXRS_HIGH]; |
1097 | 1148 | ||
1149 | if (!MACHINE_HAS_VX) | ||
1150 | return -ENODEV; | ||
1098 | if (target->thread.vxrs) { | 1151 | if (target->thread.vxrs) { |
1099 | if (target == current) | 1152 | if (target == current) |
1100 | save_vx_regs(target->thread.vxrs); | 1153 | save_vx_regs(target->thread.vxrs); |
@@ -1112,6 +1165,8 @@ static int s390_vxrs_high_set(struct task_struct *target, | |||
1112 | { | 1165 | { |
1113 | int rc; | 1166 | int rc; |
1114 | 1167 | ||
1168 | if (!MACHINE_HAS_VX) | ||
1169 | return -ENODEV; | ||
1115 | if (!target->thread.vxrs) { | 1170 | if (!target->thread.vxrs) { |
1116 | rc = alloc_vector_registers(target); | 1171 | rc = alloc_vector_registers(target); |
1117 | if (rc) | 1172 | if (rc) |
@@ -1196,7 +1251,6 @@ static const struct user_regset s390_regsets[] = { | |||
1196 | .n = __NUM_VXRS_LOW, | 1251 | .n = __NUM_VXRS_LOW, |
1197 | .size = sizeof(__u64), | 1252 | .size = sizeof(__u64), |
1198 | .align = sizeof(__u64), | 1253 | .align = sizeof(__u64), |
1199 | .active = s390_vxrs_active, | ||
1200 | .get = s390_vxrs_low_get, | 1254 | .get = s390_vxrs_low_get, |
1201 | .set = s390_vxrs_low_set, | 1255 | .set = s390_vxrs_low_set, |
1202 | }, | 1256 | }, |
@@ -1205,7 +1259,6 @@ static const struct user_regset s390_regsets[] = { | |||
1205 | .n = __NUM_VXRS_HIGH, | 1259 | .n = __NUM_VXRS_HIGH, |
1206 | .size = sizeof(__vector128), | 1260 | .size = sizeof(__vector128), |
1207 | .align = sizeof(__vector128), | 1261 | .align = sizeof(__vector128), |
1208 | .active = s390_vxrs_active, | ||
1209 | .get = s390_vxrs_high_get, | 1262 | .get = s390_vxrs_high_get, |
1210 | .set = s390_vxrs_high_set, | 1263 | .set = s390_vxrs_high_set, |
1211 | }, | 1264 | }, |
@@ -1419,7 +1472,6 @@ static const struct user_regset s390_compat_regsets[] = { | |||
1419 | .n = __NUM_VXRS_LOW, | 1472 | .n = __NUM_VXRS_LOW, |
1420 | .size = sizeof(__u64), | 1473 | .size = sizeof(__u64), |
1421 | .align = sizeof(__u64), | 1474 | .align = sizeof(__u64), |
1422 | .active = s390_vxrs_active, | ||
1423 | .get = s390_vxrs_low_get, | 1475 | .get = s390_vxrs_low_get, |
1424 | .set = s390_vxrs_low_set, | 1476 | .set = s390_vxrs_low_set, |
1425 | }, | 1477 | }, |
@@ -1428,7 +1480,6 @@ static const struct user_regset s390_compat_regsets[] = { | |||
1428 | .n = __NUM_VXRS_HIGH, | 1480 | .n = __NUM_VXRS_HIGH, |
1429 | .size = sizeof(__vector128), | 1481 | .size = sizeof(__vector128), |
1430 | .align = sizeof(__vector128), | 1482 | .align = sizeof(__vector128), |
1431 | .active = s390_vxrs_active, | ||
1432 | .get = s390_vxrs_high_get, | 1483 | .get = s390_vxrs_high_get, |
1433 | .set = s390_vxrs_high_set, | 1484 | .set = s390_vxrs_high_set, |
1434 | }, | 1485 | }, |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index e80d9ff9a56d..4e532c67832f 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/ctype.h> | 41 | #include <linux/ctype.h> |
42 | #include <linux/reboot.h> | 42 | #include <linux/reboot.h> |
43 | #include <linux/topology.h> | 43 | #include <linux/topology.h> |
44 | #include <linux/ftrace.h> | ||
45 | #include <linux/kexec.h> | 44 | #include <linux/kexec.h> |
46 | #include <linux/crash_dump.h> | 45 | #include <linux/crash_dump.h> |
47 | #include <linux/memory.h> | 46 | #include <linux/memory.h> |
@@ -356,7 +355,6 @@ static void __init setup_lowcore(void) | |||
356 | lc->steal_timer = S390_lowcore.steal_timer; | 355 | lc->steal_timer = S390_lowcore.steal_timer; |
357 | lc->last_update_timer = S390_lowcore.last_update_timer; | 356 | lc->last_update_timer = S390_lowcore.last_update_timer; |
358 | lc->last_update_clock = S390_lowcore.last_update_clock; | 357 | lc->last_update_clock = S390_lowcore.last_update_clock; |
359 | lc->ftrace_func = S390_lowcore.ftrace_func; | ||
360 | 358 | ||
361 | restart_stack = __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0); | 359 | restart_stack = __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0); |
362 | restart_stack += ASYNC_SIZE; | 360 | restart_stack += ASYNC_SIZE; |
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 0c1a0ff0a558..6a2ac257d98f 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c | |||
@@ -371,7 +371,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
371 | restorer = (unsigned long) ka->sa.sa_restorer | PSW_ADDR_AMODE; | 371 | restorer = (unsigned long) ka->sa.sa_restorer | PSW_ADDR_AMODE; |
372 | } else { | 372 | } else { |
373 | /* Signal frame without vector registers are short ! */ | 373 | /* Signal frame without vector registers are short ! */ |
374 | __u16 __user *svc = (void *) frame + frame_size - 2; | 374 | __u16 __user *svc = (void __user *) frame + frame_size - 2; |
375 | if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc)) | 375 | if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc)) |
376 | return -EFAULT; | 376 | return -EFAULT; |
377 | restorer = (unsigned long) svc | PSW_ADDR_AMODE; | 377 | restorer = (unsigned long) svc | PSW_ADDR_AMODE; |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 6fd9e60101f1..0b499f5cbe19 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -236,7 +236,6 @@ static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu) | |||
236 | lc->percpu_offset = __per_cpu_offset[cpu]; | 236 | lc->percpu_offset = __per_cpu_offset[cpu]; |
237 | lc->kernel_asce = S390_lowcore.kernel_asce; | 237 | lc->kernel_asce = S390_lowcore.kernel_asce; |
238 | lc->machine_flags = S390_lowcore.machine_flags; | 238 | lc->machine_flags = S390_lowcore.machine_flags; |
239 | lc->ftrace_func = S390_lowcore.ftrace_func; | ||
240 | lc->user_timer = lc->system_timer = lc->steal_timer = 0; | 239 | lc->user_timer = lc->system_timer = lc->steal_timer = 0; |
241 | __ctl_store(lc->cregs_save_area, 0, 15); | 240 | __ctl_store(lc->cregs_save_area, 0, 15); |
242 | save_access_regs((unsigned int *) lc->access_regs_save_area); | 241 | save_access_regs((unsigned int *) lc->access_regs_save_area); |
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 9f7087fd58de..a2987243bc76 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
@@ -360,3 +360,5 @@ SYSCALL(sys_seccomp,sys_seccomp,compat_sys_seccomp) | |||
360 | SYSCALL(sys_getrandom,sys_getrandom,compat_sys_getrandom) | 360 | SYSCALL(sys_getrandom,sys_getrandom,compat_sys_getrandom) |
361 | SYSCALL(sys_memfd_create,sys_memfd_create,compat_sys_memfd_create) /* 350 */ | 361 | SYSCALL(sys_memfd_create,sys_memfd_create,compat_sys_memfd_create) /* 350 */ |
362 | SYSCALL(sys_bpf,sys_bpf,compat_sys_bpf) | 362 | SYSCALL(sys_bpf,sys_bpf,compat_sys_bpf) |
363 | SYSCALL(sys_ni_syscall,sys_s390_pci_mmio_write,compat_sys_s390_pci_mmio_write) | ||
364 | SYSCALL(sys_ni_syscall,sys_s390_pci_mmio_read,compat_sys_s390_pci_mmio_read) | ||
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 005d665fe4a5..20660dddb2d6 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -61,10 +61,11 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators); | |||
61 | /* | 61 | /* |
62 | * Scheduler clock - returns current time in nanosec units. | 62 | * Scheduler clock - returns current time in nanosec units. |
63 | */ | 63 | */ |
64 | unsigned long long notrace __kprobes sched_clock(void) | 64 | unsigned long long notrace sched_clock(void) |
65 | { | 65 | { |
66 | return tod_to_ns(get_tod_clock_monotonic()); | 66 | return tod_to_ns(get_tod_clock_monotonic()); |
67 | } | 67 | } |
68 | NOKPROBE_SYMBOL(sched_clock); | ||
68 | 69 | ||
69 | /* | 70 | /* |
70 | * Monotonic_clock - returns # of nanoseconds passed since time_init() | 71 | * Monotonic_clock - returns # of nanoseconds passed since time_init() |
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 9ff5ecba26ab..f081cf1157c3 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -49,7 +49,8 @@ static inline void report_user_fault(struct pt_regs *regs, int signr) | |||
49 | return; | 49 | return; |
50 | if (!printk_ratelimit()) | 50 | if (!printk_ratelimit()) |
51 | return; | 51 | return; |
52 | printk("User process fault: interruption code 0x%X ", regs->int_code); | 52 | printk("User process fault: interruption code %04x ilc:%d ", |
53 | regs->int_code & 0xffff, regs->int_code >> 17); | ||
53 | print_vma_addr("in ", regs->psw.addr & PSW_ADDR_INSN); | 54 | print_vma_addr("in ", regs->psw.addr & PSW_ADDR_INSN); |
54 | printk("\n"); | 55 | printk("\n"); |
55 | show_regs(regs); | 56 | show_regs(regs); |
@@ -87,16 +88,16 @@ void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str) | |||
87 | } | 88 | } |
88 | } | 89 | } |
89 | 90 | ||
90 | static void __kprobes do_trap(struct pt_regs *regs, int si_signo, int si_code, | 91 | static void do_trap(struct pt_regs *regs, int si_signo, int si_code, char *str) |
91 | char *str) | ||
92 | { | 92 | { |
93 | if (notify_die(DIE_TRAP, str, regs, 0, | 93 | if (notify_die(DIE_TRAP, str, regs, 0, |
94 | regs->int_code, si_signo) == NOTIFY_STOP) | 94 | regs->int_code, si_signo) == NOTIFY_STOP) |
95 | return; | 95 | return; |
96 | do_report_trap(regs, si_signo, si_code, str); | 96 | do_report_trap(regs, si_signo, si_code, str); |
97 | } | 97 | } |
98 | NOKPROBE_SYMBOL(do_trap); | ||
98 | 99 | ||
99 | void __kprobes do_per_trap(struct pt_regs *regs) | 100 | void do_per_trap(struct pt_regs *regs) |
100 | { | 101 | { |
101 | siginfo_t info; | 102 | siginfo_t info; |
102 | 103 | ||
@@ -111,6 +112,7 @@ void __kprobes do_per_trap(struct pt_regs *regs) | |||
111 | (void __force __user *) current->thread.per_event.address; | 112 | (void __force __user *) current->thread.per_event.address; |
112 | force_sig_info(SIGTRAP, &info, current); | 113 | force_sig_info(SIGTRAP, &info, current); |
113 | } | 114 | } |
115 | NOKPROBE_SYMBOL(do_per_trap); | ||
114 | 116 | ||
115 | void default_trap_handler(struct pt_regs *regs) | 117 | void default_trap_handler(struct pt_regs *regs) |
116 | { | 118 | { |
@@ -151,8 +153,6 @@ DO_ERROR_INFO(privileged_op, SIGILL, ILL_PRVOPC, | |||
151 | "privileged operation") | 153 | "privileged operation") |
152 | DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN, | 154 | DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN, |
153 | "special operation exception") | 155 | "special operation exception") |
154 | DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, | ||
155 | "translation exception") | ||
156 | 156 | ||
157 | #ifdef CONFIG_64BIT | 157 | #ifdef CONFIG_64BIT |
158 | DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN, | 158 | DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN, |
@@ -179,7 +179,13 @@ static inline void do_fp_trap(struct pt_regs *regs, int fpc) | |||
179 | do_trap(regs, SIGFPE, si_code, "floating point exception"); | 179 | do_trap(regs, SIGFPE, si_code, "floating point exception"); |
180 | } | 180 | } |
181 | 181 | ||
182 | void __kprobes illegal_op(struct pt_regs *regs) | 182 | void translation_exception(struct pt_regs *regs) |
183 | { | ||
184 | /* May never happen. */ | ||
185 | die(regs, "Translation exception"); | ||
186 | } | ||
187 | |||
188 | void illegal_op(struct pt_regs *regs) | ||
183 | { | 189 | { |
184 | siginfo_t info; | 190 | siginfo_t info; |
185 | __u8 opcode[6]; | 191 | __u8 opcode[6]; |
@@ -252,7 +258,7 @@ void __kprobes illegal_op(struct pt_regs *regs) | |||
252 | if (signal) | 258 | if (signal) |
253 | do_trap(regs, signal, ILL_ILLOPC, "illegal operation"); | 259 | do_trap(regs, signal, ILL_ILLOPC, "illegal operation"); |
254 | } | 260 | } |
255 | 261 | NOKPROBE_SYMBOL(illegal_op); | |
256 | 262 | ||
257 | #ifdef CONFIG_MATHEMU | 263 | #ifdef CONFIG_MATHEMU |
258 | void specification_exception(struct pt_regs *regs) | 264 | void specification_exception(struct pt_regs *regs) |
@@ -469,7 +475,7 @@ void space_switch_exception(struct pt_regs *regs) | |||
469 | do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event"); | 475 | do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event"); |
470 | } | 476 | } |
471 | 477 | ||
472 | void __kprobes kernel_stack_overflow(struct pt_regs * regs) | 478 | void kernel_stack_overflow(struct pt_regs *regs) |
473 | { | 479 | { |
474 | bust_spinlocks(1); | 480 | bust_spinlocks(1); |
475 | printk("Kernel stack overflow.\n"); | 481 | printk("Kernel stack overflow.\n"); |
@@ -477,6 +483,7 @@ void __kprobes kernel_stack_overflow(struct pt_regs * regs) | |||
477 | bust_spinlocks(0); | 483 | bust_spinlocks(0); |
478 | panic("Corrupt kernel stack, can't continue."); | 484 | panic("Corrupt kernel stack, can't continue."); |
479 | } | 485 | } |
486 | NOKPROBE_SYMBOL(kernel_stack_overflow); | ||
480 | 487 | ||
481 | void __init trap_init(void) | 488 | void __init trap_init(void) |
482 | { | 489 | { |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 55aade49b6d1..6b049ee75a56 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -271,7 +271,7 @@ static int kvm_s390_mem_control(struct kvm *kvm, struct kvm_device_attr *attr) | |||
271 | case KVM_S390_VM_MEM_CLR_CMMA: | 271 | case KVM_S390_VM_MEM_CLR_CMMA: |
272 | mutex_lock(&kvm->lock); | 272 | mutex_lock(&kvm->lock); |
273 | idx = srcu_read_lock(&kvm->srcu); | 273 | idx = srcu_read_lock(&kvm->srcu); |
274 | page_table_reset_pgste(kvm->arch.gmap->mm, 0, TASK_SIZE, false); | 274 | s390_reset_cmma(kvm->arch.gmap->mm); |
275 | srcu_read_unlock(&kvm->srcu, idx); | 275 | srcu_read_unlock(&kvm->srcu, idx); |
276 | mutex_unlock(&kvm->lock); | 276 | mutex_unlock(&kvm->lock); |
277 | ret = 0; | 277 | ret = 0; |
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 72bb2dd8b9cd..f47cb0c6d906 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -156,21 +156,25 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu) | |||
156 | return 0; | 156 | return 0; |
157 | } | 157 | } |
158 | 158 | ||
159 | static void __skey_check_enable(struct kvm_vcpu *vcpu) | 159 | static int __skey_check_enable(struct kvm_vcpu *vcpu) |
160 | { | 160 | { |
161 | int rc = 0; | ||
161 | if (!(vcpu->arch.sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE))) | 162 | if (!(vcpu->arch.sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE))) |
162 | return; | 163 | return rc; |
163 | 164 | ||
164 | s390_enable_skey(); | 165 | rc = s390_enable_skey(); |
165 | trace_kvm_s390_skey_related_inst(vcpu); | 166 | trace_kvm_s390_skey_related_inst(vcpu); |
166 | vcpu->arch.sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE); | 167 | vcpu->arch.sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE); |
168 | return rc; | ||
167 | } | 169 | } |
168 | 170 | ||
169 | 171 | ||
170 | static int handle_skey(struct kvm_vcpu *vcpu) | 172 | static int handle_skey(struct kvm_vcpu *vcpu) |
171 | { | 173 | { |
172 | __skey_check_enable(vcpu); | 174 | int rc = __skey_check_enable(vcpu); |
173 | 175 | ||
176 | if (rc) | ||
177 | return rc; | ||
174 | vcpu->stat.instruction_storage_key++; | 178 | vcpu->stat.instruction_storage_key++; |
175 | 179 | ||
176 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | 180 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) |
@@ -683,7 +687,10 @@ static int handle_pfmf(struct kvm_vcpu *vcpu) | |||
683 | } | 687 | } |
684 | 688 | ||
685 | if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK) { | 689 | if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK) { |
686 | __skey_check_enable(vcpu); | 690 | int rc = __skey_check_enable(vcpu); |
691 | |||
692 | if (rc) | ||
693 | return rc; | ||
687 | if (set_guest_storage_key(current->mm, useraddr, | 694 | if (set_guest_storage_key(current->mm, useraddr, |
688 | vcpu->run->s.regs.gprs[reg1] & PFMF_KEY, | 695 | vcpu->run->s.regs.gprs[reg1] & PFMF_KEY, |
689 | vcpu->run->s.regs.gprs[reg1] & PFMF_NQ)) | 696 | vcpu->run->s.regs.gprs[reg1] & PFMF_NQ)) |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index a2b81d6ce8a5..811937bb90be 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -261,8 +261,8 @@ static inline void report_user_fault(struct pt_regs *regs, long signr) | |||
261 | return; | 261 | return; |
262 | if (!printk_ratelimit()) | 262 | if (!printk_ratelimit()) |
263 | return; | 263 | return; |
264 | printk(KERN_ALERT "User process fault: interruption code 0x%X ", | 264 | printk(KERN_ALERT "User process fault: interruption code %04x ilc:%d", |
265 | regs->int_code); | 265 | regs->int_code & 0xffff, regs->int_code >> 17); |
266 | print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN); | 266 | print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN); |
267 | printk(KERN_CONT "\n"); | 267 | printk(KERN_CONT "\n"); |
268 | printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n", | 268 | printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n", |
@@ -548,7 +548,7 @@ out: | |||
548 | return fault; | 548 | return fault; |
549 | } | 549 | } |
550 | 550 | ||
551 | void __kprobes do_protection_exception(struct pt_regs *regs) | 551 | void do_protection_exception(struct pt_regs *regs) |
552 | { | 552 | { |
553 | unsigned long trans_exc_code; | 553 | unsigned long trans_exc_code; |
554 | int fault; | 554 | int fault; |
@@ -574,8 +574,9 @@ void __kprobes do_protection_exception(struct pt_regs *regs) | |||
574 | if (unlikely(fault)) | 574 | if (unlikely(fault)) |
575 | do_fault_error(regs, fault); | 575 | do_fault_error(regs, fault); |
576 | } | 576 | } |
577 | NOKPROBE_SYMBOL(do_protection_exception); | ||
577 | 578 | ||
578 | void __kprobes do_dat_exception(struct pt_regs *regs) | 579 | void do_dat_exception(struct pt_regs *regs) |
579 | { | 580 | { |
580 | int access, fault; | 581 | int access, fault; |
581 | 582 | ||
@@ -584,6 +585,7 @@ void __kprobes do_dat_exception(struct pt_regs *regs) | |||
584 | if (unlikely(fault)) | 585 | if (unlikely(fault)) |
585 | do_fault_error(regs, fault); | 586 | do_fault_error(regs, fault); |
586 | } | 587 | } |
588 | NOKPROBE_SYMBOL(do_dat_exception); | ||
587 | 589 | ||
588 | #ifdef CONFIG_PFAULT | 590 | #ifdef CONFIG_PFAULT |
589 | /* | 591 | /* |
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 1b79ca67392f..71c7eff2c89f 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/rcupdate.h> | 18 | #include <linux/rcupdate.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/swapops.h> | 20 | #include <linux/swapops.h> |
21 | #include <linux/ksm.h> | ||
22 | #include <linux/mman.h> | ||
21 | 23 | ||
22 | #include <asm/pgtable.h> | 24 | #include <asm/pgtable.h> |
23 | #include <asm/pgalloc.h> | 25 | #include <asm/pgalloc.h> |
@@ -750,8 +752,7 @@ int gmap_ipte_notify(struct gmap *gmap, unsigned long gaddr, unsigned long len) | |||
750 | break; | 752 | break; |
751 | /* Walk the process page table, lock and get pte pointer */ | 753 | /* Walk the process page table, lock and get pte pointer */ |
752 | ptep = get_locked_pte(gmap->mm, addr, &ptl); | 754 | ptep = get_locked_pte(gmap->mm, addr, &ptl); |
753 | if (unlikely(!ptep)) | 755 | VM_BUG_ON(!ptep); |
754 | continue; | ||
755 | /* Set notification bit in the pgste of the pte */ | 756 | /* Set notification bit in the pgste of the pte */ |
756 | entry = *ptep; | 757 | entry = *ptep; |
757 | if ((pte_val(entry) & (_PAGE_INVALID | _PAGE_PROTECT)) == 0) { | 758 | if ((pte_val(entry) & (_PAGE_INVALID | _PAGE_PROTECT)) == 0) { |
@@ -761,7 +762,7 @@ int gmap_ipte_notify(struct gmap *gmap, unsigned long gaddr, unsigned long len) | |||
761 | gaddr += PAGE_SIZE; | 762 | gaddr += PAGE_SIZE; |
762 | len -= PAGE_SIZE; | 763 | len -= PAGE_SIZE; |
763 | } | 764 | } |
764 | spin_unlock(ptl); | 765 | pte_unmap_unlock(ptep, ptl); |
765 | } | 766 | } |
766 | up_read(&gmap->mm->mmap_sem); | 767 | up_read(&gmap->mm->mmap_sem); |
767 | return rc; | 768 | return rc; |
@@ -834,99 +835,6 @@ static inline void page_table_free_pgste(unsigned long *table) | |||
834 | __free_page(page); | 835 | __free_page(page); |
835 | } | 836 | } |
836 | 837 | ||
837 | static inline unsigned long page_table_reset_pte(struct mm_struct *mm, pmd_t *pmd, | ||
838 | unsigned long addr, unsigned long end, bool init_skey) | ||
839 | { | ||
840 | pte_t *start_pte, *pte; | ||
841 | spinlock_t *ptl; | ||
842 | pgste_t pgste; | ||
843 | |||
844 | start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl); | ||
845 | pte = start_pte; | ||
846 | do { | ||
847 | pgste = pgste_get_lock(pte); | ||
848 | pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK; | ||
849 | if (init_skey) { | ||
850 | unsigned long address; | ||
851 | |||
852 | pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT | | ||
853 | PGSTE_GR_BIT | PGSTE_GC_BIT); | ||
854 | |||
855 | /* skip invalid and not writable pages */ | ||
856 | if (pte_val(*pte) & _PAGE_INVALID || | ||
857 | !(pte_val(*pte) & _PAGE_WRITE)) { | ||
858 | pgste_set_unlock(pte, pgste); | ||
859 | continue; | ||
860 | } | ||
861 | |||
862 | address = pte_val(*pte) & PAGE_MASK; | ||
863 | page_set_storage_key(address, PAGE_DEFAULT_KEY, 1); | ||
864 | } | ||
865 | pgste_set_unlock(pte, pgste); | ||
866 | } while (pte++, addr += PAGE_SIZE, addr != end); | ||
867 | pte_unmap_unlock(start_pte, ptl); | ||
868 | |||
869 | return addr; | ||
870 | } | ||
871 | |||
872 | static inline unsigned long page_table_reset_pmd(struct mm_struct *mm, pud_t *pud, | ||
873 | unsigned long addr, unsigned long end, bool init_skey) | ||
874 | { | ||
875 | unsigned long next; | ||
876 | pmd_t *pmd; | ||
877 | |||
878 | pmd = pmd_offset(pud, addr); | ||
879 | do { | ||
880 | next = pmd_addr_end(addr, end); | ||
881 | if (pmd_none_or_clear_bad(pmd)) | ||
882 | continue; | ||
883 | next = page_table_reset_pte(mm, pmd, addr, next, init_skey); | ||
884 | } while (pmd++, addr = next, addr != end); | ||
885 | |||
886 | return addr; | ||
887 | } | ||
888 | |||
889 | static inline unsigned long page_table_reset_pud(struct mm_struct *mm, pgd_t *pgd, | ||
890 | unsigned long addr, unsigned long end, bool init_skey) | ||
891 | { | ||
892 | unsigned long next; | ||
893 | pud_t *pud; | ||
894 | |||
895 | pud = pud_offset(pgd, addr); | ||
896 | do { | ||
897 | next = pud_addr_end(addr, end); | ||
898 | if (pud_none_or_clear_bad(pud)) | ||
899 | continue; | ||
900 | next = page_table_reset_pmd(mm, pud, addr, next, init_skey); | ||
901 | } while (pud++, addr = next, addr != end); | ||
902 | |||
903 | return addr; | ||
904 | } | ||
905 | |||
906 | void page_table_reset_pgste(struct mm_struct *mm, unsigned long start, | ||
907 | unsigned long end, bool init_skey) | ||
908 | { | ||
909 | unsigned long addr, next; | ||
910 | pgd_t *pgd; | ||
911 | |||
912 | down_write(&mm->mmap_sem); | ||
913 | if (init_skey && mm_use_skey(mm)) | ||
914 | goto out_up; | ||
915 | addr = start; | ||
916 | pgd = pgd_offset(mm, addr); | ||
917 | do { | ||
918 | next = pgd_addr_end(addr, end); | ||
919 | if (pgd_none_or_clear_bad(pgd)) | ||
920 | continue; | ||
921 | next = page_table_reset_pud(mm, pgd, addr, next, init_skey); | ||
922 | } while (pgd++, addr = next, addr != end); | ||
923 | if (init_skey) | ||
924 | current->mm->context.use_skey = 1; | ||
925 | out_up: | ||
926 | up_write(&mm->mmap_sem); | ||
927 | } | ||
928 | EXPORT_SYMBOL(page_table_reset_pgste); | ||
929 | |||
930 | int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, | 838 | int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, |
931 | unsigned long key, bool nq) | 839 | unsigned long key, bool nq) |
932 | { | 840 | { |
@@ -992,11 +900,6 @@ static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm) | |||
992 | return NULL; | 900 | return NULL; |
993 | } | 901 | } |
994 | 902 | ||
995 | void page_table_reset_pgste(struct mm_struct *mm, unsigned long start, | ||
996 | unsigned long end, bool init_skey) | ||
997 | { | ||
998 | } | ||
999 | |||
1000 | static inline void page_table_free_pgste(unsigned long *table) | 903 | static inline void page_table_free_pgste(unsigned long *table) |
1001 | { | 904 | { |
1002 | } | 905 | } |
@@ -1347,13 +1250,89 @@ EXPORT_SYMBOL_GPL(s390_enable_sie); | |||
1347 | * Enable storage key handling from now on and initialize the storage | 1250 | * Enable storage key handling from now on and initialize the storage |
1348 | * keys with the default key. | 1251 | * keys with the default key. |
1349 | */ | 1252 | */ |
1350 | void s390_enable_skey(void) | 1253 | static int __s390_enable_skey(pte_t *pte, unsigned long addr, |
1254 | unsigned long next, struct mm_walk *walk) | ||
1351 | { | 1255 | { |
1352 | page_table_reset_pgste(current->mm, 0, TASK_SIZE, true); | 1256 | unsigned long ptev; |
1257 | pgste_t pgste; | ||
1258 | |||
1259 | pgste = pgste_get_lock(pte); | ||
1260 | /* | ||
1261 | * Remove all zero page mappings, | ||
1262 | * after establishing a policy to forbid zero page mappings | ||
1263 | * following faults for that page will get fresh anonymous pages | ||
1264 | */ | ||
1265 | if (is_zero_pfn(pte_pfn(*pte))) { | ||
1266 | ptep_flush_direct(walk->mm, addr, pte); | ||
1267 | pte_val(*pte) = _PAGE_INVALID; | ||
1268 | } | ||
1269 | /* Clear storage key */ | ||
1270 | pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT | | ||
1271 | PGSTE_GR_BIT | PGSTE_GC_BIT); | ||
1272 | ptev = pte_val(*pte); | ||
1273 | if (!(ptev & _PAGE_INVALID) && (ptev & _PAGE_WRITE)) | ||
1274 | page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 1); | ||
1275 | pgste_set_unlock(pte, pgste); | ||
1276 | return 0; | ||
1277 | } | ||
1278 | |||
1279 | int s390_enable_skey(void) | ||
1280 | { | ||
1281 | struct mm_walk walk = { .pte_entry = __s390_enable_skey }; | ||
1282 | struct mm_struct *mm = current->mm; | ||
1283 | struct vm_area_struct *vma; | ||
1284 | int rc = 0; | ||
1285 | |||
1286 | down_write(&mm->mmap_sem); | ||
1287 | if (mm_use_skey(mm)) | ||
1288 | goto out_up; | ||
1289 | |||
1290 | mm->context.use_skey = 1; | ||
1291 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | ||
1292 | if (ksm_madvise(vma, vma->vm_start, vma->vm_end, | ||
1293 | MADV_UNMERGEABLE, &vma->vm_flags)) { | ||
1294 | mm->context.use_skey = 0; | ||
1295 | rc = -ENOMEM; | ||
1296 | goto out_up; | ||
1297 | } | ||
1298 | } | ||
1299 | mm->def_flags &= ~VM_MERGEABLE; | ||
1300 | |||
1301 | walk.mm = mm; | ||
1302 | walk_page_range(0, TASK_SIZE, &walk); | ||
1303 | |||
1304 | out_up: | ||
1305 | up_write(&mm->mmap_sem); | ||
1306 | return rc; | ||
1353 | } | 1307 | } |
1354 | EXPORT_SYMBOL_GPL(s390_enable_skey); | 1308 | EXPORT_SYMBOL_GPL(s390_enable_skey); |
1355 | 1309 | ||
1356 | /* | 1310 | /* |
1311 | * Reset CMMA state, make all pages stable again. | ||
1312 | */ | ||
1313 | static int __s390_reset_cmma(pte_t *pte, unsigned long addr, | ||
1314 | unsigned long next, struct mm_walk *walk) | ||
1315 | { | ||
1316 | pgste_t pgste; | ||
1317 | |||
1318 | pgste = pgste_get_lock(pte); | ||
1319 | pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK; | ||
1320 | pgste_set_unlock(pte, pgste); | ||
1321 | return 0; | ||
1322 | } | ||
1323 | |||
1324 | void s390_reset_cmma(struct mm_struct *mm) | ||
1325 | { | ||
1326 | struct mm_walk walk = { .pte_entry = __s390_reset_cmma }; | ||
1327 | |||
1328 | down_write(&mm->mmap_sem); | ||
1329 | walk.mm = mm; | ||
1330 | walk_page_range(0, TASK_SIZE, &walk); | ||
1331 | up_write(&mm->mmap_sem); | ||
1332 | } | ||
1333 | EXPORT_SYMBOL_GPL(s390_reset_cmma); | ||
1334 | |||
1335 | /* | ||
1357 | * Test and reset if a guest page is dirty | 1336 | * Test and reset if a guest page is dirty |
1358 | */ | 1337 | */ |
1359 | bool gmap_test_and_clear_dirty(unsigned long address, struct gmap *gmap) | 1338 | bool gmap_test_and_clear_dirty(unsigned long address, struct gmap *gmap) |
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile index a9e1dc4ae442..805d8b29193a 100644 --- a/arch/s390/pci/Makefile +++ b/arch/s390/pci/Makefile | |||
@@ -3,4 +3,4 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_sysfs.o \ | 5 | obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_sysfs.o \ |
6 | pci_event.o pci_debug.o pci_insn.o | 6 | pci_event.o pci_debug.o pci_insn.o pci_mmio.o |
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index d59c82569750..3290f11ae1d9 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
@@ -369,8 +369,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
369 | 369 | ||
370 | if (type == PCI_CAP_ID_MSI && nvec > 1) | 370 | if (type == PCI_CAP_ID_MSI && nvec > 1) |
371 | return 1; | 371 | return 1; |
372 | msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX); | 372 | msi_vecs = min_t(unsigned int, nvec, zdev->max_msi); |
373 | msi_vecs = min_t(unsigned int, msi_vecs, CONFIG_PCI_NR_MSI); | ||
374 | 373 | ||
375 | /* Allocate adapter summary indicator bit */ | 374 | /* Allocate adapter summary indicator bit */ |
376 | rc = -EIO; | 375 | rc = -EIO; |
@@ -474,7 +473,8 @@ static void zpci_map_resources(struct zpci_dev *zdev) | |||
474 | len = pci_resource_len(pdev, i); | 473 | len = pci_resource_len(pdev, i); |
475 | if (!len) | 474 | if (!len) |
476 | continue; | 475 | continue; |
477 | pdev->resource[i].start = (resource_size_t) pci_iomap(pdev, i, 0); | 476 | pdev->resource[i].start = |
477 | (resource_size_t __force) pci_iomap(pdev, i, 0); | ||
478 | pdev->resource[i].end = pdev->resource[i].start + len - 1; | 478 | pdev->resource[i].end = pdev->resource[i].start + len - 1; |
479 | } | 479 | } |
480 | } | 480 | } |
@@ -489,7 +489,8 @@ static void zpci_unmap_resources(struct zpci_dev *zdev) | |||
489 | len = pci_resource_len(pdev, i); | 489 | len = pci_resource_len(pdev, i); |
490 | if (!len) | 490 | if (!len) |
491 | continue; | 491 | continue; |
492 | pci_iounmap(pdev, (void *) pdev->resource[i].start); | 492 | pci_iounmap(pdev, (void __iomem __force *) |
493 | pdev->resource[i].start); | ||
493 | } | 494 | } |
494 | } | 495 | } |
495 | 496 | ||
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index 6e22a247de9b..d6e411ed8b1f 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c | |||
@@ -62,6 +62,7 @@ static void clp_store_query_pci_fngrp(struct zpci_dev *zdev, | |||
62 | zdev->tlb_refresh = response->refresh; | 62 | zdev->tlb_refresh = response->refresh; |
63 | zdev->dma_mask = response->dasm; | 63 | zdev->dma_mask = response->dasm; |
64 | zdev->msi_addr = response->msia; | 64 | zdev->msi_addr = response->msia; |
65 | zdev->max_msi = response->noi; | ||
65 | zdev->fmb_update = response->mui; | 66 | zdev->fmb_update = response->mui; |
66 | 67 | ||
67 | switch (response->version) { | 68 | switch (response->version) { |
diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c index eec598c5939f..3229a2e570df 100644 --- a/arch/s390/pci/pci_debug.c +++ b/arch/s390/pci/pci_debug.c | |||
@@ -158,10 +158,7 @@ int __init zpci_debug_init(void) | |||
158 | 158 | ||
159 | void zpci_debug_exit(void) | 159 | void zpci_debug_exit(void) |
160 | { | 160 | { |
161 | if (pci_debug_msg_id) | 161 | debug_unregister(pci_debug_msg_id); |
162 | debug_unregister(pci_debug_msg_id); | 162 | debug_unregister(pci_debug_err_id); |
163 | if (pci_debug_err_id) | ||
164 | debug_unregister(pci_debug_err_id); | ||
165 | |||
166 | debugfs_remove(debugfs_root); | 163 | debugfs_remove(debugfs_root); |
167 | } | 164 | } |
diff --git a/arch/s390/pci/pci_mmio.c b/arch/s390/pci/pci_mmio.c new file mode 100644 index 000000000000..62c5ea6d8682 --- /dev/null +++ b/arch/s390/pci/pci_mmio.c | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * Access to PCI I/O memory from user space programs. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2014 | ||
5 | * Author(s): Alexey Ishchuk <aishchuk@linux.vnet.ibm.com> | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/syscalls.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/mm.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/pci.h> | ||
13 | |||
14 | static long get_pfn(unsigned long user_addr, unsigned long access, | ||
15 | unsigned long *pfn) | ||
16 | { | ||
17 | struct vm_area_struct *vma; | ||
18 | long ret; | ||
19 | |||
20 | down_read(¤t->mm->mmap_sem); | ||
21 | ret = -EINVAL; | ||
22 | vma = find_vma(current->mm, user_addr); | ||
23 | if (!vma) | ||
24 | goto out; | ||
25 | ret = -EACCES; | ||
26 | if (!(vma->vm_flags & access)) | ||
27 | goto out; | ||
28 | ret = follow_pfn(vma, user_addr, pfn); | ||
29 | out: | ||
30 | up_read(¤t->mm->mmap_sem); | ||
31 | return ret; | ||
32 | } | ||
33 | |||
34 | SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr, | ||
35 | const void __user *, user_buffer, size_t, length) | ||
36 | { | ||
37 | u8 local_buf[64]; | ||
38 | void __iomem *io_addr; | ||
39 | void *buf; | ||
40 | unsigned long pfn; | ||
41 | long ret; | ||
42 | |||
43 | if (!zpci_is_enabled()) | ||
44 | return -ENODEV; | ||
45 | |||
46 | if (length <= 0 || PAGE_SIZE - (mmio_addr & ~PAGE_MASK) < length) | ||
47 | return -EINVAL; | ||
48 | if (length > 64) { | ||
49 | buf = kmalloc(length, GFP_KERNEL); | ||
50 | if (!buf) | ||
51 | return -ENOMEM; | ||
52 | } else | ||
53 | buf = local_buf; | ||
54 | |||
55 | ret = get_pfn(mmio_addr, VM_WRITE, &pfn); | ||
56 | if (ret) | ||
57 | goto out; | ||
58 | io_addr = (void *)((pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); | ||
59 | |||
60 | ret = -EFAULT; | ||
61 | if ((unsigned long) io_addr < ZPCI_IOMAP_ADDR_BASE) | ||
62 | goto out; | ||
63 | |||
64 | if (copy_from_user(buf, user_buffer, length)) | ||
65 | goto out; | ||
66 | |||
67 | memcpy_toio(io_addr, buf, length); | ||
68 | ret = 0; | ||
69 | out: | ||
70 | if (buf != local_buf) | ||
71 | kfree(buf); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr, | ||
76 | void __user *, user_buffer, size_t, length) | ||
77 | { | ||
78 | u8 local_buf[64]; | ||
79 | void __iomem *io_addr; | ||
80 | void *buf; | ||
81 | unsigned long pfn; | ||
82 | long ret; | ||
83 | |||
84 | if (!zpci_is_enabled()) | ||
85 | return -ENODEV; | ||
86 | |||
87 | if (length <= 0 || PAGE_SIZE - (mmio_addr & ~PAGE_MASK) < length) | ||
88 | return -EINVAL; | ||
89 | if (length > 64) { | ||
90 | buf = kmalloc(length, GFP_KERNEL); | ||
91 | if (!buf) | ||
92 | return -ENOMEM; | ||
93 | } else | ||
94 | buf = local_buf; | ||
95 | |||
96 | ret = get_pfn(mmio_addr, VM_READ, &pfn); | ||
97 | if (ret) | ||
98 | goto out; | ||
99 | io_addr = (void *)((pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); | ||
100 | |||
101 | ret = -EFAULT; | ||
102 | if ((unsigned long) io_addr < ZPCI_IOMAP_ADDR_BASE) | ||
103 | goto out; | ||
104 | |||
105 | memcpy_fromio(buf, io_addr, length); | ||
106 | |||
107 | if (copy_to_user(user_buffer, buf, length)) | ||
108 | goto out; | ||
109 | |||
110 | ret = 0; | ||
111 | out: | ||
112 | if (buf != local_buf) | ||
113 | kfree(buf); | ||
114 | return ret; | ||
115 | } | ||
diff --git a/arch/x86/include/asm/xen/cpuid.h b/arch/x86/include/asm/xen/cpuid.h new file mode 100644 index 000000000000..0d809e9fc975 --- /dev/null +++ b/arch/x86/include/asm/xen/cpuid.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /****************************************************************************** | ||
2 | * arch-x86/cpuid.h | ||
3 | * | ||
4 | * CPUID interface to Xen. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | * of this software and associated documentation files (the "Software"), to | ||
8 | * deal in the Software without restriction, including without limitation the | ||
9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
10 | * sell copies of the Software, and to permit persons to whom the Software is | ||
11 | * furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be included in | ||
14 | * all copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
22 | * DEALINGS IN THE SOFTWARE. | ||
23 | * | ||
24 | * Copyright (c) 2007 Citrix Systems, Inc. | ||
25 | * | ||
26 | * Authors: | ||
27 | * Keir Fraser <keir@xen.org> | ||
28 | */ | ||
29 | |||
30 | #ifndef __XEN_PUBLIC_ARCH_X86_CPUID_H__ | ||
31 | #define __XEN_PUBLIC_ARCH_X86_CPUID_H__ | ||
32 | |||
33 | /* | ||
34 | * For compatibility with other hypervisor interfaces, the Xen cpuid leaves | ||
35 | * can be found at the first otherwise unused 0x100 aligned boundary starting | ||
36 | * from 0x40000000. | ||
37 | * | ||
38 | * e.g If viridian extensions are enabled for an HVM domain, the Xen cpuid | ||
39 | * leaves will start at 0x40000100 | ||
40 | */ | ||
41 | |||
42 | #define XEN_CPUID_FIRST_LEAF 0x40000000 | ||
43 | #define XEN_CPUID_LEAF(i) (XEN_CPUID_FIRST_LEAF + (i)) | ||
44 | |||
45 | /* | ||
46 | * Leaf 1 (0x40000x00) | ||
47 | * EAX: Largest Xen-information leaf. All leaves up to an including @EAX | ||
48 | * are supported by the Xen host. | ||
49 | * EBX-EDX: "XenVMMXenVMM" signature, allowing positive identification | ||
50 | * of a Xen host. | ||
51 | */ | ||
52 | #define XEN_CPUID_SIGNATURE_EBX 0x566e6558 /* "XenV" */ | ||
53 | #define XEN_CPUID_SIGNATURE_ECX 0x65584d4d /* "MMXe" */ | ||
54 | #define XEN_CPUID_SIGNATURE_EDX 0x4d4d566e /* "nVMM" */ | ||
55 | |||
56 | /* | ||
57 | * Leaf 2 (0x40000x01) | ||
58 | * EAX[31:16]: Xen major version. | ||
59 | * EAX[15: 0]: Xen minor version. | ||
60 | * EBX-EDX: Reserved (currently all zeroes). | ||
61 | */ | ||
62 | |||
63 | /* | ||
64 | * Leaf 3 (0x40000x02) | ||
65 | * EAX: Number of hypercall transfer pages. This register is always guaranteed | ||
66 | * to specify one hypercall page. | ||
67 | * EBX: Base address of Xen-specific MSRs. | ||
68 | * ECX: Features 1. Unused bits are set to zero. | ||
69 | * EDX: Features 2. Unused bits are set to zero. | ||
70 | */ | ||
71 | |||
72 | /* Does the host support MMU_PT_UPDATE_PRESERVE_AD for this guest? */ | ||
73 | #define _XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD 0 | ||
74 | #define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD (1u<<0) | ||
75 | |||
76 | /* | ||
77 | * Leaf 5 (0x40000x04) | ||
78 | * HVM-specific features | ||
79 | */ | ||
80 | |||
81 | /* EAX Features */ | ||
82 | /* Virtualized APIC registers */ | ||
83 | #define XEN_HVM_CPUID_APIC_ACCESS_VIRT (1u << 0) | ||
84 | /* Virtualized x2APIC accesses */ | ||
85 | #define XEN_HVM_CPUID_X2APIC_VIRT (1u << 1) | ||
86 | /* Memory mapped from other domains has valid IOMMU entries */ | ||
87 | #define XEN_HVM_CPUID_IOMMU_MAPPINGS (1u << 2) | ||
88 | |||
89 | #define XEN_CPUID_MAX_NUM_LEAVES 4 | ||
90 | |||
91 | #endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */ | ||
diff --git a/arch/x86/include/asm/xen/page-coherent.h b/arch/x86/include/asm/xen/page-coherent.h index 7f02fe4e2c7b..acd844c017d3 100644 --- a/arch/x86/include/asm/xen/page-coherent.h +++ b/arch/x86/include/asm/xen/page-coherent.h | |||
@@ -22,8 +22,8 @@ static inline void xen_free_coherent_pages(struct device *hwdev, size_t size, | |||
22 | } | 22 | } |
23 | 23 | ||
24 | static inline void xen_dma_map_page(struct device *hwdev, struct page *page, | 24 | static inline void xen_dma_map_page(struct device *hwdev, struct page *page, |
25 | unsigned long offset, size_t size, enum dma_data_direction dir, | 25 | dma_addr_t dev_addr, unsigned long offset, size_t size, |
26 | struct dma_attrs *attrs) { } | 26 | enum dma_data_direction dir, struct dma_attrs *attrs) { } |
27 | 27 | ||
28 | static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, | 28 | static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle, |
29 | size_t size, enum dma_data_direction dir, | 29 | size_t size, enum dma_data_direction dir, |
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index c949923a5668..f58ef6c0613b 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
@@ -236,4 +236,11 @@ void make_lowmem_page_readwrite(void *vaddr); | |||
236 | #define xen_remap(cookie, size) ioremap((cookie), (size)); | 236 | #define xen_remap(cookie, size) ioremap((cookie), (size)); |
237 | #define xen_unmap(cookie) iounmap((cookie)) | 237 | #define xen_unmap(cookie) iounmap((cookie)) |
238 | 238 | ||
239 | static inline bool xen_arch_need_swiotlb(struct device *dev, | ||
240 | unsigned long pfn, | ||
241 | unsigned long mfn) | ||
242 | { | ||
243 | return false; | ||
244 | } | ||
245 | |||
239 | #endif /* _ASM_X86_XEN_PAGE_H */ | 246 | #endif /* _ASM_X86_XEN_PAGE_H */ |
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 1819a91bbb9f..c489ef2c1a39 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <xen/features.h> | 23 | #include <xen/features.h> |
24 | #include <xen/events.h> | 24 | #include <xen/events.h> |
25 | #include <asm/xen/pci.h> | 25 | #include <asm/xen/pci.h> |
26 | #include <asm/xen/cpuid.h> | ||
27 | #include <asm/apic.h> | ||
26 | #include <asm/i8259.h> | 28 | #include <asm/i8259.h> |
27 | 29 | ||
28 | static int xen_pcifront_enable_irq(struct pci_dev *dev) | 30 | static int xen_pcifront_enable_irq(struct pci_dev *dev) |
@@ -423,6 +425,28 @@ int __init pci_xen_init(void) | |||
423 | return 0; | 425 | return 0; |
424 | } | 426 | } |
425 | 427 | ||
428 | #ifdef CONFIG_PCI_MSI | ||
429 | void __init xen_msi_init(void) | ||
430 | { | ||
431 | if (!disable_apic) { | ||
432 | /* | ||
433 | * If hardware supports (x2)APIC virtualization (as indicated | ||
434 | * by hypervisor's leaf 4) then we don't need to use pirqs/ | ||
435 | * event channels for MSI handling and instead use regular | ||
436 | * APIC processing | ||
437 | */ | ||
438 | uint32_t eax = cpuid_eax(xen_cpuid_base() + 4); | ||
439 | |||
440 | if (((eax & XEN_HVM_CPUID_X2APIC_VIRT) && x2apic_mode) || | ||
441 | ((eax & XEN_HVM_CPUID_APIC_ACCESS_VIRT) && cpu_has_apic)) | ||
442 | return; | ||
443 | } | ||
444 | |||
445 | x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs; | ||
446 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; | ||
447 | } | ||
448 | #endif | ||
449 | |||
426 | int __init pci_xen_hvm_init(void) | 450 | int __init pci_xen_hvm_init(void) |
427 | { | 451 | { |
428 | if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs)) | 452 | if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs)) |
@@ -437,8 +461,11 @@ int __init pci_xen_hvm_init(void) | |||
437 | #endif | 461 | #endif |
438 | 462 | ||
439 | #ifdef CONFIG_PCI_MSI | 463 | #ifdef CONFIG_PCI_MSI |
440 | x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs; | 464 | /* |
441 | x86_msi.teardown_msi_irq = xen_teardown_msi_irq; | 465 | * We need to wait until after x2apic is initialized |
466 | * before we can set MSI IRQ ops. | ||
467 | */ | ||
468 | x86_platform.apic_post_init = xen_msi_init; | ||
442 | #endif | 469 | #endif |
443 | return 0; | 470 | return 0; |
444 | } | 471 | } |