> -----Original Message-----
> From: sathyanarayanan kuppuswamy
> [mailto:[email protected]]
> Sent: Thursday, August 3, 2017 3:29 AM
> To: Chakravarty, Souvik K <[email protected]>;
> [email protected]; [email protected]; Zha, Qipeng
> <[email protected]>; [email protected]; [email protected];
> [email protected]; [email protected]
> Cc: [email protected]; [email protected];
> [email protected]
> Subject: Re: [RFC v1 3/6] platform/x86: intel_pmc_ipc: Use MFD framework
> to create dependent devices
> 
> 
> 
> On 08/01/2017 10:14 PM, Chakravarty, Souvik K wrote:
> >
> >> -----Original Message-----
> >> From: [email protected]
> >> [mailto:platform-driver- [email protected]] On Behalf Of
> >> [email protected]
> >> Sent: Tuesday, August 1, 2017 11:44 PM
> >> To: [email protected]; [email protected]; Zha, Qipeng
> >> <[email protected]>; [email protected]; [email protected];
> >> [email protected]; [email protected]
> >> Cc: [email protected];
> >> [email protected];
> >> [email protected]; Kuppuswamy Sathyanarayanan
> >> <[email protected]>
> >> Subject: [RFC v1 3/6] platform/x86: intel_pmc_ipc: Use MFD framework
> >> to create dependent devices
> >>
> >> From: Kuppuswamy Sathyanarayanan
> >> <[email protected]>
> >>
> >> 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
> >> <[email protected]>
> >> ---
> >>   drivers/platform/x86/intel_pmc_ipc.c | 376
> >> +++++++++++++-------------------
> >> ---
> >>   1 file changed, 141 insertions(+), 235 deletions(-)
> >>
> >> diff --git a/drivers/platform/x86/intel_pmc_ipc.c
> >> b/drivers/platform/x86/intel_pmc_ipc.c
> >> index ad0416e..43533ec 100644
> >> --- a/drivers/platform/x86/intel_pmc_ipc.c
> >> +++ b/drivers/platform/x86/intel_pmc_ipc.c
> >> @@ -33,6 +33,7 @@
> >>   #include <linux/suspend.h>
> >>   #include <linux/acpi.h>
> >>   #include <linux/io-64-nonatomic-lo-hi.h>
> >> +#include <linux/mfd/core.h>
> >>
> >>   #include <asm/intel_pmc_ipc.h>
> >>
> >> @@ -105,8 +106,6 @@
> >>   #define TELEM_SSRAM_SIZE         240
> >>   #define TELEM_PMC_SSRAM_OFFSET           0x1B00
> >>   #define TELEM_PUNIT_SSRAM_OFFSET 0x1A00
> >> -#define TCO_PMC_OFFSET                    0x8
> >> -#define TCO_PMC_SIZE                      0x4
> >>
> >>   /* PMC register bit definitions */
> >>
> >> @@ -115,6 +114,13 @@
> >>   #define PMC_CFG_NO_REBOOT_EN             (1 << 4)
> >>   #define PMC_CFG_NO_REBOOT_DIS            (0 << 4)
> >>
> >> +enum {
> >> +  PMC_IPC_PUNIT_MFD_BLOCK,
> >> +  PMC_IPC_WATCHDOG_MFD_BLOCK,
> >> +  PMC_IPC_TELEMETRY_MFD_BLOCK,
> >> +  PMC_IPC_MAX_MFD_BLOCK
> >> +};
> >> +
> >>   static struct intel_pmc_ipc_dev {
> >>    struct device *dev;
> >>    void __iomem *ipc_base;
> >> @@ -123,25 +129,12 @@ static struct intel_pmc_ipc_dev {
> >>    int cmd;
> >>    struct completion cmd_complete;
> >>
> >> -  /* The following PMC BARs share the same ACPI device with the IPC
> >> */
> >> -  resource_size_t acpi_io_base;
> >> -  int acpi_io_size;
> >> -  struct platform_device *tco_dev;
> >> -
> >>    /* gcr */
> >>    void __iomem *gcr_mem_base;
> >>    bool has_gcr_regs;
> >>
> >> -  /* punit */
> >> -  struct platform_device *punit_dev;
> >> -
> >>    /* Telemetry */
> >> -  resource_size_t telem_pmc_ssram_base;
> >> -  resource_size_t telem_punit_ssram_base;
> >> -  int telem_pmc_ssram_size;
> >> -  int telem_punit_ssram_size;
> >>    u8 telem_res_inval;
> >> -  struct platform_device *telemetry_dev;
> >>   } ipcdev;
> >>
> >>   static char *ipc_err_sources[] = {
> >> @@ -613,7 +606,7 @@ static const struct attribute_group
> >> intel_ipc_group = {
> >>    .attrs = intel_ipc_attrs,
> >>   };
> >>
> >> -static struct resource punit_res_array[] = {
> >> +static struct resource punit_ipc_resources[] = {
> >>    /* Punit BIOS */
> >>    {
> >>            .flags = IORESOURCE_MEM,
> >> @@ -637,10 +630,7 @@ static struct resource punit_res_array[] = {
> >>    },
> >>   };
> >>
> >> -#define TCO_RESOURCE_ACPI_IO              0
> >> -#define TCO_RESOURCE_SMI_EN_IO            1
> >> -#define TCO_RESOURCE_GCR_MEM              2
> >> -static struct resource tco_res[] = {
> >> +static struct resource watchdog_ipc_resources[] = {
> >>    /* ACPI - TCO */
> >>    {
> >>            .flags = IORESOURCE_IO,
> >> @@ -658,9 +648,7 @@ static struct itco_wdt_platform_data tco_info =
> {
> >>    .update_no_reboot_bit = update_no_reboot_bit,  };
> >>
> >> -#define TELEMETRY_RESOURCE_PUNIT_SSRAM    0
> >> -#define TELEMETRY_RESOURCE_PMC_SSRAM      1
> >> -static struct resource telemetry_res[] = {
> >> +static struct resource telemetry_ipc_resources[] = {
> >>    /*Telemetry*/
> >>    {
> >>            .flags = IORESOURCE_MEM,
> >> @@ -670,224 +658,152 @@ static struct resource telemetry_res[] = {
> >>    },
> >>   };
> >>
> >> -static int ipc_create_punit_device(void) -{
> >> -  struct platform_device *pdev;
> >> -  const struct platform_device_info pdevinfo = {
> >> -          .parent = ipcdev.dev,
> >> -          .name = PUNIT_DEVICE_NAME,
> >> -          .id = -1,
> >> -          .res = punit_res_array,
> >> -          .num_res = ARRAY_SIZE(punit_res_array),
> >> -          };
> >> -
> >> -  pdev = platform_device_register_full(&pdevinfo);
> >> -  if (IS_ERR(pdev))
> >> -          return PTR_ERR(pdev);
> >> -
> >> -  ipcdev.punit_dev = pdev;
> >> -
> >> -  return 0;
> >> -}
> >> -
> >> -static int ipc_create_tco_device(void) -{
> >> -  struct platform_device *pdev;
> >> -  struct resource *res;
> >> -  const struct platform_device_info pdevinfo = {
> >> -          .parent = ipcdev.dev,
> >> -          .name = TCO_DEVICE_NAME,
> >> -          .id = -1,
> >> -          .res = tco_res,
> >> -          .num_res = ARRAY_SIZE(tco_res),
> >> -          .data = &tco_info,
> >> -          .size_data = sizeof(tco_info),
> >> -          };
> >> -
> >> -  res = tco_res + TCO_RESOURCE_ACPI_IO;
> >> -  res->start = ipcdev.acpi_io_base + TCO_BASE_OFFSET;
> >> -  res->end = res->start + TCO_REGS_SIZE - 1;
> >> -
> >> -  res = tco_res + TCO_RESOURCE_SMI_EN_IO;
> >> -  res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET;
> >> -  res->end = res->start + SMI_EN_SIZE - 1;
> >> -
> >> -  pdev = platform_device_register_full(&pdevinfo);
> >> -  if (IS_ERR(pdev))
> >> -          return PTR_ERR(pdev);
> >> -
> >> -  ipcdev.tco_dev = pdev;
> >> -
> >> -  return 0;
> >> -}
> >> -
> >> -static int ipc_create_telemetry_device(void) -{
> >> -  struct platform_device *pdev;
> >> -  struct resource *res;
> >> -  const struct platform_device_info pdevinfo = {
> >> -          .parent = ipcdev.dev,
> >> -          .name = TELEMETRY_DEVICE_NAME,
> >> -          .id = -1,
> >> -          .res = telemetry_res,
> >> -          .num_res = ARRAY_SIZE(telemetry_res),
> >> -          };
> >> -
> >> -  res = telemetry_res + TELEMETRY_RESOURCE_PUNIT_SSRAM;
> >> -  res->start = ipcdev.telem_punit_ssram_base;
> >> -  res->end = res->start + ipcdev.telem_punit_ssram_size - 1;
> >> -
> >> -  res = telemetry_res + TELEMETRY_RESOURCE_PMC_SSRAM;
> >> -  res->start = ipcdev.telem_pmc_ssram_base;
> >> -  res->end = res->start + ipcdev.telem_pmc_ssram_size - 1;
> >> -
> >> -  pdev = platform_device_register_full(&pdevinfo);
> >> -  if (IS_ERR(pdev))
> >> -          return PTR_ERR(pdev);
> >> -
> >> -  ipcdev.telemetry_dev = pdev;
> >> -
> >> -  return 0;
> >> -}
> >> -
> >> -static int ipc_create_pmc_devices(void)
> >> +static int ipc_create_pmc_devices(struct platform_device *pdev)
> >>   {
> >> -  int ret;
> >> -
> >> -  /* If we have ACPI based watchdog use that instead */
> >> +  u8 n = 0;
> >> +  struct mfd_cell *pmc_mfd_cells;
> >> +
> >> +  pmc_mfd_cells = devm_kzalloc(&pdev->dev,
> >> +                  (sizeof(*pmc_mfd_cells) *
> >> PMC_IPC_MAX_MFD_BLOCK),
> >> +                  GFP_KERNEL);
> >> +  if (!pmc_mfd_cells)
> >> +          return -ENOMEM;
> >> +
> >> +  /* Create PUNIT IPC MFD cell */
> >> +  pmc_mfd_cells[n].name = PUNIT_DEVICE_NAME;
> >> +  pmc_mfd_cells[n].id = -1;
> >> +  pmc_mfd_cells[n].num_resources =
> >> ARRAY_SIZE(punit_ipc_resources);
> >> +  pmc_mfd_cells[n].resources = punit_ipc_resources;
> >> +  pmc_mfd_cells[n].ignore_resource_conflicts = 1;
> >> +  n++;
> > Since it's not really a loop, cant the enum values of MFD block be used
> instead of 'n'? Will be more readable/intuitive.
> In this case, watchdog and telemetry device creation is optional and hence
> we can't use fixed index when creating mfd-cells. If one of these devices is
> not available then the number of valid-mfd-cells and the index number of
> individual device cell in pmc_mfd_cells array will change.
Agreed. I read in a hurry.

> >
> >> +
> >> +  /* If we have ACPI based watchdog use that instead, othewise
> >> create
> >> +   * a MFD cell for iTCO watchdog*/
> >>    if (!acpi_has_watchdog()) {
> >> -          ret = ipc_create_tco_device();
> >> -          if (ret) {
> >> -                  dev_err(ipcdev.dev, "Failed to add tco platform
> >> device\n");
> >> -                  return ret;
> >> -          }
> >> -  }
> >> -
> >> -  ret = ipc_create_punit_device();
> >> -  if (ret) {
> >> -          dev_err(ipcdev.dev, "Failed to add punit platform
> >> device\n");
> >> -          platform_device_unregister(ipcdev.tco_dev);
> >> +          pmc_mfd_cells[n].name = TCO_DEVICE_NAME;
> >> +          pmc_mfd_cells[n].id = -1;
> >> +          pmc_mfd_cells[n].platform_data = &tco_info;
> >> +          pmc_mfd_cells[n].pdata_size = sizeof(tco_info);
> >> +          pmc_mfd_cells[n].num_resources =
> >> +                  ARRAY_SIZE(watchdog_ipc_resources);
> >> +          pmc_mfd_cells[n].resources = watchdog_ipc_resources;
> >> +          pmc_mfd_cells[n].ignore_resource_conflicts = 1;
> >> +          n++;
> > Same as above.
> Same as above.
> >
> >>    }
> >>
> >>    if (!ipcdev.telem_res_inval) {
> >> -          ret = ipc_create_telemetry_device();
> >> -          if (ret)
> >> -                  dev_warn(ipcdev.dev,
> >> -                          "Failed to add telemetry platform
> >> device\n");
> >> +          pmc_mfd_cells[n].name = TELEMETRY_DEVICE_NAME;
> >> +          pmc_mfd_cells[n].id = -1;
> >> +          pmc_mfd_cells[n].num_resources =
> >> +                  ARRAY_SIZE(telemetry_ipc_resources);
> >> +          pmc_mfd_cells[n].resources = telemetry_ipc_resources;
> >> +          pmc_mfd_cells[n].ignore_resource_conflicts = 1;
> >> +          n++;
> > Same as above.
> Same as above.
> >>    }
> >>
> >> -  return ret;
> >> +  return devm_mfd_add_devices(&pdev->dev, -1, pmc_mfd_cells, n,
> >> NULL,
> >> +                              0, NULL);
> >>   }
> >>
> >>   static int ipc_plat_get_res(struct platform_device *pdev)  {
> >> -  struct resource *res, *punit_res;
> >> +  struct resource *res;
> >>    void __iomem *addr;
> >> -  int size;
> >> +  int mindex, pindex = 0;
> >>
> >> +  /* Get iTCO watchdog resources */
> >>    res = platform_get_resource(pdev, IORESOURCE_IO,
> >>                                PLAT_RESOURCE_ACPI_IO_INDEX);
> >>    if (!res) {
> >>            dev_err(&pdev->dev, "Failed to get io resource\n");
> >>            return -ENXIO;
> >>    }
> >> -  size = resource_size(res);
> >> -  ipcdev.acpi_io_base = res->start;
> >> -  ipcdev.acpi_io_size = size;
> >> -  dev_info(&pdev->dev, "io res: %pR\n", res);
> >> -
> >> -  punit_res = punit_res_array;
> >> -  /* This is index 0 to cover BIOS data register */
> >> -  res = platform_get_resource(pdev, IORESOURCE_MEM,
> >> -                              PLAT_RESOURCE_BIOS_DATA_INDEX);
> >> -  if (!res) {
> >> -          dev_err(&pdev->dev, "Failed to get res of punit BIOS
> >> data\n");
> >> -          return -ENXIO;
> >> -  }
> >> -  *punit_res = *res;
> >> -  dev_info(&pdev->dev, "punit BIOS data res: %pR\n", res);
> >> -
> >> -  /* This is index 1 to cover BIOS interface register */
> >> -  res = platform_get_resource(pdev, IORESOURCE_MEM,
> >> -                              PLAT_RESOURCE_BIOS_IFACE_INDEX);
> >> -  if (!res) {
> >> -          dev_err(&pdev->dev, "Failed to get res of punit BIOS
> >> iface\n");
> >> -          return -ENXIO;
> >> -  }
> >> -  *++punit_res = *res;
> >> -  dev_info(&pdev->dev, "punit BIOS interface res: %pR\n", res);
> >> -
> >> -  /* This is index 2 to cover ISP data register, optional */
> >> -  res = platform_get_resource(pdev, IORESOURCE_MEM,
> >> -                              PLAT_RESOURCE_ISP_DATA_INDEX);
> >> -  ++punit_res;
> >> -  if (res) {
> >> -          *punit_res = *res;
> >> -          dev_info(&pdev->dev, "punit ISP data res: %pR\n", res);
> >> -  }
> >>
> >> -  /* This is index 3 to cover ISP interface register, optional */
> >> -  res = platform_get_resource(pdev, IORESOURCE_MEM,
> >> -                              PLAT_RESOURCE_ISP_IFACE_INDEX);
> >> -  ++punit_res;
> >> -  if (res) {
> >> -          *punit_res = *res;
> >> -          dev_info(&pdev->dev, "punit ISP interface res: %pR\n", res);
> >> -  }
> >> -
> >> -  /* This is index 4 to cover GTD data register, optional */
> >> -  res = platform_get_resource(pdev, IORESOURCE_MEM,
> >> -                              PLAT_RESOURCE_GTD_DATA_INDEX);
> >> -  ++punit_res;
> >> -  if (res) {
> >> -          *punit_res = *res;
> >> -          dev_info(&pdev->dev, "punit GTD data res: %pR\n", res);
> >> -  }
> >> -
> >> -  /* This is index 5 to cover GTD interface register, optional */
> >> -  res = platform_get_resource(pdev, IORESOURCE_MEM,
> >> -                              PLAT_RESOURCE_GTD_IFACE_INDEX);
> >> -  ++punit_res;
> >> -  if (res) {
> >> -          *punit_res = *res;
> >> -          dev_info(&pdev->dev, "punit GTD interface res: %pR\n",
> >> res);
> >> -  }
> >> -
> >> -  res = platform_get_resource(pdev, IORESOURCE_MEM,
> >> -                              PLAT_RESOURCE_IPC_INDEX);
> >> -  if (!res) {
> >> -          dev_err(&pdev->dev, "Failed to get ipc resource\n");
> >> -          return -ENXIO;
> >> -  }
> >> -  res->end = (res->start + PLAT_RESOURCE_IPC_SIZE +
> >> -              PLAT_RESOURCE_GCR_SIZE - 1);
> >> -
> >> -  addr = devm_ioremap_resource(&pdev->dev, res);
> >> -  if (IS_ERR(addr)) {
> >> -          dev_err(&pdev->dev,
> >> -                  "PMC I/O memory remapping failed\n");
> >> -          return PTR_ERR(addr);
> >> -  }
> >> -
> >> -  ipcdev.ipc_base = addr;
> >> -
> >> -  ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET;
> >> -  dev_info(&pdev->dev, "ipc res: %pR\n", res);
> >> -
> >> -  ipcdev.telem_res_inval = 0;
> >> -  res = platform_get_resource(pdev, IORESOURCE_MEM,
> >> -                              PLAT_RESOURCE_TELEM_SSRAM_INDEX);
> >> -  if (!res) {
> >> -          dev_err(&pdev->dev, "Failed to get telemetry ssram
> >> resource\n");
> >> -          ipcdev.telem_res_inval = 1;
> >> -  } else {
> >> -          ipcdev.telem_punit_ssram_base = res->start +
> >> -
> >>    TELEM_PUNIT_SSRAM_OFFSET;
> >> -          ipcdev.telem_punit_ssram_size = TELEM_SSRAM_SIZE;
> >> -          ipcdev.telem_pmc_ssram_base = res->start +
> >> -
> >>    TELEM_PMC_SSRAM_OFFSET;
> >> -          ipcdev.telem_pmc_ssram_size = TELEM_SSRAM_SIZE;
> >> -          dev_info(&pdev->dev, "telemetry ssram res: %pR\n", res);
> >> +  watchdog_ipc_resources[0].start = res->start + TCO_BASE_OFFSET;
> >> +  watchdog_ipc_resources[0].end = res->start +
> >> +          TCO_BASE_OFFSET + TCO_REGS_SIZE - 1;
> >> +  watchdog_ipc_resources[1].start = res->start + SMI_EN_OFFSET;
> >> +  watchdog_ipc_resources[1].end = res->start +
> >> +          SMI_EN_OFFSET + SMI_EN_SIZE - 1;
> > The 0/1 magic may be replaced with MACROS here and elsewhere.
> I think I tried it first and then later removed it because the length of few
> lines go over and 80.
> >
> >> +
> >> +  dev_info(&pdev->dev, "watchdog res 0: %pR\n",
> >> +                  &watchdog_ipc_resources[0]);
> >> +  dev_info(&pdev->dev, "watchdog res 1: %pR\n",
> >> +                  &watchdog_ipc_resources[1]);
> >> +
> >> +  for (mindex = 0; mindex <= PLAT_RESOURCE_GTD_IFACE_INDEX;
> >> mindex++) {
> > Here we are relying on the fact that the GTD_IFACE_INDEX is at offset 7.
> It's however not by design but a side-effect of how the BIOS places the
> resources.
> > So perhaps not a good idea to use it, since GTD_IFACE is not meant to be
> a terminator/max delimiter.
> We can add a new macro like  "#define PLAT_RESOURCE_MAX_INDEX 8"
> and use it in this loop.
> 
> But, In future, If BIOS changes its resource order or removes certain
> resources then it needs corresponding changes to this driver. And when
> they fix that issue, they have to make sure the MAX_INDEX value is
> appropriately modified.
> 
> So even using separate macro doesn't completely isolates it from BIOS
> resource changes.

Well you are right as far as changing the MACRO value is. 
But using a MAX_INDEX is intuitive and changing the MAX_INDEX value is also 
intuitive.
OTOH if you maintain the GTD_IFACE, you have to change the loop delimiter to a 
different IFACE's (e.g. ISP_DATA) every time the BIOS changes and this seems to 
be a bit strange, esp. when only the index max value has changed.
Isn't the above case exactly not what a MAX macro is designed to do?

> >
> >> +
> >> +          res = platform_get_resource(pdev, IORESOURCE_MEM,
> >> mindex);
> >> +
> >> +          switch (mindex) {
> >> +          /* Get PUNIT resources */
> >> +          case PLAT_RESOURCE_BIOS_DATA_INDEX:
> >> +          case PLAT_RESOURCE_BIOS_IFACE_INDEX:
> >> +                  /* BIOS resources are required, so return error if not
> >> +                   * available */
> >> +                  if (!res) {
> >> +                          dev_err(&pdev->dev,
> >> +                                  "Failed to get punit mem resource
> >> %d\n",
> >> +                                  pindex);
> >> +                          return -ENXIO;
> >> +                  }
> >> +          case PLAT_RESOURCE_ISP_DATA_INDEX:
> >> +          case PLAT_RESOURCE_ISP_IFACE_INDEX:
> >> +          case PLAT_RESOURCE_GTD_DATA_INDEX:
> >> +          case PLAT_RESOURCE_GTD_IFACE_INDEX:
> >> +                  /* if not valid resource, skip the rest of steps */
> >> +                  if (!res) {
> >> +                          pindex++;
> >> +                          continue;
> >> +                  }
> >> +                  memcpy(&punit_ipc_resources[pindex], res,
> >> +                                  sizeof(*res));
> >> +                  dev_info(&pdev->dev, "PUNIT memory res: %pR\n",
> >> +                                  &punit_ipc_resources[pindex]);
> >> +                  pindex++;
> >> +                  break;
> >> +          /* Get Telemetry resources */
> >> +          case PLAT_RESOURCE_TELEM_SSRAM_INDEX:
> >> +                  if (!res) {
> >> +                          dev_warn(&pdev->dev,
> >> +                                  "Failed to get telemtry sram res\n");
> >> +                          ipcdev.telem_res_inval = 1;
> >> +                          continue;
> >> +                  }
> >> +                  telemetry_ipc_resources[0].start = res->start +
> >> +                          TELEM_PUNIT_SSRAM_OFFSET;
> >> +                  telemetry_ipc_resources[0].end = res->start +
> >> +                          TELEM_PUNIT_SSRAM_OFFSET +
> >> TELEM_SSRAM_SIZE - 1;
> >> +                  telemetry_ipc_resources[1].start = res->start +
> >> +                          TELEM_PMC_SSRAM_OFFSET;
> >> +                  telemetry_ipc_resources[1].end = res->start +
> >> +                          TELEM_PMC_SSRAM_OFFSET +
> >> TELEM_SSRAM_SIZE - 1;
> >> +
> >> +                  dev_info(&pdev->dev, "telemetry punit ssram res:
> >> %pR\n",
> >> +                                  &telemetry_ipc_resources[0]);
> >> +                  dev_info(&pdev->dev, "telemetry pmc ssram res:
> >> %pR\n",
> >> +                                  &telemetry_ipc_resources[1]);
> >> +                  break;
> >> +          /* Get IPC resources */
> >> +          case PLAT_RESOURCE_IPC_INDEX:
> >> +                  if (!res) {
> >> +                          dev_err(&pdev->dev,
> >> +                                  "Failed to get IPC resources\n");
> >> +                          return -ENXIO;
> >> +                  }
> >> +                  res->end = (res->start + PLAT_RESOURCE_IPC_SIZE +
> >> +                              PLAT_RESOURCE_GCR_SIZE - 1);
> >> +                  addr = devm_ioremap_resource(&pdev->dev, res);
> >> +                  if (IS_ERR(addr)) {
> >> +                          dev_err(&pdev->dev,
> >> +                                  "PMC I/O memory remapping
> >> failed\n");
> >> +                          return PTR_ERR(addr);
> >> +                  }
> >> +                  ipcdev.ipc_base = addr;
> >> +                  ipcdev.gcr_mem_base = addr +
> >> PLAT_RESOURCE_GCR_OFFSET;
> >> +                  dev_info(&pdev->dev, "PMC IPC resource %pR\n",
> >> res);
> >> +                  break;
> >> +          };
> >>    }
> >>
> >>    return 0;
> >> @@ -943,7 +859,7 @@ static int ipc_plat_probe(struct platform_device
> >> *pdev)
> >>            return ret;
> >>    }
> >>
> >> -  ret = ipc_create_pmc_devices();
> >> +  ret = ipc_create_pmc_devices(pdev);
> >>    if (ret) {
> >>            dev_err(&pdev->dev, "Failed to create pmc devices\n");
> >>            return ret;
> >> @@ -952,36 +868,26 @@ static int ipc_plat_probe(struct
> >> platform_device
> >> *pdev)
> >>    if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc,
> IRQF_NO_SUSPEND,
> >>                         "intel_pmc_ipc", &ipcdev)) {
> >>            dev_err(&pdev->dev, "Failed to request irq\n");
> >> -          ret = -EBUSY;
> >> -          goto unregister_devices;
> >> +          return -EBUSY;
> >>    }
> >>
> >>    ret = sysfs_create_group(&pdev->dev.kobj, &intel_ipc_group);
> >>    if (ret) {
> >>            dev_err(&pdev->dev, "Failed to create sysfs group %d\n",
> >>                    ret);
> >> -          goto unregister_devices;
> >> +          return ret;
> >>    }
> >>
> >>    ipcdev.has_gcr_regs = true;
> >>
> >>    return 0;
> >> -
> >> -unregister_devices:
> >> -  platform_device_unregister(ipcdev.tco_dev);
> >> -  platform_device_unregister(ipcdev.punit_dev);
> >> -  platform_device_unregister(ipcdev.telemetry_dev);
> >> -
> >> -  return ret;
> >>   }
> >>
> >>   static int ipc_plat_remove(struct platform_device *pdev)  {
> >>    sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group);
> >> -  platform_device_unregister(ipcdev.tco_dev);
> >> -  platform_device_unregister(ipcdev.punit_dev);
> >> -  platform_device_unregister(ipcdev.telemetry_dev);
> >>    ipcdev.dev = NULL;
> >> +
> >>    return 0;
> >>   }
> >>
> >> --
> >> 2.7.4
> >
> 
> --
> Sathyanarayanan Kuppuswamy
> Linux kernel developer

Reply via email to