aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/powermac/feature.c11
-rw-r--r--drivers/macintosh/smu.c25
-rw-r--r--include/asm-powerpc/pmac_feature.h8
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}
3031EXPORT_SYMBOL(pmac_resume_agp_for_card); 3035EXPORT_SYMBOL(pmac_resume_agp_for_card);
3036
3037int 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 */
402extern 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__ */