aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>2017-10-29 05:49:55 -0400
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>2017-11-05 06:53:14 -0500
commit43aaf4f03f063b12bcba2f8b800fdec85e2acc75 (patch)
tree20a444b026703c0af7565dc2c01924c4befe27dc
parent6cc8cbbc8868033f279b63e98b26b75eaa0006ab (diff)
platform/x86: intel_pmc_ipc: Use MFD framework to create dependent devices
Currently, we have lot of repetitive code in dependent device resource allocation and device creation handling code. This logic can be improved if we use MFD framework for dependent device creation. This patch adds this support. Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-rw-r--r--drivers/platform/x86/intel_pmc_ipc.c398
1 files changed, 139 insertions, 259 deletions
diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c
index e03fa31446ca..e36144c337cd 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -20,6 +20,7 @@
20#include <linux/errno.h> 20#include <linux/errno.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/device.h> 22#include <linux/device.h>
23#include <linux/mfd/core.h>
23#include <linux/pm.h> 24#include <linux/pm.h>
24#include <linux/pci.h> 25#include <linux/pci.h>
25#include <linux/platform_device.h> 26#include <linux/platform_device.h>
@@ -88,6 +89,7 @@
88#define PLAT_RESOURCE_ISP_IFACE_INDEX 5 89#define PLAT_RESOURCE_ISP_IFACE_INDEX 5
89#define PLAT_RESOURCE_GTD_DATA_INDEX 6 90#define PLAT_RESOURCE_GTD_DATA_INDEX 6
90#define PLAT_RESOURCE_GTD_IFACE_INDEX 7 91#define PLAT_RESOURCE_GTD_IFACE_INDEX 7
92#define PLAT_RESOURCE_MEM_MAX_INDEX 8
91#define PLAT_RESOURCE_ACPI_IO_INDEX 0 93#define PLAT_RESOURCE_ACPI_IO_INDEX 0
92 94
93/* 95/*
@@ -106,8 +108,6 @@
106#define TELEM_SSRAM_SIZE 240 108#define TELEM_SSRAM_SIZE 240
107#define TELEM_PMC_SSRAM_OFFSET 0x1B00 109#define TELEM_PMC_SSRAM_OFFSET 0x1B00
108#define TELEM_PUNIT_SSRAM_OFFSET 0x1A00 110#define TELEM_PUNIT_SSRAM_OFFSET 0x1A00
109#define TCO_PMC_OFFSET 0x8
110#define TCO_PMC_SIZE 0x4
111 111
112/* PMC register bit definitions */ 112/* PMC register bit definitions */
113 113
@@ -124,26 +124,10 @@ static struct intel_pmc_ipc_dev {
124 int cmd; 124 int cmd;
125 struct completion cmd_complete; 125 struct completion cmd_complete;
126 126
127 /* The following PMC BARs share the same ACPI device with the IPC */
128 resource_size_t acpi_io_base;
129 int acpi_io_size;
130 struct platform_device *tco_dev;
131
132 /* gcr */ 127 /* gcr */
133 void __iomem *gcr_mem_base; 128 void __iomem *gcr_mem_base;
134 bool has_gcr_regs; 129 bool has_gcr_regs;
135 spinlock_t gcr_lock; 130 spinlock_t gcr_lock;
136
137 /* punit */
138 struct platform_device *punit_dev;
139
140 /* Telemetry */
141 resource_size_t telem_pmc_ssram_base;
142 resource_size_t telem_punit_ssram_base;
143 int telem_pmc_ssram_size;
144 int telem_punit_ssram_size;
145 u8 telem_res_inval;
146 struct platform_device *telemetry_dev;
147} ipcdev; 131} ipcdev;
148 132
149static char *ipc_err_sources[] = { 133static char *ipc_err_sources[] = {
@@ -508,7 +492,7 @@ static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
508 ret = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc", 492 ret = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc",
509 pmc); 493 pmc);
510 if (ret) { 494 if (ret) {
511 dev_err(&pdev->dev, "Failed to request irq\n"); 495 dev_err(&pdev->dev, "Failed to request IRQ\n");
512 return ret; 496 return ret;
513 } 497 }
514 498
@@ -593,44 +577,6 @@ static const struct attribute_group intel_ipc_group = {
593 .attrs = intel_ipc_attrs, 577 .attrs = intel_ipc_attrs,
594}; 578};
595 579
596static struct resource punit_res_array[] = {
597 /* Punit BIOS */
598 {
599 .flags = IORESOURCE_MEM,
600 },
601 {
602 .flags = IORESOURCE_MEM,
603 },
604 /* Punit ISP */
605 {
606 .flags = IORESOURCE_MEM,
607 },
608 {
609 .flags = IORESOURCE_MEM,
610 },
611 /* Punit GTD */
612 {
613 .flags = IORESOURCE_MEM,
614 },
615 {
616 .flags = IORESOURCE_MEM,
617 },
618};
619
620#define TCO_RESOURCE_ACPI_IO 0
621#define TCO_RESOURCE_SMI_EN_IO 1
622#define TCO_RESOURCE_GCR_MEM 2
623static struct resource tco_res[] = {
624 /* ACPI - TCO */
625 {
626 .flags = IORESOURCE_IO,
627 },
628 /* ACPI - SMI */
629 {
630 .flags = IORESOURCE_IO,
631 },
632};
633
634static struct itco_wdt_platform_data tco_info = { 580static struct itco_wdt_platform_data tco_info = {
635 .name = "Apollo Lake SoC", 581 .name = "Apollo Lake SoC",
636 .version = 5, 582 .version = 5,
@@ -638,234 +584,177 @@ static struct itco_wdt_platform_data tco_info = {
638 .update_no_reboot_bit = update_no_reboot_bit, 584 .update_no_reboot_bit = update_no_reboot_bit,
639}; 585};
640 586
641#define TELEMETRY_RESOURCE_PUNIT_SSRAM 0 587static int ipc_create_punit_device(struct platform_device *pdev)
642#define TELEMETRY_RESOURCE_PMC_SSRAM 1
643static struct resource telemetry_res[] = {
644 /*Telemetry*/
645 {
646 .flags = IORESOURCE_MEM,
647 },
648 {
649 .flags = IORESOURCE_MEM,
650 },
651};
652
653static int ipc_create_punit_device(void)
654{ 588{
655 struct platform_device *pdev; 589 struct resource punit_res[PLAT_RESOURCE_MEM_MAX_INDEX];
656 const struct platform_device_info pdevinfo = { 590 struct mfd_cell punit_cell;
657 .parent = ipcdev.dev, 591 struct resource *res;
658 .name = PUNIT_DEVICE_NAME, 592 int mindex, pindex = 0;
659 .id = -1, 593
660 .res = punit_res_array, 594 for (mindex = 0; mindex <= PLAT_RESOURCE_MEM_MAX_INDEX; mindex++) {
661 .num_res = ARRAY_SIZE(punit_res_array), 595
596 res = platform_get_resource(pdev, IORESOURCE_MEM, mindex);
597
598 switch (mindex) {
599 /* Get PUNIT resources */
600 case PLAT_RESOURCE_BIOS_DATA_INDEX:
601 case PLAT_RESOURCE_BIOS_IFACE_INDEX:
602 /* BIOS resources are required, so return error if not
603 * available
604 */
605 if (!res) {
606 dev_err(&pdev->dev,
607 "Failed to get PUNIT MEM resource %d\n",
608 pindex);
609 return -ENXIO;
610 }
611 case PLAT_RESOURCE_ISP_DATA_INDEX:
612 case PLAT_RESOURCE_ISP_IFACE_INDEX:
613 case PLAT_RESOURCE_GTD_DATA_INDEX:
614 case PLAT_RESOURCE_GTD_IFACE_INDEX:
615 /* if valid resource found, copy the resource to PUNIT
616 * resource
617 */
618 if (res)
619 memcpy(&punit_res[pindex], res, sizeof(*res));
620 punit_res[pindex].flags = IORESOURCE_MEM;
621 dev_dbg(&pdev->dev, "PUNIT memory res: %pR\n",
622 &punit_res[pindex]);
623 pindex++;
624 break;
662 }; 625 };
626 }
663 627
664 pdev = platform_device_register_full(&pdevinfo); 628 /* Create PUNIT IPC MFD cell */
665 if (IS_ERR(pdev)) 629 punit_cell.name = PUNIT_DEVICE_NAME;
666 return PTR_ERR(pdev); 630 punit_cell.num_resources = ARRAY_SIZE(punit_res);
667 631 punit_cell.resources = punit_res;
668 ipcdev.punit_dev = pdev; 632 punit_cell.ignore_resource_conflicts = 1;
669 633
670 return 0; 634 return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
635 &punit_cell, 1, NULL, 0, NULL);
671} 636}
672 637
673static int ipc_create_tco_device(void) 638static int ipc_create_wdt_device(struct platform_device *pdev)
674{ 639{
675 struct platform_device *pdev; 640 static struct resource wdt_ipc_res[2];
676 struct resource *res; 641 struct resource *res;
677 const struct platform_device_info pdevinfo = { 642 static struct mfd_cell wdt_cell;
678 .parent = ipcdev.dev,
679 .name = TCO_DEVICE_NAME,
680 .id = -1,
681 .res = tco_res,
682 .num_res = ARRAY_SIZE(tco_res),
683 .data = &tco_info,
684 .size_data = sizeof(tco_info),
685 };
686 643
687 res = tco_res + TCO_RESOURCE_ACPI_IO; 644 /* If we have ACPI based watchdog use that instead, othewise create
688 res->start = ipcdev.acpi_io_base + TCO_BASE_OFFSET; 645 * a MFD cell for iTCO watchdog
689 res->end = res->start + TCO_REGS_SIZE - 1; 646 */
647 if (acpi_has_watchdog())
648 return 0;
690 649
691 res = tco_res + TCO_RESOURCE_SMI_EN_IO; 650 /* Get iTCO watchdog resources */
692 res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET; 651 res = platform_get_resource(pdev, IORESOURCE_IO,
693 res->end = res->start + SMI_EN_SIZE - 1; 652 PLAT_RESOURCE_ACPI_IO_INDEX);
653 if (!res) {
654 dev_err(&pdev->dev, "Failed to get WDT resource\n");
655 return -ENXIO;
656 }
694 657
695 pdev = platform_device_register_full(&pdevinfo); 658 wdt_ipc_res[0].start = res->start + TCO_BASE_OFFSET;
696 if (IS_ERR(pdev)) 659 wdt_ipc_res[0].end = res->start +
697 return PTR_ERR(pdev); 660 TCO_BASE_OFFSET + TCO_REGS_SIZE - 1;
661 wdt_ipc_res[0].flags = IORESOURCE_IO;
662 wdt_ipc_res[1].start = res->start + SMI_EN_OFFSET;
663 wdt_ipc_res[1].end = res->start +
664 SMI_EN_OFFSET + SMI_EN_SIZE - 1;
665 wdt_ipc_res[1].flags = IORESOURCE_IO;
698 666
699 ipcdev.tco_dev = pdev; 667 dev_dbg(&pdev->dev, "watchdog res 0: %pR\n", &wdt_ipc_res[0]);
668 dev_dbg(&pdev->dev, "watchdog res 1: %pR\n", &wdt_ipc_res[1]);
700 669
701 return 0; 670 wdt_cell.name = TCO_DEVICE_NAME;
671 wdt_cell.platform_data = &tco_info;
672 wdt_cell.pdata_size = sizeof(tco_info);
673 wdt_cell.num_resources = ARRAY_SIZE(wdt_ipc_res);
674 wdt_cell.resources = wdt_ipc_res;
675 wdt_cell.ignore_resource_conflicts = 1;
676
677 return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
678 &wdt_cell, 1, NULL, 0, NULL);
702} 679}
703 680
704static int ipc_create_telemetry_device(void) 681static int ipc_create_telemetry_device(struct platform_device *pdev)
705{ 682{
706 struct platform_device *pdev; 683 struct resource telemetry_ipc_res[2];
684 struct mfd_cell telemetry_cell;
707 struct resource *res; 685 struct resource *res;
708 const struct platform_device_info pdevinfo = {
709 .parent = ipcdev.dev,
710 .name = TELEMETRY_DEVICE_NAME,
711 .id = -1,
712 .res = telemetry_res,
713 .num_res = ARRAY_SIZE(telemetry_res),
714 };
715 686
716 res = telemetry_res + TELEMETRY_RESOURCE_PUNIT_SSRAM; 687 /* Get telemetry resources */
717 res->start = ipcdev.telem_punit_ssram_base; 688 res = platform_get_resource(pdev, IORESOURCE_MEM,
718 res->end = res->start + ipcdev.telem_punit_ssram_size - 1; 689 PLAT_RESOURCE_TELEM_SSRAM_INDEX);
690 if (!res) {
691 dev_err(&pdev->dev, "Failed to get telemetry resource\n");
692 return -ENXIO;
693 }
719 694
720 res = telemetry_res + TELEMETRY_RESOURCE_PMC_SSRAM; 695 telemetry_ipc_res[0].start = res->start + TELEM_PUNIT_SSRAM_OFFSET;
721 res->start = ipcdev.telem_pmc_ssram_base; 696 telemetry_ipc_res[0].end = res->start +
722 res->end = res->start + ipcdev.telem_pmc_ssram_size - 1; 697 TELEM_PUNIT_SSRAM_OFFSET + TELEM_SSRAM_SIZE - 1;
698 telemetry_ipc_res[0].flags = IORESOURCE_MEM;
699 telemetry_ipc_res[1].start = res->start + TELEM_PMC_SSRAM_OFFSET;
700 telemetry_ipc_res[1].end = res->start +
701 TELEM_PMC_SSRAM_OFFSET + TELEM_SSRAM_SIZE - 1;
702 telemetry_ipc_res[1].flags = IORESOURCE_MEM;
723 703
724 pdev = platform_device_register_full(&pdevinfo); 704 dev_dbg(&pdev->dev, "Telemetry res 0: %pR\n", &telemetry_ipc_res[0]);
725 if (IS_ERR(pdev)) 705 dev_dbg(&pdev->dev, "Telemetry res 1: %pR\n", &telemetry_ipc_res[1]);
726 return PTR_ERR(pdev);
727 706
728 ipcdev.telemetry_dev = pdev; 707 telemetry_cell.name = TELEMETRY_DEVICE_NAME;
708 telemetry_cell.num_resources = ARRAY_SIZE(telemetry_ipc_res);
709 telemetry_cell.resources = telemetry_ipc_res;
710 telemetry_cell.ignore_resource_conflicts = 1;
729 711
730 return 0; 712 return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
713 &telemetry_cell, 1, NULL, 0, NULL);
731} 714}
732 715
733static int ipc_create_pmc_devices(void) 716static int ipc_create_pmc_devices(struct platform_device *pdev)
734{ 717{
735 int ret; 718 int ret;
736 719
737 /* If we have ACPI based watchdog use that instead */ 720 ret = ipc_create_punit_device(pdev);
738 if (!acpi_has_watchdog()) { 721 if (ret < 0)
739 ret = ipc_create_tco_device(); 722 return ret;
740 if (ret) {
741 dev_err(ipcdev.dev, "Failed to add tco platform device\n");
742 return ret;
743 }
744 }
745 723
746 ret = ipc_create_punit_device(); 724 ret = ipc_create_wdt_device(pdev);
747 if (ret) { 725 if (ret < 0)
748 dev_err(ipcdev.dev, "Failed to add punit platform device\n"); 726 return ret;
749 platform_device_unregister(ipcdev.tco_dev);
750 }
751 727
752 if (!ipcdev.telem_res_inval) { 728 ret = ipc_create_telemetry_device(pdev);
753 ret = ipc_create_telemetry_device(); 729 if (ret < 0)
754 if (ret) 730 return ret;
755 dev_warn(ipcdev.dev,
756 "Failed to add telemetry platform device\n");
757 }
758 731
759 return ret; 732 return 0;
760} 733}
761 734
762static int ipc_plat_get_res(struct platform_device *pdev) 735static int ipc_plat_get_res(struct platform_device *pdev)
763{ 736{
764 struct resource *res, *punit_res; 737 struct resource *res;
765 void __iomem *addr; 738 void __iomem *addr;
766 int size;
767
768 res = platform_get_resource(pdev, IORESOURCE_IO,
769 PLAT_RESOURCE_ACPI_IO_INDEX);
770 if (!res) {
771 dev_err(&pdev->dev, "Failed to get io resource\n");
772 return -ENXIO;
773 }
774 size = resource_size(res);
775 ipcdev.acpi_io_base = res->start;
776 ipcdev.acpi_io_size = size;
777 dev_info(&pdev->dev, "io res: %pR\n", res);
778
779 punit_res = punit_res_array;
780 /* This is index 0 to cover BIOS data register */
781 res = platform_get_resource(pdev, IORESOURCE_MEM,
782 PLAT_RESOURCE_BIOS_DATA_INDEX);
783 if (!res) {
784 dev_err(&pdev->dev, "Failed to get res of punit BIOS data\n");
785 return -ENXIO;
786 }
787 *punit_res = *res;
788 dev_info(&pdev->dev, "punit BIOS data res: %pR\n", res);
789
790 /* This is index 1 to cover BIOS interface register */
791 res = platform_get_resource(pdev, IORESOURCE_MEM,
792 PLAT_RESOURCE_BIOS_IFACE_INDEX);
793 if (!res) {
794 dev_err(&pdev->dev, "Failed to get res of punit BIOS iface\n");
795 return -ENXIO;
796 }
797 *++punit_res = *res;
798 dev_info(&pdev->dev, "punit BIOS interface res: %pR\n", res);
799
800 /* This is index 2 to cover ISP data register, optional */
801 res = platform_get_resource(pdev, IORESOURCE_MEM,
802 PLAT_RESOURCE_ISP_DATA_INDEX);
803 ++punit_res;
804 if (res) {
805 *punit_res = *res;
806 dev_info(&pdev->dev, "punit ISP data res: %pR\n", res);
807 }
808
809 /* This is index 3 to cover ISP interface register, optional */
810 res = platform_get_resource(pdev, IORESOURCE_MEM,
811 PLAT_RESOURCE_ISP_IFACE_INDEX);
812 ++punit_res;
813 if (res) {
814 *punit_res = *res;
815 dev_info(&pdev->dev, "punit ISP interface res: %pR\n", res);
816 }
817
818 /* This is index 4 to cover GTD data register, optional */
819 res = platform_get_resource(pdev, IORESOURCE_MEM,
820 PLAT_RESOURCE_GTD_DATA_INDEX);
821 ++punit_res;
822 if (res) {
823 *punit_res = *res;
824 dev_info(&pdev->dev, "punit GTD data res: %pR\n", res);
825 }
826
827 /* This is index 5 to cover GTD interface register, optional */
828 res = platform_get_resource(pdev, IORESOURCE_MEM,
829 PLAT_RESOURCE_GTD_IFACE_INDEX);
830 ++punit_res;
831 if (res) {
832 *punit_res = *res;
833 dev_info(&pdev->dev, "punit GTD interface res: %pR\n", res);
834 }
835 739
740 /* Get IPC resources */
836 res = platform_get_resource(pdev, IORESOURCE_MEM, 741 res = platform_get_resource(pdev, IORESOURCE_MEM,
837 PLAT_RESOURCE_IPC_INDEX); 742 PLAT_RESOURCE_IPC_INDEX);
838 if (!res) { 743 if (!res) {
839 dev_err(&pdev->dev, "Failed to get ipc resource\n"); 744 dev_err(&pdev->dev, "Failed to get IPC resources\n");
840 return -ENXIO; 745 return -ENXIO;
841 } 746 }
842 size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE; 747
843 res->end = res->start + size - 1; 748 res->end = res->start +
749 PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE - 1;
844 750
845 addr = devm_ioremap_resource(&pdev->dev, res); 751 addr = devm_ioremap_resource(&pdev->dev, res);
846 if (IS_ERR(addr)) 752 if (IS_ERR(addr))
847 return PTR_ERR(addr); 753 return PTR_ERR(addr);
848 754
849 ipcdev.ipc_base = addr; 755 ipcdev.ipc_base = addr;
850
851 ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; 756 ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET;
852 dev_info(&pdev->dev, "ipc res: %pR\n", res); 757 dev_dbg(&pdev->dev, "PMC IPC resource %pR\n", res);
853
854 ipcdev.telem_res_inval = 0;
855 res = platform_get_resource(pdev, IORESOURCE_MEM,
856 PLAT_RESOURCE_TELEM_SSRAM_INDEX);
857 if (!res) {
858 dev_err(&pdev->dev, "Failed to get telemetry ssram resource\n");
859 ipcdev.telem_res_inval = 1;
860 } else {
861 ipcdev.telem_punit_ssram_base = res->start +
862 TELEM_PUNIT_SSRAM_OFFSET;
863 ipcdev.telem_punit_ssram_size = TELEM_SSRAM_SIZE;
864 ipcdev.telem_pmc_ssram_base = res->start +
865 TELEM_PMC_SSRAM_OFFSET;
866 ipcdev.telem_pmc_ssram_size = TELEM_SSRAM_SIZE;
867 dev_info(&pdev->dev, "telemetry ssram res: %pR\n", res);
868 }
869 758
870 return 0; 759 return 0;
871} 760}
@@ -911,7 +800,7 @@ static int ipc_plat_probe(struct platform_device *pdev)
911 800
912 ipcdev.irq = platform_get_irq(pdev, 0); 801 ipcdev.irq = platform_get_irq(pdev, 0);
913 if (ipcdev.irq < 0) { 802 if (ipcdev.irq < 0) {
914 dev_err(&pdev->dev, "Failed to get irq\n"); 803 dev_err(&pdev->dev, "Failed to get IRQ\n");
915 return -EINVAL; 804 return -EINVAL;
916 } 805 }
917 806
@@ -921,47 +810,38 @@ static int ipc_plat_probe(struct platform_device *pdev)
921 return ret; 810 return ret;
922 } 811 }
923 812
924 ret = ipc_create_pmc_devices(); 813 ret = ipc_create_pmc_devices(pdev);
925 if (ret) { 814 if (ret) {
926 dev_err(&pdev->dev, "Failed to create pmc devices\n"); 815 dev_err(&pdev->dev, "Failed to create PMC devices\n");
927 return ret; 816 return ret;
928 } 817 }
929 818
930 if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND, 819 ret = devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND,
931 "intel_pmc_ipc", &ipcdev)) { 820 "intel_pmc_ipc", &ipcdev);
932 dev_err(&pdev->dev, "Failed to request irq\n"); 821 if (ret) {
933 ret = -EBUSY; 822 dev_err(&pdev->dev, "Failed to request IRQ\n");
934 goto err_irq; 823 return ret;
935 } 824 }
936 825
937 ret = sysfs_create_group(&pdev->dev.kobj, &intel_ipc_group); 826 ret = sysfs_create_group(&pdev->dev.kobj, &intel_ipc_group);
938 if (ret) { 827 if (ret) {
939 dev_err(&pdev->dev, "Failed to create sysfs group %d\n", 828 dev_err(&pdev->dev, "Failed to create sysfs group %d\n",
940 ret); 829 ret);
941 goto err_sys; 830 devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);
831 return ret;
942 } 832 }
943 833
944 ipcdev.has_gcr_regs = true; 834 ipcdev.has_gcr_regs = true;
945 835
946 return 0; 836 return 0;
947err_sys:
948 devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);
949err_irq:
950 platform_device_unregister(ipcdev.tco_dev);
951 platform_device_unregister(ipcdev.punit_dev);
952 platform_device_unregister(ipcdev.telemetry_dev);
953
954 return ret;
955} 837}
956 838
957static int ipc_plat_remove(struct platform_device *pdev) 839static int ipc_plat_remove(struct platform_device *pdev)
958{ 840{
959 sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group); 841 sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group);
960 devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); 842 devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);
961 platform_device_unregister(ipcdev.tco_dev);
962 platform_device_unregister(ipcdev.punit_dev);
963 platform_device_unregister(ipcdev.telemetry_dev);
964 ipcdev.dev = NULL; 843 ipcdev.dev = NULL;
844
965 return 0; 845 return 0;
966} 846}
967 847
@@ -980,12 +860,12 @@ static int __init intel_pmc_ipc_init(void)
980 860
981 ret = platform_driver_register(&ipc_plat_driver); 861 ret = platform_driver_register(&ipc_plat_driver);
982 if (ret) { 862 if (ret) {
983 pr_err("Failed to register PMC ipc platform driver\n"); 863 pr_err("Failed to register PMC IPC platform driver\n");
984 return ret; 864 return ret;
985 } 865 }
986 ret = pci_register_driver(&ipc_pci_driver); 866 ret = pci_register_driver(&ipc_pci_driver);
987 if (ret) { 867 if (ret) {
988 pr_err("Failed to register PMC ipc pci driver\n"); 868 pr_err("Failed to register PMC IPC PCI driver\n");
989 platform_driver_unregister(&ipc_plat_driver); 869 platform_driver_unregister(&ipc_plat_driver);
990 return ret; 870 return ret;
991 } 871 }