aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2011-10-18 05:41:22 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2011-10-24 08:09:20 -0400
commit360545c1fcdd458053ede5794c3255c44164cc4a (patch)
treeee7966859b264eaef0ca102608fd99e796b59513 /arch/x86
parentb4a310373209b87ba455f45227b5361cb746b946 (diff)
x86, mrst: add platform support for MSIC MFD driver
The MSIC MFD driver creates platform devices for MSIC device drivers so we don't need to create them in platform code anymore. This patch adds a new runtime check which determines whether we are running on a Medfield platform and enables the MSIC MFD driver accordingly. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/platform/mrst/mrst.c169
1 files changed, 154 insertions, 15 deletions
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
index 51ec016c20d6..8a7cb3259562 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -25,6 +25,7 @@
25#include <linux/irq.h> 25#include <linux/irq.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/notifier.h> 27#include <linux/notifier.h>
28#include <linux/mfd/intel_msic.h>
28 29
29#include <asm/setup.h> 30#include <asm/setup.h>
30#include <asm/mpspec_def.h> 31#include <asm/mpspec_def.h>
@@ -481,6 +482,128 @@ static void __init *no_platform_data(void *info)
481 return NULL; 482 return NULL;
482} 483}
483 484
485static struct resource msic_resources[] = {
486 {
487 .start = INTEL_MSIC_IRQ_PHYS_BASE,
488 .end = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
489 .flags = IORESOURCE_MEM,
490 },
491};
492
493static struct intel_msic_platform_data msic_pdata;
494
495static struct platform_device msic_device = {
496 .name = "intel_msic",
497 .id = -1,
498 .dev = {
499 .platform_data = &msic_pdata,
500 },
501 .num_resources = ARRAY_SIZE(msic_resources),
502 .resource = msic_resources,
503};
504
505static inline bool mrst_has_msic(void)
506{
507 return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL;
508}
509
510static int msic_scu_status_change(struct notifier_block *nb,
511 unsigned long code, void *data)
512{
513 if (code == SCU_DOWN) {
514 platform_device_unregister(&msic_device);
515 return 0;
516 }
517
518 return platform_device_register(&msic_device);
519}
520
521static int __init msic_init(void)
522{
523 static struct notifier_block msic_scu_notifier = {
524 .notifier_call = msic_scu_status_change,
525 };
526
527 /*
528 * We need to be sure that the SCU IPC is ready before MSIC device
529 * can be registered.
530 */
531 if (mrst_has_msic())
532 intel_scu_notifier_add(&msic_scu_notifier);
533
534 return 0;
535}
536arch_initcall(msic_init);
537
538/*
539 * msic_generic_platform_data - sets generic platform data for the block
540 * @info: pointer to the SFI device table entry for this block
541 * @block: MSIC block
542 *
543 * Function sets IRQ number from the SFI table entry for given device to
544 * the MSIC platform data.
545 */
546static void *msic_generic_platform_data(void *info, enum intel_msic_block block)
547{
548 struct sfi_device_table_entry *entry = info;
549
550 BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
551 msic_pdata.irq[block] = entry->irq;
552
553 return no_platform_data(info);
554}
555
556static void *msic_battery_platform_data(void *info)
557{
558 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
559}
560
561static void *msic_gpio_platform_data(void *info)
562{
563 static struct intel_msic_gpio_pdata pdata;
564 int gpio = get_gpio_by_name("msic_gpio_base");
565
566 if (gpio < 0)
567 return NULL;
568
569 pdata.gpio_base = gpio;
570 msic_pdata.gpio = &pdata;
571
572 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
573}
574
575static void *msic_audio_platform_data(void *info)
576{
577 struct platform_device *pdev;
578
579 pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
580 if (IS_ERR(pdev)) {
581 pr_err("failed to create audio platform device\n");
582 return NULL;
583 }
584
585 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
586}
587
588static void *msic_power_btn_platform_data(void *info)
589{
590 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
591}
592
593static void *msic_ocd_platform_data(void *info)
594{
595 static struct intel_msic_ocd_pdata pdata;
596 int gpio = get_gpio_by_name("ocd_gpio");
597
598 if (gpio < 0)
599 return NULL;
600
601 pdata.gpio = gpio;
602 msic_pdata.ocd = &pdata;
603
604 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
605}
606
484static const struct devs_id __initconst device_ids[] = { 607static const struct devs_id __initconst device_ids[] = {
485 {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, 608 {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
486 {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, 609 {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
@@ -489,7 +612,14 @@ static const struct devs_id __initconst device_ids[] = {
489 {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, 612 {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data},
490 {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, 613 {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
491 {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, 614 {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
492 {"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, 615
616 /* MSIC subdevices */
617 {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
618 {"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data},
619 {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data},
620 {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data},
621 {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data},
622
493 {}, 623 {},
494}; 624};
495 625
@@ -610,19 +740,37 @@ static void __init install_irq_resource(struct platform_device *pdev, int irq)
610 platform_device_add_resources(pdev, &res, 1); 740 platform_device_add_resources(pdev, &res, 1);
611} 741}
612 742
613static void __init sfi_handle_ipc_dev(struct platform_device *pdev) 743static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *entry)
614{ 744{
615 const struct devs_id *dev = device_ids; 745 const struct devs_id *dev = device_ids;
746 struct platform_device *pdev;
616 void *pdata = NULL; 747 void *pdata = NULL;
617 748
618 while (dev->name[0]) { 749 while (dev->name[0]) {
619 if (dev->type == SFI_DEV_TYPE_IPC && 750 if (dev->type == SFI_DEV_TYPE_IPC &&
620 !strncmp(dev->name, pdev->name, SFI_NAME_LEN)) { 751 !strncmp(dev->name, entry->name, SFI_NAME_LEN)) {
621 pdata = dev->get_platform_data(pdev); 752 pdata = dev->get_platform_data(entry);
622 break; 753 break;
623 } 754 }
624 dev++; 755 dev++;
625 } 756 }
757
758 /*
759 * On Medfield the platform device creation is handled by the MSIC
760 * MFD driver so we don't need to do it here.
761 */
762 if (mrst_has_msic())
763 return;
764
765 /* ID as IRQ is a hack that will go away */
766 pdev = platform_device_alloc(entry->name, entry->irq);
767 if (pdev == NULL) {
768 pr_err("out of memory for SFI platform device '%s'.\n",
769 entry->name);
770 return;
771 }
772 install_irq_resource(pdev, entry->irq);
773
626 pdev->dev.platform_data = pdata; 774 pdev->dev.platform_data = pdata;
627 intel_scu_device_register(pdev); 775 intel_scu_device_register(pdev);
628} 776}
@@ -675,7 +823,6 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
675 struct sfi_device_table_entry *pentry; 823 struct sfi_device_table_entry *pentry;
676 struct spi_board_info spi_info; 824 struct spi_board_info spi_info;
677 struct i2c_board_info i2c_info; 825 struct i2c_board_info i2c_info;
678 struct platform_device *pdev;
679 int num, i, bus; 826 int num, i, bus;
680 int ioapic; 827 int ioapic;
681 struct io_apic_irq_attr irq_attr; 828 struct io_apic_irq_attr irq_attr;
@@ -703,17 +850,9 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
703 850
704 switch (pentry->type) { 851 switch (pentry->type) {
705 case SFI_DEV_TYPE_IPC: 852 case SFI_DEV_TYPE_IPC:
706 /* ID as IRQ is a hack that will go away */
707 pdev = platform_device_alloc(pentry->name, irq);
708 if (pdev == NULL) {
709 pr_err("out of memory for SFI platform device '%s'.\n",
710 pentry->name);
711 continue;
712 }
713 install_irq_resource(pdev, irq);
714 pr_debug("info[%2d]: IPC bus, name = %16.16s, " 853 pr_debug("info[%2d]: IPC bus, name = %16.16s, "
715 "irq = 0x%2x\n", i, pentry->name, irq); 854 "irq = 0x%2x\n", i, pentry->name, pentry->irq);
716 sfi_handle_ipc_dev(pdev); 855 sfi_handle_ipc_dev(pentry);
717 break; 856 break;
718 case SFI_DEV_TYPE_SPI: 857 case SFI_DEV_TYPE_SPI:
719 memset(&spi_info, 0, sizeof(spi_info)); 858 memset(&spi_info, 0, sizeof(spi_info));