spmi: pmic-arb: Make core resources acquiring a version operation
authorAbel Vesa <abel.vesa@linaro.org>
Tue, 7 May 2024 21:07:47 +0000 (14:07 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 8 May 2024 18:46:10 +0000 (19:46 +0100)
Rather than setting up the core, obsrv and chnls in probe by using
version specific conditionals, add a dedicated "get_core_resources"
version specific op and move the acquiring in there. Since there are
no current users of the second bus yet, drop the comment about why
devm_platform_ioremap_resource can't be used in case of "core",
as it is not applicable anymore.
Don't switch to devm_platform_ioremap_resource though as we need
to keep track of core size.

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
Link: https://lore.kernel.org/r/20240417-spmi-multi-master-support-v10-5-5bc6d322e266@linaro.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Link: https://lore.kernel.org/r/20240507210809.3479953-11-sboyd@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/spmi/spmi-pmic-arb.c

index fe45d62a42e25eb79a8aaf8b04f326c489386b99..db33ca0e11b8de03671ff010a5dcb5c904edb3ac 100644 (file)
@@ -186,6 +186,7 @@ struct spmi_pmic_arb {
  * struct pmic_arb_ver_ops - version dependent functionality.
  *
  * @ver_str:           version string.
+ * @get_core_resources:        initializes the core, observer and channels
  * @init_apid:         finds the apid base and count
  * @ppid_to_apid:      finds the apid for a given ppid.
  * @non_data_cmd:      on v1 issues an spmi non-data command.
@@ -206,6 +207,7 @@ struct spmi_pmic_arb {
  */
 struct pmic_arb_ver_ops {
        const char *ver_str;
+       int (*get_core_resources)(struct platform_device *pdev, void __iomem *core);
        int (*init_apid)(struct spmi_pmic_arb *pmic_arb);
        int (*ppid_to_apid)(struct spmi_pmic_arb *pmic_arb, u16 ppid);
        /* spmi commands (read_cmd, write_cmd, cmd) functionality */
@@ -961,6 +963,19 @@ static int pmic_arb_init_apid_min_max(struct spmi_pmic_arb *pmic_arb)
        return 0;
 }
 
+static int pmic_arb_get_core_resources_v1(struct platform_device *pdev,
+                                         void __iomem *core)
+{
+       struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
+
+       pmic_arb->wr_base = core;
+       pmic_arb->rd_base = core;
+
+       pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS;
+
+       return 0;
+}
+
 static int pmic_arb_init_apid_v1(struct spmi_pmic_arb *pmic_arb)
 {
        u32 *mapping_table;
@@ -1062,6 +1077,33 @@ static u16 pmic_arb_find_apid(struct spmi_pmic_arb *pmic_arb, u16 ppid)
        return apid;
 }
 
+static int pmic_arb_get_obsrvr_chnls_v2(struct platform_device *pdev)
+{
+       struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
+
+       pmic_arb->rd_base = devm_platform_ioremap_resource_byname(pdev, "obsrvr");
+       if (IS_ERR(pmic_arb->rd_base))
+               return PTR_ERR(pmic_arb->rd_base);
+
+       pmic_arb->wr_base = devm_platform_ioremap_resource_byname(pdev, "chnls");
+       if (IS_ERR(pmic_arb->wr_base))
+               return PTR_ERR(pmic_arb->wr_base);
+
+       return 0;
+}
+
+static int pmic_arb_get_core_resources_v2(struct platform_device *pdev,
+                                         void __iomem *core)
+{
+       struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
+
+       pmic_arb->core = core;
+
+       pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS;
+
+       return pmic_arb_get_obsrvr_chnls_v2(pdev);
+}
+
 static int pmic_arb_ppid_to_apid_v2(struct spmi_pmic_arb *pmic_arb, u16 ppid)
 {
        u16 apid_valid;
@@ -1239,6 +1281,18 @@ static int pmic_arb_offset_v5(struct spmi_pmic_arb *pmic_arb, u8 sid, u16 addr,
        return offset;
 }
 
+static int pmic_arb_get_core_resources_v7(struct platform_device *pdev,
+                                         void __iomem *core)
+{
+       struct spmi_pmic_arb *pmic_arb = platform_get_drvdata(pdev);
+
+       pmic_arb->core = core;
+
+       pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS_V7;
+
+       return pmic_arb_get_obsrvr_chnls_v2(pdev);
+}
+
 /*
  * v7 offset per ee and per apid for observer channels and per apid for
  * read/write channels.
@@ -1419,6 +1473,7 @@ pmic_arb_apid_owner_v7(struct spmi_pmic_arb *pmic_arb, u16 n)
 
 static const struct pmic_arb_ver_ops pmic_arb_v1 = {
        .ver_str                = "v1",
+       .get_core_resources     = pmic_arb_get_core_resources_v1,
        .init_apid              = pmic_arb_init_apid_v1,
        .ppid_to_apid           = pmic_arb_ppid_to_apid_v1,
        .non_data_cmd           = pmic_arb_non_data_cmd_v1,
@@ -1434,6 +1489,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v1 = {
 
 static const struct pmic_arb_ver_ops pmic_arb_v2 = {
        .ver_str                = "v2",
+       .get_core_resources     = pmic_arb_get_core_resources_v2,
        .init_apid              = pmic_arb_init_apid_v1,
        .ppid_to_apid           = pmic_arb_ppid_to_apid_v2,
        .non_data_cmd           = pmic_arb_non_data_cmd_v2,
@@ -1449,6 +1505,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v2 = {
 
 static const struct pmic_arb_ver_ops pmic_arb_v3 = {
        .ver_str                = "v3",
+       .get_core_resources     = pmic_arb_get_core_resources_v2,
        .init_apid              = pmic_arb_init_apid_v1,
        .ppid_to_apid           = pmic_arb_ppid_to_apid_v2,
        .non_data_cmd           = pmic_arb_non_data_cmd_v2,
@@ -1464,6 +1521,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v3 = {
 
 static const struct pmic_arb_ver_ops pmic_arb_v5 = {
        .ver_str                = "v5",
+       .get_core_resources     = pmic_arb_get_core_resources_v2,
        .init_apid              = pmic_arb_init_apid_v5,
        .ppid_to_apid           = pmic_arb_ppid_to_apid_v5,
        .non_data_cmd           = pmic_arb_non_data_cmd_v2,
@@ -1479,6 +1537,7 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = {
 
 static const struct pmic_arb_ver_ops pmic_arb_v7 = {
        .ver_str                = "v7",
+       .get_core_resources     = pmic_arb_get_core_resources_v7,
        .init_apid              = pmic_arb_init_apid_v5,
        .ppid_to_apid           = pmic_arb_ppid_to_apid_v5,
        .non_data_cmd           = pmic_arb_non_data_cmd_v2,
@@ -1515,16 +1574,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
        pmic_arb = spmi_controller_get_drvdata(ctrl);
        pmic_arb->spmic = ctrl;
 
-       /*
-        * Please don't replace this with devm_platform_ioremap_resource() or
-        * devm_ioremap_resource().  These both result in a call to
-        * devm_request_mem_region() which prevents multiple mappings of this
-        * register address range.  SoCs with PMIC arbiter v7 may define two
-        * arbiter devices, for the two physical SPMI interfaces, which  share
-        * some register address ranges (i.e. "core", "obsrvr", and "chnls").
-        * Ensure that both devices probe successfully by calling devm_ioremap()
-        * which does not result in a devm_request_mem_region() call.
-        */
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
        core = devm_ioremap(&ctrl->dev, res->start, resource_size(res));
        if (!core)
@@ -1534,44 +1583,23 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
 
        hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
 
-       if (hw_ver < PMIC_ARB_VERSION_V2_MIN) {
+       if (hw_ver < PMIC_ARB_VERSION_V2_MIN)
                pmic_arb->ver_ops = &pmic_arb_v1;
-               pmic_arb->wr_base = core;
-               pmic_arb->rd_base = core;
-       } else {
-               pmic_arb->core = core;
-
-               if (hw_ver < PMIC_ARB_VERSION_V3_MIN)
-                       pmic_arb->ver_ops = &pmic_arb_v2;
-               else if (hw_ver < PMIC_ARB_VERSION_V5_MIN)
-                       pmic_arb->ver_ops = &pmic_arb_v3;
-               else if (hw_ver < PMIC_ARB_VERSION_V7_MIN)
-                       pmic_arb->ver_ops = &pmic_arb_v5;
-               else
-                       pmic_arb->ver_ops = &pmic_arb_v7;
-
-               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                                  "obsrvr");
-               pmic_arb->rd_base = devm_ioremap(&ctrl->dev, res->start,
-                                                resource_size(res));
-               if (!pmic_arb->rd_base)
-                       return -ENOMEM;
-
-               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                                  "chnls");
-               pmic_arb->wr_base = devm_ioremap(&ctrl->dev, res->start,
-                                                resource_size(res));
-               if (!pmic_arb->wr_base)
-                       return -ENOMEM;
-       }
+       else if (hw_ver < PMIC_ARB_VERSION_V3_MIN)
+               pmic_arb->ver_ops = &pmic_arb_v2;
+       else if (hw_ver < PMIC_ARB_VERSION_V5_MIN)
+               pmic_arb->ver_ops = &pmic_arb_v3;
+       else if (hw_ver < PMIC_ARB_VERSION_V7_MIN)
+               pmic_arb->ver_ops = &pmic_arb_v5;
+       else
+               pmic_arb->ver_ops = &pmic_arb_v7;
 
        dev_info(&ctrl->dev, "PMIC arbiter version %s (0x%x)\n",
                 pmic_arb->ver_ops->ver_str, hw_ver);
 
-       if (hw_ver < PMIC_ARB_VERSION_V7_MIN)
-               pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS;
-       else
-               pmic_arb->max_periphs = PMIC_ARB_MAX_PERIPHS_V7;
+       err = pmic_arb->ver_ops->get_core_resources(pdev, core);
+       if (err)
+               return err;
 
        err = pmic_arb->ver_ops->init_apid(pmic_arb);
        if (err)