aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/macintosh/smu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/macintosh/smu.c')
-rw-r--r--drivers/macintosh/smu.c55
1 files changed, 38 insertions, 17 deletions
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index ff6d9bfdc3d2..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,27 +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 if (np->n_intrs > 0)
501 smu->db_irq = np->intrs[0].line;
502
503 of_node_put(np);
504 508
505 /* Now look for the smu-interrupt GPIO */ 509 /* Now look for the smu-interrupt GPIO */
506 do { 510 do {
507 np = of_find_node_by_name(NULL, "smu-interrupt"); 511 smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt");
508 if (np == NULL) 512 if (smu->msg_node == NULL)
509 break; 513 break;
510 data = (u32 *)get_property(np, "reg", NULL); 514 data = (u32 *)get_property(smu->msg_node, "reg", NULL);
511 if (data == NULL) { 515 if (data == NULL) {
512 of_node_put(np); 516 of_node_put(smu->msg_node);
517 smu->msg_node = NULL;
513 break; 518 break;
514 } 519 }
515 smu->msg = *data; 520 smu->msg = *data;
516 if (smu->msg < 0x50) 521 if (smu->msg < 0x50)
517 smu->msg += 0x50; 522 smu->msg += 0x50;
518 if (np->n_intrs > 0)
519 smu->msg_irq = np->intrs[0].line;
520 of_node_put(np);
521 } while(0); 523 } while(0);
522 524
523 /* 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
@@ -549,6 +551,19 @@ static int smu_late_init(void)
549 smu->i2c_timer.function = smu_i2c_retry; 551 smu->i2c_timer.function = smu_i2c_retry;
550 smu->i2c_timer.data = (unsigned long)smu; 552 smu->i2c_timer.data = (unsigned long)smu;
551 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
552 /* 567 /*
553 * Try to request the interrupts 568 * Try to request the interrupts
554 */ 569 */
@@ -573,6 +588,7 @@ static int smu_late_init(void)
573 } 588 }
574 } 589 }
575 590
591 smu_irq_inited = 1;
576 return 0; 592 return 0;
577} 593}
578/* 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
@@ -744,6 +760,11 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
744 if (fail && --cmd->retries > 0) { 760 if (fail && --cmd->retries > 0) {
745 DPRINTK("SMU: i2c failure, starting timer...\n"); 761 DPRINTK("SMU: i2c failure, starting timer...\n");
746 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 }
747 mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5)); 768 mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5));
748 return; 769 return;
749 } 770 }