diff options
Diffstat (limited to 'drivers/macintosh/smu.c')
-rw-r--r-- | drivers/macintosh/smu.c | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 96226116a646..9ecd76849e35 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c | |||
@@ -94,6 +94,8 @@ struct smu_device { | |||
94 | static struct smu_device *smu; | 94 | static struct smu_device *smu; |
95 | static DECLARE_MUTEX(smu_part_access); | 95 | static DECLARE_MUTEX(smu_part_access); |
96 | 96 | ||
97 | static void smu_i2c_retry(unsigned long data); | ||
98 | |||
97 | /* | 99 | /* |
98 | * SMU driver low level stuff | 100 | * SMU driver low level stuff |
99 | */ | 101 | */ |
@@ -469,7 +471,6 @@ int __init smu_init (void) | |||
469 | smu->of_node = np; | 471 | smu->of_node = np; |
470 | smu->db_irq = NO_IRQ; | 472 | smu->db_irq = NO_IRQ; |
471 | smu->msg_irq = NO_IRQ; | 473 | smu->msg_irq = NO_IRQ; |
472 | init_timer(&smu->i2c_timer); | ||
473 | 474 | ||
474 | /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a | 475 | /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a |
475 | * 32 bits value safely | 476 | * 32 bits value safely |
@@ -544,6 +545,10 @@ static int smu_late_init(void) | |||
544 | if (!smu) | 545 | if (!smu) |
545 | return 0; | 546 | return 0; |
546 | 547 | ||
548 | init_timer(&smu->i2c_timer); | ||
549 | smu->i2c_timer.function = smu_i2c_retry; | ||
550 | smu->i2c_timer.data = (unsigned long)smu; | ||
551 | |||
547 | /* | 552 | /* |
548 | * Try to request the interrupts | 553 | * Try to request the interrupts |
549 | */ | 554 | */ |
@@ -570,28 +575,41 @@ static int smu_late_init(void) | |||
570 | 575 | ||
571 | return 0; | 576 | return 0; |
572 | } | 577 | } |
573 | arch_initcall(smu_late_init); | 578 | /* This has to be before arch_initcall as the low i2c stuff relies on the |
579 | * above having been done before we reach arch_initcalls | ||
580 | */ | ||
581 | core_initcall(smu_late_init); | ||
574 | 582 | ||
575 | /* | 583 | /* |
576 | * sysfs visibility | 584 | * sysfs visibility |
577 | */ | 585 | */ |
578 | 586 | ||
587 | static void smu_create_i2c(struct device_node *np) | ||
588 | { | ||
589 | char name[32]; | ||
590 | u32 *reg = (u32 *)get_property(np, "reg", NULL); | ||
591 | |||
592 | if (reg != NULL) { | ||
593 | sprintf(name, "smu-i2c-%02x", *reg); | ||
594 | of_platform_device_create(np, name, &smu->of_dev->dev); | ||
595 | } | ||
596 | } | ||
597 | |||
579 | static void smu_expose_childs(void *unused) | 598 | static void smu_expose_childs(void *unused) |
580 | { | 599 | { |
581 | struct device_node *np; | 600 | struct device_node *np, *gp; |
582 | 601 | ||
583 | for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) { | 602 | for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) { |
584 | if (device_is_compatible(np, "smu-i2c")) { | 603 | if (device_is_compatible(np, "smu-i2c-control")) { |
585 | char name[32]; | 604 | gp = NULL; |
586 | u32 *reg = (u32 *)get_property(np, "reg", NULL); | 605 | while ((gp = of_get_next_child(np, gp)) != NULL) |
587 | 606 | if (device_is_compatible(gp, "i2c-bus")) | |
588 | if (reg == NULL) | 607 | smu_create_i2c(gp); |
589 | continue; | 608 | } else if (device_is_compatible(np, "smu-i2c")) |
590 | sprintf(name, "smu-i2c-%02x", *reg); | 609 | smu_create_i2c(np); |
591 | of_platform_device_create(np, name, &smu->of_dev->dev); | ||
592 | } | ||
593 | if (device_is_compatible(np, "smu-sensors")) | 610 | if (device_is_compatible(np, "smu-sensors")) |
594 | of_platform_device_create(np, "smu-sensors", &smu->of_dev->dev); | 611 | of_platform_device_create(np, "smu-sensors", |
612 | &smu->of_dev->dev); | ||
595 | } | 613 | } |
596 | 614 | ||
597 | } | 615 | } |
@@ -712,13 +730,13 @@ static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail) | |||
712 | 730 | ||
713 | static void smu_i2c_retry(unsigned long data) | 731 | static void smu_i2c_retry(unsigned long data) |
714 | { | 732 | { |
715 | struct smu_i2c_cmd *cmd = (struct smu_i2c_cmd *)data; | 733 | struct smu_i2c_cmd *cmd = smu->cmd_i2c_cur; |
716 | 734 | ||
717 | DPRINTK("SMU: i2c failure, requeuing...\n"); | 735 | DPRINTK("SMU: i2c failure, requeuing...\n"); |
718 | 736 | ||
719 | /* requeue command simply by resetting reply_len */ | 737 | /* requeue command simply by resetting reply_len */ |
720 | cmd->pdata[0] = 0xff; | 738 | cmd->pdata[0] = 0xff; |
721 | cmd->scmd.reply_len = 0x10; | 739 | cmd->scmd.reply_len = sizeof(cmd->pdata); |
722 | smu_queue_cmd(&cmd->scmd); | 740 | smu_queue_cmd(&cmd->scmd); |
723 | } | 741 | } |
724 | 742 | ||
@@ -747,10 +765,8 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc) | |||
747 | */ | 765 | */ |
748 | if (fail && --cmd->retries > 0) { | 766 | if (fail && --cmd->retries > 0) { |
749 | DPRINTK("SMU: i2c failure, starting timer...\n"); | 767 | DPRINTK("SMU: i2c failure, starting timer...\n"); |
750 | smu->i2c_timer.function = smu_i2c_retry; | 768 | BUG_ON(cmd != smu->cmd_i2c_cur); |
751 | smu->i2c_timer.data = (unsigned long)cmd; | 769 | mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5)); |
752 | smu->i2c_timer.expires = jiffies + msecs_to_jiffies(5); | ||
753 | add_timer(&smu->i2c_timer); | ||
754 | return; | 770 | return; |
755 | } | 771 | } |
756 | 772 | ||
@@ -764,7 +780,7 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc) | |||
764 | 780 | ||
765 | /* Ok, initial command complete, now poll status */ | 781 | /* Ok, initial command complete, now poll status */ |
766 | scmd->reply_buf = cmd->pdata; | 782 | scmd->reply_buf = cmd->pdata; |
767 | scmd->reply_len = 0x10; | 783 | scmd->reply_len = sizeof(cmd->pdata); |
768 | scmd->data_buf = cmd->pdata; | 784 | scmd->data_buf = cmd->pdata; |
769 | scmd->data_len = 1; | 785 | scmd->data_len = 1; |
770 | cmd->pdata[0] = 0; | 786 | cmd->pdata[0] = 0; |
@@ -786,7 +802,7 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd) | |||
786 | cmd->scmd.done = smu_i2c_low_completion; | 802 | cmd->scmd.done = smu_i2c_low_completion; |
787 | cmd->scmd.misc = cmd; | 803 | cmd->scmd.misc = cmd; |
788 | cmd->scmd.reply_buf = cmd->pdata; | 804 | cmd->scmd.reply_buf = cmd->pdata; |
789 | cmd->scmd.reply_len = 0x10; | 805 | cmd->scmd.reply_len = sizeof(cmd->pdata); |
790 | cmd->scmd.data_buf = (u8 *)(char *)&cmd->info; | 806 | cmd->scmd.data_buf = (u8 *)(char *)&cmd->info; |
791 | cmd->scmd.status = 1; | 807 | cmd->scmd.status = 1; |
792 | cmd->stage = 0; | 808 | cmd->stage = 0; |