diff options
-rw-r--r-- | arch/powerpc/platforms/powermac/feature.c | 11 | ||||
-rw-r--r-- | drivers/macintosh/smu.c | 25 | ||||
-rw-r--r-- | include/asm-powerpc/pmac_feature.h | 8 |
3 files changed, 42 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index ba931be2175c..5169ecc37123 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
@@ -2565,6 +2565,8 @@ static void __init probe_uninorth(void) | |||
2565 | 2565 | ||
2566 | /* Locate core99 Uni-N */ | 2566 | /* Locate core99 Uni-N */ |
2567 | uninorth_node = of_find_node_by_name(NULL, "uni-n"); | 2567 | uninorth_node = of_find_node_by_name(NULL, "uni-n"); |
2568 | uninorth_maj = 1; | ||
2569 | |||
2568 | /* Locate G5 u3 */ | 2570 | /* Locate G5 u3 */ |
2569 | if (uninorth_node == NULL) { | 2571 | if (uninorth_node == NULL) { |
2570 | uninorth_node = of_find_node_by_name(NULL, "u3"); | 2572 | uninorth_node = of_find_node_by_name(NULL, "u3"); |
@@ -2575,8 +2577,10 @@ static void __init probe_uninorth(void) | |||
2575 | uninorth_node = of_find_node_by_name(NULL, "u4"); | 2577 | uninorth_node = of_find_node_by_name(NULL, "u4"); |
2576 | uninorth_maj = 4; | 2578 | uninorth_maj = 4; |
2577 | } | 2579 | } |
2578 | if (uninorth_node == NULL) | 2580 | if (uninorth_node == NULL) { |
2581 | uninorth_maj = 0; | ||
2579 | return; | 2582 | return; |
2583 | } | ||
2580 | 2584 | ||
2581 | addrp = of_get_property(uninorth_node, "reg", NULL); | 2585 | addrp = of_get_property(uninorth_node, "reg", NULL); |
2582 | if (addrp == NULL) | 2586 | if (addrp == NULL) |
@@ -3029,3 +3033,8 @@ void pmac_resume_agp_for_card(struct pci_dev *dev) | |||
3029 | pmac_agp_resume(pmac_agp_bridge); | 3033 | pmac_agp_resume(pmac_agp_bridge); |
3030 | } | 3034 | } |
3031 | EXPORT_SYMBOL(pmac_resume_agp_for_card); | 3035 | EXPORT_SYMBOL(pmac_resume_agp_for_card); |
3036 | |||
3037 | int pmac_get_uninorth_variant(void) | ||
3038 | { | ||
3039 | return uninorth_maj; | ||
3040 | } | ||
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 8ba49385c3ff..77ad192962c5 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c | |||
@@ -85,6 +85,7 @@ struct smu_device { | |||
85 | u32 cmd_buf_abs; /* command buffer absolute */ | 85 | u32 cmd_buf_abs; /* command buffer absolute */ |
86 | struct list_head cmd_list; | 86 | struct list_head cmd_list; |
87 | struct smu_cmd *cmd_cur; /* pending command */ | 87 | struct smu_cmd *cmd_cur; /* pending command */ |
88 | int broken_nap; | ||
88 | struct list_head cmd_i2c_list; | 89 | struct list_head cmd_i2c_list; |
89 | struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */ | 90 | struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */ |
90 | struct timer_list i2c_timer; | 91 | struct timer_list i2c_timer; |
@@ -135,6 +136,19 @@ static void smu_start_cmd(void) | |||
135 | fend = faddr + smu->cmd_buf->length + 2; | 136 | fend = faddr + smu->cmd_buf->length + 2; |
136 | flush_inval_dcache_range(faddr, fend); | 137 | flush_inval_dcache_range(faddr, fend); |
137 | 138 | ||
139 | |||
140 | /* We also disable NAP mode for the duration of the command | ||
141 | * on U3 based machines. | ||
142 | * This is slightly racy as it can be written back to 1 by a sysctl | ||
143 | * but that never happens in practice. There seem to be an issue with | ||
144 | * U3 based machines such as the iMac G5 where napping for the | ||
145 | * whole duration of the command prevents the SMU from fetching it | ||
146 | * from memory. This might be related to the strange i2c based | ||
147 | * mechanism the SMU uses to access memory. | ||
148 | */ | ||
149 | if (smu->broken_nap) | ||
150 | powersave_nap = 0; | ||
151 | |||
138 | /* This isn't exactly a DMA mapping here, I suspect | 152 | /* This isn't exactly a DMA mapping here, I suspect |
139 | * the SMU is actually communicating with us via i2c to the | 153 | * the SMU is actually communicating with us via i2c to the |
140 | * northbridge or the CPU to access RAM. | 154 | * northbridge or the CPU to access RAM. |
@@ -211,6 +225,10 @@ static irqreturn_t smu_db_intr(int irq, void *arg) | |||
211 | misc = cmd->misc; | 225 | misc = cmd->misc; |
212 | mb(); | 226 | mb(); |
213 | cmd->status = rc; | 227 | cmd->status = rc; |
228 | |||
229 | /* Re-enable NAP mode */ | ||
230 | if (smu->broken_nap) | ||
231 | powersave_nap = 1; | ||
214 | bail: | 232 | bail: |
215 | /* Start next command if any */ | 233 | /* Start next command if any */ |
216 | smu_start_cmd(); | 234 | smu_start_cmd(); |
@@ -461,7 +479,7 @@ int __init smu_init (void) | |||
461 | if (np == NULL) | 479 | if (np == NULL) |
462 | return -ENODEV; | 480 | return -ENODEV; |
463 | 481 | ||
464 | printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR); | 482 | printk(KERN_INFO "SMU: Driver %s %s\n", VERSION, AUTHOR); |
465 | 483 | ||
466 | if (smu_cmdbuf_abs == 0) { | 484 | if (smu_cmdbuf_abs == 0) { |
467 | printk(KERN_ERR "SMU: Command buffer not allocated !\n"); | 485 | printk(KERN_ERR "SMU: Command buffer not allocated !\n"); |
@@ -533,6 +551,11 @@ int __init smu_init (void) | |||
533 | goto fail; | 551 | goto fail; |
534 | } | 552 | } |
535 | 553 | ||
554 | /* U3 has an issue with NAP mode when issuing SMU commands */ | ||
555 | smu->broken_nap = pmac_get_uninorth_variant() < 4; | ||
556 | if (smu->broken_nap) | ||
557 | printk(KERN_INFO "SMU: using NAP mode workaround\n"); | ||
558 | |||
536 | sys_ctrler = SYS_CTRLER_SMU; | 559 | sys_ctrler = SYS_CTRLER_SMU; |
537 | return 0; | 560 | return 0; |
538 | 561 | ||
diff --git a/include/asm-powerpc/pmac_feature.h b/include/asm-powerpc/pmac_feature.h index 26bcb0aa164a..877c35a4356e 100644 --- a/include/asm-powerpc/pmac_feature.h +++ b/include/asm-powerpc/pmac_feature.h | |||
@@ -392,6 +392,14 @@ extern u32 __iomem *uninorth_base; | |||
392 | #define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) | 392 | #define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) |
393 | #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) | 393 | #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) |
394 | 394 | ||
395 | /* Uninorth variant: | ||
396 | * | ||
397 | * 0 = not uninorth | ||
398 | * 1 = U1.x or U2.x | ||
399 | * 3 = U3 | ||
400 | * 4 = U4 | ||
401 | */ | ||
402 | extern int pmac_get_uninorth_variant(void); | ||
395 | 403 | ||
396 | #endif /* __ASM_POWERPC_PMAC_FEATURE_H */ | 404 | #endif /* __ASM_POWERPC_PMAC_FEATURE_H */ |
397 | #endif /* __KERNEL__ */ | 405 | #endif /* __KERNEL__ */ |