diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-03 12:40:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-03 12:40:51 -0400 |
commit | a0a4194c943bc64dd7b6e26cccb036cb26b81363 (patch) | |
tree | 4282f0dd573344d10f69616eb05868b5cd563cc1 /arch/x86/platform | |
parent | cf0223503e6198292cdcc864e01eeb5fe7490752 (diff) | |
parent | b958f7a7cbdfbf59ba61de7ebb9c59b0ee3a7967 (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.c | 176 |
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 | ||
488 | static 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 | |||
496 | static struct intel_msic_platform_data msic_pdata; | ||
497 | |||
498 | static 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 | |||
508 | static inline bool mrst_has_msic(void) | ||
509 | { | ||
510 | return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL; | ||
511 | } | ||
512 | |||
513 | static 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 | |||
524 | static 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 | } | ||
539 | arch_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 | */ | ||
549 | static 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 | |||
559 | static void *msic_battery_platform_data(void *info) | ||
560 | { | ||
561 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY); | ||
562 | } | ||
563 | |||
564 | static 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 | |||
578 | static 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 | |||
591 | static void *msic_power_btn_platform_data(void *info) | ||
592 | { | ||
593 | return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN); | ||
594 | } | ||
595 | |||
596 | static 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 | |||
486 | static const struct devs_id __initconst device_ids[] = { | 610 | static 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 | ||
692 | BLOCKING_NOTIFIER_HEAD(intel_scu_notifier); | ||
693 | EXPORT_SYMBOL_GPL(intel_scu_notifier); | ||
694 | |||
561 | /* Called by IPC driver */ | 695 | /* Called by IPC driver */ |
562 | void intel_scu_devices_create(void) | 696 | void 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 | } |
586 | EXPORT_SYMBOL_GPL(intel_scu_devices_create); | 721 | EXPORT_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 | ||
609 | static void __init sfi_handle_ipc_dev(struct platform_device *pdev) | 746 | static 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)); |