aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-03 12:40:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-03 12:40:51 -0400
commita0a4194c943bc64dd7b6e26cccb036cb26b81363 (patch)
tree4282f0dd573344d10f69616eb05868b5cd563cc1 /arch/x86/platform
parentcf0223503e6198292cdcc864e01eeb5fe7490752 (diff)
parentb958f7a7cbdfbf59ba61de7ebb9c59b0ee3a7967 (diff)
Merge branch 'for-next' of git://git.infradead.org/users/sameo/mfd-2.6
* 'for-next' of git://git.infradead.org/users/sameo/mfd-2.6: (80 commits) mfd: Fix missing abx500 header file updates mfd: Add missing <linux/io.h> include to intel_msic x86, mrst: add platform support for MSIC MFD driver mfd: Expose TurnOnStatus in ab8500 sysfs mfd: Remove support for early drop ab8500 chip mfd: Add support for ab8500 v3.3 mfd: Add ab8500 interrupt disable hook mfd: Convert db8500-prcmu panic() into pr_crit() mfd: Refactor db8500-prcmu request_clock() function mfd: Rename db8500-prcmu init function mfd: Fix db5500-prcmu defines mfd: db8500-prcmu voltage domain consumers additions mfd: db8500-prcmu reset code retrieval mfd: db8500-prcmu tweak for modem wakeup mfd: Add db8500-pcmu watchdog accessor functions for watchdog mfd: hwacc power state db8500-prcmu accessor mfd: Add db8500-prcmu accessors for PLL and SGA clock mfd: Move to the new db500 PRCMU API mfd: Create a common interface for dbx500 PRCMU drivers mfd: Initialize DB8500 PRCMU regs ... Fix up trivial conflicts in arch/arm/mach-imx/mach-mx31moboard.c arch/arm/mach-omap2/board-omap3beagle.c arch/arm/mach-u300/include/mach/irqs.h drivers/mfd/wm831x-spi.c
Diffstat (limited to 'arch/x86/platform')
-rw-r--r--arch/x86/platform/mrst/mrst.c176
1 files changed, 161 insertions, 15 deletions
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
index e6379526675b..6ed7afdaf4af 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -26,6 +26,8 @@
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/irq.h> 27#include <linux/irq.h>
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/notifier.h>
30#include <linux/mfd/intel_msic.h>
29 31
30#include <asm/setup.h> 32#include <asm/setup.h>
31#include <asm/mpspec_def.h> 33#include <asm/mpspec_def.h>
@@ -483,6 +485,128 @@ static void __init *no_platform_data(void *info)
483 return NULL; 485 return NULL;
484} 486}
485 487
488static struct resource msic_resources[] = {
489 {
490 .start = INTEL_MSIC_IRQ_PHYS_BASE,
491 .end = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
492 .flags = IORESOURCE_MEM,
493 },
494};
495
496static struct intel_msic_platform_data msic_pdata;
497
498static struct platform_device msic_device = {
499 .name = "intel_msic",
500 .id = -1,
501 .dev = {
502 .platform_data = &msic_pdata,
503 },
504 .num_resources = ARRAY_SIZE(msic_resources),
505 .resource = msic_resources,
506};
507
508static inline bool mrst_has_msic(void)
509{
510 return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL;
511}
512
513static int msic_scu_status_change(struct notifier_block *nb,
514 unsigned long code, void *data)
515{
516 if (code == SCU_DOWN) {
517 platform_device_unregister(&msic_device);
518 return 0;
519 }
520
521 return platform_device_register(&msic_device);
522}
523
524static int __init msic_init(void)
525{
526 static struct notifier_block msic_scu_notifier = {
527 .notifier_call = msic_scu_status_change,
528 };
529
530 /*
531 * We need to be sure that the SCU IPC is ready before MSIC device
532 * can be registered.
533 */
534 if (mrst_has_msic())
535 intel_scu_notifier_add(&msic_scu_notifier);
536
537 return 0;
538}
539arch_initcall(msic_init);
540
541/*
542 * msic_generic_platform_data - sets generic platform data for the block
543 * @info: pointer to the SFI device table entry for this block
544 * @block: MSIC block
545 *
546 * Function sets IRQ number from the SFI table entry for given device to
547 * the MSIC platform data.
548 */
549static void *msic_generic_platform_data(void *info, enum intel_msic_block block)
550{
551 struct sfi_device_table_entry *entry = info;
552
553 BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
554 msic_pdata.irq[block] = entry->irq;
555
556 return no_platform_data(info);
557}
558
559static void *msic_battery_platform_data(void *info)
560{
561 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
562}
563
564static void *msic_gpio_platform_data(void *info)
565{
566 static struct intel_msic_gpio_pdata pdata;
567 int gpio = get_gpio_by_name("msic_gpio_base");
568
569 if (gpio < 0)
570 return NULL;
571
572 pdata.gpio_base = gpio;
573 msic_pdata.gpio = &pdata;
574
575 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
576}
577
578static void *msic_audio_platform_data(void *info)
579{
580 struct platform_device *pdev;
581
582 pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
583 if (IS_ERR(pdev)) {
584 pr_err("failed to create audio platform device\n");
585 return NULL;
586 }
587
588 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
589}
590
591static void *msic_power_btn_platform_data(void *info)
592{
593 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
594}
595
596static void *msic_ocd_platform_data(void *info)
597{
598 static struct intel_msic_ocd_pdata pdata;
599 int gpio = get_gpio_by_name("ocd_gpio");
600
601 if (gpio < 0)
602 return NULL;
603
604 pdata.gpio = gpio;
605 msic_pdata.ocd = &pdata;
606
607 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
608}
609
486static const struct devs_id __initconst device_ids[] = { 610static const struct devs_id __initconst device_ids[] = {
487 {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, 611 {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
488 {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, 612 {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
@@ -491,7 +615,14 @@ static const struct devs_id __initconst device_ids[] = {
491 {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, 615 {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data},
492 {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, 616 {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
493 {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, 617 {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
494 {"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, 618
619 /* MSIC subdevices */
620 {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
621 {"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data},
622 {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data},
623 {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data},
624 {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data},
625
495 {}, 626 {},
496}; 627};
497 628
@@ -558,6 +689,9 @@ static void __init intel_scu_i2c_device_register(int bus,
558 i2c_devs[i2c_next_dev++] = new_dev; 689 i2c_devs[i2c_next_dev++] = new_dev;
559} 690}
560 691
692BLOCKING_NOTIFIER_HEAD(intel_scu_notifier);
693EXPORT_SYMBOL_GPL(intel_scu_notifier);
694
561/* Called by IPC driver */ 695/* Called by IPC driver */
562void intel_scu_devices_create(void) 696void intel_scu_devices_create(void)
563{ 697{
@@ -582,6 +716,7 @@ void intel_scu_devices_create(void)
582 } else 716 } else
583 i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1); 717 i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
584 } 718 }
719 intel_scu_notifier_post(SCU_AVAILABLE, 0L);
585} 720}
586EXPORT_SYMBOL_GPL(intel_scu_devices_create); 721EXPORT_SYMBOL_GPL(intel_scu_devices_create);
587 722
@@ -590,6 +725,8 @@ void intel_scu_devices_destroy(void)
590{ 725{
591 int i; 726 int i;
592 727
728 intel_scu_notifier_post(SCU_DOWN, 0L);
729
593 for (i = 0; i < ipc_next_dev; i++) 730 for (i = 0; i < ipc_next_dev; i++)
594 platform_device_del(ipc_devs[i]); 731 platform_device_del(ipc_devs[i]);
595} 732}
@@ -606,19 +743,37 @@ static void __init install_irq_resource(struct platform_device *pdev, int irq)
606 platform_device_add_resources(pdev, &res, 1); 743 platform_device_add_resources(pdev, &res, 1);
607} 744}
608 745
609static void __init sfi_handle_ipc_dev(struct platform_device *pdev) 746static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *entry)
610{ 747{
611 const struct devs_id *dev = device_ids; 748 const struct devs_id *dev = device_ids;
749 struct platform_device *pdev;
612 void *pdata = NULL; 750 void *pdata = NULL;
613 751
614 while (dev->name[0]) { 752 while (dev->name[0]) {
615 if (dev->type == SFI_DEV_TYPE_IPC && 753 if (dev->type == SFI_DEV_TYPE_IPC &&
616 !strncmp(dev->name, pdev->name, SFI_NAME_LEN)) { 754 !strncmp(dev->name, entry->name, SFI_NAME_LEN)) {
617 pdata = dev->get_platform_data(pdev); 755 pdata = dev->get_platform_data(entry);
618 break; 756 break;
619 } 757 }
620 dev++; 758 dev++;
621 } 759 }
760
761 /*
762 * On Medfield the platform device creation is handled by the MSIC
763 * MFD driver so we don't need to do it here.
764 */
765 if (mrst_has_msic())
766 return;
767
768 /* ID as IRQ is a hack that will go away */
769 pdev = platform_device_alloc(entry->name, entry->irq);
770 if (pdev == NULL) {
771 pr_err("out of memory for SFI platform device '%s'.\n",
772 entry->name);
773 return;
774 }
775 install_irq_resource(pdev, entry->irq);
776
622 pdev->dev.platform_data = pdata; 777 pdev->dev.platform_data = pdata;
623 intel_scu_device_register(pdev); 778 intel_scu_device_register(pdev);
624} 779}
@@ -671,7 +826,6 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
671 struct sfi_device_table_entry *pentry; 826 struct sfi_device_table_entry *pentry;
672 struct spi_board_info spi_info; 827 struct spi_board_info spi_info;
673 struct i2c_board_info i2c_info; 828 struct i2c_board_info i2c_info;
674 struct platform_device *pdev;
675 int num, i, bus; 829 int num, i, bus;
676 int ioapic; 830 int ioapic;
677 struct io_apic_irq_attr irq_attr; 831 struct io_apic_irq_attr irq_attr;
@@ -699,17 +853,9 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
699 853
700 switch (pentry->type) { 854 switch (pentry->type) {
701 case SFI_DEV_TYPE_IPC: 855 case SFI_DEV_TYPE_IPC:
702 /* ID as IRQ is a hack that will go away */
703 pdev = platform_device_alloc(pentry->name, irq);
704 if (pdev == NULL) {
705 pr_err("out of memory for SFI platform device '%s'.\n",
706 pentry->name);
707 continue;
708 }
709 install_irq_resource(pdev, irq);
710 pr_debug("info[%2d]: IPC bus, name = %16.16s, " 856 pr_debug("info[%2d]: IPC bus, name = %16.16s, "
711 "irq = 0x%2x\n", i, pentry->name, irq); 857 "irq = 0x%2x\n", i, pentry->name, pentry->irq);
712 sfi_handle_ipc_dev(pdev); 858 sfi_handle_ipc_dev(pentry);
713 break; 859 break;
714 case SFI_DEV_TYPE_SPI: 860 case SFI_DEV_TYPE_SPI:
715 memset(&spi_info, 0, sizeof(spi_info)); 861 memset(&spi_info, 0, sizeof(spi_info));