aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/macintosh
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/macintosh')
-rw-r--r--drivers/macintosh/smu.c53
1 files changed, 38 insertions, 15 deletions
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index f139a74696fe..00ef46898147 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -75,9 +75,11 @@ struct smu_device {
75 struct of_device *of_dev; 75 struct of_device *of_dev;
76 int doorbell; /* doorbell gpio */ 76 int doorbell; /* doorbell gpio */
77 u32 __iomem *db_buf; /* doorbell buffer */ 77 u32 __iomem *db_buf; /* doorbell buffer */
78 int db_irq; 78 struct device_node *db_node;
79 unsigned int db_irq;
79 int msg; 80 int msg;
80 int msg_irq; 81 struct device_node *msg_node;
82 unsigned int msg_irq;
81 struct smu_cmd_buf *cmd_buf; /* command buffer virtual */ 83 struct smu_cmd_buf *cmd_buf; /* command buffer virtual */
82 u32 cmd_buf_abs; /* command buffer absolute */ 84 u32 cmd_buf_abs; /* command buffer absolute */
83 struct list_head cmd_list; 85 struct list_head cmd_list;
@@ -93,6 +95,7 @@ struct smu_device {
93 */ 95 */
94static struct smu_device *smu; 96static struct smu_device *smu;
95static DEFINE_MUTEX(smu_part_access); 97static DEFINE_MUTEX(smu_part_access);
98static int smu_irq_inited;
96 99
97static void smu_i2c_retry(unsigned long data); 100static void smu_i2c_retry(unsigned long data);
98 101
@@ -257,6 +260,10 @@ int smu_queue_cmd(struct smu_cmd *cmd)
257 smu_start_cmd(); 260 smu_start_cmd();
258 spin_unlock_irqrestore(&smu->lock, flags); 261 spin_unlock_irqrestore(&smu->lock, flags);
259 262
263 /* Workaround for early calls when irq isn't available */
264 if (!smu_irq_inited || smu->db_irq == NO_IRQ)
265 smu_spinwait_cmd(cmd);
266
260 return 0; 267 return 0;
261} 268}
262EXPORT_SYMBOL(smu_queue_cmd); 269EXPORT_SYMBOL(smu_queue_cmd);
@@ -478,14 +485,15 @@ int __init smu_init (void)
478 smu->cmd_buf_abs = (u32)smu_cmdbuf_abs; 485 smu->cmd_buf_abs = (u32)smu_cmdbuf_abs;
479 smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs); 486 smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs);
480 487
481 np = of_find_node_by_name(NULL, "smu-doorbell"); 488 smu->db_node = of_find_node_by_name(NULL, "smu-doorbell");
482 if (np == NULL) { 489 if (smu->db_node == NULL) {
483 printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n"); 490 printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n");
484 goto fail; 491 goto fail;
485 } 492 }
486 data = (u32 *)get_property(np, "reg", NULL); 493 data = (u32 *)get_property(smu->db_node, "reg", NULL);
487 if (data == NULL) { 494 if (data == NULL) {
488 of_node_put(np); 495 of_node_put(smu->db_node);
496 smu->db_node = NULL;
489 printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); 497 printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
490 goto fail; 498 goto fail;
491 } 499 }
@@ -497,25 +505,21 @@ int __init smu_init (void)
497 smu->doorbell = *data; 505 smu->doorbell = *data;
498 if (smu->doorbell < 0x50) 506 if (smu->doorbell < 0x50)
499 smu->doorbell += 0x50; 507 smu->doorbell += 0x50;
500 smu->db_irq = irq_of_parse_and_map(np, 0);
501
502 of_node_put(np);
503 508
504 /* Now look for the smu-interrupt GPIO */ 509 /* Now look for the smu-interrupt GPIO */
505 do { 510 do {
506 np = of_find_node_by_name(NULL, "smu-interrupt"); 511 smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt");
507 if (np == NULL) 512 if (smu->msg_node == NULL)
508 break; 513 break;
509 data = (u32 *)get_property(np, "reg", NULL); 514 data = (u32 *)get_property(smu->msg_node, "reg", NULL);
510 if (data == NULL) { 515 if (data == NULL) {
511 of_node_put(np); 516 of_node_put(smu->msg_node);
517 smu->msg_node = NULL;
512 break; 518 break;
513 } 519 }
514 smu->msg = *data; 520 smu->msg = *data;
515 if (smu->msg < 0x50) 521 if (smu->msg < 0x50)
516 smu->msg += 0x50; 522 smu->msg += 0x50;
517 smu->msg_irq = irq_of_parse_and_map(np, 0);
518 of_node_put(np);
519 } while(0); 523 } while(0);
520 524
521 /* Doorbell buffer is currently hard-coded, I didn't find a proper 525 /* Doorbell buffer is currently hard-coded, I didn't find a proper
@@ -547,6 +551,19 @@ static int smu_late_init(void)
547 smu->i2c_timer.function = smu_i2c_retry; 551 smu->i2c_timer.function = smu_i2c_retry;
548 smu->i2c_timer.data = (unsigned long)smu; 552 smu->i2c_timer.data = (unsigned long)smu;
549 553
554 if (smu->db_node) {
555 smu->db_irq = irq_of_parse_and_map(smu->db_node, 0);
556 if (smu->db_irq == NO_IRQ)
557 printk(KERN_ERR "smu: failed to map irq for node %s\n",
558 smu->db_node->full_name);
559 }
560 if (smu->msg_node) {
561 smu->msg_irq = irq_of_parse_and_map(smu->msg_node, 0);
562 if (smu->msg_irq == NO_IRQ)
563 printk(KERN_ERR "smu: failed to map irq for node %s\n",
564 smu->msg_node->full_name);
565 }
566
550 /* 567 /*
551 * Try to request the interrupts 568 * Try to request the interrupts
552 */ 569 */
@@ -571,6 +588,7 @@ static int smu_late_init(void)
571 } 588 }
572 } 589 }
573 590
591 smu_irq_inited = 1;
574 return 0; 592 return 0;
575} 593}
576/* This has to be before arch_initcall as the low i2c stuff relies on the 594/* This has to be before arch_initcall as the low i2c stuff relies on the
@@ -742,6 +760,11 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
742 if (fail && --cmd->retries > 0) { 760 if (fail && --cmd->retries > 0) {
743 DPRINTK("SMU: i2c failure, starting timer...\n"); 761 DPRINTK("SMU: i2c failure, starting timer...\n");
744 BUG_ON(cmd != smu->cmd_i2c_cur); 762 BUG_ON(cmd != smu->cmd_i2c_cur);
763 if (!smu_irq_inited) {
764 mdelay(5);
765 smu_i2c_retry(0);
766 return;
767 }
745 mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5)); 768 mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5));
746 return; 769 return;
747 } 770 }