diff options
Diffstat (limited to 'arch/powerpc')
35 files changed, 277 insertions, 2024 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c33e3ad2c8fd..508e3fe934d2 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -341,7 +341,7 @@ config SWIOTLB | |||
| 341 | 341 | ||
| 342 | config HOTPLUG_CPU | 342 | config HOTPLUG_CPU |
| 343 | bool "Support for enabling/disabling CPUs" | 343 | bool "Support for enabling/disabling CPUs" |
| 344 | depends on SMP && HOTPLUG && (PPC_PSERIES || \ | 344 | depends on SMP && (PPC_PSERIES || \ |
| 345 | PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC)) | 345 | PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC)) |
| 346 | ---help--- | 346 | ---help--- |
| 347 | Say Y here to be able to disable and re-enable individual | 347 | Say Y here to be able to disable and re-enable individual |
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index 349ed85c7d61..08891d07aeb6 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h | |||
| @@ -107,8 +107,9 @@ struct kvmppc_vcpu_book3s { | |||
| 107 | #define CONTEXT_GUEST 1 | 107 | #define CONTEXT_GUEST 1 |
| 108 | #define CONTEXT_GUEST_END 2 | 108 | #define CONTEXT_GUEST_END 2 |
| 109 | 109 | ||
| 110 | #define VSID_REAL 0x1fffffffffc00000ULL | 110 | #define VSID_REAL 0x0fffffffffc00000ULL |
| 111 | #define VSID_BAT 0x1fffffffffb00000ULL | 111 | #define VSID_BAT 0x0fffffffffb00000ULL |
| 112 | #define VSID_1T 0x1000000000000000ULL | ||
| 112 | #define VSID_REAL_DR 0x2000000000000000ULL | 113 | #define VSID_REAL_DR 0x2000000000000000ULL |
| 113 | #define VSID_REAL_IR 0x4000000000000000ULL | 114 | #define VSID_REAL_IR 0x4000000000000000ULL |
| 114 | #define VSID_PR 0x8000000000000000ULL | 115 | #define VSID_PR 0x8000000000000000ULL |
| @@ -123,6 +124,7 @@ extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu); | |||
| 123 | extern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu); | 124 | extern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu); |
| 124 | extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte); | 125 | extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte); |
| 125 | extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr); | 126 | extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr); |
| 127 | extern void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong eaddr, ulong seg_size); | ||
| 126 | extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu); | 128 | extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu); |
| 127 | extern int kvmppc_book3s_hv_page_fault(struct kvm_run *run, | 129 | extern int kvmppc_book3s_hv_page_fault(struct kvm_run *run, |
| 128 | struct kvm_vcpu *vcpu, unsigned long addr, | 130 | struct kvm_vcpu *vcpu, unsigned long addr, |
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index a73668a5f30d..b467530e2485 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h | |||
| @@ -38,7 +38,7 @@ extern void drop_cop(unsigned long acop, struct mm_struct *mm); | |||
| 38 | 38 | ||
| 39 | /* | 39 | /* |
| 40 | * switch_mm is the entry point called from the architecture independent | 40 | * switch_mm is the entry point called from the architecture independent |
| 41 | * code in kernel/sched.c | 41 | * code in kernel/sched/core.c |
| 42 | */ | 42 | */ |
| 43 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 43 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, |
| 44 | struct task_struct *tsk) | 44 | struct task_struct *tsk) |
diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h b/arch/powerpc/include/asm/mpc52xx_psc.h index 2966df604221..d0ece257d310 100644 --- a/arch/powerpc/include/asm/mpc52xx_psc.h +++ b/arch/powerpc/include/asm/mpc52xx_psc.h | |||
| @@ -299,4 +299,53 @@ struct mpc512x_psc_fifo { | |||
| 299 | #define rxdata_32 rxdata.rxdata_32 | 299 | #define rxdata_32 rxdata.rxdata_32 |
| 300 | }; | 300 | }; |
| 301 | 301 | ||
| 302 | struct mpc5125_psc { | ||
| 303 | u8 mr1; /* PSC + 0x00 */ | ||
| 304 | u8 reserved0[3]; | ||
| 305 | u8 mr2; /* PSC + 0x04 */ | ||
| 306 | u8 reserved1[3]; | ||
| 307 | struct { | ||
| 308 | u16 status; /* PSC + 0x08 */ | ||
| 309 | u8 reserved2[2]; | ||
| 310 | u8 clock_select; /* PSC + 0x0c */ | ||
| 311 | u8 reserved3[3]; | ||
| 312 | } sr_csr; | ||
| 313 | u8 command; /* PSC + 0x10 */ | ||
| 314 | u8 reserved4[3]; | ||
| 315 | union { /* PSC + 0x14 */ | ||
| 316 | u8 buffer_8; | ||
| 317 | u16 buffer_16; | ||
| 318 | u32 buffer_32; | ||
| 319 | } buffer; | ||
| 320 | struct { | ||
| 321 | u8 ipcr; /* PSC + 0x18 */ | ||
| 322 | u8 reserved5[3]; | ||
| 323 | u8 acr; /* PSC + 0x1c */ | ||
| 324 | u8 reserved6[3]; | ||
| 325 | } ipcr_acr; | ||
| 326 | struct { | ||
| 327 | u16 isr; /* PSC + 0x20 */ | ||
| 328 | u8 reserved7[2]; | ||
| 329 | u16 imr; /* PSC + 0x24 */ | ||
| 330 | u8 reserved8[2]; | ||
| 331 | } isr_imr; | ||
| 332 | u8 ctur; /* PSC + 0x28 */ | ||
| 333 | u8 reserved9[3]; | ||
| 334 | u8 ctlr; /* PSC + 0x2c */ | ||
| 335 | u8 reserved10[3]; | ||
| 336 | u32 ccr; /* PSC + 0x30 */ | ||
| 337 | u32 ac97slots; /* PSC + 0x34 */ | ||
| 338 | u32 ac97cmd; /* PSC + 0x38 */ | ||
| 339 | u32 ac97data; /* PSC + 0x3c */ | ||
| 340 | u8 reserved11[4]; | ||
| 341 | u8 ip; /* PSC + 0x44 */ | ||
| 342 | u8 reserved12[3]; | ||
| 343 | u8 op1; /* PSC + 0x48 */ | ||
| 344 | u8 reserved13[3]; | ||
| 345 | u8 op0; /* PSC + 0x4c */ | ||
| 346 | u8 reserved14[3]; | ||
| 347 | u32 sicr; /* PSC + 0x50 */ | ||
| 348 | u8 reserved15[4]; /* make eq. sizeof(mpc52xx_psc) */ | ||
| 349 | }; | ||
| 350 | |||
| 302 | #endif /* __ASM_MPC52xx_PSC_H__ */ | 351 | #endif /* __ASM_MPC52xx_PSC_H__ */ |
diff --git a/arch/powerpc/include/asm/mutex.h b/arch/powerpc/include/asm/mutex.h index 5399f7e18102..127ab23e1f6c 100644 --- a/arch/powerpc/include/asm/mutex.h +++ b/arch/powerpc/include/asm/mutex.h | |||
| @@ -82,17 +82,15 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) | |||
| 82 | * __mutex_fastpath_lock_retval - try to take the lock by moving the count | 82 | * __mutex_fastpath_lock_retval - try to take the lock by moving the count |
| 83 | * from 1 to a 0 value | 83 | * from 1 to a 0 value |
| 84 | * @count: pointer of type atomic_t | 84 | * @count: pointer of type atomic_t |
| 85 | * @fail_fn: function to call if the original value was not 1 | ||
| 86 | * | 85 | * |
| 87 | * Change the count from 1 to a value lower than 1, and call <fail_fn> if | 86 | * Change the count from 1 to a value lower than 1. This function returns 0 |
| 88 | * it wasn't 1 originally. This function returns 0 if the fastpath succeeds, | 87 | * if the fastpath succeeds, or -1 otherwise. |
| 89 | * or anything the slow path function returns. | ||
| 90 | */ | 88 | */ |
| 91 | static inline int | 89 | static inline int |
| 92 | __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) | 90 | __mutex_fastpath_lock_retval(atomic_t *count) |
| 93 | { | 91 | { |
| 94 | if (unlikely(__mutex_dec_return_lock(count) < 0)) | 92 | if (unlikely(__mutex_dec_return_lock(count) < 0)) |
| 95 | return fail_fn(count); | 93 | return -1; |
| 96 | return 0; | 94 | return 0; |
| 97 | } | 95 | } |
| 98 | 96 | ||
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 7aeb9555f6ea..b6293d26bd39 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h | |||
| @@ -198,9 +198,6 @@ extern void paging_init(void); | |||
| 198 | */ | 198 | */ |
| 199 | #define kern_addr_valid(addr) (1) | 199 | #define kern_addr_valid(addr) (1) |
| 200 | 200 | ||
| 201 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ | ||
| 202 | remap_pfn_range(vma, vaddr, pfn, size, prot) | ||
| 203 | |||
| 204 | #include <asm-generic/pgtable.h> | 201 | #include <asm-generic/pgtable.h> |
| 205 | 202 | ||
| 206 | 203 | ||
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index 4db49590acf5..9485b43a7c00 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h | |||
| @@ -178,7 +178,7 @@ do { \ | |||
| 178 | long __pu_err; \ | 178 | long __pu_err; \ |
| 179 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ | 179 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ |
| 180 | if (!is_kernel_addr((unsigned long)__pu_addr)) \ | 180 | if (!is_kernel_addr((unsigned long)__pu_addr)) \ |
| 181 | might_sleep(); \ | 181 | might_fault(); \ |
| 182 | __chk_user_ptr(ptr); \ | 182 | __chk_user_ptr(ptr); \ |
| 183 | __put_user_size((x), __pu_addr, (size), __pu_err); \ | 183 | __put_user_size((x), __pu_addr, (size), __pu_err); \ |
| 184 | __pu_err; \ | 184 | __pu_err; \ |
| @@ -188,7 +188,7 @@ do { \ | |||
| 188 | ({ \ | 188 | ({ \ |
| 189 | long __pu_err = -EFAULT; \ | 189 | long __pu_err = -EFAULT; \ |
| 190 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ | 190 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ |
| 191 | might_sleep(); \ | 191 | might_fault(); \ |
| 192 | if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ | 192 | if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ |
| 193 | __put_user_size((x), __pu_addr, (size), __pu_err); \ | 193 | __put_user_size((x), __pu_addr, (size), __pu_err); \ |
| 194 | __pu_err; \ | 194 | __pu_err; \ |
| @@ -268,7 +268,7 @@ do { \ | |||
| 268 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | 268 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
| 269 | __chk_user_ptr(ptr); \ | 269 | __chk_user_ptr(ptr); \ |
| 270 | if (!is_kernel_addr((unsigned long)__gu_addr)) \ | 270 | if (!is_kernel_addr((unsigned long)__gu_addr)) \ |
| 271 | might_sleep(); \ | 271 | might_fault(); \ |
| 272 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ | 272 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
| 273 | (x) = (__typeof__(*(ptr)))__gu_val; \ | 273 | (x) = (__typeof__(*(ptr)))__gu_val; \ |
| 274 | __gu_err; \ | 274 | __gu_err; \ |
| @@ -282,7 +282,7 @@ do { \ | |||
| 282 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | 282 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
| 283 | __chk_user_ptr(ptr); \ | 283 | __chk_user_ptr(ptr); \ |
| 284 | if (!is_kernel_addr((unsigned long)__gu_addr)) \ | 284 | if (!is_kernel_addr((unsigned long)__gu_addr)) \ |
| 285 | might_sleep(); \ | 285 | might_fault(); \ |
| 286 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ | 286 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
| 287 | (x) = (__typeof__(*(ptr)))__gu_val; \ | 287 | (x) = (__typeof__(*(ptr)))__gu_val; \ |
| 288 | __gu_err; \ | 288 | __gu_err; \ |
| @@ -294,7 +294,7 @@ do { \ | |||
| 294 | long __gu_err = -EFAULT; \ | 294 | long __gu_err = -EFAULT; \ |
| 295 | unsigned long __gu_val = 0; \ | 295 | unsigned long __gu_val = 0; \ |
| 296 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | 296 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
| 297 | might_sleep(); \ | 297 | might_fault(); \ |
| 298 | if (access_ok(VERIFY_READ, __gu_addr, (size))) \ | 298 | if (access_ok(VERIFY_READ, __gu_addr, (size))) \ |
| 299 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ | 299 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
| 300 | (x) = (__typeof__(*(ptr)))__gu_val; \ | 300 | (x) = (__typeof__(*(ptr)))__gu_val; \ |
| @@ -419,14 +419,14 @@ static inline unsigned long __copy_to_user_inatomic(void __user *to, | |||
| 419 | static inline unsigned long __copy_from_user(void *to, | 419 | static inline unsigned long __copy_from_user(void *to, |
| 420 | const void __user *from, unsigned long size) | 420 | const void __user *from, unsigned long size) |
| 421 | { | 421 | { |
| 422 | might_sleep(); | 422 | might_fault(); |
| 423 | return __copy_from_user_inatomic(to, from, size); | 423 | return __copy_from_user_inatomic(to, from, size); |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | static inline unsigned long __copy_to_user(void __user *to, | 426 | static inline unsigned long __copy_to_user(void __user *to, |
| 427 | const void *from, unsigned long size) | 427 | const void *from, unsigned long size) |
| 428 | { | 428 | { |
| 429 | might_sleep(); | 429 | might_fault(); |
| 430 | return __copy_to_user_inatomic(to, from, size); | 430 | return __copy_to_user_inatomic(to, from, size); |
| 431 | } | 431 | } |
| 432 | 432 | ||
| @@ -434,7 +434,7 @@ extern unsigned long __clear_user(void __user *addr, unsigned long size); | |||
| 434 | 434 | ||
| 435 | static inline unsigned long clear_user(void __user *addr, unsigned long size) | 435 | static inline unsigned long clear_user(void __user *addr, unsigned long size) |
| 436 | { | 436 | { |
| 437 | might_sleep(); | 437 | might_fault(); |
| 438 | if (likely(access_ok(VERIFY_WRITE, addr, size))) | 438 | if (likely(access_ok(VERIFY_WRITE, addr, size))) |
| 439 | return __clear_user(addr, size); | 439 | return __clear_user(addr, size); |
| 440 | if ((unsigned long)addr < TASK_SIZE) { | 440 | if ((unsigned long)addr < TASK_SIZE) { |
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 9ec3fe174cba..779a78c26435 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c | |||
| @@ -69,16 +69,6 @@ void __init setup_kdump_trampoline(void) | |||
| 69 | } | 69 | } |
| 70 | #endif /* CONFIG_NONSTATIC_KERNEL */ | 70 | #endif /* CONFIG_NONSTATIC_KERNEL */ |
| 71 | 71 | ||
| 72 | static int __init parse_savemaxmem(char *p) | ||
| 73 | { | ||
| 74 | if (p) | ||
| 75 | saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1; | ||
| 76 | |||
| 77 | return 1; | ||
| 78 | } | ||
| 79 | __setup("savemaxmem=", parse_savemaxmem); | ||
| 80 | |||
| 81 | |||
| 82 | static size_t copy_oldmem_vaddr(void *vaddr, char *buf, size_t csize, | 72 | static size_t copy_oldmem_vaddr(void *vaddr, char *buf, size_t csize, |
| 83 | unsigned long offset, int userbuf) | 73 | unsigned long offset, int userbuf) |
| 84 | { | 74 | { |
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c index 6782221d49bd..db28032e320e 100644 --- a/arch/powerpc/kernel/kvm.c +++ b/arch/powerpc/kernel/kvm.c | |||
| @@ -750,13 +750,8 @@ EXPORT_SYMBOL_GPL(kvm_hypercall); | |||
| 750 | 750 | ||
| 751 | static __init void kvm_free_tmp(void) | 751 | static __init void kvm_free_tmp(void) |
| 752 | { | 752 | { |
| 753 | unsigned long start, end; | 753 | free_reserved_area(&kvm_tmp[kvm_tmp_index], |
| 754 | 754 | &kvm_tmp[ARRAY_SIZE(kvm_tmp)], -1, NULL); | |
| 755 | start = (ulong)&kvm_tmp[kvm_tmp_index + (PAGE_SIZE - 1)] & PAGE_MASK; | ||
| 756 | end = (ulong)&kvm_tmp[ARRAY_SIZE(kvm_tmp)] & PAGE_MASK; | ||
| 757 | |||
| 758 | /* Free the tmp space we don't need */ | ||
| 759 | free_reserved_area(start, end, 0, NULL); | ||
| 760 | } | 755 | } |
| 761 | 756 | ||
| 762 | static int __init kvm_guest_init(void) | 757 | static int __init kvm_guest_init(void) |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index eabeec991016..f46914a0f33e 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
| @@ -994,7 +994,7 @@ void pcibios_setup_bus_self(struct pci_bus *bus) | |||
| 994 | ppc_md.pci_dma_bus_setup(bus); | 994 | ppc_md.pci_dma_bus_setup(bus); |
| 995 | } | 995 | } |
| 996 | 996 | ||
| 997 | void pcibios_setup_device(struct pci_dev *dev) | 997 | static void pcibios_setup_device(struct pci_dev *dev) |
| 998 | { | 998 | { |
| 999 | /* Fixup NUMA node as it may not be setup yet by the generic | 999 | /* Fixup NUMA node as it may not be setup yet by the generic |
| 1000 | * code and is needed by the DMA init | 1000 | * code and is needed by the DMA init |
| @@ -1015,6 +1015,17 @@ void pcibios_setup_device(struct pci_dev *dev) | |||
| 1015 | ppc_md.pci_irq_fixup(dev); | 1015 | ppc_md.pci_irq_fixup(dev); |
| 1016 | } | 1016 | } |
| 1017 | 1017 | ||
| 1018 | int pcibios_add_device(struct pci_dev *dev) | ||
| 1019 | { | ||
| 1020 | /* | ||
| 1021 | * We can only call pcibios_setup_device() after bus setup is complete, | ||
| 1022 | * since some of the platform specific DMA setup code depends on it. | ||
| 1023 | */ | ||
| 1024 | if (dev->bus->is_added) | ||
| 1025 | pcibios_setup_device(dev); | ||
| 1026 | return 0; | ||
| 1027 | } | ||
| 1028 | |||
| 1018 | void pcibios_setup_bus_devices(struct pci_bus *bus) | 1029 | void pcibios_setup_bus_devices(struct pci_bus *bus) |
| 1019 | { | 1030 | { |
| 1020 | struct pci_dev *dev; | 1031 | struct pci_dev *dev; |
| @@ -1469,10 +1480,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
| 1469 | if (ppc_md.pcibios_enable_device_hook(dev)) | 1480 | if (ppc_md.pcibios_enable_device_hook(dev)) |
| 1470 | return -EINVAL; | 1481 | return -EINVAL; |
| 1471 | 1482 | ||
| 1472 | /* avoid pcie irq fix up impact on cardbus */ | ||
| 1473 | if (dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) | ||
| 1474 | pcibios_setup_device(dev); | ||
| 1475 | |||
| 1476 | return pci_enable_resources(dev, mask); | 1483 | return pci_enable_resources(dev, mask); |
| 1477 | } | 1484 | } |
| 1478 | 1485 | ||
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 2a67e9baa59f..6b0ba5854d99 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c | |||
| @@ -128,7 +128,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
| 128 | const char *type; | 128 | const char *type; |
| 129 | struct pci_slot *slot; | 129 | struct pci_slot *slot; |
| 130 | 130 | ||
| 131 | dev = alloc_pci_dev(); | 131 | dev = pci_alloc_dev(bus); |
| 132 | if (!dev) | 132 | if (!dev) |
| 133 | return NULL; | 133 | return NULL; |
| 134 | type = of_get_property(node, "device_type", NULL); | 134 | type = of_get_property(node, "device_type", NULL); |
| @@ -137,7 +137,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
| 137 | 137 | ||
| 138 | pr_debug(" create device, devfn: %x, type: %s\n", devfn, type); | 138 | pr_debug(" create device, devfn: %x, type: %s\n", devfn, type); |
| 139 | 139 | ||
| 140 | dev->bus = bus; | ||
| 141 | dev->dev.of_node = of_node_get(node); | 140 | dev->dev.of_node = of_node_get(node); |
| 142 | dev->dev.parent = bus->bridge; | 141 | dev->dev.parent = bus->bridge; |
| 143 | dev->dev.bus = &pci_bus_type; | 142 | dev->dev.bus = &pci_bus_type; |
| @@ -165,7 +164,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
| 165 | pr_debug(" class: 0x%x\n", dev->class); | 164 | pr_debug(" class: 0x%x\n", dev->class); |
| 166 | pr_debug(" revision: 0x%x\n", dev->revision); | 165 | pr_debug(" revision: 0x%x\n", dev->revision); |
| 167 | 166 | ||
| 168 | dev->current_state = 4; /* unknown power state */ | 167 | dev->current_state = PCI_UNKNOWN; /* unknown power state */ |
| 169 | dev->error_state = pci_channel_io_normal; | 168 | dev->error_state = pci_channel_io_normal; |
| 170 | dev->dma_mask = 0xffffffff; | 169 | dev->dma_mask = 0xffffffff; |
| 171 | 170 | ||
diff --git a/arch/powerpc/kernel/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c index feb8580fdc84..c30612aad68e 100644 --- a/arch/powerpc/kernel/proc_powerpc.c +++ b/arch/powerpc/kernel/proc_powerpc.c | |||
| @@ -29,25 +29,9 @@ | |||
| 29 | 29 | ||
| 30 | #ifdef CONFIG_PPC64 | 30 | #ifdef CONFIG_PPC64 |
| 31 | 31 | ||
| 32 | static loff_t page_map_seek( struct file *file, loff_t off, int whence) | 32 | static loff_t page_map_seek(struct file *file, loff_t off, int whence) |
| 33 | { | 33 | { |
| 34 | loff_t new; | 34 | return fixed_size_llseek(file, off, whence, PAGE_SIZE); |
| 35 | switch(whence) { | ||
| 36 | case 0: | ||
| 37 | new = off; | ||
| 38 | break; | ||
| 39 | case 1: | ||
| 40 | new = file->f_pos + off; | ||
| 41 | break; | ||
| 42 | case 2: | ||
| 43 | new = PAGE_SIZE + off; | ||
| 44 | break; | ||
| 45 | default: | ||
| 46 | return -EINVAL; | ||
| 47 | } | ||
| 48 | if ( new < 0 || new > PAGE_SIZE ) | ||
| 49 | return -EINVAL; | ||
| 50 | return (file->f_pos = new); | ||
| 51 | } | 35 | } |
| 52 | 36 | ||
| 53 | static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, | 37 | static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, |
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 422de3f4d46c..008cd856c5b5 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile | |||
| @@ -5,9 +5,10 @@ | |||
| 5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror |
| 6 | 6 | ||
| 7 | ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm | 7 | ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm |
| 8 | KVM := ../../../virt/kvm | ||
| 8 | 9 | ||
| 9 | common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o \ | 10 | common-objs-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ |
| 10 | eventfd.o) | 11 | $(KVM)/eventfd.o |
| 11 | 12 | ||
| 12 | CFLAGS_44x_tlb.o := -I. | 13 | CFLAGS_44x_tlb.o := -I. |
| 13 | CFLAGS_e500_mmu.o := -I. | 14 | CFLAGS_e500_mmu.o := -I. |
| @@ -53,7 +54,7 @@ kvm-e500mc-objs := \ | |||
| 53 | kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs) | 54 | kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs) |
| 54 | 55 | ||
| 55 | kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \ | 56 | kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \ |
| 56 | ../../../virt/kvm/coalesced_mmio.o \ | 57 | $(KVM)/coalesced_mmio.o \ |
| 57 | fpu.o \ | 58 | fpu.o \ |
| 58 | book3s_paired_singles.o \ | 59 | book3s_paired_singles.o \ |
| 59 | book3s_pr.o \ | 60 | book3s_pr.o \ |
| @@ -86,8 +87,8 @@ kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \ | |||
| 86 | book3s_xics.o | 87 | book3s_xics.o |
| 87 | 88 | ||
| 88 | kvm-book3s_64-module-objs := \ | 89 | kvm-book3s_64-module-objs := \ |
| 89 | ../../../virt/kvm/kvm_main.o \ | 90 | $(KVM)/kvm_main.o \ |
| 90 | ../../../virt/kvm/eventfd.o \ | 91 | $(KVM)/eventfd.o \ |
| 91 | powerpc.o \ | 92 | powerpc.o \ |
| 92 | emulate.o \ | 93 | emulate.o \ |
| 93 | book3s.o \ | 94 | book3s.o \ |
| @@ -111,7 +112,7 @@ kvm-book3s_32-objs := \ | |||
| 111 | kvm-objs-$(CONFIG_KVM_BOOK3S_32) := $(kvm-book3s_32-objs) | 112 | kvm-objs-$(CONFIG_KVM_BOOK3S_32) := $(kvm-book3s_32-objs) |
| 112 | 113 | ||
| 113 | kvm-objs-$(CONFIG_KVM_MPIC) += mpic.o | 114 | kvm-objs-$(CONFIG_KVM_MPIC) += mpic.o |
| 114 | kvm-objs-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(addprefix ../../../virt/kvm/, irqchip.o) | 115 | kvm-objs-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o |
| 115 | 116 | ||
| 116 | kvm-objs := $(kvm-objs-m) $(kvm-objs-y) | 117 | kvm-objs := $(kvm-objs-m) $(kvm-objs-y) |
| 117 | 118 | ||
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c index b871721c0050..739bfbadb85e 100644 --- a/arch/powerpc/kvm/book3s_64_mmu.c +++ b/arch/powerpc/kvm/book3s_64_mmu.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <asm/tlbflush.h> | 26 | #include <asm/tlbflush.h> |
| 27 | #include <asm/kvm_ppc.h> | 27 | #include <asm/kvm_ppc.h> |
| 28 | #include <asm/kvm_book3s.h> | 28 | #include <asm/kvm_book3s.h> |
| 29 | #include <asm/mmu-hash64.h> | ||
| 29 | 30 | ||
| 30 | /* #define DEBUG_MMU */ | 31 | /* #define DEBUG_MMU */ |
| 31 | 32 | ||
| @@ -76,6 +77,24 @@ static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe( | |||
| 76 | return NULL; | 77 | return NULL; |
| 77 | } | 78 | } |
| 78 | 79 | ||
| 80 | static int kvmppc_slb_sid_shift(struct kvmppc_slb *slbe) | ||
| 81 | { | ||
| 82 | return slbe->tb ? SID_SHIFT_1T : SID_SHIFT; | ||
| 83 | } | ||
| 84 | |||
| 85 | static u64 kvmppc_slb_offset_mask(struct kvmppc_slb *slbe) | ||
| 86 | { | ||
| 87 | return (1ul << kvmppc_slb_sid_shift(slbe)) - 1; | ||
| 88 | } | ||
| 89 | |||
| 90 | static u64 kvmppc_slb_calc_vpn(struct kvmppc_slb *slb, gva_t eaddr) | ||
| 91 | { | ||
| 92 | eaddr &= kvmppc_slb_offset_mask(slb); | ||
| 93 | |||
| 94 | return (eaddr >> VPN_SHIFT) | | ||
| 95 | ((slb->vsid) << (kvmppc_slb_sid_shift(slb) - VPN_SHIFT)); | ||
| 96 | } | ||
| 97 | |||
| 79 | static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, | 98 | static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, |
| 80 | bool data) | 99 | bool data) |
| 81 | { | 100 | { |
| @@ -85,11 +104,7 @@ static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
| 85 | if (!slb) | 104 | if (!slb) |
| 86 | return 0; | 105 | return 0; |
| 87 | 106 | ||
| 88 | if (slb->tb) | 107 | return kvmppc_slb_calc_vpn(slb, eaddr); |
| 89 | return (((u64)eaddr >> 12) & 0xfffffff) | | ||
| 90 | (((u64)slb->vsid) << 28); | ||
| 91 | |||
| 92 | return (((u64)eaddr >> 12) & 0xffff) | (((u64)slb->vsid) << 16); | ||
| 93 | } | 108 | } |
| 94 | 109 | ||
| 95 | static int kvmppc_mmu_book3s_64_get_pagesize(struct kvmppc_slb *slbe) | 110 | static int kvmppc_mmu_book3s_64_get_pagesize(struct kvmppc_slb *slbe) |
| @@ -100,7 +115,8 @@ static int kvmppc_mmu_book3s_64_get_pagesize(struct kvmppc_slb *slbe) | |||
| 100 | static u32 kvmppc_mmu_book3s_64_get_page(struct kvmppc_slb *slbe, gva_t eaddr) | 115 | static u32 kvmppc_mmu_book3s_64_get_page(struct kvmppc_slb *slbe, gva_t eaddr) |
| 101 | { | 116 | { |
| 102 | int p = kvmppc_mmu_book3s_64_get_pagesize(slbe); | 117 | int p = kvmppc_mmu_book3s_64_get_pagesize(slbe); |
| 103 | return ((eaddr & 0xfffffff) >> p); | 118 | |
| 119 | return ((eaddr & kvmppc_slb_offset_mask(slbe)) >> p); | ||
| 104 | } | 120 | } |
| 105 | 121 | ||
| 106 | static hva_t kvmppc_mmu_book3s_64_get_pteg( | 122 | static hva_t kvmppc_mmu_book3s_64_get_pteg( |
| @@ -109,13 +125,15 @@ static hva_t kvmppc_mmu_book3s_64_get_pteg( | |||
| 109 | bool second) | 125 | bool second) |
| 110 | { | 126 | { |
| 111 | u64 hash, pteg, htabsize; | 127 | u64 hash, pteg, htabsize; |
| 112 | u32 page; | 128 | u32 ssize; |
| 113 | hva_t r; | 129 | hva_t r; |
| 130 | u64 vpn; | ||
| 114 | 131 | ||
| 115 | page = kvmppc_mmu_book3s_64_get_page(slbe, eaddr); | ||
| 116 | htabsize = ((1 << ((vcpu_book3s->sdr1 & 0x1f) + 11)) - 1); | 132 | htabsize = ((1 << ((vcpu_book3s->sdr1 & 0x1f) + 11)) - 1); |
| 117 | 133 | ||
| 118 | hash = slbe->vsid ^ page; | 134 | vpn = kvmppc_slb_calc_vpn(slbe, eaddr); |
| 135 | ssize = slbe->tb ? MMU_SEGSIZE_1T : MMU_SEGSIZE_256M; | ||
| 136 | hash = hpt_hash(vpn, kvmppc_mmu_book3s_64_get_pagesize(slbe), ssize); | ||
| 119 | if (second) | 137 | if (second) |
| 120 | hash = ~hash; | 138 | hash = ~hash; |
| 121 | hash &= ((1ULL << 39ULL) - 1ULL); | 139 | hash &= ((1ULL << 39ULL) - 1ULL); |
| @@ -146,7 +164,7 @@ static u64 kvmppc_mmu_book3s_64_get_avpn(struct kvmppc_slb *slbe, gva_t eaddr) | |||
| 146 | u64 avpn; | 164 | u64 avpn; |
| 147 | 165 | ||
| 148 | avpn = kvmppc_mmu_book3s_64_get_page(slbe, eaddr); | 166 | avpn = kvmppc_mmu_book3s_64_get_page(slbe, eaddr); |
| 149 | avpn |= slbe->vsid << (28 - p); | 167 | avpn |= slbe->vsid << (kvmppc_slb_sid_shift(slbe) - p); |
| 150 | 168 | ||
| 151 | if (p < 24) | 169 | if (p < 24) |
| 152 | avpn >>= ((80 - p) - 56) - 8; | 170 | avpn >>= ((80 - p) - 56) - 8; |
| @@ -167,7 +185,6 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
| 167 | int i; | 185 | int i; |
| 168 | u8 key = 0; | 186 | u8 key = 0; |
| 169 | bool found = false; | 187 | bool found = false; |
| 170 | bool perm_err = false; | ||
| 171 | int second = 0; | 188 | int second = 0; |
| 172 | ulong mp_ea = vcpu->arch.magic_page_ea; | 189 | ulong mp_ea = vcpu->arch.magic_page_ea; |
| 173 | 190 | ||
| @@ -190,13 +207,15 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
| 190 | if (!slbe) | 207 | if (!slbe) |
| 191 | goto no_seg_found; | 208 | goto no_seg_found; |
| 192 | 209 | ||
| 210 | avpn = kvmppc_mmu_book3s_64_get_avpn(slbe, eaddr); | ||
| 211 | if (slbe->tb) | ||
| 212 | avpn |= SLB_VSID_B_1T; | ||
| 213 | |||
| 193 | do_second: | 214 | do_second: |
| 194 | ptegp = kvmppc_mmu_book3s_64_get_pteg(vcpu_book3s, slbe, eaddr, second); | 215 | ptegp = kvmppc_mmu_book3s_64_get_pteg(vcpu_book3s, slbe, eaddr, second); |
| 195 | if (kvm_is_error_hva(ptegp)) | 216 | if (kvm_is_error_hva(ptegp)) |
| 196 | goto no_page_found; | 217 | goto no_page_found; |
| 197 | 218 | ||
| 198 | avpn = kvmppc_mmu_book3s_64_get_avpn(slbe, eaddr); | ||
| 199 | |||
| 200 | if(copy_from_user(pteg, (void __user *)ptegp, sizeof(pteg))) { | 219 | if(copy_from_user(pteg, (void __user *)ptegp, sizeof(pteg))) { |
| 201 | printk(KERN_ERR "KVM can't copy data from 0x%lx!\n", ptegp); | 220 | printk(KERN_ERR "KVM can't copy data from 0x%lx!\n", ptegp); |
| 202 | goto no_page_found; | 221 | goto no_page_found; |
| @@ -219,7 +238,7 @@ do_second: | |||
| 219 | continue; | 238 | continue; |
| 220 | 239 | ||
| 221 | /* AVPN compare */ | 240 | /* AVPN compare */ |
| 222 | if (HPTE_V_AVPN_VAL(avpn) == HPTE_V_AVPN_VAL(v)) { | 241 | if (HPTE_V_COMPARE(avpn, v)) { |
| 223 | u8 pp = (r & HPTE_R_PP) | key; | 242 | u8 pp = (r & HPTE_R_PP) | key; |
| 224 | int eaddr_mask = 0xFFF; | 243 | int eaddr_mask = 0xFFF; |
| 225 | 244 | ||
| @@ -248,11 +267,6 @@ do_second: | |||
| 248 | break; | 267 | break; |
| 249 | } | 268 | } |
| 250 | 269 | ||
| 251 | if (!gpte->may_read) { | ||
| 252 | perm_err = true; | ||
| 253 | continue; | ||
| 254 | } | ||
| 255 | |||
| 256 | dprintk("KVM MMU: Translated 0x%lx [0x%llx] -> 0x%llx " | 270 | dprintk("KVM MMU: Translated 0x%lx [0x%llx] -> 0x%llx " |
| 257 | "-> 0x%lx\n", | 271 | "-> 0x%lx\n", |
| 258 | eaddr, avpn, gpte->vpage, gpte->raddr); | 272 | eaddr, avpn, gpte->vpage, gpte->raddr); |
| @@ -281,6 +295,8 @@ do_second: | |||
| 281 | if (pteg[i+1] != oldr) | 295 | if (pteg[i+1] != oldr) |
| 282 | copy_to_user((void __user *)ptegp, pteg, sizeof(pteg)); | 296 | copy_to_user((void __user *)ptegp, pteg, sizeof(pteg)); |
| 283 | 297 | ||
| 298 | if (!gpte->may_read) | ||
| 299 | return -EPERM; | ||
| 284 | return 0; | 300 | return 0; |
| 285 | } else { | 301 | } else { |
| 286 | dprintk("KVM MMU: No PTE found (ea=0x%lx sdr1=0x%llx " | 302 | dprintk("KVM MMU: No PTE found (ea=0x%lx sdr1=0x%llx " |
| @@ -296,13 +312,7 @@ do_second: | |||
| 296 | } | 312 | } |
| 297 | } | 313 | } |
| 298 | 314 | ||
| 299 | |||
| 300 | no_page_found: | 315 | no_page_found: |
| 301 | |||
| 302 | |||
| 303 | if (perm_err) | ||
| 304 | return -EPERM; | ||
| 305 | |||
| 306 | return -ENOENT; | 316 | return -ENOENT; |
| 307 | 317 | ||
| 308 | no_seg_found: | 318 | no_seg_found: |
| @@ -334,7 +344,7 @@ static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb) | |||
| 334 | slbe->large = (rs & SLB_VSID_L) ? 1 : 0; | 344 | slbe->large = (rs & SLB_VSID_L) ? 1 : 0; |
| 335 | slbe->tb = (rs & SLB_VSID_B_1T) ? 1 : 0; | 345 | slbe->tb = (rs & SLB_VSID_B_1T) ? 1 : 0; |
| 336 | slbe->esid = slbe->tb ? esid_1t : esid; | 346 | slbe->esid = slbe->tb ? esid_1t : esid; |
| 337 | slbe->vsid = rs >> 12; | 347 | slbe->vsid = (rs & ~SLB_VSID_B) >> (kvmppc_slb_sid_shift(slbe) - 16); |
| 338 | slbe->valid = (rb & SLB_ESID_V) ? 1 : 0; | 348 | slbe->valid = (rb & SLB_ESID_V) ? 1 : 0; |
| 339 | slbe->Ks = (rs & SLB_VSID_KS) ? 1 : 0; | 349 | slbe->Ks = (rs & SLB_VSID_KS) ? 1 : 0; |
| 340 | slbe->Kp = (rs & SLB_VSID_KP) ? 1 : 0; | 350 | slbe->Kp = (rs & SLB_VSID_KP) ? 1 : 0; |
| @@ -375,6 +385,7 @@ static u64 kvmppc_mmu_book3s_64_slbmfev(struct kvm_vcpu *vcpu, u64 slb_nr) | |||
| 375 | static void kvmppc_mmu_book3s_64_slbie(struct kvm_vcpu *vcpu, u64 ea) | 385 | static void kvmppc_mmu_book3s_64_slbie(struct kvm_vcpu *vcpu, u64 ea) |
| 376 | { | 386 | { |
| 377 | struct kvmppc_slb *slbe; | 387 | struct kvmppc_slb *slbe; |
| 388 | u64 seg_size; | ||
| 378 | 389 | ||
| 379 | dprintk("KVM MMU: slbie(0x%llx)\n", ea); | 390 | dprintk("KVM MMU: slbie(0x%llx)\n", ea); |
| 380 | 391 | ||
| @@ -386,8 +397,11 @@ static void kvmppc_mmu_book3s_64_slbie(struct kvm_vcpu *vcpu, u64 ea) | |||
| 386 | dprintk("KVM MMU: slbie(0x%llx, 0x%llx)\n", ea, slbe->esid); | 397 | dprintk("KVM MMU: slbie(0x%llx, 0x%llx)\n", ea, slbe->esid); |
| 387 | 398 | ||
| 388 | slbe->valid = false; | 399 | slbe->valid = false; |
| 400 | slbe->orige = 0; | ||
| 401 | slbe->origv = 0; | ||
| 389 | 402 | ||
| 390 | kvmppc_mmu_map_segment(vcpu, ea); | 403 | seg_size = 1ull << kvmppc_slb_sid_shift(slbe); |
| 404 | kvmppc_mmu_flush_segment(vcpu, ea & ~(seg_size - 1), seg_size); | ||
| 391 | } | 405 | } |
| 392 | 406 | ||
| 393 | static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu) | 407 | static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu) |
| @@ -396,8 +410,11 @@ static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu) | |||
| 396 | 410 | ||
| 397 | dprintk("KVM MMU: slbia()\n"); | 411 | dprintk("KVM MMU: slbia()\n"); |
| 398 | 412 | ||
| 399 | for (i = 1; i < vcpu->arch.slb_nr; i++) | 413 | for (i = 1; i < vcpu->arch.slb_nr; i++) { |
| 400 | vcpu->arch.slb[i].valid = false; | 414 | vcpu->arch.slb[i].valid = false; |
| 415 | vcpu->arch.slb[i].orige = 0; | ||
| 416 | vcpu->arch.slb[i].origv = 0; | ||
| 417 | } | ||
| 401 | 418 | ||
| 402 | if (vcpu->arch.shared->msr & MSR_IR) { | 419 | if (vcpu->arch.shared->msr & MSR_IR) { |
| 403 | kvmppc_mmu_flush_segments(vcpu); | 420 | kvmppc_mmu_flush_segments(vcpu); |
| @@ -467,8 +484,14 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | |||
| 467 | 484 | ||
| 468 | if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { | 485 | if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
| 469 | slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea); | 486 | slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea); |
| 470 | if (slb) | 487 | if (slb) { |
| 471 | gvsid = slb->vsid; | 488 | gvsid = slb->vsid; |
| 489 | if (slb->tb) { | ||
| 490 | gvsid <<= SID_SHIFT_1T - SID_SHIFT; | ||
| 491 | gvsid |= esid & ((1ul << (SID_SHIFT_1T - SID_SHIFT)) - 1); | ||
| 492 | gvsid |= VSID_1T; | ||
| 493 | } | ||
| 494 | } | ||
| 472 | } | 495 | } |
| 473 | 496 | ||
| 474 | switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { | 497 | switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c index 3a9a1aceb14f..b350d9494b26 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c | |||
| @@ -301,6 +301,23 @@ out: | |||
| 301 | return r; | 301 | return r; |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong ea, ulong seg_size) | ||
| 305 | { | ||
| 306 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
| 307 | ulong seg_mask = -seg_size; | ||
| 308 | int i; | ||
| 309 | |||
| 310 | for (i = 1; i < svcpu->slb_max; i++) { | ||
| 311 | if ((svcpu->slb[i].esid & SLB_ESID_V) && | ||
| 312 | (svcpu->slb[i].esid & seg_mask) == ea) { | ||
| 313 | /* Invalidate this entry */ | ||
| 314 | svcpu->slb[i].esid = 0; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | svcpu_put(svcpu); | ||
| 319 | } | ||
| 320 | |||
| 304 | void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) | 321 | void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) |
| 305 | { | 322 | { |
| 306 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | 323 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); |
| @@ -325,9 +342,9 @@ int kvmppc_mmu_init(struct kvm_vcpu *vcpu) | |||
| 325 | return -1; | 342 | return -1; |
| 326 | vcpu3s->context_id[0] = err; | 343 | vcpu3s->context_id[0] = err; |
| 327 | 344 | ||
| 328 | vcpu3s->proto_vsid_max = ((vcpu3s->context_id[0] + 1) | 345 | vcpu3s->proto_vsid_max = ((u64)(vcpu3s->context_id[0] + 1) |
| 329 | << ESID_BITS) - 1; | 346 | << ESID_BITS) - 1; |
| 330 | vcpu3s->proto_vsid_first = vcpu3s->context_id[0] << ESID_BITS; | 347 | vcpu3s->proto_vsid_first = (u64)vcpu3s->context_id[0] << ESID_BITS; |
| 331 | vcpu3s->proto_vsid_next = vcpu3s->proto_vsid_first; | 348 | vcpu3s->proto_vsid_next = vcpu3s->proto_vsid_first; |
| 332 | 349 | ||
| 333 | kvmppc_mmu_hpte_init(vcpu); | 350 | kvmppc_mmu_hpte_init(vcpu); |
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S index 56b983e7b738..4f0caecc0f9d 100644 --- a/arch/powerpc/kvm/book3s_64_slb.S +++ b/arch/powerpc/kvm/book3s_64_slb.S | |||
| @@ -66,10 +66,6 @@ slb_exit_skip_ ## num: | |||
| 66 | 66 | ||
| 67 | ld r12, PACA_SLBSHADOWPTR(r13) | 67 | ld r12, PACA_SLBSHADOWPTR(r13) |
| 68 | 68 | ||
| 69 | /* Save off the first entry so we can slbie it later */ | ||
| 70 | ld r10, SHADOW_SLB_ESID(0)(r12) | ||
| 71 | ld r11, SHADOW_SLB_VSID(0)(r12) | ||
| 72 | |||
| 73 | /* Remove bolted entries */ | 69 | /* Remove bolted entries */ |
| 74 | UNBOLT_SLB_ENTRY(0) | 70 | UNBOLT_SLB_ENTRY(0) |
| 75 | UNBOLT_SLB_ENTRY(1) | 71 | UNBOLT_SLB_ENTRY(1) |
| @@ -81,15 +77,10 @@ slb_exit_skip_ ## num: | |||
| 81 | 77 | ||
| 82 | /* Flush SLB */ | 78 | /* Flush SLB */ |
| 83 | 79 | ||
| 80 | li r10, 0 | ||
| 81 | slbmte r10, r10 | ||
| 84 | slbia | 82 | slbia |
| 85 | 83 | ||
| 86 | /* r0 = esid & ESID_MASK */ | ||
| 87 | rldicr r10, r10, 0, 35 | ||
| 88 | /* r0 |= CLASS_BIT(VSID) */ | ||
| 89 | rldic r12, r11, 56 - 36, 36 | ||
| 90 | or r10, r10, r12 | ||
| 91 | slbie r10 | ||
| 92 | |||
| 93 | /* Fill SLB with our shadow */ | 84 | /* Fill SLB with our shadow */ |
| 94 | 85 | ||
| 95 | lbz r12, SVCPU_SLB_MAX(r3) | 86 | lbz r12, SVCPU_SLB_MAX(r3) |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 550f5928b394..2efa9dde741a 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
| @@ -1864,7 +1864,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) | |||
| 1864 | 1864 | ||
| 1865 | up_out: | 1865 | up_out: |
| 1866 | up_read(¤t->mm->mmap_sem); | 1866 | up_read(¤t->mm->mmap_sem); |
| 1867 | goto out; | 1867 | goto out_srcu; |
| 1868 | } | 1868 | } |
| 1869 | 1869 | ||
| 1870 | int kvmppc_core_init_vm(struct kvm *kvm) | 1870 | int kvmppc_core_init_vm(struct kvm *kvm) |
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index bdc40b8e77d9..19498a567a81 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
| @@ -1239,8 +1239,7 @@ out: | |||
| 1239 | #ifdef CONFIG_PPC64 | 1239 | #ifdef CONFIG_PPC64 |
| 1240 | int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info) | 1240 | int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info) |
| 1241 | { | 1241 | { |
| 1242 | /* No flags */ | 1242 | info->flags = KVM_PPC_1T_SEGMENTS; |
| 1243 | info->flags = 0; | ||
| 1244 | 1243 | ||
| 1245 | /* SLB is always 64 entries */ | 1244 | /* SLB is always 64 entries */ |
| 1246 | info->slb_size = 64; | 1245 | info->slb_size = 64; |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 5cd7ad0c1176..dcc94f016007 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
| @@ -673,7 +673,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
| 673 | ret = s; | 673 | ret = s; |
| 674 | goto out; | 674 | goto out; |
| 675 | } | 675 | } |
| 676 | kvmppc_lazy_ee_enable(); | ||
| 677 | 676 | ||
| 678 | kvm_guest_enter(); | 677 | kvm_guest_enter(); |
| 679 | 678 | ||
| @@ -699,6 +698,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
| 699 | kvmppc_load_guest_fp(vcpu); | 698 | kvmppc_load_guest_fp(vcpu); |
| 700 | #endif | 699 | #endif |
| 701 | 700 | ||
| 701 | kvmppc_lazy_ee_enable(); | ||
| 702 | |||
| 702 | ret = __kvmppc_vcpu_run(kvm_run, vcpu); | 703 | ret = __kvmppc_vcpu_run(kvm_run, vcpu); |
| 703 | 704 | ||
| 704 | /* No need for kvm_guest_exit. It's done in handle_exit. | 705 | /* No need for kvm_guest_exit. It's done in handle_exit. |
| @@ -795,7 +796,7 @@ static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, | |||
| 795 | kvmppc_fill_pt_regs(®s); | 796 | kvmppc_fill_pt_regs(®s); |
| 796 | timer_interrupt(®s); | 797 | timer_interrupt(®s); |
| 797 | break; | 798 | break; |
| 798 | #if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3E_64) | 799 | #if defined(CONFIG_PPC_DOORBELL) |
| 799 | case BOOKE_INTERRUPT_DOORBELL: | 800 | case BOOKE_INTERRUPT_DOORBELL: |
| 800 | kvmppc_fill_pt_regs(®s); | 801 | kvmppc_fill_pt_regs(®s); |
| 801 | doorbell_exception(®s); | 802 | doorbell_exception(®s); |
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index 631a2650e4e4..2c52ada30775 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c | |||
| @@ -169,6 +169,9 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | |||
| 169 | vcpu->arch.shared->sprg3 = spr_val; | 169 | vcpu->arch.shared->sprg3 = spr_val; |
| 170 | break; | 170 | break; |
| 171 | 171 | ||
| 172 | /* PIR can legally be written, but we ignore it */ | ||
| 173 | case SPRN_PIR: break; | ||
| 174 | |||
| 172 | default: | 175 | default: |
| 173 | emulated = kvmppc_core_emulate_mtspr(vcpu, sprn, | 176 | emulated = kvmppc_core_emulate_mtspr(vcpu, sprn, |
| 174 | spr_val); | 177 | spr_val); |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 237c8e5f2640..4210549ac95e 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
| @@ -357,7 +357,7 @@ void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages) | |||
| 357 | int alloc_bootmem_huge_page(struct hstate *hstate) | 357 | int alloc_bootmem_huge_page(struct hstate *hstate) |
| 358 | { | 358 | { |
| 359 | struct huge_bootmem_page *m; | 359 | struct huge_bootmem_page *m; |
| 360 | int idx = shift_to_mmu_psize(hstate->order + PAGE_SHIFT); | 360 | int idx = shift_to_mmu_psize(huge_page_shift(hstate)); |
| 361 | int nr_gpages = gpage_freearray[idx].nr_gpages; | 361 | int nr_gpages = gpage_freearray[idx].nr_gpages; |
| 362 | 362 | ||
| 363 | if (nr_gpages == 0) | 363 | if (nr_gpages == 0) |
| @@ -592,8 +592,14 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud, | |||
| 592 | do { | 592 | do { |
| 593 | pmd = pmd_offset(pud, addr); | 593 | pmd = pmd_offset(pud, addr); |
| 594 | next = pmd_addr_end(addr, end); | 594 | next = pmd_addr_end(addr, end); |
| 595 | if (pmd_none_or_clear_bad(pmd)) | 595 | if (!is_hugepd(pmd)) { |
| 596 | /* | ||
| 597 | * if it is not hugepd pointer, we should already find | ||
| 598 | * it cleared. | ||
| 599 | */ | ||
| 600 | WARN_ON(!pmd_none_or_clear_bad(pmd)); | ||
| 596 | continue; | 601 | continue; |
| 602 | } | ||
| 597 | #ifdef CONFIG_PPC_FSL_BOOK3E | 603 | #ifdef CONFIG_PPC_FSL_BOOK3E |
| 598 | /* | 604 | /* |
| 599 | * Increment next by the size of the huge mapping since | 605 | * Increment next by the size of the huge mapping since |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 0988a26e0413..1cb1ea133a2c 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
| @@ -299,47 +299,13 @@ void __init paging_init(void) | |||
| 299 | 299 | ||
| 300 | void __init mem_init(void) | 300 | void __init mem_init(void) |
| 301 | { | 301 | { |
| 302 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
| 303 | int nid; | ||
| 304 | #endif | ||
| 305 | pg_data_t *pgdat; | ||
| 306 | unsigned long i; | ||
| 307 | struct page *page; | ||
| 308 | unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize; | ||
| 309 | |||
| 310 | #ifdef CONFIG_SWIOTLB | 302 | #ifdef CONFIG_SWIOTLB |
| 311 | swiotlb_init(0); | 303 | swiotlb_init(0); |
| 312 | #endif | 304 | #endif |
| 313 | 305 | ||
| 314 | num_physpages = memblock_phys_mem_size() >> PAGE_SHIFT; | ||
| 315 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); | 306 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); |
| 316 | 307 | set_max_mapnr(max_pfn); | |
| 317 | #ifdef CONFIG_NEED_MULTIPLE_NODES | 308 | free_all_bootmem(); |
| 318 | for_each_online_node(nid) { | ||
| 319 | if (NODE_DATA(nid)->node_spanned_pages != 0) { | ||
| 320 | printk("freeing bootmem node %d\n", nid); | ||
| 321 | totalram_pages += | ||
| 322 | free_all_bootmem_node(NODE_DATA(nid)); | ||
| 323 | } | ||
| 324 | } | ||
| 325 | #else | ||
| 326 | max_mapnr = max_pfn; | ||
| 327 | totalram_pages += free_all_bootmem(); | ||
| 328 | #endif | ||
| 329 | for_each_online_pgdat(pgdat) { | ||
| 330 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | ||
| 331 | if (!pfn_valid(pgdat->node_start_pfn + i)) | ||
| 332 | continue; | ||
| 333 | page = pgdat_page_nr(pgdat, i); | ||
| 334 | if (PageReserved(page)) | ||
| 335 | reservedpages++; | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | codesize = (unsigned long)&_sdata - (unsigned long)&_stext; | ||
| 340 | datasize = (unsigned long)&_edata - (unsigned long)&_sdata; | ||
| 341 | initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin; | ||
| 342 | bsssize = (unsigned long)&__bss_stop - (unsigned long)&__bss_start; | ||
| 343 | 309 | ||
| 344 | #ifdef CONFIG_HIGHMEM | 310 | #ifdef CONFIG_HIGHMEM |
| 345 | { | 311 | { |
| @@ -349,13 +315,9 @@ void __init mem_init(void) | |||
| 349 | for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) { | 315 | for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) { |
| 350 | phys_addr_t paddr = (phys_addr_t)pfn << PAGE_SHIFT; | 316 | phys_addr_t paddr = (phys_addr_t)pfn << PAGE_SHIFT; |
| 351 | struct page *page = pfn_to_page(pfn); | 317 | struct page *page = pfn_to_page(pfn); |
| 352 | if (memblock_is_reserved(paddr)) | 318 | if (!memblock_is_reserved(paddr)) |
| 353 | continue; | 319 | free_highmem_page(page); |
| 354 | free_highmem_page(page); | ||
| 355 | reservedpages--; | ||
| 356 | } | 320 | } |
| 357 | printk(KERN_DEBUG "High memory: %luk\n", | ||
| 358 | totalhigh_pages << (PAGE_SHIFT-10)); | ||
| 359 | } | 321 | } |
| 360 | #endif /* CONFIG_HIGHMEM */ | 322 | #endif /* CONFIG_HIGHMEM */ |
| 361 | 323 | ||
| @@ -368,16 +330,7 @@ void __init mem_init(void) | |||
| 368 | (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) - 1; | 330 | (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) - 1; |
| 369 | #endif | 331 | #endif |
| 370 | 332 | ||
| 371 | printk(KERN_INFO "Memory: %luk/%luk available (%luk kernel code, " | 333 | mem_init_print_info(NULL); |
| 372 | "%luk reserved, %luk data, %luk bss, %luk init)\n", | ||
| 373 | nr_free_pages() << (PAGE_SHIFT-10), | ||
| 374 | num_physpages << (PAGE_SHIFT-10), | ||
| 375 | codesize >> 10, | ||
| 376 | reservedpages << (PAGE_SHIFT-10), | ||
| 377 | datasize >> 10, | ||
| 378 | bsssize >> 10, | ||
| 379 | initsize >> 10); | ||
| 380 | |||
| 381 | #ifdef CONFIG_PPC32 | 334 | #ifdef CONFIG_PPC32 |
| 382 | pr_info("Kernel virtual memory layout:\n"); | 335 | pr_info("Kernel virtual memory layout:\n"); |
| 383 | pr_info(" * 0x%08lx..0x%08lx : fixmap\n", FIXADDR_START, FIXADDR_TOP); | 336 | pr_info(" * 0x%08lx..0x%08lx : fixmap\n", FIXADDR_START, FIXADDR_TOP); |
| @@ -407,7 +360,7 @@ void free_initmem(void) | |||
| 407 | #ifdef CONFIG_BLK_DEV_INITRD | 360 | #ifdef CONFIG_BLK_DEV_INITRD |
| 408 | void __init free_initrd_mem(unsigned long start, unsigned long end) | 361 | void __init free_initrd_mem(unsigned long start, unsigned long end) |
| 409 | { | 362 | { |
| 410 | free_reserved_area(start, end, 0, "initrd"); | 363 | free_reserved_area((void *)start, (void *)end, -1, "initrd"); |
| 411 | } | 364 | } |
| 412 | #endif | 365 | #endif |
| 413 | 366 | ||
diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index 023ec8a13f38..7df1c5edda87 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c | |||
| @@ -183,8 +183,8 @@ void tlb_flush(struct mmu_gather *tlb) | |||
| 183 | * since 64K pages may overlap with other bridges when using 64K pages | 183 | * since 64K pages may overlap with other bridges when using 64K pages |
| 184 | * with 4K HW pages on IO space. | 184 | * with 4K HW pages on IO space. |
| 185 | * | 185 | * |
| 186 | * Because of that usage pattern, it's only available with CONFIG_HOTPLUG | 186 | * Because of that usage pattern, it is implemented for small size rather |
| 187 | * and is implemented for small size rather than speed. | 187 | * than speed. |
| 188 | */ | 188 | */ |
| 189 | void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, | 189 | void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, |
| 190 | unsigned long end) | 190 | unsigned long end) |
diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c index 3c475d6267c7..13c3f0e547a2 100644 --- a/arch/powerpc/perf/power7-pmu.c +++ b/arch/powerpc/perf/power7-pmu.c | |||
| @@ -62,6 +62,29 @@ | |||
| 62 | #define PME_PM_BRU_FIN 0x10068 | 62 | #define PME_PM_BRU_FIN 0x10068 |
| 63 | #define PME_PM_BRU_MPRED 0x400f6 | 63 | #define PME_PM_BRU_MPRED 0x400f6 |
| 64 | 64 | ||
| 65 | #define PME_PM_CMPLU_STALL_FXU 0x20014 | ||
| 66 | #define PME_PM_CMPLU_STALL_DIV 0x40014 | ||
| 67 | #define PME_PM_CMPLU_STALL_SCALAR 0x40012 | ||
| 68 | #define PME_PM_CMPLU_STALL_SCALAR_LONG 0x20018 | ||
| 69 | #define PME_PM_CMPLU_STALL_VECTOR 0x2001c | ||
| 70 | #define PME_PM_CMPLU_STALL_VECTOR_LONG 0x4004a | ||
| 71 | #define PME_PM_CMPLU_STALL_LSU 0x20012 | ||
| 72 | #define PME_PM_CMPLU_STALL_REJECT 0x40016 | ||
| 73 | #define PME_PM_CMPLU_STALL_ERAT_MISS 0x40018 | ||
| 74 | #define PME_PM_CMPLU_STALL_DCACHE_MISS 0x20016 | ||
| 75 | #define PME_PM_CMPLU_STALL_STORE 0x2004a | ||
| 76 | #define PME_PM_CMPLU_STALL_THRD 0x1001c | ||
| 77 | #define PME_PM_CMPLU_STALL_IFU 0x4004c | ||
| 78 | #define PME_PM_CMPLU_STALL_BRU 0x4004e | ||
| 79 | #define PME_PM_GCT_NOSLOT_IC_MISS 0x2001a | ||
| 80 | #define PME_PM_GCT_NOSLOT_BR_MPRED 0x4001a | ||
| 81 | #define PME_PM_GCT_NOSLOT_BR_MPRED_IC_MISS 0x4001c | ||
| 82 | #define PME_PM_GRP_CMPL 0x30004 | ||
| 83 | #define PME_PM_1PLUS_PPC_CMPL 0x100f2 | ||
| 84 | #define PME_PM_CMPLU_STALL_DFU 0x2003c | ||
| 85 | #define PME_PM_RUN_CYC 0x200f4 | ||
| 86 | #define PME_PM_RUN_INST_CMPL 0x400fa | ||
| 87 | |||
| 65 | /* | 88 | /* |
| 66 | * Layout of constraint bits: | 89 | * Layout of constraint bits: |
| 67 | * 6666555555555544444444443333333333222222222211111111110000000000 | 90 | * 6666555555555544444444443333333333222222222211111111110000000000 |
| @@ -393,6 +416,31 @@ POWER_EVENT_ATTR(LD_MISS_L1, LD_MISS_L1); | |||
| 393 | POWER_EVENT_ATTR(BRU_FIN, BRU_FIN) | 416 | POWER_EVENT_ATTR(BRU_FIN, BRU_FIN) |
| 394 | POWER_EVENT_ATTR(BRU_MPRED, BRU_MPRED); | 417 | POWER_EVENT_ATTR(BRU_MPRED, BRU_MPRED); |
| 395 | 418 | ||
| 419 | POWER_EVENT_ATTR(CMPLU_STALL_FXU, CMPLU_STALL_FXU); | ||
| 420 | POWER_EVENT_ATTR(CMPLU_STALL_DIV, CMPLU_STALL_DIV); | ||
| 421 | POWER_EVENT_ATTR(CMPLU_STALL_SCALAR, CMPLU_STALL_SCALAR); | ||
| 422 | POWER_EVENT_ATTR(CMPLU_STALL_SCALAR_LONG, CMPLU_STALL_SCALAR_LONG); | ||
| 423 | POWER_EVENT_ATTR(CMPLU_STALL_VECTOR, CMPLU_STALL_VECTOR); | ||
| 424 | POWER_EVENT_ATTR(CMPLU_STALL_VECTOR_LONG, CMPLU_STALL_VECTOR_LONG); | ||
| 425 | POWER_EVENT_ATTR(CMPLU_STALL_LSU, CMPLU_STALL_LSU); | ||
| 426 | POWER_EVENT_ATTR(CMPLU_STALL_REJECT, CMPLU_STALL_REJECT); | ||
| 427 | |||
| 428 | POWER_EVENT_ATTR(CMPLU_STALL_ERAT_MISS, CMPLU_STALL_ERAT_MISS); | ||
| 429 | POWER_EVENT_ATTR(CMPLU_STALL_DCACHE_MISS, CMPLU_STALL_DCACHE_MISS); | ||
| 430 | POWER_EVENT_ATTR(CMPLU_STALL_STORE, CMPLU_STALL_STORE); | ||
| 431 | POWER_EVENT_ATTR(CMPLU_STALL_THRD, CMPLU_STALL_THRD); | ||
| 432 | POWER_EVENT_ATTR(CMPLU_STALL_IFU, CMPLU_STALL_IFU); | ||
| 433 | POWER_EVENT_ATTR(CMPLU_STALL_BRU, CMPLU_STALL_BRU); | ||
| 434 | POWER_EVENT_ATTR(GCT_NOSLOT_IC_MISS, GCT_NOSLOT_IC_MISS); | ||
| 435 | |||
| 436 | POWER_EVENT_ATTR(GCT_NOSLOT_BR_MPRED, GCT_NOSLOT_BR_MPRED); | ||
| 437 | POWER_EVENT_ATTR(GCT_NOSLOT_BR_MPRED_IC_MISS, GCT_NOSLOT_BR_MPRED_IC_MISS); | ||
| 438 | POWER_EVENT_ATTR(GRP_CMPL, GRP_CMPL); | ||
| 439 | POWER_EVENT_ATTR(1PLUS_PPC_CMPL, 1PLUS_PPC_CMPL); | ||
| 440 | POWER_EVENT_ATTR(CMPLU_STALL_DFU, CMPLU_STALL_DFU); | ||
| 441 | POWER_EVENT_ATTR(RUN_CYC, RUN_CYC); | ||
| 442 | POWER_EVENT_ATTR(RUN_INST_CMPL, RUN_INST_CMPL); | ||
| 443 | |||
| 396 | static struct attribute *power7_events_attr[] = { | 444 | static struct attribute *power7_events_attr[] = { |
| 397 | GENERIC_EVENT_PTR(CYC), | 445 | GENERIC_EVENT_PTR(CYC), |
| 398 | GENERIC_EVENT_PTR(GCT_NOSLOT_CYC), | 446 | GENERIC_EVENT_PTR(GCT_NOSLOT_CYC), |
| @@ -411,6 +459,31 @@ static struct attribute *power7_events_attr[] = { | |||
| 411 | POWER_EVENT_PTR(LD_MISS_L1), | 459 | POWER_EVENT_PTR(LD_MISS_L1), |
| 412 | POWER_EVENT_PTR(BRU_FIN), | 460 | POWER_EVENT_PTR(BRU_FIN), |
| 413 | POWER_EVENT_PTR(BRU_MPRED), | 461 | POWER_EVENT_PTR(BRU_MPRED), |
| 462 | |||
| 463 | POWER_EVENT_PTR(CMPLU_STALL_FXU), | ||
| 464 | POWER_EVENT_PTR(CMPLU_STALL_DIV), | ||
| 465 | POWER_EVENT_PTR(CMPLU_STALL_SCALAR), | ||
| 466 | POWER_EVENT_PTR(CMPLU_STALL_SCALAR_LONG), | ||
| 467 | POWER_EVENT_PTR(CMPLU_STALL_VECTOR), | ||
| 468 | POWER_EVENT_PTR(CMPLU_STALL_VECTOR_LONG), | ||
| 469 | POWER_EVENT_PTR(CMPLU_STALL_LSU), | ||
| 470 | POWER_EVENT_PTR(CMPLU_STALL_REJECT), | ||
| 471 | |||
| 472 | POWER_EVENT_PTR(CMPLU_STALL_ERAT_MISS), | ||
| 473 | POWER_EVENT_PTR(CMPLU_STALL_DCACHE_MISS), | ||
| 474 | POWER_EVENT_PTR(CMPLU_STALL_STORE), | ||
| 475 | POWER_EVENT_PTR(CMPLU_STALL_THRD), | ||
| 476 | POWER_EVENT_PTR(CMPLU_STALL_IFU), | ||
| 477 | POWER_EVENT_PTR(CMPLU_STALL_BRU), | ||
| 478 | POWER_EVENT_PTR(GCT_NOSLOT_IC_MISS), | ||
| 479 | POWER_EVENT_PTR(GCT_NOSLOT_BR_MPRED), | ||
| 480 | |||
| 481 | POWER_EVENT_PTR(GCT_NOSLOT_BR_MPRED_IC_MISS), | ||
| 482 | POWER_EVENT_PTR(GRP_CMPL), | ||
| 483 | POWER_EVENT_PTR(1PLUS_PPC_CMPL), | ||
| 484 | POWER_EVENT_PTR(CMPLU_STALL_DFU), | ||
| 485 | POWER_EVENT_PTR(RUN_CYC), | ||
| 486 | POWER_EVENT_PTR(RUN_INST_CMPL), | ||
| 414 | NULL | 487 | NULL |
| 415 | }; | 488 | }; |
| 416 | 489 | ||
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index b62aab3e22ec..e17cdfc5ba40 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
| @@ -193,37 +193,6 @@ config PPC_IO_WORKAROUNDS | |||
| 193 | 193 | ||
| 194 | source "drivers/cpufreq/Kconfig" | 194 | source "drivers/cpufreq/Kconfig" |
| 195 | 195 | ||
| 196 | menu "CPU Frequency drivers" | ||
| 197 | depends on CPU_FREQ | ||
| 198 | |||
| 199 | config CPU_FREQ_PMAC | ||
| 200 | bool "Support for Apple PowerBooks" | ||
| 201 | depends on ADB_PMU && PPC32 | ||
| 202 | select CPU_FREQ_TABLE | ||
| 203 | help | ||
| 204 | This adds support for frequency switching on Apple PowerBooks, | ||
| 205 | this currently includes some models of iBook & Titanium | ||
| 206 | PowerBook. | ||
| 207 | |||
| 208 | config CPU_FREQ_PMAC64 | ||
| 209 | bool "Support for some Apple G5s" | ||
| 210 | depends on PPC_PMAC && PPC64 | ||
| 211 | select CPU_FREQ_TABLE | ||
| 212 | help | ||
| 213 | This adds support for frequency switching on Apple iMac G5, | ||
| 214 | and some of the more recent desktop G5 machines as well. | ||
| 215 | |||
| 216 | config PPC_PASEMI_CPUFREQ | ||
| 217 | bool "Support for PA Semi PWRficient" | ||
| 218 | depends on PPC_PASEMI | ||
| 219 | default y | ||
| 220 | select CPU_FREQ_TABLE | ||
| 221 | help | ||
| 222 | This adds the support for frequency switching on PA Semi | ||
| 223 | PWRficient processors. | ||
| 224 | |||
| 225 | endmenu | ||
| 226 | |||
| 227 | menu "CPUIdle driver" | 196 | menu "CPUIdle driver" |
| 228 | 197 | ||
| 229 | source "drivers/cpuidle/Kconfig" | 198 | source "drivers/cpuidle/Kconfig" |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 54f3936001aa..7819c40a6bc3 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
| @@ -158,6 +158,7 @@ config E500 | |||
| 158 | config PPC_E500MC | 158 | config PPC_E500MC |
| 159 | bool "e500mc Support" | 159 | bool "e500mc Support" |
| 160 | select PPC_FPU | 160 | select PPC_FPU |
| 161 | select COMMON_CLK | ||
| 161 | depends on E500 | 162 | depends on E500 |
| 162 | help | 163 | help |
| 163 | This must be enabled for running on e500mc (and derivatives | 164 | This must be enabled for running on e500mc (and derivatives |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 35f77a42bedf..f3900427ffab 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
| @@ -238,7 +238,7 @@ const struct file_operations spufs_context_fops = { | |||
| 238 | .release = spufs_dir_close, | 238 | .release = spufs_dir_close, |
| 239 | .llseek = dcache_dir_lseek, | 239 | .llseek = dcache_dir_lseek, |
| 240 | .read = generic_read_dir, | 240 | .read = generic_read_dir, |
| 241 | .readdir = dcache_readdir, | 241 | .iterate = dcache_readdir, |
| 242 | .fsync = noop_fsync, | 242 | .fsync = noop_fsync, |
| 243 | }; | 243 | }; |
| 244 | EXPORT_SYMBOL_GPL(spufs_context_fops); | 244 | EXPORT_SYMBOL_GPL(spufs_context_fops); |
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile index ce6d789e0741..8e8d4cae5ebe 100644 --- a/arch/powerpc/platforms/pasemi/Makefile +++ b/arch/powerpc/platforms/pasemi/Makefile | |||
| @@ -1,3 +1,2 @@ | |||
| 1 | obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o dma_lib.o misc.o | 1 | obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o dma_lib.o misc.o |
| 2 | obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o | 2 | obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o |
| 3 | obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o | ||
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c deleted file mode 100644 index be1e7958909e..000000000000 --- a/arch/powerpc/platforms/pasemi/cpufreq.c +++ /dev/null | |||
| @@ -1,330 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007 PA Semi, Inc | ||
| 3 | * | ||
| 4 | * Authors: Egor Martovetsky <egor@pasemi.com> | ||
| 5 | * Olof Johansson <olof@lixom.net> | ||
| 6 | * | ||
| 7 | * Maintained by: Olof Johansson <olof@lixom.net> | ||
| 8 | * | ||
| 9 | * Based on arch/powerpc/platforms/cell/cbe_cpufreq.c: | ||
| 10 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License as published by | ||
| 14 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 15 | * any later version. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 25 | * | ||
| 26 | */ | ||
| 27 | |||
| 28 | #include <linux/cpufreq.h> | ||
| 29 | #include <linux/timer.h> | ||
| 30 | #include <linux/module.h> | ||
| 31 | |||
| 32 | #include <asm/hw_irq.h> | ||
| 33 | #include <asm/io.h> | ||
| 34 | #include <asm/prom.h> | ||
| 35 | #include <asm/time.h> | ||
| 36 | #include <asm/smp.h> | ||
| 37 | |||
| 38 | #define SDCASR_REG 0x0100 | ||
| 39 | #define SDCASR_REG_STRIDE 0x1000 | ||
| 40 | #define SDCPWR_CFGA0_REG 0x0100 | ||
| 41 | #define SDCPWR_PWST0_REG 0x0000 | ||
| 42 | #define SDCPWR_GIZTIME_REG 0x0440 | ||
| 43 | |||
| 44 | /* SDCPWR_GIZTIME_REG fields */ | ||
| 45 | #define SDCPWR_GIZTIME_GR 0x80000000 | ||
| 46 | #define SDCPWR_GIZTIME_LONGLOCK 0x000000ff | ||
| 47 | |||
| 48 | /* Offset of ASR registers from SDC base */ | ||
| 49 | #define SDCASR_OFFSET 0x120000 | ||
| 50 | |||
| 51 | static void __iomem *sdcpwr_mapbase; | ||
| 52 | static void __iomem *sdcasr_mapbase; | ||
| 53 | |||
| 54 | static DEFINE_MUTEX(pas_switch_mutex); | ||
| 55 | |||
| 56 | /* Current astate, is used when waking up from power savings on | ||
| 57 | * one core, in case the other core has switched states during | ||
| 58 | * the idle time. | ||
| 59 | */ | ||
| 60 | static int current_astate; | ||
| 61 | |||
| 62 | /* We support 5(A0-A4) power states excluding turbo(A5-A6) modes */ | ||
| 63 | static struct cpufreq_frequency_table pas_freqs[] = { | ||
| 64 | {0, 0}, | ||
| 65 | {1, 0}, | ||
| 66 | {2, 0}, | ||
| 67 | {3, 0}, | ||
| 68 | {4, 0}, | ||
| 69 | {0, CPUFREQ_TABLE_END}, | ||
| 70 | }; | ||
| 71 | |||
| 72 | static struct freq_attr *pas_cpu_freqs_attr[] = { | ||
| 73 | &cpufreq_freq_attr_scaling_available_freqs, | ||
| 74 | NULL, | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* | ||
| 78 | * hardware specific functions | ||
| 79 | */ | ||
| 80 | |||
| 81 | static int get_astate_freq(int astate) | ||
| 82 | { | ||
| 83 | u32 ret; | ||
| 84 | ret = in_le32(sdcpwr_mapbase + SDCPWR_CFGA0_REG + (astate * 0x10)); | ||
| 85 | |||
| 86 | return ret & 0x3f; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int get_cur_astate(int cpu) | ||
| 90 | { | ||
| 91 | u32 ret; | ||
| 92 | |||
| 93 | ret = in_le32(sdcpwr_mapbase + SDCPWR_PWST0_REG); | ||
| 94 | ret = (ret >> (cpu * 4)) & 0x7; | ||
| 95 | |||
| 96 | return ret; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int get_gizmo_latency(void) | ||
| 100 | { | ||
| 101 | u32 giztime, ret; | ||
| 102 | |||
| 103 | giztime = in_le32(sdcpwr_mapbase + SDCPWR_GIZTIME_REG); | ||
| 104 | |||
| 105 | /* just provide the upper bound */ | ||
| 106 | if (giztime & SDCPWR_GIZTIME_GR) | ||
| 107 | ret = (giztime & SDCPWR_GIZTIME_LONGLOCK) * 128000; | ||
| 108 | else | ||
| 109 | ret = (giztime & SDCPWR_GIZTIME_LONGLOCK) * 1000; | ||
| 110 | |||
| 111 | return ret; | ||
| 112 | } | ||
| 113 | |||
| 114 | static void set_astate(int cpu, unsigned int astate) | ||
| 115 | { | ||
| 116 | unsigned long flags; | ||
| 117 | |||
| 118 | /* Return if called before init has run */ | ||
| 119 | if (unlikely(!sdcasr_mapbase)) | ||
| 120 | return; | ||
| 121 | |||
| 122 | local_irq_save(flags); | ||
| 123 | |||
| 124 | out_le32(sdcasr_mapbase + SDCASR_REG + SDCASR_REG_STRIDE*cpu, astate); | ||
| 125 | |||
| 126 | local_irq_restore(flags); | ||
| 127 | } | ||
| 128 | |||
| 129 | int check_astate(void) | ||
| 130 | { | ||
| 131 | return get_cur_astate(hard_smp_processor_id()); | ||
| 132 | } | ||
| 133 | |||
| 134 | void restore_astate(int cpu) | ||
| 135 | { | ||
| 136 | set_astate(cpu, current_astate); | ||
| 137 | } | ||
| 138 | |||
| 139 | /* | ||
| 140 | * cpufreq functions | ||
| 141 | */ | ||
| 142 | |||
| 143 | static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
| 144 | { | ||
| 145 | const u32 *max_freqp; | ||
| 146 | u32 max_freq; | ||
| 147 | int i, cur_astate; | ||
| 148 | struct resource res; | ||
| 149 | struct device_node *cpu, *dn; | ||
| 150 | int err = -ENODEV; | ||
| 151 | |||
| 152 | cpu = of_get_cpu_node(policy->cpu, NULL); | ||
| 153 | |||
| 154 | if (!cpu) | ||
| 155 | goto out; | ||
| 156 | |||
| 157 | dn = of_find_compatible_node(NULL, NULL, "1682m-sdc"); | ||
| 158 | if (!dn) | ||
| 159 | dn = of_find_compatible_node(NULL, NULL, | ||
| 160 | "pasemi,pwrficient-sdc"); | ||
| 161 | if (!dn) | ||
| 162 | goto out; | ||
| 163 | err = of_address_to_resource(dn, 0, &res); | ||
| 164 | of_node_put(dn); | ||
| 165 | if (err) | ||
| 166 | goto out; | ||
| 167 | sdcasr_mapbase = ioremap(res.start + SDCASR_OFFSET, 0x2000); | ||
| 168 | if (!sdcasr_mapbase) { | ||
| 169 | err = -EINVAL; | ||
| 170 | goto out; | ||
| 171 | } | ||
| 172 | |||
| 173 | dn = of_find_compatible_node(NULL, NULL, "1682m-gizmo"); | ||
| 174 | if (!dn) | ||
| 175 | dn = of_find_compatible_node(NULL, NULL, | ||
| 176 | "pasemi,pwrficient-gizmo"); | ||
| 177 | if (!dn) { | ||
| 178 | err = -ENODEV; | ||
| 179 | goto out_unmap_sdcasr; | ||
| 180 | } | ||
| 181 | err = of_address_to_resource(dn, 0, &res); | ||
| 182 | of_node_put(dn); | ||
| 183 | if (err) | ||
| 184 | goto out_unmap_sdcasr; | ||
| 185 | sdcpwr_mapbase = ioremap(res.start, 0x1000); | ||
| 186 | if (!sdcpwr_mapbase) { | ||
| 187 | err = -EINVAL; | ||
| 188 | goto out_unmap_sdcasr; | ||
| 189 | } | ||
| 190 | |||
| 191 | pr_debug("init cpufreq on CPU %d\n", policy->cpu); | ||
| 192 | |||
| 193 | max_freqp = of_get_property(cpu, "clock-frequency", NULL); | ||
| 194 | if (!max_freqp) { | ||
| 195 | err = -EINVAL; | ||
| 196 | goto out_unmap_sdcpwr; | ||
| 197 | } | ||
| 198 | |||
| 199 | /* we need the freq in kHz */ | ||
| 200 | max_freq = *max_freqp / 1000; | ||
| 201 | |||
| 202 | pr_debug("max clock-frequency is at %u kHz\n", max_freq); | ||
| 203 | pr_debug("initializing frequency table\n"); | ||
| 204 | |||
| 205 | /* initialize frequency table */ | ||
| 206 | for (i=0; pas_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { | ||
| 207 | pas_freqs[i].frequency = get_astate_freq(pas_freqs[i].index) * 100000; | ||
| 208 | pr_debug("%d: %d\n", i, pas_freqs[i].frequency); | ||
| 209 | } | ||
| 210 | |||
| 211 | policy->cpuinfo.transition_latency = get_gizmo_latency(); | ||
| 212 | |||
| 213 | cur_astate = get_cur_astate(policy->cpu); | ||
| 214 | pr_debug("current astate is at %d\n",cur_astate); | ||
| 215 | |||
| 216 | policy->cur = pas_freqs[cur_astate].frequency; | ||
| 217 | cpumask_copy(policy->cpus, cpu_online_mask); | ||
| 218 | |||
| 219 | ppc_proc_freq = policy->cur * 1000ul; | ||
| 220 | |||
| 221 | cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu); | ||
| 222 | |||
| 223 | /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max | ||
| 224 | * are set correctly | ||
| 225 | */ | ||
| 226 | return cpufreq_frequency_table_cpuinfo(policy, pas_freqs); | ||
| 227 | |||
| 228 | out_unmap_sdcpwr: | ||
| 229 | iounmap(sdcpwr_mapbase); | ||
| 230 | |||
| 231 | out_unmap_sdcasr: | ||
| 232 | iounmap(sdcasr_mapbase); | ||
| 233 | out: | ||
| 234 | return err; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) | ||
| 238 | { | ||
| 239 | /* | ||
| 240 | * We don't support CPU hotplug. Don't unmap after the system | ||
| 241 | * has already made it to a running state. | ||
| 242 | */ | ||
| 243 | if (system_state != SYSTEM_BOOTING) | ||
| 244 | return 0; | ||
| 245 | |||
| 246 | if (sdcasr_mapbase) | ||
| 247 | iounmap(sdcasr_mapbase); | ||
| 248 | if (sdcpwr_mapbase) | ||
| 249 | iounmap(sdcpwr_mapbase); | ||
| 250 | |||
| 251 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | static int pas_cpufreq_verify(struct cpufreq_policy *policy) | ||
| 256 | { | ||
| 257 | return cpufreq_frequency_table_verify(policy, pas_freqs); | ||
| 258 | } | ||
| 259 | |||
| 260 | static int pas_cpufreq_target(struct cpufreq_policy *policy, | ||
| 261 | unsigned int target_freq, | ||
| 262 | unsigned int relation) | ||
| 263 | { | ||
| 264 | struct cpufreq_freqs freqs; | ||
| 265 | int pas_astate_new; | ||
| 266 | int i; | ||
| 267 | |||
| 268 | cpufreq_frequency_table_target(policy, | ||
| 269 | pas_freqs, | ||
| 270 | target_freq, | ||
| 271 | relation, | ||
| 272 | &pas_astate_new); | ||
| 273 | |||
| 274 | freqs.old = policy->cur; | ||
| 275 | freqs.new = pas_freqs[pas_astate_new].frequency; | ||
| 276 | |||
| 277 | mutex_lock(&pas_switch_mutex); | ||
| 278 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | ||
| 279 | |||
| 280 | pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", | ||
| 281 | policy->cpu, | ||
| 282 | pas_freqs[pas_astate_new].frequency, | ||
| 283 | pas_freqs[pas_astate_new].index); | ||
| 284 | |||
| 285 | current_astate = pas_astate_new; | ||
| 286 | |||
| 287 | for_each_online_cpu(i) | ||
| 288 | set_astate(i, pas_astate_new); | ||
| 289 | |||
| 290 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | ||
| 291 | mutex_unlock(&pas_switch_mutex); | ||
| 292 | |||
| 293 | ppc_proc_freq = freqs.new * 1000ul; | ||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | static struct cpufreq_driver pas_cpufreq_driver = { | ||
| 298 | .name = "pas-cpufreq", | ||
| 299 | .owner = THIS_MODULE, | ||
| 300 | .flags = CPUFREQ_CONST_LOOPS, | ||
| 301 | .init = pas_cpufreq_cpu_init, | ||
| 302 | .exit = pas_cpufreq_cpu_exit, | ||
| 303 | .verify = pas_cpufreq_verify, | ||
| 304 | .target = pas_cpufreq_target, | ||
| 305 | .attr = pas_cpu_freqs_attr, | ||
| 306 | }; | ||
| 307 | |||
| 308 | /* | ||
| 309 | * module init and destoy | ||
| 310 | */ | ||
| 311 | |||
| 312 | static int __init pas_cpufreq_init(void) | ||
| 313 | { | ||
| 314 | if (!of_machine_is_compatible("PA6T-1682M") && | ||
| 315 | !of_machine_is_compatible("pasemi,pwrficient")) | ||
| 316 | return -ENODEV; | ||
| 317 | |||
| 318 | return cpufreq_register_driver(&pas_cpufreq_driver); | ||
| 319 | } | ||
| 320 | |||
| 321 | static void __exit pas_cpufreq_exit(void) | ||
| 322 | { | ||
| 323 | cpufreq_unregister_driver(&pas_cpufreq_driver); | ||
| 324 | } | ||
| 325 | |||
| 326 | module_init(pas_cpufreq_init); | ||
| 327 | module_exit(pas_cpufreq_exit); | ||
| 328 | |||
| 329 | MODULE_LICENSE("GPL"); | ||
| 330 | MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>, Olof Johansson <olof@lixom.net>"); | ||
diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index ea47df66fee5..52c6ce1cc985 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile | |||
| @@ -9,8 +9,6 @@ obj-y += pic.o setup.o time.o feature.o pci.o \ | |||
| 9 | sleep.o low_i2c.o cache.o pfunc_core.o \ | 9 | sleep.o low_i2c.o cache.o pfunc_core.o \ |
| 10 | pfunc_base.o udbg_scc.o udbg_adb.o | 10 | pfunc_base.o udbg_scc.o udbg_adb.o |
| 11 | obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o | 11 | obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o |
| 12 | obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o | ||
| 13 | obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o | ||
| 14 | # CONFIG_NVRAM is an arch. independent tristate symbol, for pmac32 we really | 12 | # CONFIG_NVRAM is an arch. independent tristate symbol, for pmac32 we really |
| 15 | # need this to be a bool. Cheat here and pretend CONFIG_NVRAM=m is really | 13 | # need this to be a bool. Cheat here and pretend CONFIG_NVRAM=m is really |
| 16 | # CONFIG_NVRAM=y | 14 | # CONFIG_NVRAM=y |
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c deleted file mode 100644 index 3104fad82480..000000000000 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ /dev/null | |||
| @@ -1,721 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
| 3 | * Copyright (C) 2004 John Steele Scott <toojays@toojays.net> | ||
| 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 | * TODO: Need a big cleanup here. Basically, we need to have different | ||
| 10 | * cpufreq_driver structures for the different type of HW instead of the | ||
| 11 | * current mess. We also need to better deal with the detection of the | ||
| 12 | * type of machine. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/types.h> | ||
| 18 | #include <linux/errno.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/sched.h> | ||
| 22 | #include <linux/adb.h> | ||
| 23 | #include <linux/pmu.h> | ||
| 24 | #include <linux/cpufreq.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/device.h> | ||
| 27 | #include <linux/hardirq.h> | ||
| 28 | #include <asm/prom.h> | ||
| 29 | #include <asm/machdep.h> | ||
| 30 | #include <asm/irq.h> | ||
| 31 | #include <asm/pmac_feature.h> | ||
| 32 | #include <asm/mmu_context.h> | ||
| 33 | #include <asm/sections.h> | ||
| 34 | #include <asm/cputable.h> | ||
| 35 | #include <asm/time.h> | ||
| 36 | #include <asm/mpic.h> | ||
| 37 | #include <asm/keylargo.h> | ||
| 38 | #include <asm/switch_to.h> | ||
| 39 | |||
| 40 | /* WARNING !!! This will cause calibrate_delay() to be called, | ||
| 41 | * but this is an __init function ! So you MUST go edit | ||
| 42 | * init/main.c to make it non-init before enabling DEBUG_FREQ | ||
| 43 | */ | ||
| 44 | #undef DEBUG_FREQ | ||
| 45 | |||
| 46 | extern void low_choose_7447a_dfs(int dfs); | ||
| 47 | extern void low_choose_750fx_pll(int pll); | ||
| 48 | extern void low_sleep_handler(void); | ||
| 49 | |||
| 50 | /* | ||
| 51 | * Currently, PowerMac cpufreq supports only high & low frequencies | ||
| 52 | * that are set by the firmware | ||
| 53 | */ | ||
| 54 | static unsigned int low_freq; | ||
| 55 | static unsigned int hi_freq; | ||
| 56 | static unsigned int cur_freq; | ||
| 57 | static unsigned int sleep_freq; | ||
| 58 | static unsigned long transition_latency; | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Different models uses different mechanisms to switch the frequency | ||
| 62 | */ | ||
| 63 | static int (*set_speed_proc)(int low_speed); | ||
| 64 | static unsigned int (*get_speed_proc)(void); | ||
| 65 | |||
| 66 | /* | ||
| 67 | * Some definitions used by the various speedprocs | ||
| 68 | */ | ||
| 69 | static u32 voltage_gpio; | ||
| 70 | static u32 frequency_gpio; | ||
| 71 | static u32 slew_done_gpio; | ||
| 72 | static int no_schedule; | ||
| 73 | static int has_cpu_l2lve; | ||
| 74 | static int is_pmu_based; | ||
| 75 | |||
| 76 | /* There are only two frequency states for each processor. Values | ||
| 77 | * are in kHz for the time being. | ||
| 78 | */ | ||
| 79 | #define CPUFREQ_HIGH 0 | ||
| 80 | #define CPUFREQ_LOW 1 | ||
| 81 | |||
| 82 | static struct cpufreq_frequency_table pmac_cpu_freqs[] = { | ||
| 83 | {CPUFREQ_HIGH, 0}, | ||
| 84 | {CPUFREQ_LOW, 0}, | ||
| 85 | {0, CPUFREQ_TABLE_END}, | ||
| 86 | }; | ||
| 87 | |||
| 88 | static struct freq_attr* pmac_cpu_freqs_attr[] = { | ||
| 89 | &cpufreq_freq_attr_scaling_available_freqs, | ||
| 90 | NULL, | ||
| 91 | }; | ||
| 92 | |||
| 93 | static inline void local_delay(unsigned long ms) | ||
| 94 | { | ||
| 95 | if (no_schedule) | ||
| 96 | mdelay(ms); | ||
| 97 | else | ||
| 98 | msleep(ms); | ||
| 99 | } | ||
| 100 | |||
| 101 | #ifdef DEBUG_FREQ | ||
| 102 | static inline void debug_calc_bogomips(void) | ||
| 103 | { | ||
| 104 | /* This will cause a recalc of bogomips and display the | ||
| 105 | * result. We backup/restore the value to avoid affecting the | ||
| 106 | * core cpufreq framework's own calculation. | ||
| 107 | */ | ||
| 108 | unsigned long save_lpj = loops_per_jiffy; | ||
| 109 | calibrate_delay(); | ||
| 110 | loops_per_jiffy = save_lpj; | ||
| 111 | } | ||
| 112 | #endif /* DEBUG_FREQ */ | ||
| 113 | |||
| 114 | /* Switch CPU speed under 750FX CPU control | ||
| 115 | */ | ||
| 116 | static int cpu_750fx_cpu_speed(int low_speed) | ||
| 117 | { | ||
| 118 | u32 hid2; | ||
| 119 | |||
| 120 | if (low_speed == 0) { | ||
| 121 | /* ramping up, set voltage first */ | ||
| 122 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); | ||
| 123 | /* Make sure we sleep for at least 1ms */ | ||
| 124 | local_delay(10); | ||
| 125 | |||
| 126 | /* tweak L2 for high voltage */ | ||
| 127 | if (has_cpu_l2lve) { | ||
| 128 | hid2 = mfspr(SPRN_HID2); | ||
| 129 | hid2 &= ~0x2000; | ||
| 130 | mtspr(SPRN_HID2, hid2); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | #ifdef CONFIG_6xx | ||
| 134 | low_choose_750fx_pll(low_speed); | ||
| 135 | #endif | ||
| 136 | if (low_speed == 1) { | ||
| 137 | /* tweak L2 for low voltage */ | ||
| 138 | if (has_cpu_l2lve) { | ||
| 139 | hid2 = mfspr(SPRN_HID2); | ||
| 140 | hid2 |= 0x2000; | ||
| 141 | mtspr(SPRN_HID2, hid2); | ||
| 142 | } | ||
| 143 | |||
| 144 | /* ramping down, set voltage last */ | ||
| 145 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); | ||
| 146 | local_delay(10); | ||
| 147 | } | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static unsigned int cpu_750fx_get_cpu_speed(void) | ||
| 153 | { | ||
| 154 | if (mfspr(SPRN_HID1) & HID1_PS) | ||
| 155 | return low_freq; | ||
| 156 | else | ||
| 157 | return hi_freq; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* Switch CPU speed using DFS */ | ||
| 161 | static int dfs_set_cpu_speed(int low_speed) | ||
| 162 | { | ||
| 163 | if (low_speed == 0) { | ||
| 164 | /* ramping up, set voltage first */ | ||
| 165 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); | ||
| 166 | /* Make sure we sleep for at least 1ms */ | ||
| 167 | local_delay(1); | ||
| 168 | } | ||
| 169 | |||
| 170 | /* set frequency */ | ||
| 171 | #ifdef CONFIG_6xx | ||
| 172 | low_choose_7447a_dfs(low_speed); | ||
| 173 | #endif | ||
| 174 | udelay(100); | ||
| 175 | |||
| 176 | if (low_speed == 1) { | ||
| 177 | /* ramping down, set voltage last */ | ||
| 178 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); | ||
| 179 | local_delay(1); | ||
| 180 | } | ||
| 181 | |||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | static unsigned int dfs_get_cpu_speed(void) | ||
| 186 | { | ||
| 187 | if (mfspr(SPRN_HID1) & HID1_DFS) | ||
| 188 | return low_freq; | ||
| 189 | else | ||
| 190 | return hi_freq; | ||
| 191 | } | ||
| 192 | |||
| 193 | |||
| 194 | /* Switch CPU speed using slewing GPIOs | ||
| 195 | */ | ||
| 196 | static int gpios_set_cpu_speed(int low_speed) | ||
| 197 | { | ||
| 198 | int gpio, timeout = 0; | ||
| 199 | |||
| 200 | /* If ramping up, set voltage first */ | ||
| 201 | if (low_speed == 0) { | ||
| 202 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); | ||
| 203 | /* Delay is way too big but it's ok, we schedule */ | ||
| 204 | local_delay(10); | ||
| 205 | } | ||
| 206 | |||
| 207 | /* Set frequency */ | ||
| 208 | gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); | ||
| 209 | if (low_speed == ((gpio & 0x01) == 0)) | ||
| 210 | goto skip; | ||
| 211 | |||
| 212 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, | ||
| 213 | low_speed ? 0x04 : 0x05); | ||
| 214 | udelay(200); | ||
| 215 | do { | ||
| 216 | if (++timeout > 100) | ||
| 217 | break; | ||
| 218 | local_delay(1); | ||
| 219 | gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0); | ||
| 220 | } while((gpio & 0x02) == 0); | ||
| 221 | skip: | ||
| 222 | /* If ramping down, set voltage last */ | ||
| 223 | if (low_speed == 1) { | ||
| 224 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); | ||
| 225 | /* Delay is way too big but it's ok, we schedule */ | ||
| 226 | local_delay(10); | ||
| 227 | } | ||
| 228 | |||
| 229 | #ifdef DEBUG_FREQ | ||
| 230 | debug_calc_bogomips(); | ||
| 231 | #endif | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* Switch CPU speed under PMU control | ||
| 237 | */ | ||
| 238 | static int pmu_set_cpu_speed(int low_speed) | ||
| 239 | { | ||
| 240 | struct adb_request req; | ||
| 241 | unsigned long save_l2cr; | ||
| 242 | unsigned long save_l3cr; | ||
| 243 | unsigned int pic_prio; | ||
| 244 | unsigned long flags; | ||
| 245 | |||
| 246 | preempt_disable(); | ||
| 247 | |||
| 248 | #ifdef DEBUG_FREQ | ||
| 249 | printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); | ||
| 250 | #endif | ||
| 251 | pmu_suspend(); | ||
| 252 | |||
| 253 | /* Disable all interrupt sources on openpic */ | ||
| 254 | pic_prio = mpic_cpu_get_priority(); | ||
| 255 | mpic_cpu_set_priority(0xf); | ||
| 256 | |||
| 257 | /* Make sure the decrementer won't interrupt us */ | ||
| 258 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
| 259 | /* Make sure any pending DEC interrupt occurring while we did | ||
| 260 | * the above didn't re-enable the DEC */ | ||
| 261 | mb(); | ||
| 262 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
| 263 | |||
| 264 | /* We can now disable MSR_EE */ | ||
| 265 | local_irq_save(flags); | ||
| 266 | |||
| 267 | /* Giveup the FPU & vec */ | ||
| 268 | enable_kernel_fp(); | ||
| 269 | |||
| 270 | #ifdef CONFIG_ALTIVEC | ||
| 271 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | ||
| 272 | enable_kernel_altivec(); | ||
| 273 | #endif /* CONFIG_ALTIVEC */ | ||
| 274 | |||
| 275 | /* Save & disable L2 and L3 caches */ | ||
| 276 | save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ | ||
| 277 | save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ | ||
| 278 | |||
| 279 | /* Send the new speed command. My assumption is that this command | ||
| 280 | * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep | ||
| 281 | */ | ||
| 282 | pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); | ||
| 283 | while (!req.complete) | ||
| 284 | pmu_poll(); | ||
| 285 | |||
| 286 | /* Prepare the northbridge for the speed transition */ | ||
| 287 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); | ||
| 288 | |||
| 289 | /* Call low level code to backup CPU state and recover from | ||
| 290 | * hardware reset | ||
| 291 | */ | ||
| 292 | low_sleep_handler(); | ||
| 293 | |||
| 294 | /* Restore the northbridge */ | ||
| 295 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); | ||
| 296 | |||
| 297 | /* Restore L2 cache */ | ||
| 298 | if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) | ||
| 299 | _set_L2CR(save_l2cr); | ||
| 300 | /* Restore L3 cache */ | ||
| 301 | if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) | ||
| 302 | _set_L3CR(save_l3cr); | ||
| 303 | |||
| 304 | /* Restore userland MMU context */ | ||
| 305 | switch_mmu_context(NULL, current->active_mm); | ||
| 306 | |||
| 307 | #ifdef DEBUG_FREQ | ||
| 308 | printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); | ||
| 309 | #endif | ||
| 310 | |||
| 311 | /* Restore low level PMU operations */ | ||
| 312 | pmu_unlock(); | ||
| 313 | |||
| 314 | /* | ||
| 315 | * Restore decrementer; we'll take a decrementer interrupt | ||
| 316 | * as soon as interrupts are re-enabled and the generic | ||
| 317 | * clockevents code will reprogram it with the right value. | ||
| 318 | */ | ||
| 319 | set_dec(1); | ||
| 320 | |||
| 321 | /* Restore interrupts */ | ||
| 322 | mpic_cpu_set_priority(pic_prio); | ||
| 323 | |||
| 324 | /* Let interrupts flow again ... */ | ||
| 325 | local_irq_restore(flags); | ||
| 326 | |||
| 327 | #ifdef DEBUG_FREQ | ||
| 328 | debug_calc_bogomips(); | ||
| 329 | #endif | ||
| 330 | |||
| 331 | pmu_resume(); | ||
| 332 | |||
| 333 | preempt_enable(); | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode, | ||
| 339 | int notify) | ||
| 340 | { | ||
| 341 | struct cpufreq_freqs freqs; | ||
| 342 | unsigned long l3cr; | ||
| 343 | static unsigned long prev_l3cr; | ||
| 344 | |||
| 345 | freqs.old = cur_freq; | ||
| 346 | freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; | ||
| 347 | |||
| 348 | if (freqs.old == freqs.new) | ||
| 349 | return 0; | ||
| 350 | |||
| 351 | if (notify) | ||
| 352 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | ||
| 353 | if (speed_mode == CPUFREQ_LOW && | ||
| 354 | cpu_has_feature(CPU_FTR_L3CR)) { | ||
| 355 | l3cr = _get_L3CR(); | ||
| 356 | if (l3cr & L3CR_L3E) { | ||
| 357 | prev_l3cr = l3cr; | ||
| 358 | _set_L3CR(0); | ||
| 359 | } | ||
| 360 | } | ||
| 361 | set_speed_proc(speed_mode == CPUFREQ_LOW); | ||
| 362 | if (speed_mode == CPUFREQ_HIGH && | ||
| 363 | cpu_has_feature(CPU_FTR_L3CR)) { | ||
| 364 | l3cr = _get_L3CR(); | ||
| 365 | if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) | ||
| 366 | _set_L3CR(prev_l3cr); | ||
| 367 | } | ||
| 368 | if (notify) | ||
| 369 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | ||
| 370 | cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; | ||
| 371 | |||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) | ||
| 376 | { | ||
| 377 | return cur_freq; | ||
| 378 | } | ||
| 379 | |||
| 380 | static int pmac_cpufreq_verify(struct cpufreq_policy *policy) | ||
| 381 | { | ||
| 382 | return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); | ||
| 383 | } | ||
| 384 | |||
| 385 | static int pmac_cpufreq_target( struct cpufreq_policy *policy, | ||
| 386 | unsigned int target_freq, | ||
| 387 | unsigned int relation) | ||
| 388 | { | ||
| 389 | unsigned int newstate = 0; | ||
| 390 | int rc; | ||
| 391 | |||
| 392 | if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, | ||
| 393 | target_freq, relation, &newstate)) | ||
| 394 | return -EINVAL; | ||
| 395 | |||
| 396 | rc = do_set_cpu_speed(policy, newstate, 1); | ||
| 397 | |||
| 398 | ppc_proc_freq = cur_freq * 1000ul; | ||
| 399 | return rc; | ||
| 400 | } | ||
| 401 | |||
| 402 | static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
| 403 | { | ||
| 404 | if (policy->cpu != 0) | ||
| 405 | return -ENODEV; | ||
| 406 | |||
| 407 | policy->cpuinfo.transition_latency = transition_latency; | ||
| 408 | policy->cur = cur_freq; | ||
| 409 | |||
| 410 | cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); | ||
| 411 | return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); | ||
| 412 | } | ||
| 413 | |||
| 414 | static u32 read_gpio(struct device_node *np) | ||
| 415 | { | ||
| 416 | const u32 *reg = of_get_property(np, "reg", NULL); | ||
| 417 | u32 offset; | ||
| 418 | |||
| 419 | if (reg == NULL) | ||
| 420 | return 0; | ||
| 421 | /* That works for all keylargos but shall be fixed properly | ||
| 422 | * some day... The problem is that it seems we can't rely | ||
| 423 | * on the "reg" property of the GPIO nodes, they are either | ||
| 424 | * relative to the base of KeyLargo or to the base of the | ||
| 425 | * GPIO space, and the device-tree doesn't help. | ||
| 426 | */ | ||
| 427 | offset = *reg; | ||
| 428 | if (offset < KEYLARGO_GPIO_LEVELS0) | ||
| 429 | offset += KEYLARGO_GPIO_LEVELS0; | ||
| 430 | return offset; | ||
| 431 | } | ||
| 432 | |||
| 433 | static int pmac_cpufreq_suspend(struct cpufreq_policy *policy) | ||
| 434 | { | ||
| 435 | /* Ok, this could be made a bit smarter, but let's be robust for now. We | ||
| 436 | * always force a speed change to high speed before sleep, to make sure | ||
| 437 | * we have appropriate voltage and/or bus speed for the wakeup process, | ||
| 438 | * and to make sure our loops_per_jiffies are "good enough", that is will | ||
| 439 | * not cause too short delays if we sleep in low speed and wake in high | ||
| 440 | * speed.. | ||
| 441 | */ | ||
| 442 | no_schedule = 1; | ||
| 443 | sleep_freq = cur_freq; | ||
| 444 | if (cur_freq == low_freq && !is_pmu_based) | ||
| 445 | do_set_cpu_speed(policy, CPUFREQ_HIGH, 0); | ||
| 446 | return 0; | ||
| 447 | } | ||
| 448 | |||
| 449 | static int pmac_cpufreq_resume(struct cpufreq_policy *policy) | ||
| 450 | { | ||
| 451 | /* If we resume, first check if we have a get() function */ | ||
| 452 | if (get_speed_proc) | ||
| 453 | cur_freq = get_speed_proc(); | ||
| 454 | else | ||
| 455 | cur_freq = 0; | ||
| 456 | |||
| 457 | /* We don't, hrm... we don't really know our speed here, best | ||
| 458 | * is that we force a switch to whatever it was, which is | ||
| 459 | * probably high speed due to our suspend() routine | ||
| 460 | */ | ||
| 461 | do_set_cpu_speed(policy, sleep_freq == low_freq ? | ||
| 462 | CPUFREQ_LOW : CPUFREQ_HIGH, 0); | ||
| 463 | |||
| 464 | ppc_proc_freq = cur_freq * 1000ul; | ||
| 465 | |||
| 466 | no_schedule = 0; | ||
| 467 | return 0; | ||
| 468 | } | ||
| 469 | |||
| 470 | static struct cpufreq_driver pmac_cpufreq_driver = { | ||
| 471 | .verify = pmac_cpufreq_verify, | ||
| 472 | .target = pmac_cpufreq_target, | ||
| 473 | .get = pmac_cpufreq_get_speed, | ||
| 474 | .init = pmac_cpufreq_cpu_init, | ||
| 475 | .suspend = pmac_cpufreq_suspend, | ||
| 476 | .resume = pmac_cpufreq_resume, | ||
| 477 | .flags = CPUFREQ_PM_NO_WARN, | ||
| 478 | .attr = pmac_cpu_freqs_attr, | ||
| 479 | .name = "powermac", | ||
| 480 | .owner = THIS_MODULE, | ||
| 481 | }; | ||
| 482 | |||
| 483 | |||
| 484 | static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) | ||
| 485 | { | ||
| 486 | struct device_node *volt_gpio_np = of_find_node_by_name(NULL, | ||
| 487 | "voltage-gpio"); | ||
| 488 | struct device_node *freq_gpio_np = of_find_node_by_name(NULL, | ||
| 489 | "frequency-gpio"); | ||
| 490 | struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, | ||
| 491 | "slewing-done"); | ||
| 492 | const u32 *value; | ||
| 493 | |||
| 494 | /* | ||
| 495 | * Check to see if it's GPIO driven or PMU only | ||
| 496 | * | ||
| 497 | * The way we extract the GPIO address is slightly hackish, but it | ||
| 498 | * works well enough for now. We need to abstract the whole GPIO | ||
| 499 | * stuff sooner or later anyway | ||
| 500 | */ | ||
| 501 | |||
| 502 | if (volt_gpio_np) | ||
| 503 | voltage_gpio = read_gpio(volt_gpio_np); | ||
| 504 | if (freq_gpio_np) | ||
| 505 | frequency_gpio = read_gpio(freq_gpio_np); | ||
| 506 | if (slew_done_gpio_np) | ||
| 507 | slew_done_gpio = read_gpio(slew_done_gpio_np); | ||
| 508 | |||
| 509 | /* If we use the frequency GPIOs, calculate the min/max speeds based | ||
| 510 | * on the bus frequencies | ||
| 511 | */ | ||
| 512 | if (frequency_gpio && slew_done_gpio) { | ||
| 513 | int lenp, rc; | ||
| 514 | const u32 *freqs, *ratio; | ||
| 515 | |||
| 516 | freqs = of_get_property(cpunode, "bus-frequencies", &lenp); | ||
| 517 | lenp /= sizeof(u32); | ||
| 518 | if (freqs == NULL || lenp != 2) { | ||
| 519 | printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); | ||
| 520 | return 1; | ||
| 521 | } | ||
| 522 | ratio = of_get_property(cpunode, "processor-to-bus-ratio*2", | ||
| 523 | NULL); | ||
| 524 | if (ratio == NULL) { | ||
| 525 | printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); | ||
| 526 | return 1; | ||
| 527 | } | ||
| 528 | |||
| 529 | /* Get the min/max bus frequencies */ | ||
| 530 | low_freq = min(freqs[0], freqs[1]); | ||
| 531 | hi_freq = max(freqs[0], freqs[1]); | ||
| 532 | |||
| 533 | /* Grrrr.. It _seems_ that the device-tree is lying on the low bus | ||
| 534 | * frequency, it claims it to be around 84Mhz on some models while | ||
| 535 | * it appears to be approx. 101Mhz on all. Let's hack around here... | ||
| 536 | * fortunately, we don't need to be too precise | ||
| 537 | */ | ||
| 538 | if (low_freq < 98000000) | ||
| 539 | low_freq = 101000000; | ||
| 540 | |||
| 541 | /* Convert those to CPU core clocks */ | ||
| 542 | low_freq = (low_freq * (*ratio)) / 2000; | ||
| 543 | hi_freq = (hi_freq * (*ratio)) / 2000; | ||
| 544 | |||
| 545 | /* Now we get the frequencies, we read the GPIO to see what is out current | ||
| 546 | * speed | ||
| 547 | */ | ||
| 548 | rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); | ||
| 549 | cur_freq = (rc & 0x01) ? hi_freq : low_freq; | ||
| 550 | |||
| 551 | set_speed_proc = gpios_set_cpu_speed; | ||
| 552 | return 1; | ||
| 553 | } | ||
| 554 | |||
| 555 | /* If we use the PMU, look for the min & max frequencies in the | ||
| 556 | * device-tree | ||
| 557 | */ | ||
| 558 | value = of_get_property(cpunode, "min-clock-frequency", NULL); | ||
| 559 | if (!value) | ||
| 560 | return 1; | ||
| 561 | low_freq = (*value) / 1000; | ||
| 562 | /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree | ||
| 563 | * here */ | ||
| 564 | if (low_freq < 100000) | ||
| 565 | low_freq *= 10; | ||
| 566 | |||
| 567 | value = of_get_property(cpunode, "max-clock-frequency", NULL); | ||
| 568 | if (!value) | ||
| 569 | return 1; | ||
| 570 | hi_freq = (*value) / 1000; | ||
| 571 | set_speed_proc = pmu_set_cpu_speed; | ||
| 572 | is_pmu_based = 1; | ||
| 573 | |||
| 574 | return 0; | ||
| 575 | } | ||
| 576 | |||
| 577 | static int pmac_cpufreq_init_7447A(struct device_node *cpunode) | ||
| 578 | { | ||
| 579 | struct device_node *volt_gpio_np; | ||
| 580 | |||
| 581 | if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL) | ||
| 582 | return 1; | ||
| 583 | |||
| 584 | volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); | ||
| 585 | if (volt_gpio_np) | ||
| 586 | voltage_gpio = read_gpio(volt_gpio_np); | ||
| 587 | if (!voltage_gpio){ | ||
| 588 | printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); | ||
| 589 | return 1; | ||
| 590 | } | ||
| 591 | |||
| 592 | /* OF only reports the high frequency */ | ||
| 593 | hi_freq = cur_freq; | ||
| 594 | low_freq = cur_freq/2; | ||
| 595 | |||
| 596 | /* Read actual frequency from CPU */ | ||
| 597 | cur_freq = dfs_get_cpu_speed(); | ||
| 598 | set_speed_proc = dfs_set_cpu_speed; | ||
| 599 | get_speed_proc = dfs_get_cpu_speed; | ||
| 600 | |||
| 601 | return 0; | ||
| 602 | } | ||
| 603 | |||
| 604 | static int pmac_cpufreq_init_750FX(struct device_node *cpunode) | ||
| 605 | { | ||
| 606 | struct device_node *volt_gpio_np; | ||
| 607 | u32 pvr; | ||
| 608 | const u32 *value; | ||
| 609 | |||
| 610 | if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL) | ||
| 611 | return 1; | ||
| 612 | |||
| 613 | hi_freq = cur_freq; | ||
| 614 | value = of_get_property(cpunode, "reduced-clock-frequency", NULL); | ||
| 615 | if (!value) | ||
| 616 | return 1; | ||
| 617 | low_freq = (*value) / 1000; | ||
| 618 | |||
| 619 | volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); | ||
| 620 | if (volt_gpio_np) | ||
| 621 | voltage_gpio = read_gpio(volt_gpio_np); | ||
| 622 | |||
| 623 | pvr = mfspr(SPRN_PVR); | ||
| 624 | has_cpu_l2lve = !((pvr & 0xf00) == 0x100); | ||
| 625 | |||
| 626 | set_speed_proc = cpu_750fx_cpu_speed; | ||
| 627 | get_speed_proc = cpu_750fx_get_cpu_speed; | ||
| 628 | cur_freq = cpu_750fx_get_cpu_speed(); | ||
| 629 | |||
| 630 | return 0; | ||
| 631 | } | ||
| 632 | |||
| 633 | /* Currently, we support the following machines: | ||
| 634 | * | ||
| 635 | * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) | ||
| 636 | * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) | ||
| 637 | * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) | ||
| 638 | * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) | ||
| 639 | * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) | ||
| 640 | * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) | ||
| 641 | * - Recent MacRISC3 laptops | ||
| 642 | * - All new machines with 7447A CPUs | ||
| 643 | */ | ||
| 644 | static int __init pmac_cpufreq_setup(void) | ||
| 645 | { | ||
| 646 | struct device_node *cpunode; | ||
| 647 | const u32 *value; | ||
| 648 | |||
| 649 | if (strstr(cmd_line, "nocpufreq")) | ||
| 650 | return 0; | ||
| 651 | |||
| 652 | /* Assume only one CPU */ | ||
| 653 | cpunode = of_find_node_by_type(NULL, "cpu"); | ||
| 654 | if (!cpunode) | ||
| 655 | goto out; | ||
| 656 | |||
| 657 | /* Get current cpu clock freq */ | ||
| 658 | value = of_get_property(cpunode, "clock-frequency", NULL); | ||
| 659 | if (!value) | ||
| 660 | goto out; | ||
| 661 | cur_freq = (*value) / 1000; | ||
| 662 | transition_latency = CPUFREQ_ETERNAL; | ||
| 663 | |||
| 664 | /* Check for 7447A based MacRISC3 */ | ||
| 665 | if (of_machine_is_compatible("MacRISC3") && | ||
| 666 | of_get_property(cpunode, "dynamic-power-step", NULL) && | ||
| 667 | PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { | ||
| 668 | pmac_cpufreq_init_7447A(cpunode); | ||
| 669 | transition_latency = 8000000; | ||
| 670 | /* Check for other MacRISC3 machines */ | ||
| 671 | } else if (of_machine_is_compatible("PowerBook3,4") || | ||
| 672 | of_machine_is_compatible("PowerBook3,5") || | ||
| 673 | of_machine_is_compatible("MacRISC3")) { | ||
| 674 | pmac_cpufreq_init_MacRISC3(cpunode); | ||
| 675 | /* Else check for iBook2 500/600 */ | ||
| 676 | } else if (of_machine_is_compatible("PowerBook4,1")) { | ||
| 677 | hi_freq = cur_freq; | ||
| 678 | low_freq = 400000; | ||
| 679 | set_speed_proc = pmu_set_cpu_speed; | ||
| 680 | is_pmu_based = 1; | ||
| 681 | } | ||
| 682 | /* Else check for TiPb 550 */ | ||
| 683 | else if (of_machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { | ||
| 684 | hi_freq = cur_freq; | ||
| 685 | low_freq = 500000; | ||
| 686 | set_speed_proc = pmu_set_cpu_speed; | ||
| 687 | is_pmu_based = 1; | ||
| 688 | } | ||
| 689 | /* Else check for TiPb 400 & 500 */ | ||
| 690 | else if (of_machine_is_compatible("PowerBook3,2")) { | ||
| 691 | /* We only know about the 400 MHz and the 500Mhz model | ||
| 692 | * they both have 300 MHz as low frequency | ||
| 693 | */ | ||
| 694 | if (cur_freq < 350000 || cur_freq > 550000) | ||
| 695 | goto out; | ||
| 696 | hi_freq = cur_freq; | ||
| 697 | low_freq = 300000; | ||
| 698 | set_speed_proc = pmu_set_cpu_speed; | ||
| 699 | is_pmu_based = 1; | ||
| 700 | } | ||
| 701 | /* Else check for 750FX */ | ||
| 702 | else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) | ||
| 703 | pmac_cpufreq_init_750FX(cpunode); | ||
| 704 | out: | ||
| 705 | of_node_put(cpunode); | ||
| 706 | if (set_speed_proc == NULL) | ||
| 707 | return -ENODEV; | ||
| 708 | |||
| 709 | pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; | ||
| 710 | pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; | ||
| 711 | ppc_proc_freq = cur_freq * 1000ul; | ||
| 712 | |||
| 713 | printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); | ||
| 714 | printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", | ||
| 715 | low_freq/1000, hi_freq/1000, cur_freq/1000); | ||
| 716 | |||
| 717 | return cpufreq_register_driver(&pmac_cpufreq_driver); | ||
| 718 | } | ||
| 719 | |||
| 720 | module_init(pmac_cpufreq_setup); | ||
| 721 | |||
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c deleted file mode 100644 index 7ba423431cfe..000000000000 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ /dev/null | |||
| @@ -1,746 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
| 3 | * and Markus Demleitner <msdemlei@cl.uni-heidelberg.de> | ||
| 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 driver adds basic cpufreq support for SMU & 970FX based G5 Macs, | ||
| 10 | * that is iMac G5 and latest single CPU desktop. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #undef DEBUG | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/types.h> | ||
| 17 | #include <linux/errno.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/delay.h> | ||
| 20 | #include <linux/sched.h> | ||
| 21 | #include <linux/cpufreq.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/completion.h> | ||
| 24 | #include <linux/mutex.h> | ||
| 25 | #include <asm/prom.h> | ||
| 26 | #include <asm/machdep.h> | ||
| 27 | #include <asm/irq.h> | ||
| 28 | #include <asm/sections.h> | ||
| 29 | #include <asm/cputable.h> | ||
| 30 | #include <asm/time.h> | ||
| 31 | #include <asm/smu.h> | ||
| 32 | #include <asm/pmac_pfunc.h> | ||
| 33 | |||
| 34 | #define DBG(fmt...) pr_debug(fmt) | ||
| 35 | |||
| 36 | /* see 970FX user manual */ | ||
| 37 | |||
| 38 | #define SCOM_PCR 0x0aa001 /* PCR scom addr */ | ||
| 39 | |||
| 40 | #define PCR_HILO_SELECT 0x80000000U /* 1 = PCR, 0 = PCRH */ | ||
| 41 | #define PCR_SPEED_FULL 0x00000000U /* 1:1 speed value */ | ||
| 42 | #define PCR_SPEED_HALF 0x00020000U /* 1:2 speed value */ | ||
| 43 | #define PCR_SPEED_QUARTER 0x00040000U /* 1:4 speed value */ | ||
| 44 | #define PCR_SPEED_MASK 0x000e0000U /* speed mask */ | ||
| 45 | #define PCR_SPEED_SHIFT 17 | ||
| 46 | #define PCR_FREQ_REQ_VALID 0x00010000U /* freq request valid */ | ||
| 47 | #define PCR_VOLT_REQ_VALID 0x00008000U /* volt request valid */ | ||
| 48 | #define PCR_TARGET_TIME_MASK 0x00006000U /* target time */ | ||
| 49 | #define PCR_STATLAT_MASK 0x00001f00U /* STATLAT value */ | ||
| 50 | #define PCR_SNOOPLAT_MASK 0x000000f0U /* SNOOPLAT value */ | ||
| 51 | #define PCR_SNOOPACC_MASK 0x0000000fU /* SNOOPACC value */ | ||
| 52 | |||
| 53 | #define SCOM_PSR 0x408001 /* PSR scom addr */ | ||
| 54 | /* warning: PSR is a 64 bits register */ | ||
| 55 | #define PSR_CMD_RECEIVED 0x2000000000000000U /* command received */ | ||
| 56 | #define PSR_CMD_COMPLETED 0x1000000000000000U /* command completed */ | ||
| 57 | #define PSR_CUR_SPEED_MASK 0x0300000000000000U /* current speed */ | ||
| 58 | #define PSR_CUR_SPEED_SHIFT (56) | ||
| 59 | |||
| 60 | /* | ||
| 61 | * The G5 only supports two frequencies (Quarter speed is not supported) | ||
| 62 | */ | ||
| 63 | #define CPUFREQ_HIGH 0 | ||
| 64 | #define CPUFREQ_LOW 1 | ||
| 65 | |||
| 66 | static struct cpufreq_frequency_table g5_cpu_freqs[] = { | ||
| 67 | {CPUFREQ_HIGH, 0}, | ||
| 68 | {CPUFREQ_LOW, 0}, | ||
| 69 | {0, CPUFREQ_TABLE_END}, | ||
| 70 | }; | ||
| 71 | |||
| 72 | static struct freq_attr* g5_cpu_freqs_attr[] = { | ||
| 73 | &cpufreq_freq_attr_scaling_available_freqs, | ||
| 74 | NULL, | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* Power mode data is an array of the 32 bits PCR values to use for | ||
| 78 | * the various frequencies, retrieved from the device-tree | ||
| 79 | */ | ||
| 80 | static int g5_pmode_cur; | ||
| 81 | |||
| 82 | static void (*g5_switch_volt)(int speed_mode); | ||
| 83 | static int (*g5_switch_freq)(int speed_mode); | ||
| 84 | static int (*g5_query_freq)(void); | ||
| 85 | |||
| 86 | static DEFINE_MUTEX(g5_switch_mutex); | ||
| 87 | |||
| 88 | static unsigned long transition_latency; | ||
| 89 | |||
| 90 | #ifdef CONFIG_PMAC_SMU | ||
| 91 | |||
| 92 | static const u32 *g5_pmode_data; | ||
| 93 | static int g5_pmode_max; | ||
| 94 | |||
| 95 | static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ | ||
| 96 | static int g5_fvt_count; /* number of op. points */ | ||
| 97 | static int g5_fvt_cur; /* current op. point */ | ||
| 98 | |||
| 99 | /* | ||
| 100 | * SMU based voltage switching for Neo2 platforms | ||
| 101 | */ | ||
| 102 | |||
| 103 | static void g5_smu_switch_volt(int speed_mode) | ||
| 104 | { | ||
| 105 | struct smu_simple_cmd cmd; | ||
| 106 | |||
| 107 | DECLARE_COMPLETION_ONSTACK(comp); | ||
| 108 | smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, smu_done_complete, | ||
| 109 | &comp, 'V', 'S', 'L', 'E', 'W', | ||
| 110 | 0xff, g5_fvt_cur+1, speed_mode); | ||
| 111 | wait_for_completion(&comp); | ||
| 112 | } | ||
| 113 | |||
| 114 | /* | ||
| 115 | * Platform function based voltage/vdnap switching for Neo2 | ||
| 116 | */ | ||
| 117 | |||
| 118 | static struct pmf_function *pfunc_set_vdnap0; | ||
| 119 | static struct pmf_function *pfunc_vdnap0_complete; | ||
| 120 | |||
| 121 | static void g5_vdnap_switch_volt(int speed_mode) | ||
| 122 | { | ||
| 123 | struct pmf_args args; | ||
| 124 | u32 slew, done = 0; | ||
| 125 | unsigned long timeout; | ||
| 126 | |||
| 127 | slew = (speed_mode == CPUFREQ_LOW) ? 1 : 0; | ||
| 128 | args.count = 1; | ||
| 129 | args.u[0].p = &slew; | ||
| 130 | |||
| 131 | pmf_call_one(pfunc_set_vdnap0, &args); | ||
| 132 | |||
| 133 | /* It's an irq GPIO so we should be able to just block here, | ||
| 134 | * I'll do that later after I've properly tested the IRQ code for | ||
| 135 | * platform functions | ||
| 136 | */ | ||
| 137 | timeout = jiffies + HZ/10; | ||
| 138 | while(!time_after(jiffies, timeout)) { | ||
| 139 | args.count = 1; | ||
| 140 | args.u[0].p = &done; | ||
| 141 | pmf_call_one(pfunc_vdnap0_complete, &args); | ||
| 142 | if (done) | ||
| 143 | break; | ||
| 144 | msleep(1); | ||
| 145 | } | ||
| 146 | if (done == 0) | ||
| 147 | printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n"); | ||
| 148 | } | ||
| 149 | |||
| 150 | |||
| 151 | /* | ||
| 152 | * SCOM based frequency switching for 970FX rev3 | ||
| 153 | */ | ||
| 154 | static int g5_scom_switch_freq(int speed_mode) | ||
| 155 | { | ||
| 156 | unsigned long flags; | ||
| 157 | int to; | ||
| 158 | |||
| 159 | /* If frequency is going up, first ramp up the voltage */ | ||
| 160 | if (speed_mode < g5_pmode_cur) | ||
| 161 | g5_switch_volt(speed_mode); | ||
| 162 | |||
| 163 | local_irq_save(flags); | ||
| 164 | |||
| 165 | /* Clear PCR high */ | ||
| 166 | scom970_write(SCOM_PCR, 0); | ||
| 167 | /* Clear PCR low */ | ||
| 168 | scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0); | ||
| 169 | /* Set PCR low */ | ||
| 170 | scom970_write(SCOM_PCR, PCR_HILO_SELECT | | ||
| 171 | g5_pmode_data[speed_mode]); | ||
| 172 | |||
| 173 | /* Wait for completion */ | ||
| 174 | for (to = 0; to < 10; to++) { | ||
| 175 | unsigned long psr = scom970_read(SCOM_PSR); | ||
| 176 | |||
| 177 | if ((psr & PSR_CMD_RECEIVED) == 0 && | ||
| 178 | (((psr >> PSR_CUR_SPEED_SHIFT) ^ | ||
| 179 | (g5_pmode_data[speed_mode] >> PCR_SPEED_SHIFT)) & 0x3) | ||
| 180 | == 0) | ||
| 181 | break; | ||
| 182 | if (psr & PSR_CMD_COMPLETED) | ||
| 183 | break; | ||
| 184 | udelay(100); | ||
| 185 | } | ||
| 186 | |||
| 187 | local_irq_restore(flags); | ||
| 188 | |||
| 189 | /* If frequency is going down, last ramp the voltage */ | ||
| 190 | if (speed_mode > g5_pmode_cur) | ||
| 191 | g5_switch_volt(speed_mode); | ||
| 192 | |||
| 193 | g5_pmode_cur = speed_mode; | ||
| 194 | ppc_proc_freq = g5_cpu_freqs[speed_mode].frequency * 1000ul; | ||
| 195 | |||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int g5_scom_query_freq(void) | ||
| 200 | { | ||
| 201 | unsigned long psr = scom970_read(SCOM_PSR); | ||
| 202 | int i; | ||
| 203 | |||
| 204 | for (i = 0; i <= g5_pmode_max; i++) | ||
| 205 | if ((((psr >> PSR_CUR_SPEED_SHIFT) ^ | ||
| 206 | (g5_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0) | ||
| 207 | break; | ||
| 208 | return i; | ||
| 209 | } | ||
| 210 | |||
| 211 | /* | ||
| 212 | * Fake voltage switching for platforms with missing support | ||
| 213 | */ | ||
| 214 | |||
| 215 | static void g5_dummy_switch_volt(int speed_mode) | ||
| 216 | { | ||
| 217 | } | ||
| 218 | |||
| 219 | #endif /* CONFIG_PMAC_SMU */ | ||
| 220 | |||
| 221 | /* | ||
| 222 | * Platform function based voltage switching for PowerMac7,2 & 7,3 | ||
| 223 | */ | ||
| 224 | |||
| 225 | static struct pmf_function *pfunc_cpu0_volt_high; | ||
| 226 | static struct pmf_function *pfunc_cpu0_volt_low; | ||
| 227 | static struct pmf_function *pfunc_cpu1_volt_high; | ||
| 228 | static struct pmf_function *pfunc_cpu1_volt_low; | ||
| 229 | |||
| 230 | static void g5_pfunc_switch_volt(int speed_mode) | ||
| 231 | { | ||
| 232 | if (speed_mode == CPUFREQ_HIGH) { | ||
| 233 | if (pfunc_cpu0_volt_high) | ||
| 234 | pmf_call_one(pfunc_cpu0_volt_high, NULL); | ||
| 235 | if (pfunc_cpu1_volt_high) | ||
| 236 | pmf_call_one(pfunc_cpu1_volt_high, NULL); | ||
| 237 | } else { | ||
| 238 | if (pfunc_cpu0_volt_low) | ||
| 239 | pmf_call_one(pfunc_cpu0_volt_low, NULL); | ||
| 240 | if (pfunc_cpu1_volt_low) | ||
| 241 | pmf_call_one(pfunc_cpu1_volt_low, NULL); | ||
| 242 | } | ||
| 243 | msleep(10); /* should be faster , to fix */ | ||
| 244 | } | ||
| 245 | |||
| 246 | /* | ||
| 247 | * Platform function based frequency switching for PowerMac7,2 & 7,3 | ||
| 248 | */ | ||
| 249 | |||
| 250 | static struct pmf_function *pfunc_cpu_setfreq_high; | ||
| 251 | static struct pmf_function *pfunc_cpu_setfreq_low; | ||
| 252 | static struct pmf_function *pfunc_cpu_getfreq; | ||
| 253 | static struct pmf_function *pfunc_slewing_done; | ||
| 254 | |||
| 255 | static int g5_pfunc_switch_freq(int speed_mode) | ||
| 256 | { | ||
| 257 | struct pmf_args args; | ||
| 258 | u32 done = 0; | ||
| 259 | unsigned long timeout; | ||
| 260 | int rc; | ||
| 261 | |||
| 262 | DBG("g5_pfunc_switch_freq(%d)\n", speed_mode); | ||
| 263 | |||
| 264 | /* If frequency is going up, first ramp up the voltage */ | ||
| 265 | if (speed_mode < g5_pmode_cur) | ||
| 266 | g5_switch_volt(speed_mode); | ||
| 267 | |||
| 268 | /* Do it */ | ||
| 269 | if (speed_mode == CPUFREQ_HIGH) | ||
| 270 | rc = pmf_call_one(pfunc_cpu_setfreq_high, NULL); | ||
| 271 | else | ||
| 272 | rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL); | ||
| 273 | |||
| 274 | if (rc) | ||
| 275 | printk(KERN_WARNING "cpufreq: pfunc switch error %d\n", rc); | ||
| 276 | |||
| 277 | /* It's an irq GPIO so we should be able to just block here, | ||
| 278 | * I'll do that later after I've properly tested the IRQ code for | ||
| 279 | * platform functions | ||
| 280 | */ | ||
| 281 | timeout = jiffies + HZ/10; | ||
| 282 | while(!time_after(jiffies, timeout)) { | ||
| 283 | args.count = 1; | ||
| 284 | args.u[0].p = &done; | ||
| 285 | pmf_call_one(pfunc_slewing_done, &args); | ||
| 286 | if (done) | ||
| 287 | break; | ||
| 288 | msleep(1); | ||
| 289 | } | ||
| 290 | if (done == 0) | ||
| 291 | printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n"); | ||
| 292 | |||
| 293 | /* If frequency is going down, last ramp the voltage */ | ||
| 294 | if (speed_mode > g5_pmode_cur) | ||
| 295 | g5_switch_volt(speed_mode); | ||
| 296 | |||
| 297 | g5_pmode_cur = speed_mode; | ||
| 298 | ppc_proc_freq = g5_cpu_freqs[speed_mode].frequency * 1000ul; | ||
| 299 | |||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int g5_pfunc_query_freq(void) | ||
| 304 | { | ||
| 305 | struct pmf_args args; | ||
| 306 | u32 val = 0; | ||
| 307 | |||
| 308 | args.count = 1; | ||
| 309 | args.u[0].p = &val; | ||
| 310 | pmf_call_one(pfunc_cpu_getfreq, &args); | ||
| 311 | return val ? CPUFREQ_HIGH : CPUFREQ_LOW; | ||
| 312 | } | ||
| 313 | |||
| 314 | |||
| 315 | /* | ||
| 316 | * Common interface to the cpufreq core | ||
| 317 | */ | ||
| 318 | |||
| 319 | static int g5_cpufreq_verify(struct cpufreq_policy *policy) | ||
| 320 | { | ||
| 321 | return cpufreq_frequency_table_verify(policy, g5_cpu_freqs); | ||
| 322 | } | ||
| 323 | |||
| 324 | static int g5_cpufreq_target(struct cpufreq_policy *policy, | ||
| 325 | unsigned int target_freq, unsigned int relation) | ||
| 326 | { | ||
| 327 | unsigned int newstate = 0; | ||
| 328 | struct cpufreq_freqs freqs; | ||
| 329 | int rc; | ||
| 330 | |||
| 331 | if (cpufreq_frequency_table_target(policy, g5_cpu_freqs, | ||
| 332 | target_freq, relation, &newstate)) | ||
| 333 | return -EINVAL; | ||
| 334 | |||
| 335 | if (g5_pmode_cur == newstate) | ||
| 336 | return 0; | ||
| 337 | |||
| 338 | mutex_lock(&g5_switch_mutex); | ||
| 339 | |||
| 340 | freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; | ||
| 341 | freqs.new = g5_cpu_freqs[newstate].frequency; | ||
| 342 | |||
| 343 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); | ||
| 344 | rc = g5_switch_freq(newstate); | ||
| 345 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); | ||
| 346 | |||
| 347 | mutex_unlock(&g5_switch_mutex); | ||
| 348 | |||
| 349 | return rc; | ||
| 350 | } | ||
| 351 | |||
| 352 | static unsigned int g5_cpufreq_get_speed(unsigned int cpu) | ||
| 353 | { | ||
| 354 | return g5_cpu_freqs[g5_pmode_cur].frequency; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
| 358 | { | ||
| 359 | policy->cpuinfo.transition_latency = transition_latency; | ||
| 360 | policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; | ||
| 361 | /* secondary CPUs are tied to the primary one by the | ||
| 362 | * cpufreq core if in the secondary policy we tell it that | ||
| 363 | * it actually must be one policy together with all others. */ | ||
| 364 | cpumask_copy(policy->cpus, cpu_online_mask); | ||
| 365 | cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); | ||
| 366 | |||
| 367 | return cpufreq_frequency_table_cpuinfo(policy, | ||
| 368 | g5_cpu_freqs); | ||
| 369 | } | ||
| 370 | |||
| 371 | |||
| 372 | static struct cpufreq_driver g5_cpufreq_driver = { | ||
| 373 | .name = "powermac", | ||
| 374 | .owner = THIS_MODULE, | ||
| 375 | .flags = CPUFREQ_CONST_LOOPS, | ||
| 376 | .init = g5_cpufreq_cpu_init, | ||
| 377 | .verify = g5_cpufreq_verify, | ||
| 378 | .target = g5_cpufreq_target, | ||
| 379 | .get = g5_cpufreq_get_speed, | ||
| 380 | .attr = g5_cpu_freqs_attr, | ||
| 381 | }; | ||
| 382 | |||
| 383 | |||
| 384 | #ifdef CONFIG_PMAC_SMU | ||
| 385 | |||
| 386 | static int __init g5_neo2_cpufreq_init(struct device_node *cpus) | ||
| 387 | { | ||
| 388 | struct device_node *cpunode; | ||
| 389 | unsigned int psize, ssize; | ||
| 390 | unsigned long max_freq; | ||
| 391 | char *freq_method, *volt_method; | ||
| 392 | const u32 *valp; | ||
| 393 | u32 pvr_hi; | ||
| 394 | int use_volts_vdnap = 0; | ||
| 395 | int use_volts_smu = 0; | ||
| 396 | int rc = -ENODEV; | ||
| 397 | |||
| 398 | /* Check supported platforms */ | ||
| 399 | if (of_machine_is_compatible("PowerMac8,1") || | ||
| 400 | of_machine_is_compatible("PowerMac8,2") || | ||
| 401 | of_machine_is_compatible("PowerMac9,1")) | ||
| 402 | use_volts_smu = 1; | ||
| 403 | else if (of_machine_is_compatible("PowerMac11,2")) | ||
| 404 | use_volts_vdnap = 1; | ||
| 405 | else | ||
| 406 | return -ENODEV; | ||
| 407 | |||
| 408 | /* Get first CPU node */ | ||
| 409 | for (cpunode = NULL; | ||
| 410 | (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) { | ||
| 411 | const u32 *reg = of_get_property(cpunode, "reg", NULL); | ||
| 412 | if (reg == NULL || (*reg) != 0) | ||
| 413 | continue; | ||
| 414 | if (!strcmp(cpunode->type, "cpu")) | ||
| 415 | break; | ||
| 416 | } | ||
| 417 | if (cpunode == NULL) { | ||
| 418 | printk(KERN_ERR "cpufreq: Can't find any CPU 0 node\n"); | ||
| 419 | return -ENODEV; | ||
| 420 | } | ||
| 421 | |||
| 422 | /* Check 970FX for now */ | ||
| 423 | valp = of_get_property(cpunode, "cpu-version", NULL); | ||
| 424 | if (!valp) { | ||
| 425 | DBG("No cpu-version property !\n"); | ||
| 426 | goto bail_noprops; | ||
| 427 | } | ||
| 428 | pvr_hi = (*valp) >> 16; | ||
| 429 | if (pvr_hi != 0x3c && pvr_hi != 0x44) { | ||
| 430 | printk(KERN_ERR "cpufreq: Unsupported CPU version\n"); | ||
| 431 | goto bail_noprops; | ||
| 432 | } | ||
| 433 | |||
| 434 | /* Look for the powertune data in the device-tree */ | ||
| 435 | g5_pmode_data = of_get_property(cpunode, "power-mode-data",&psize); | ||
| 436 | if (!g5_pmode_data) { | ||
| 437 | DBG("No power-mode-data !\n"); | ||
| 438 | goto bail_noprops; | ||
| 439 | } | ||
| 440 | g5_pmode_max = psize / sizeof(u32) - 1; | ||
| 441 | |||
| 442 | if (use_volts_smu) { | ||
| 443 | const struct smu_sdbp_header *shdr; | ||
| 444 | |||
| 445 | /* Look for the FVT table */ | ||
| 446 | shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); | ||
| 447 | if (!shdr) | ||
| 448 | goto bail_noprops; | ||
| 449 | g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1]; | ||
| 450 | ssize = (shdr->len * sizeof(u32)) - | ||
| 451 | sizeof(struct smu_sdbp_header); | ||
| 452 | g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt); | ||
| 453 | g5_fvt_cur = 0; | ||
| 454 | |||
| 455 | /* Sanity checking */ | ||
| 456 | if (g5_fvt_count < 1 || g5_pmode_max < 1) | ||
| 457 | goto bail_noprops; | ||
| 458 | |||
| 459 | g5_switch_volt = g5_smu_switch_volt; | ||
| 460 | volt_method = "SMU"; | ||
| 461 | } else if (use_volts_vdnap) { | ||
| 462 | struct device_node *root; | ||
| 463 | |||
| 464 | root = of_find_node_by_path("/"); | ||
| 465 | if (root == NULL) { | ||
| 466 | printk(KERN_ERR "cpufreq: Can't find root of " | ||
| 467 | "device tree\n"); | ||
| 468 | goto bail_noprops; | ||
| 469 | } | ||
| 470 | pfunc_set_vdnap0 = pmf_find_function(root, "set-vdnap0"); | ||
| 471 | pfunc_vdnap0_complete = | ||
| 472 | pmf_find_function(root, "slewing-done"); | ||
| 473 | if (pfunc_set_vdnap0 == NULL || | ||
| 474 | pfunc_vdnap0_complete == NULL) { | ||
| 475 | printk(KERN_ERR "cpufreq: Can't find required " | ||
| 476 | "platform function\n"); | ||
| 477 | goto bail_noprops; | ||
| 478 | } | ||
| 479 | |||
| 480 | g5_switch_volt = g5_vdnap_switch_volt; | ||
| 481 | volt_method = "GPIO"; | ||
| 482 | } else { | ||
| 483 | g5_switch_volt = g5_dummy_switch_volt; | ||
| 484 | volt_method = "none"; | ||
| 485 | } | ||
| 486 | |||
| 487 | /* | ||
| 488 | * From what I see, clock-frequency is always the maximal frequency. | ||
| 489 | * The current driver can not slew sysclk yet, so we really only deal | ||
| 490 | * with powertune steps for now. We also only implement full freq and | ||
| 491 | * half freq in this version. So far, I haven't yet seen a machine | ||
| 492 | * supporting anything else. | ||
| 493 | */ | ||
| 494 | valp = of_get_property(cpunode, "clock-frequency", NULL); | ||
| 495 | if (!valp) | ||
| 496 | return -ENODEV; | ||
| 497 | max_freq = (*valp)/1000; | ||
| 498 | g5_cpu_freqs[0].frequency = max_freq; | ||
| 499 | g5_cpu_freqs[1].frequency = max_freq/2; | ||
| 500 | |||
| 501 | /* Set callbacks */ | ||
| 502 | transition_latency = 12000; | ||
| 503 | g5_switch_freq = g5_scom_switch_freq; | ||
| 504 | g5_query_freq = g5_scom_query_freq; | ||
| 505 | freq_method = "SCOM"; | ||
| 506 | |||
| 507 | /* Force apply current frequency to make sure everything is in | ||
| 508 | * sync (voltage is right for example). Firmware may leave us with | ||
| 509 | * a strange setting ... | ||
| 510 | */ | ||
| 511 | g5_switch_volt(CPUFREQ_HIGH); | ||
| 512 | msleep(10); | ||
| 513 | g5_pmode_cur = -1; | ||
| 514 | g5_switch_freq(g5_query_freq()); | ||
| 515 | |||
| 516 | printk(KERN_INFO "Registering G5 CPU frequency driver\n"); | ||
| 517 | printk(KERN_INFO "Frequency method: %s, Voltage method: %s\n", | ||
| 518 | freq_method, volt_method); | ||
| 519 | printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", | ||
| 520 | g5_cpu_freqs[1].frequency/1000, | ||
| 521 | g5_cpu_freqs[0].frequency/1000, | ||
| 522 | g5_cpu_freqs[g5_pmode_cur].frequency/1000); | ||
| 523 | |||
| 524 | rc = cpufreq_register_driver(&g5_cpufreq_driver); | ||
| 525 | |||
| 526 | /* We keep the CPU node on hold... hopefully, Apple G5 don't have | ||
| 527 | * hotplug CPU with a dynamic device-tree ... | ||
| 528 | */ | ||
| 529 | return rc; | ||
| 530 | |||
| 531 | bail_noprops: | ||
| 532 | of_node_put(cpunode); | ||
| 533 | |||
| 534 | return rc; | ||
| 535 | } | ||
| 536 | |||
| 537 | #endif /* CONFIG_PMAC_SMU */ | ||
| 538 | |||
| 539 | |||
| 540 | static int __init g5_pm72_cpufreq_init(struct device_node *cpus) | ||
| 541 | { | ||
| 542 | struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL; | ||
| 543 | const u8 *eeprom = NULL; | ||
| 544 | const u32 *valp; | ||
| 545 | u64 max_freq, min_freq, ih, il; | ||
| 546 | int has_volt = 1, rc = 0; | ||
| 547 | |||
| 548 | DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and" | ||
| 549 | " RackMac3,1...\n"); | ||
| 550 | |||
| 551 | /* Get first CPU node */ | ||
| 552 | for (cpunode = NULL; | ||
| 553 | (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) { | ||
| 554 | if (!strcmp(cpunode->type, "cpu")) | ||
| 555 | break; | ||
| 556 | } | ||
| 557 | if (cpunode == NULL) { | ||
| 558 | printk(KERN_ERR "cpufreq: Can't find any CPU node\n"); | ||
| 559 | return -ENODEV; | ||
| 560 | } | ||
| 561 | |||
| 562 | /* Lookup the cpuid eeprom node */ | ||
| 563 | cpuid = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/cpuid@a0"); | ||
| 564 | if (cpuid != NULL) | ||
| 565 | eeprom = of_get_property(cpuid, "cpuid", NULL); | ||
| 566 | if (eeprom == NULL) { | ||
| 567 | printk(KERN_ERR "cpufreq: Can't find cpuid EEPROM !\n"); | ||
| 568 | rc = -ENODEV; | ||
| 569 | goto bail; | ||
| 570 | } | ||
| 571 | |||
| 572 | /* Lookup the i2c hwclock */ | ||
| 573 | for (hwclock = NULL; | ||
| 574 | (hwclock = of_find_node_by_name(hwclock, "i2c-hwclock")) != NULL;){ | ||
| 575 | const char *loc = of_get_property(hwclock, | ||
| 576 | "hwctrl-location", NULL); | ||
| 577 | if (loc == NULL) | ||
| 578 | continue; | ||
| 579 | if (strcmp(loc, "CPU CLOCK")) | ||
| 580 | continue; | ||
| 581 | if (!of_get_property(hwclock, "platform-get-frequency", NULL)) | ||
| 582 | continue; | ||
| 583 | break; | ||
| 584 | } | ||
| 585 | if (hwclock == NULL) { | ||
| 586 | printk(KERN_ERR "cpufreq: Can't find i2c clock chip !\n"); | ||
| 587 | rc = -ENODEV; | ||
| 588 | goto bail; | ||
| 589 | } | ||
| 590 | |||
| 591 | DBG("cpufreq: i2c clock chip found: %s\n", hwclock->full_name); | ||
| 592 | |||
| 593 | /* Now get all the platform functions */ | ||
| 594 | pfunc_cpu_getfreq = | ||
| 595 | pmf_find_function(hwclock, "get-frequency"); | ||
| 596 | pfunc_cpu_setfreq_high = | ||
| 597 | pmf_find_function(hwclock, "set-frequency-high"); | ||
| 598 | pfunc_cpu_setfreq_low = | ||
| 599 | pmf_find_function(hwclock, "set-frequency-low"); | ||
| 600 | pfunc_slewing_done = | ||
| 601 | pmf_find_function(hwclock, "slewing-done"); | ||
| 602 | pfunc_cpu0_volt_high = | ||
| 603 | pmf_find_function(hwclock, "set-voltage-high-0"); | ||
| 604 | pfunc_cpu0_volt_low = | ||
| 605 | pmf_find_function(hwclock, "set-voltage-low-0"); | ||
| 606 | pfunc_cpu1_volt_high = | ||
| 607 | pmf_find_function(hwclock, "set-voltage-high-1"); | ||
| 608 | pfunc_cpu1_volt_low = | ||
| 609 | pmf_find_function(hwclock, "set-voltage-low-1"); | ||
| 610 | |||
| 611 | /* Check we have minimum requirements */ | ||
| 612 | if (pfunc_cpu_getfreq == NULL || pfunc_cpu_setfreq_high == NULL || | ||
| 613 | pfunc_cpu_setfreq_low == NULL || pfunc_slewing_done == NULL) { | ||
| 614 | printk(KERN_ERR "cpufreq: Can't find platform functions !\n"); | ||
| 615 | rc = -ENODEV; | ||
| 616 | goto bail; | ||
| 617 | } | ||
| 618 | |||
| 619 | /* Check that we have complete sets */ | ||
| 620 | if (pfunc_cpu0_volt_high == NULL || pfunc_cpu0_volt_low == NULL) { | ||
| 621 | pmf_put_function(pfunc_cpu0_volt_high); | ||
| 622 | pmf_put_function(pfunc_cpu0_volt_low); | ||
| 623 | pfunc_cpu0_volt_high = pfunc_cpu0_volt_low = NULL; | ||
| 624 | has_volt = 0; | ||
| 625 | } | ||
| 626 | if (!has_volt || | ||
| 627 | pfunc_cpu1_volt_high == NULL || pfunc_cpu1_volt_low == NULL) { | ||
| 628 | pmf_put_function(pfunc_cpu1_volt_high); | ||
| 629 | pmf_put_function(pfunc_cpu1_volt_low); | ||
| 630 | pfunc_cpu1_volt_high = pfunc_cpu1_volt_low = NULL; | ||
| 631 | } | ||
| 632 | |||
| 633 | /* Note: The device tree also contains a "platform-set-values" | ||
| 634 | * function for which I haven't quite figured out the usage. It | ||
| 635 | * might have to be called on init and/or wakeup, I'm not too sure | ||
| 636 | * but things seem to work fine without it so far ... | ||
| 637 | */ | ||
| 638 | |||
| 639 | /* Get max frequency from device-tree */ | ||
| 640 | valp = of_get_property(cpunode, "clock-frequency", NULL); | ||
| 641 | if (!valp) { | ||
| 642 | printk(KERN_ERR "cpufreq: Can't find CPU frequency !\n"); | ||
| 643 | rc = -ENODEV; | ||
| 644 | goto bail; | ||
| 645 | } | ||
| 646 | |||
| 647 | max_freq = (*valp)/1000; | ||
| 648 | |||
| 649 | /* Now calculate reduced frequency by using the cpuid input freq | ||
| 650 | * ratio. This requires 64 bits math unless we are willing to lose | ||
| 651 | * some precision | ||
| 652 | */ | ||
| 653 | ih = *((u32 *)(eeprom + 0x10)); | ||
| 654 | il = *((u32 *)(eeprom + 0x20)); | ||
| 655 | |||
| 656 | /* Check for machines with no useful settings */ | ||
| 657 | if (il == ih) { | ||
| 658 | printk(KERN_WARNING "cpufreq: No low frequency mode available" | ||
| 659 | " on this model !\n"); | ||
| 660 | rc = -ENODEV; | ||
| 661 | goto bail; | ||
| 662 | } | ||
| 663 | |||
| 664 | min_freq = 0; | ||
| 665 | if (ih != 0 && il != 0) | ||
| 666 | min_freq = (max_freq * il) / ih; | ||
| 667 | |||
| 668 | /* Sanity check */ | ||
| 669 | if (min_freq >= max_freq || min_freq < 1000) { | ||
| 670 | printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n"); | ||
| 671 | rc = -ENXIO; | ||
| 672 | goto bail; | ||
| 673 | } | ||
| 674 | g5_cpu_freqs[0].frequency = max_freq; | ||
| 675 | g5_cpu_freqs[1].frequency = min_freq; | ||
| 676 | |||
| 677 | /* Set callbacks */ | ||
| 678 | transition_latency = CPUFREQ_ETERNAL; | ||
| 679 | g5_switch_volt = g5_pfunc_switch_volt; | ||
| 680 | g5_switch_freq = g5_pfunc_switch_freq; | ||
| 681 | g5_query_freq = g5_pfunc_query_freq; | ||
| 682 | |||
| 683 | /* Force apply current frequency to make sure everything is in | ||
| 684 | * sync (voltage is right for example). Firmware may leave us with | ||
| 685 | * a strange setting ... | ||
| 686 | */ | ||
| 687 | g5_switch_volt(CPUFREQ_HIGH); | ||
| 688 | msleep(10); | ||
| 689 | g5_pmode_cur = -1; | ||
| 690 | g5_switch_freq(g5_query_freq()); | ||
| 691 | |||
| 692 | printk(KERN_INFO "Registering G5 CPU frequency driver\n"); | ||
| 693 | printk(KERN_INFO "Frequency method: i2c/pfunc, " | ||
| 694 | "Voltage method: %s\n", has_volt ? "i2c/pfunc" : "none"); | ||
| 695 | printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", | ||
| 696 | g5_cpu_freqs[1].frequency/1000, | ||
| 697 | g5_cpu_freqs[0].frequency/1000, | ||
| 698 | g5_cpu_freqs[g5_pmode_cur].frequency/1000); | ||
| 699 | |||
| 700 | rc = cpufreq_register_driver(&g5_cpufreq_driver); | ||
| 701 | bail: | ||
| 702 | if (rc != 0) { | ||
| 703 | pmf_put_function(pfunc_cpu_getfreq); | ||
| 704 | pmf_put_function(pfunc_cpu_setfreq_high); | ||
| 705 | pmf_put_function(pfunc_cpu_setfreq_low); | ||
| 706 | pmf_put_function(pfunc_slewing_done); | ||
| 707 | pmf_put_function(pfunc_cpu0_volt_high); | ||
| 708 | pmf_put_function(pfunc_cpu0_volt_low); | ||
| 709 | pmf_put_function(pfunc_cpu1_volt_high); | ||
| 710 | pmf_put_function(pfunc_cpu1_volt_low); | ||
| 711 | } | ||
| 712 | of_node_put(hwclock); | ||
| 713 | of_node_put(cpuid); | ||
| 714 | of_node_put(cpunode); | ||
| 715 | |||
| 716 | return rc; | ||
| 717 | } | ||
| 718 | |||
| 719 | static int __init g5_cpufreq_init(void) | ||
| 720 | { | ||
| 721 | struct device_node *cpus; | ||
| 722 | int rc = 0; | ||
| 723 | |||
| 724 | cpus = of_find_node_by_path("/cpus"); | ||
| 725 | if (cpus == NULL) { | ||
| 726 | DBG("No /cpus node !\n"); | ||
| 727 | return -ENODEV; | ||
| 728 | } | ||
| 729 | |||
| 730 | if (of_machine_is_compatible("PowerMac7,2") || | ||
| 731 | of_machine_is_compatible("PowerMac7,3") || | ||
| 732 | of_machine_is_compatible("RackMac3,1")) | ||
| 733 | rc = g5_pm72_cpufreq_init(cpus); | ||
| 734 | #ifdef CONFIG_PMAC_SMU | ||
| 735 | else | ||
| 736 | rc = g5_neo2_cpufreq_init(cpus); | ||
| 737 | #endif /* CONFIG_PMAC_SMU */ | ||
| 738 | |||
| 739 | of_node_put(cpus); | ||
| 740 | return rc; | ||
| 741 | } | ||
| 742 | |||
| 743 | module_init(g5_cpufreq_init); | ||
| 744 | |||
| 745 | |||
| 746 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index 5a4c87903057..5ce3ba7ad137 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c | |||
| @@ -294,8 +294,6 @@ void __init eeh_addr_cache_build(void) | |||
| 294 | spin_lock_init(&pci_io_addr_cache_root.piar_lock); | 294 | spin_lock_init(&pci_io_addr_cache_root.piar_lock); |
| 295 | 295 | ||
| 296 | for_each_pci_dev(dev) { | 296 | for_each_pci_dev(dev) { |
| 297 | eeh_addr_cache_insert_dev(dev); | ||
| 298 | |||
| 299 | dn = pci_device_to_OF_node(dev); | 297 | dn = pci_device_to_OF_node(dev); |
| 300 | if (!dn) | 298 | if (!dn) |
| 301 | continue; | 299 | continue; |
| @@ -308,6 +306,8 @@ void __init eeh_addr_cache_build(void) | |||
| 308 | dev->dev.archdata.edev = edev; | 306 | dev->dev.archdata.edev = edev; |
| 309 | edev->pdev = dev; | 307 | edev->pdev = dev; |
| 310 | 308 | ||
| 309 | eeh_addr_cache_insert_dev(dev); | ||
| 310 | |||
| 311 | eeh_sysfs_add_device(dev); | 311 | eeh_sysfs_add_device(dev); |
| 312 | } | 312 | } |
| 313 | 313 | ||
diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c b/arch/powerpc/platforms/pseries/eeh_pe.c index fe43d1aa2cf1..9d4a9e8562b2 100644 --- a/arch/powerpc/platforms/pseries/eeh_pe.c +++ b/arch/powerpc/platforms/pseries/eeh_pe.c | |||
| @@ -639,7 +639,8 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) | |||
| 639 | 639 | ||
| 640 | if (pe->type & EEH_PE_PHB) { | 640 | if (pe->type & EEH_PE_PHB) { |
| 641 | bus = pe->phb->bus; | 641 | bus = pe->phb->bus; |
| 642 | } else if (pe->type & EEH_PE_BUS) { | 642 | } else if (pe->type & EEH_PE_BUS || |
| 643 | pe->type & EEH_PE_DEVICE) { | ||
| 643 | edev = list_first_entry(&pe->edevs, struct eeh_dev, list); | 644 | edev = list_first_entry(&pe->edevs, struct eeh_dev, list); |
| 644 | pdev = eeh_dev_to_pci_dev(edev); | 645 | pdev = eeh_dev_to_pci_dev(edev); |
| 645 | if (pdev) | 646 | if (pdev) |
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 028ac1f71b51..46ac1ddea683 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
| @@ -97,22 +97,14 @@ static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn, | |||
| 97 | return indirect_read_config(bus, devfn, offset, len, val); | 97 | return indirect_read_config(bus, devfn, offset, len, val); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | static struct pci_ops fsl_indirect_pci_ops = | 100 | #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) |
| 101 | |||
| 102 | static struct pci_ops fsl_indirect_pcie_ops = | ||
| 101 | { | 103 | { |
| 102 | .read = fsl_indirect_read_config, | 104 | .read = fsl_indirect_read_config, |
| 103 | .write = indirect_write_config, | 105 | .write = indirect_write_config, |
| 104 | }; | 106 | }; |
| 105 | 107 | ||
| 106 | static void __init fsl_setup_indirect_pci(struct pci_controller* hose, | ||
| 107 | resource_size_t cfg_addr, | ||
| 108 | resource_size_t cfg_data, u32 flags) | ||
| 109 | { | ||
| 110 | setup_indirect_pci(hose, cfg_addr, cfg_data, flags); | ||
| 111 | hose->ops = &fsl_indirect_pci_ops; | ||
| 112 | } | ||
| 113 | |||
| 114 | #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) | ||
| 115 | |||
| 116 | #define MAX_PHYS_ADDR_BITS 40 | 108 | #define MAX_PHYS_ADDR_BITS 40 |
| 117 | static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS; | 109 | static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS; |
| 118 | 110 | ||
| @@ -504,13 +496,15 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary) | |||
| 504 | if (!hose->private_data) | 496 | if (!hose->private_data) |
| 505 | goto no_bridge; | 497 | goto no_bridge; |
| 506 | 498 | ||
| 507 | fsl_setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4, | 499 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4, |
| 508 | PPC_INDIRECT_TYPE_BIG_ENDIAN); | 500 | PPC_INDIRECT_TYPE_BIG_ENDIAN); |
| 509 | 501 | ||
| 510 | if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0) | 502 | if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0) |
| 511 | hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK; | 503 | hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK; |
| 512 | 504 | ||
| 513 | if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { | 505 | if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { |
| 506 | /* use fsl_indirect_read_config for PCIe */ | ||
| 507 | hose->ops = &fsl_indirect_pcie_ops; | ||
| 514 | /* For PCIE read HEADER_TYPE to identify controler mode */ | 508 | /* For PCIE read HEADER_TYPE to identify controler mode */ |
| 515 | early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type); | 509 | early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type); |
| 516 | if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) | 510 | if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) |
| @@ -814,8 +808,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev) | |||
| 814 | if (ret) | 808 | if (ret) |
| 815 | goto err0; | 809 | goto err0; |
| 816 | } else { | 810 | } else { |
| 817 | fsl_setup_indirect_pci(hose, rsrc_cfg.start, | 811 | setup_indirect_pci(hose, rsrc_cfg.start, |
| 818 | rsrc_cfg.start + 4, 0); | 812 | rsrc_cfg.start + 4, 0); |
| 819 | } | 813 | } |
| 820 | 814 | ||
| 821 | printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " | 815 | printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " |
