Merge tag 'devicetree-for-6.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 27 Apr 2023 17:09:05 +0000 (10:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 27 Apr 2023 17:09:05 +0000 (10:09 -0700)
Pull more devicetree updates from Rob Herring:

 - First part of DT header detangling dropping cpu.h from of_device.h
   and replacing some includes with forward declarations. A handful of
   drivers needed some adjustment to their includes as a result.

 - Refactor of_device.h to be used by bus drivers rather than various
   device drivers. This moves non-bus related functions out of
   of_device.h. The end goal is for of_platform.h and of_device.h to
   stop including each other.

 - Refactor open coded parsing of "ranges" in some bus drivers to use DT
   address parsing functions

 - Add some new address parsing functions of_property_read_reg(),
   of_range_count(), and of_range_to_resource() in preparation to
   convert more open coded parsing of DT addresses to use them.

 - Treewide clean-ups to use of_property_read_bool() and
   of_property_present() as appropriate. The ones here are the ones that
   didn't get picked up elsewhere.

* tag 'devicetree-for-6.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (34 commits)
  bus: tegra-gmi: Replace of_platform.h with explicit includes
  hte: Use of_property_present() for testing DT property presence
  w1: w1-gpio: Use of_property_read_bool() for boolean properties
  virt: fsl: Use of_property_present() for testing DT property presence
  soc: fsl: Use of_property_present() for testing DT property presence
  sbus: display7seg: Use of_property_read_bool() for boolean properties
  sparc: Use of_property_read_bool() for boolean properties
  sparc: Use of_property_present() for testing DT property presence
  bus: mvebu-mbus: Remove open coded "ranges" parsing
  of/address: Add of_property_read_reg() helper
  of/address: Add of_range_count() helper
  of/address: Add support for 3 address cell bus
  of/address: Add of_range_to_resource() helper
  of: unittest: Add bus address range parsing tests
  of: Drop cpu.h include from of_device.h
  OPP: Adjust includes to remove of_device.h
  irqchip: loongson-eiointc: Add explicit include for cpuhotplug.h
  cpuidle: Adjust includes to remove of_device.h
  cpufreq: sun50i: Add explicit include for cpu.h
  cpufreq: Adjust includes to remove of_device.h
  ...

16 files changed:
1  2 
arch/riscv/kernel/setup.c
drivers/base/cacheinfo.c
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/pcc-cpufreq.c
drivers/cpufreq/pmac32-cpufreq.c
drivers/cpufreq/qcom-cpufreq-hw.c
drivers/cpufreq/tegra124-cpufreq.c
drivers/cpufreq/tegra20-cpufreq.c
drivers/cpuidle/cpuidle-riscv-sbi.c
drivers/irqchip/irq-loongson-eiointc.c
drivers/of/address.c
drivers/of/unittest.c
drivers/opp/of.c
drivers/soc/mediatek/mtk-svs.c
include/linux/cpufreq.h

index a059b73f4ddb263744e47774d0549efe24e5933c,dcfa4b6fa4b1ed7c3e79f3acc927dd4d7a516533..3020f44dcf58a58f9ab54a5a908c93ae6ca713b0
@@@ -8,6 -8,7 +8,7 @@@
   *  Nick Kossifidis <mick@ics.forth.gr>
   */
  
+ #include <linux/cpu.h>
  #include <linux/init.h>
  #include <linux/mm.h>
  #include <linux/memblock.h>
@@@ -15,7 -16,6 +16,6 @@@
  #include <linux/console.h>
  #include <linux/screen_info.h>
  #include <linux/of_fdt.h>
- #include <linux/of_platform.h>
  #include <linux/sched/task.h>
  #include <linux/smp.h>
  #include <linux/efi.h>
@@@ -278,8 -278,12 +278,8 @@@ void __init setup_arch(char **cmdline_p
  #if IS_ENABLED(CONFIG_BUILTIN_DTB)
        unflatten_and_copy_device_tree();
  #else
 -      if (early_init_dt_verify(__va(XIP_FIXUP(dtb_early_pa))))
 -              unflatten_device_tree();
 -      else
 -              pr_err("No DTB found in kernel mappings\n");
 +      unflatten_device_tree();
  #endif
 -      early_init_fdt_scan_reserved_mem();
        misc_mem_init();
  
        init_resources();
diff --combined drivers/base/cacheinfo.c
index f3903d002819e8ef9f7702a4670613319e342267,a5f7a1063411760248ea879403fba63426779142..41f0eadf193138d408dc83f50f29d45f91a7b2b8
@@@ -14,7 -14,7 +14,7 @@@
  #include <linux/cpu.h>
  #include <linux/device.h>
  #include <linux/init.h>
- #include <linux/of_device.h>
+ #include <linux/of.h>
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/smp.h>
@@@ -474,18 -474,12 +474,18 @@@ int detect_cache_attributes(unsigned in
  
  populate_leaves:
        /*
 -       * populate_cache_leaves() may completely setup the cache leaves and
 -       * shared_cpu_map or it may leave it partially setup.
 +       * If LLC is valid the cache leaves were already populated so just go to
 +       * update the cpu map.
         */
 -      ret = populate_cache_leaves(cpu);
 -      if (ret)
 -              goto free_ci;
 +      if (!last_level_cache_is_valid(cpu)) {
 +              /*
 +               * populate_cache_leaves() may completely setup the cache leaves and
 +               * shared_cpu_map or it may leave it partially setup.
 +               */
 +              ret = populate_cache_leaves(cpu);
 +              if (ret)
 +                      goto free_ci;
 +      }
  
        /*
         * For systems using DT for cache hierarchy, fw_token
index e1a5384cf21c89aeef96f7517efd598aee725039,78adfb2ffff6e7d09111304057a689cd08fbd310..29904395e95f9ca3b6c24d845584a5da141a99b0
@@@ -20,6 -20,6 +20,7 @@@
  #include <linux/dmi.h>
  #include <linux/slab.h>
  #include <linux/string_helpers.h>
++#include <linux/platform_device.h>
  
  #include <linux/acpi.h>
  #include <linux/io.h>
@@@ -965,7 -965,7 +966,7 @@@ static void __init acpi_cpufreq_boost_i
        acpi_cpufreq_driver.boost_enabled = boost_state(0);
  }
  
 -static int __init acpi_cpufreq_init(void)
 +static int __init acpi_cpufreq_probe(struct platform_device *pdev)
  {
        int ret;
  
        return ret;
  }
  
 -static void __exit acpi_cpufreq_exit(void)
 +static int acpi_cpufreq_remove(struct platform_device *pdev)
  {
        pr_debug("%s\n", __func__);
  
        cpufreq_unregister_driver(&acpi_cpufreq_driver);
  
        free_acpi_perf_data();
 +
 +      return 0;
 +}
 +
 +static struct platform_driver acpi_cpufreq_platdrv = {
 +      .driver = {
 +              .name   = "acpi-cpufreq",
 +      },
 +      .remove         = acpi_cpufreq_remove,
 +};
 +
 +static int __init acpi_cpufreq_init(void)
 +{
 +      return platform_driver_probe(&acpi_cpufreq_platdrv, acpi_cpufreq_probe);
 +}
 +
 +static void __exit acpi_cpufreq_exit(void)
 +{
 +      platform_driver_unregister(&acpi_cpufreq_platdrv);
  }
  
  module_param(acpi_pstate_strict, uint, 0644);
@@@ -1046,4 -1027,18 +1047,4 @@@ MODULE_PARM_DESC(acpi_pstate_strict
  late_initcall(acpi_cpufreq_init);
  module_exit(acpi_cpufreq_exit);
  
 -static const struct x86_cpu_id __maybe_unused acpi_cpufreq_ids[] = {
 -      X86_MATCH_FEATURE(X86_FEATURE_ACPI, NULL),
 -      X86_MATCH_FEATURE(X86_FEATURE_HW_PSTATE, NULL),
 -      {}
 -};
 -MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids);
 -
 -static const struct acpi_device_id __maybe_unused processor_device_ids[] = {
 -      {ACPI_PROCESSOR_OBJECT_HID, },
 -      {ACPI_PROCESSOR_DEVICE_HID, },
 -      {},
 -};
 -MODULE_DEVICE_TABLE(acpi, processor_device_ids);
 -
 -MODULE_ALIAS("acpi");
 +MODULE_ALIAS("platform:acpi-cpufreq");
index 45218143473524c158d302e782db1975932b5de7,f9675e1a8529832e1b5453c9c5d52d711133bd1a..338cf6cc659604d7f686944ae004074c29d79245
@@@ -6,7 -6,6 +6,6 @@@
  
  #include <linux/err.h>
  #include <linux/of.h>
- #include <linux/of_device.h>
  #include <linux/platform_device.h>
  
  #include "cpufreq-dt.h"
@@@ -152,7 -151,6 +151,7 @@@ static const struct of_device_id blockl
        { .compatible = "qcom,sm6115", },
        { .compatible = "qcom,sm6350", },
        { .compatible = "qcom,sm6375", },
 +      { .compatible = "qcom,sm7225", },
        { .compatible = "qcom,sm8150", },
        { .compatible = "qcom,sm8250", },
        { .compatible = "qcom,sm8350", },
@@@ -180,7 -178,7 +179,7 @@@ static bool __init cpu0_node_has_opp_v2
        struct device_node *np = of_cpu_device_node_get(0);
        bool ret = false;
  
 -      if (of_get_property(np, "operating-points-v2", NULL))
 +      if (of_property_present(np, "operating-points-v2"))
                ret = true;
  
        of_node_put(np);
index 0c362932ca6002b9b00124bfbed46cba581ca534,9f3fc7a073d075ba50ae3e3f72be03070db59316..1d2cfea9858afc121d8ecf4048d5bf2bfc9afe4a
@@@ -31,6 -31,6 +31,7 @@@
  #include <linux/cpufreq.h>
  #include <linux/compiler.h>
  #include <linux/slab.h>
++#include <linux/platform_device.h>
  
  #include <linux/acpi.h>
  #include <linux/io.h>
@@@ -384,7 -384,7 +385,7 @@@ out_free
        return ret;
  }
  
 -static int __init pcc_cpufreq_probe(void)
 +static int __init pcc_cpufreq_evaluate(void)
  {
        acpi_status status;
        struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
@@@ -576,7 -576,7 +577,7 @@@ static struct cpufreq_driver pcc_cpufre
        .name = "pcc-cpufreq",
  };
  
 -static int __init pcc_cpufreq_init(void)
 +static int __init pcc_cpufreq_probe(struct platform_device *pdev)
  {
        int ret;
  
        if (acpi_disabled)
                return -ENODEV;
  
 -      ret = pcc_cpufreq_probe();
 +      ret = pcc_cpufreq_evaluate();
        if (ret) {
 -              pr_debug("pcc_cpufreq_init: PCCH evaluation failed\n");
 +              pr_debug("pcc_cpufreq_probe: PCCH evaluation failed\n");
                return ret;
        }
  
        return ret;
  }
  
 -static void __exit pcc_cpufreq_exit(void)
 +static int pcc_cpufreq_remove(struct platform_device *pdev)
  {
        cpufreq_unregister_driver(&pcc_cpufreq_driver);
  
        pcc_clear_mapping();
  
        free_percpu(pcc_cpu_info);
 +
 +      return 0;
  }
  
 -static const struct acpi_device_id __maybe_unused processor_device_ids[] = {
 -      {ACPI_PROCESSOR_OBJECT_HID, },
 -      {ACPI_PROCESSOR_DEVICE_HID, },
 -      {},
 +static struct platform_driver pcc_cpufreq_platdrv = {
 +      .driver = {
 +              .name   = "pcc-cpufreq",
 +      },
 +      .remove         = pcc_cpufreq_remove,
  };
 -MODULE_DEVICE_TABLE(acpi, processor_device_ids);
 +
 +static int __init pcc_cpufreq_init(void)
 +{
 +      return platform_driver_probe(&pcc_cpufreq_platdrv, pcc_cpufreq_probe);
 +}
 +
 +static void __exit pcc_cpufreq_exit(void)
 +{
 +      platform_driver_unregister(&pcc_cpufreq_platdrv);
 +}
 +
 +MODULE_ALIAS("platform:pcc-cpufreq");
  
  MODULE_AUTHOR("Matthew Garrett, Naga Chumbalkar");
  MODULE_VERSION(PCC_VERSION);
index 7ec6d1bb4592e19e40fb0c712e3a854982a62e4f,a28716d8fc540afbfbfdeca42e00b47323685e77..ec75e79659ace83e71b08125f9266f131e97ad5c
@@@ -23,7 -23,7 +23,7 @@@
  #include <linux/init.h>
  #include <linux/device.h>
  #include <linux/hardirq.h>
- #include <linux/of_device.h>
+ #include <linux/of.h>
  
  #include <asm/machdep.h>
  #include <asm/irq.h>
@@@ -546,7 -546,7 +546,7 @@@ static int pmac_cpufreq_init_7447A(stru
  {
        struct device_node *volt_gpio_np;
  
 -      if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL)
 +      if (!of_property_read_bool(cpunode, "dynamic-power-step"))
                return 1;
  
        volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
@@@ -576,7 -576,7 +576,7 @@@ static int pmac_cpufreq_init_750FX(stru
        u32 pvr;
        const u32 *value;
  
 -      if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL)
 +      if (!of_property_read_bool(cpunode, "dynamic-power-step"))
                return 1;
  
        hi_freq = cur_freq;
@@@ -632,7 -632,7 +632,7 @@@ static int __init pmac_cpufreq_setup(vo
  
        /*  Check for 7447A based MacRISC3 */
        if (of_machine_is_compatible("MacRISC3") &&
 -          of_get_property(cpunode, "dynamic-power-step", NULL) &&
 +          of_property_read_bool(cpunode, "dynamic-power-step") &&
            PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {
                pmac_cpufreq_init_7447A(cpunode);
  
index eb54f7f17ab507a71772baba47f1ebaddf1485b4,df165a078d141ffebe88cf9df9560a4c404c3341..a78d7a27b4b56fd45da8423ef4776c0514358efc
  #include <linux/interrupt.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
- #include <linux/of_address.h>
- #include <linux/of_platform.h>
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
  #include <linux/pm_opp.h>
 -#include <linux/pm_qos.h>
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/units.h>
@@@ -28,8 -29,6 +28,8 @@@
  
  #define GT_IRQ_STATUS                 BIT(2)
  
 +#define MAX_FREQ_DOMAINS              3
 +
  struct qcom_cpufreq_soc_data {
        u32 reg_enable;
        u32 reg_domain_state;
@@@ -44,6 -43,7 +44,6 @@@
  
  struct qcom_cpufreq_data {
        void __iomem *base;
 -      struct resource *res;
  
        /*
         * Mutex to synchronize between de-init sequence and re-starting LMh
@@@ -58,6 -58,8 +58,6 @@@
        struct clk_hw cpu_clk;
  
        bool per_core_dcvs;
 -
 -      struct freq_qos_request throttle_freq_req;
  };
  
  static struct {
@@@ -347,6 -349,8 +347,6 @@@ static void qcom_lmh_dcvs_notify(struc
  
        throttled_freq = freq_hz / HZ_PER_KHZ;
  
 -      freq_qos_update_request(&data->throttle_freq_req, throttled_freq);
 -
        /* Update thermal pressure (the boost frequencies are accepted) */
        arch_update_thermal_pressure(policy->related_cpus, throttled_freq);
  
@@@ -439,6 -443,14 +439,6 @@@ static int qcom_cpufreq_hw_lmh_init(str
        if (data->throttle_irq < 0)
                return data->throttle_irq;
  
 -      ret = freq_qos_add_request(&policy->constraints,
 -                                 &data->throttle_freq_req, FREQ_QOS_MAX,
 -                                 FREQ_QOS_MAX_DEFAULT_VALUE);
 -      if (ret < 0) {
 -              dev_err(&pdev->dev, "Failed to add freq constraint (%d)\n", ret);
 -              return ret;
 -      }
 -
        data->cancel_throttle = false;
        data->policy = policy;
  
@@@ -505,6 -517,7 +505,6 @@@ static void qcom_cpufreq_hw_lmh_exit(st
        if (data->throttle_irq <= 0)
                return;
  
 -      freq_qos_remove_request(&data->throttle_freq_req);
        free_irq(data->throttle_irq, data);
  }
  
@@@ -577,12 -590,16 +577,12 @@@ static int qcom_cpufreq_hw_cpu_exit(str
  {
        struct device *cpu_dev = get_cpu_device(policy->cpu);
        struct qcom_cpufreq_data *data = policy->driver_data;
 -      struct resource *res = data->res;
 -      void __iomem *base = data->base;
  
        dev_pm_opp_remove_all_dynamic(cpu_dev);
        dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
        qcom_cpufreq_hw_lmh_exit(data);
        kfree(policy->freq_table);
        kfree(data);
 -      iounmap(base);
 -      release_mem_region(res->start, resource_size(res));
  
        return 0;
  }
@@@ -634,9 -651,10 +634,9 @@@ static int qcom_cpufreq_hw_driver_probe
  {
        struct clk_hw_onecell_data *clk_data;
        struct device *dev = &pdev->dev;
 -      struct device_node *soc_node;
        struct device *cpu_dev;
        struct clk *clk;
 -      int ret, i, num_domains, reg_sz;
 +      int ret, i, num_domains;
  
        clk = clk_get(dev, "xo");
        if (IS_ERR(clk))
        if (ret)
                return ret;
  
 -      /* Allocate qcom_cpufreq_data based on the available frequency domains in DT */
 -      soc_node = of_get_parent(dev->of_node);
 -      if (!soc_node)
 -              return -EINVAL;
 -
 -      ret = of_property_read_u32(soc_node, "#address-cells", &reg_sz);
 -      if (ret)
 -              goto of_exit;
 -
 -      ret = of_property_read_u32(soc_node, "#size-cells", &i);
 -      if (ret)
 -              goto of_exit;
 -
 -      reg_sz += i;
 -
 -      num_domains = of_property_count_elems_of_size(dev->of_node, "reg", sizeof(u32) * reg_sz);
 -      if (num_domains <= 0)
 -              return num_domains;
 +      for (num_domains = 0; num_domains < MAX_FREQ_DOMAINS; num_domains++)
 +              if (!platform_get_resource(pdev, IORESOURCE_MEM, num_domains))
 +                      break;
  
        qcom_cpufreq.data = devm_kzalloc(dev, sizeof(struct qcom_cpufreq_data) * num_domains,
                                         GFP_KERNEL);
        for (i = 0; i < num_domains; i++) {
                struct qcom_cpufreq_data *data = &qcom_cpufreq.data[i];
                struct clk_init_data clk_init = {};
 -              struct resource *res;
                void __iomem *base;
  
 -              base = devm_platform_get_and_ioremap_resource(pdev, i, &res);
 +              base = devm_platform_ioremap_resource(pdev, i);
                if (IS_ERR(base)) {
 -                      dev_err(dev, "Failed to map resource %pR\n", res);
 +                      dev_err(dev, "Failed to map resource index %d\n", i);
                        return PTR_ERR(base);
                }
  
                data->base = base;
 -              data->res = res;
  
                /* Register CPU clock for each frequency domain */
                clk_init.name = kasprintf(GFP_KERNEL, "qcom_cpufreq%d", i);
        else
                dev_dbg(dev, "QCOM CPUFreq HW driver initialized\n");
  
 -of_exit:
 -      of_node_put(soc_node);
 -
        return ret;
  }
  
index 788672c0c8340b06b1a71e1f1674979d0115f3b0,312ca5ddc6c411013d75f335a3ed8ff928a6c8db..aae951d4e77cfd0136564f5f8e3ad60d1f694e3b
@@@ -11,7 -11,6 +11,6 @@@
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
- #include <linux/of_device.h>
  #include <linux/of.h>
  #include <linux/platform_device.h>
  #include <linux/pm_opp.h>
@@@ -221,3 -220,4 +220,3 @@@ module_init(tegra_cpufreq_init)
  
  MODULE_AUTHOR("Tuomas Tynkkynen <ttynkkynen@nvidia.com>");
  MODULE_DESCRIPTION("cpufreq driver for NVIDIA Tegra124");
 -MODULE_LICENSE("GPL v2");
index dfd2de4f8e07e4c01ac7a7b81ce5e2e0c5be659d,5d1f5f87e46dcfec75dbbd67e257eb5909bf124e..a573186704a50fbc94c7abf502f16dae6f0bd95c
@@@ -12,7 -12,7 +12,7 @@@
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/module.h>
- #include <linux/of_device.h>
+ #include <linux/of.h>
  #include <linux/platform_device.h>
  #include <linux/pm_opp.h>
  #include <linux/types.h>
@@@ -25,7 -25,7 +25,7 @@@ static bool cpu0_node_has_opp_v2_prop(v
        struct device_node *np = of_cpu_device_node_get(0);
        bool ret = false;
  
 -      if (of_get_property(np, "operating-points-v2", NULL))
 +      if (of_property_present(np, "operating-points-v2"))
                ret = true;
  
        of_node_put(np);
index 1fab1abc6eb63dc841cbacce4ac0838181c2dc5d,ae0b838a06340b7d4286e72ff5c89ec904067c07..f2ccda2c38711c5fcc339b2ac49b56b047e4b4db
@@@ -8,6 -8,7 +8,7 @@@
  
  #define pr_fmt(fmt) "cpuidle-riscv-sbi: " fmt
  
+ #include <linux/cpuhotplug.h>
  #include <linux/cpuidle.h>
  #include <linux/cpumask.h>
  #include <linux/cpu_pm.h>
@@@ -15,7 -16,6 +16,6 @@@
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/of.h>
- #include <linux/of_device.h>
  #include <linux/slab.h>
  #include <linux/platform_device.h>
  #include <linux/pm_domain.h>
@@@ -497,7 -497,7 +497,7 @@@ static int sbi_genpd_probe(struct devic
         * initialize a genpd/genpd-of-provider pair when it's found.
         */
        for_each_child_of_node(np, node) {
 -              if (!of_find_property(node, "#power-domain-cells", NULL))
 +              if (!of_property_present(node, "#power-domain-cells"))
                        continue;
  
                ret = sbi_pd_init(node);
@@@ -548,8 -548,8 +548,8 @@@ static int sbi_cpuidle_probe(struct pla
        for_each_possible_cpu(cpu) {
                np = of_cpu_device_node_get(cpu);
                if (np &&
 -                  of_find_property(np, "power-domains", NULL) &&
 -                  of_find_property(np, "power-domain-names", NULL)) {
 +                  of_property_present(np, "power-domains") &&
 +                  of_property_present(np, "power-domain-names")) {
                        continue;
                } else {
                        sbi_cpuidle_use_osi = false;
index 90181c42840b4e92a8b7a8a59d3da5280532ada3,fd9d87f1470e2ab82699c43b774f8420e02d5fd3..71ef19f77a5a02a3bb5bb130125ec9dfb5c9135c
@@@ -7,16 -7,13 +7,13 @@@
  
  #define pr_fmt(fmt) "eiointc: " fmt
  
+ #include <linux/cpuhotplug.h>
  #include <linux/interrupt.h>
  #include <linux/irq.h>
  #include <linux/irqchip.h>
  #include <linux/irqdomain.h>
  #include <linux/irqchip/chained_irq.h>
  #include <linux/kernel.h>
- #include <linux/platform_device.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- #include <linux/of_platform.h>
  #include <linux/syscore_ops.h>
  
  #define EIOINTC_REG_NODEMAP   0x14a0
@@@ -280,6 -277,9 +277,6 @@@ static void acpi_set_vec_parent(int nod
  {
        int i;
  
 -      if (cpu_has_flatmode)
 -              node = cpu_to_node(node * CORES_PER_EIO_NODE);
 -
        for (i = 0; i < MAX_IO_PICS; i++) {
                if (node == vec_group[i].node) {
                        vec_group[i].parent = parent;
@@@ -340,27 -340,19 +337,27 @@@ static int __init pch_pic_parse_madt(un
        if (parent)
                return pch_pic_acpi_init(parent, pchpic_entry);
  
 -      return -EINVAL;
 +      return 0;
  }
  
  static int __init pch_msi_parse_madt(union acpi_subtable_headers *header,
                                        const unsigned long end)
  {
 +      struct irq_domain *parent;
        struct acpi_madt_msi_pic *pchmsi_entry = (struct acpi_madt_msi_pic *)header;
 -      struct irq_domain *parent = acpi_get_vec_parent(eiointc_priv[nr_pics - 1]->node, msi_group);
 +      int node;
 +
 +      if (cpu_has_flatmode)
 +              node = cpu_to_node(eiointc_priv[nr_pics - 1]->node * CORES_PER_EIO_NODE);
 +      else
 +              node = eiointc_priv[nr_pics - 1]->node;
 +
 +      parent = acpi_get_vec_parent(node, msi_group);
  
        if (parent)
                return pch_msi_acpi_init(parent, pchmsi_entry);
  
 -      return -EINVAL;
 +      return 0;
  }
  
  static int __init acpi_cascade_irqdomain_init(void)
@@@ -384,7 -376,6 +381,7 @@@ int __init eiointc_acpi_init(struct irq
        int i, ret, parent_irq;
        unsigned long node_map;
        struct eiointc_priv *priv;
 +      int node;
  
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
        parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade);
        irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);
  
 -      register_syscore_ops(&eiointc_syscore_ops);
 -      cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
 +      if (nr_pics == 1) {
 +              register_syscore_ops(&eiointc_syscore_ops);
 +              cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
                                  "irqchip/loongarch/intc:starting",
                                  eiointc_router_init, NULL);
 +      }
  
 -      acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group);
 -      acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group);
 +      if (cpu_has_flatmode)
 +              node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE);
 +      else
 +              node = acpi_eiointc->node;
 +      acpi_set_vec_parent(node, priv->eiointc_domain, pch_group);
 +      acpi_set_vec_parent(node, priv->eiointc_domain, msi_group);
        ret = acpi_cascade_irqdomain_init();
  
        return ret;
diff --combined drivers/of/address.c
index 3aaa63e66fcf0b2ef1b50845d3cb6d433501fe3e,fdb15c6fb3b17e82865d17b06da3a7f4194a64ec..0d49f8c9ed88e978e3764d4e47204cb5d69e54be
  #define OF_CHECK_ADDR_COUNT(na)       ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS)
  #define OF_CHECK_COUNTS(na, ns)       (OF_CHECK_ADDR_COUNT(na) && (ns) > 0)
  
 -static struct of_bus *of_match_bus(struct device_node *np);
 -static int __of_address_to_resource(struct device_node *dev, int index,
 -              int bar_no, struct resource *r);
 -static bool of_mmio_is_nonposted(struct device_node *np);
 -
  /* Debug utility */
  #ifdef DEBUG
  static void of_dump_addr(const char *s, const __be32 *addr, int na)
@@@ -90,11 -95,17 +90,17 @@@ static int of_bus_default_translate(__b
        return 0;
  }
  
+ static unsigned int of_bus_default_flags_get_flags(const __be32 *addr)
+ {
+       return of_read_number(addr, 1);
+ }
  static unsigned int of_bus_default_get_flags(const __be32 *addr)
  {
        return IORESOURCE_MEM;
  }
  
  #ifdef CONFIG_PCI
  static unsigned int of_bus_pci_get_flags(const __be32 *addr)
  {
@@@ -190,6 -201,17 +196,6 @@@ static int of_bus_pci_translate(__be32 
  }
  #endif /* CONFIG_PCI */
  
 -int of_pci_address_to_resource(struct device_node *dev, int bar,
 -                             struct resource *r)
 -{
 -
 -      if (!IS_ENABLED(CONFIG_PCI))
 -              return -ENOSYS;
 -
 -      return __of_address_to_resource(dev, -1, bar, r);
 -}
 -EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
 -
  /*
   * of_pci_range_to_resource - Create a resource from an of_pci_range
   * @range:    the PCI range that describes the resource
   * @res:      pointer to a valid resource that will be updated to
   *              reflect the values contained in the range.
   *
 - * Returns EINVAL if the range cannot be converted to resource.
 + * Returns -EINVAL if the range cannot be converted to resource.
   *
   * Note that if the range is an IO range, the resource will be converted
   * using pci_address_to_pio() which can fail if it is called too early or
@@@ -213,9 -235,6 +219,6 @@@ int of_pci_range_to_resource(struct of_
        res->parent = res->child = res->sibling = NULL;
        res->name = np->full_name;
  
-       if (!IS_ENABLED(CONFIG_PCI))
-               return -ENOSYS;
        if (res->flags & IORESOURCE_IO) {
                unsigned long port;
                err = pci_register_io_range(&np->fwnode, range->cpu_addr,
@@@ -247,6 -266,34 +250,34 @@@ invalid_range
  }
  EXPORT_SYMBOL(of_pci_range_to_resource);
  
+ /*
+  * of_range_to_resource - Create a resource from a ranges entry
+  * @np:               device node where the range belongs to
+  * @index:    the 'ranges' index to convert to a resource
+  * @res:      pointer to a valid resource that will be updated to
+  *              reflect the values contained in the range.
+  *
+  * Returns ENOENT if the entry is not found or EINVAL if the range cannot be
+  * converted to resource.
+  */
+ int of_range_to_resource(struct device_node *np, int index, struct resource *res)
+ {
+       int ret, i = 0;
+       struct of_range_parser parser;
+       struct of_range range;
+       ret = of_range_parser_init(&parser, np);
+       if (ret)
+               return ret;
+       for_each_of_range(&parser, &range)
+               if (i++ == index)
+                       return of_pci_range_to_resource(&range, np, res);
+       return -ENOENT;
+ }
+ EXPORT_SYMBOL(of_range_to_resource);
  /*
   * ISA bus specific translator
   */
@@@ -303,6 -350,11 +334,11 @@@ static unsigned int of_bus_isa_get_flag
        return flags;
  }
  
+ static int of_bus_default_flags_match(struct device_node *np)
+ {
+       return of_bus_n_addr_cells(np) == 3;
+ }
  /*
   * Array of bus specific translators
   */
@@@ -332,6 -384,17 +368,17 @@@ static struct of_bus of_busses[] = 
                .has_flags = true,
                .get_flags = of_bus_isa_get_flags,
        },
+       /* Default with flags cell */
+       {
+               .name = "default-flags",
+               .addresses = "reg",
+               .match = of_bus_default_flags_match,
+               .count_cells = of_bus_default_count_cells,
+               .map = of_bus_default_map,
+               .translate = of_bus_default_translate,
+               .has_flags = true,
+               .get_flags = of_bus_default_flags_get_flags,
+       },
        /* Default */
        {
                .name = "default",
@@@ -697,6 -760,29 +744,29 @@@ const __be32 *__of_get_address(struct d
  }
  EXPORT_SYMBOL(__of_get_address);
  
+ /**
+  * of_property_read_reg - Retrieve the specified "reg" entry index without translating
+  * @np: device tree node for which to retrieve "reg" from
+  * @idx: "reg" entry index to read
+  * @addr: return value for the untranslated address
+  * @size: return value for the entry size
+  *
+  * Returns -EINVAL if "reg" is not found. Returns 0 on success with addr and
+  * size values filled in.
+  */
+ int of_property_read_reg(struct device_node *np, int idx, u64 *addr, u64 *size)
+ {
+       const __be32 *prop = of_get_address(np, idx, size, NULL);
+       if (!prop)
+               return -EINVAL;
+       *addr = of_read_number(prop, of_n_addr_cells(np));
+       return 0;
+ }
+ EXPORT_SYMBOL(of_property_read_reg);
  static int parser_init(struct of_pci_range_parser *parser,
                        struct device_node *node, const char *name)
  {
@@@ -818,6 -904,126 +888,6 @@@ static u64 of_translate_ioport(struct d
        return port;
  }
  
 -static int __of_address_to_resource(struct device_node *dev, int index, int bar_no,
 -              struct resource *r)
 -{
 -      u64 taddr;
 -      const __be32    *addrp;
 -      u64             size;
 -      unsigned int    flags;
 -      const char      *name = NULL;
 -
 -      addrp = __of_get_address(dev, index, bar_no, &size, &flags);
 -      if (addrp == NULL)
 -              return -EINVAL;
 -
 -      /* Get optional "reg-names" property to add a name to a resource */
 -      if (index >= 0)
 -              of_property_read_string_index(dev, "reg-names", index, &name);
 -
 -      if (flags & IORESOURCE_MEM)
 -              taddr = of_translate_address(dev, addrp);
 -      else if (flags & IORESOURCE_IO)
 -              taddr = of_translate_ioport(dev, addrp, size);
 -      else
 -              return -EINVAL;
 -
 -      if (taddr == OF_BAD_ADDR)
 -              return -EINVAL;
 -      memset(r, 0, sizeof(struct resource));
 -
 -      if (of_mmio_is_nonposted(dev))
 -              flags |= IORESOURCE_MEM_NONPOSTED;
 -
 -      r->start = taddr;
 -      r->end = taddr + size - 1;
 -      r->flags = flags;
 -      r->name = name ? name : dev->full_name;
 -
 -      return 0;
 -}
 -
 -/**
 - * of_address_to_resource - Translate device tree address and return as resource
 - * @dev:      Caller's Device Node
 - * @index:    Index into the array
 - * @r:                Pointer to resource array
 - *
 - * Note that if your address is a PIO address, the conversion will fail if
 - * the physical address can't be internally converted to an IO token with
 - * pci_address_to_pio(), that is because it's either called too early or it
 - * can't be matched to any host bridge IO space
 - */
 -int of_address_to_resource(struct device_node *dev, int index,
 -                         struct resource *r)
 -{
 -      return __of_address_to_resource(dev, index, -1, r);
 -}
 -EXPORT_SYMBOL_GPL(of_address_to_resource);
 -
 -/**
 - * of_iomap - Maps the memory mapped IO for a given device_node
 - * @np:               the device whose io range will be mapped
 - * @index:    index of the io range
 - *
 - * Returns a pointer to the mapped memory
 - */
 -void __iomem *of_iomap(struct device_node *np, int index)
 -{
 -      struct resource res;
 -
 -      if (of_address_to_resource(np, index, &res))
 -              return NULL;
 -
 -      if (res.flags & IORESOURCE_MEM_NONPOSTED)
 -              return ioremap_np(res.start, resource_size(&res));
 -      else
 -              return ioremap(res.start, resource_size(&res));
 -}
 -EXPORT_SYMBOL(of_iomap);
 -
 -/*
 - * of_io_request_and_map - Requests a resource and maps the memory mapped IO
 - *                       for a given device_node
 - * @device:   the device whose io range will be mapped
 - * @index:    index of the io range
 - * @name:     name "override" for the memory region request or NULL
 - *
 - * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded
 - * error code on failure. Usage example:
 - *
 - *    base = of_io_request_and_map(node, 0, "foo");
 - *    if (IS_ERR(base))
 - *            return PTR_ERR(base);
 - */
 -void __iomem *of_io_request_and_map(struct device_node *np, int index,
 -                                  const char *name)
 -{
 -      struct resource res;
 -      void __iomem *mem;
 -
 -      if (of_address_to_resource(np, index, &res))
 -              return IOMEM_ERR_PTR(-EINVAL);
 -
 -      if (!name)
 -              name = res.name;
 -      if (!request_mem_region(res.start, resource_size(&res), name))
 -              return IOMEM_ERR_PTR(-EBUSY);
 -
 -      if (res.flags & IORESOURCE_MEM_NONPOSTED)
 -              mem = ioremap_np(res.start, resource_size(&res));
 -      else
 -              mem = ioremap(res.start, resource_size(&res));
 -
 -      if (!mem) {
 -              release_mem_region(res.start, resource_size(&res));
 -              return IOMEM_ERR_PTR(-ENOMEM);
 -      }
 -
 -      return mem;
 -}
 -EXPORT_SYMBOL(of_io_request_and_map);
 -
  #ifdef CONFIG_HAS_DMA
  /**
   * of_dma_get_range - Get DMA range info and put it into a map array
@@@ -1014,136 -1220,3 +1084,136 @@@ static bool of_mmio_is_nonposted(struc
        of_node_put(parent);
        return nonposted;
  }
 +
 +static int __of_address_to_resource(struct device_node *dev, int index, int bar_no,
 +              struct resource *r)
 +{
 +      u64 taddr;
 +      const __be32    *addrp;
 +      u64             size;
 +      unsigned int    flags;
 +      const char      *name = NULL;
 +
 +      addrp = __of_get_address(dev, index, bar_no, &size, &flags);
 +      if (addrp == NULL)
 +              return -EINVAL;
 +
 +      /* Get optional "reg-names" property to add a name to a resource */
 +      if (index >= 0)
 +              of_property_read_string_index(dev, "reg-names", index, &name);
 +
 +      if (flags & IORESOURCE_MEM)
 +              taddr = of_translate_address(dev, addrp);
 +      else if (flags & IORESOURCE_IO)
 +              taddr = of_translate_ioport(dev, addrp, size);
 +      else
 +              return -EINVAL;
 +
 +      if (taddr == OF_BAD_ADDR)
 +              return -EINVAL;
 +      memset(r, 0, sizeof(struct resource));
 +
 +      if (of_mmio_is_nonposted(dev))
 +              flags |= IORESOURCE_MEM_NONPOSTED;
 +
 +      r->start = taddr;
 +      r->end = taddr + size - 1;
 +      r->flags = flags;
 +      r->name = name ? name : dev->full_name;
 +
 +      return 0;
 +}
 +
 +/**
 + * of_address_to_resource - Translate device tree address and return as resource
 + * @dev:      Caller's Device Node
 + * @index:    Index into the array
 + * @r:                Pointer to resource array
 + *
 + * Returns -EINVAL if the range cannot be converted to resource.
 + *
 + * Note that if your address is a PIO address, the conversion will fail if
 + * the physical address can't be internally converted to an IO token with
 + * pci_address_to_pio(), that is because it's either called too early or it
 + * can't be matched to any host bridge IO space
 + */
 +int of_address_to_resource(struct device_node *dev, int index,
 +                         struct resource *r)
 +{
 +      return __of_address_to_resource(dev, index, -1, r);
 +}
 +EXPORT_SYMBOL_GPL(of_address_to_resource);
 +
 +int of_pci_address_to_resource(struct device_node *dev, int bar,
 +                             struct resource *r)
 +{
 +
 +      if (!IS_ENABLED(CONFIG_PCI))
 +              return -ENOSYS;
 +
 +      return __of_address_to_resource(dev, -1, bar, r);
 +}
 +EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
 +
 +/**
 + * of_iomap - Maps the memory mapped IO for a given device_node
 + * @np:               the device whose io range will be mapped
 + * @index:    index of the io range
 + *
 + * Returns a pointer to the mapped memory
 + */
 +void __iomem *of_iomap(struct device_node *np, int index)
 +{
 +      struct resource res;
 +
 +      if (of_address_to_resource(np, index, &res))
 +              return NULL;
 +
 +      if (res.flags & IORESOURCE_MEM_NONPOSTED)
 +              return ioremap_np(res.start, resource_size(&res));
 +      else
 +              return ioremap(res.start, resource_size(&res));
 +}
 +EXPORT_SYMBOL(of_iomap);
 +
 +/*
 + * of_io_request_and_map - Requests a resource and maps the memory mapped IO
 + *                       for a given device_node
 + * @device:   the device whose io range will be mapped
 + * @index:    index of the io range
 + * @name:     name "override" for the memory region request or NULL
 + *
 + * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded
 + * error code on failure. Usage example:
 + *
 + *    base = of_io_request_and_map(node, 0, "foo");
 + *    if (IS_ERR(base))
 + *            return PTR_ERR(base);
 + */
 +void __iomem *of_io_request_and_map(struct device_node *np, int index,
 +                                  const char *name)
 +{
 +      struct resource res;
 +      void __iomem *mem;
 +
 +      if (of_address_to_resource(np, index, &res))
 +              return IOMEM_ERR_PTR(-EINVAL);
 +
 +      if (!name)
 +              name = res.name;
 +      if (!request_mem_region(res.start, resource_size(&res), name))
 +              return IOMEM_ERR_PTR(-EBUSY);
 +
 +      if (res.flags & IORESOURCE_MEM_NONPOSTED)
 +              mem = ioremap_np(res.start, resource_size(&res));
 +      else
 +              mem = ioremap(res.start, resource_size(&res));
 +
 +      if (!mem) {
 +              release_mem_region(res.start, resource_size(&res));
 +              return IOMEM_ERR_PTR(-ENOMEM);
 +      }
 +
 +      return mem;
 +}
 +EXPORT_SYMBOL(of_io_request_and_map);
diff --combined drivers/of/unittest.c
index ab3e914452562a10e1de5c89ee2f2041768eb1e8,e73ecbef977b34a904e8ca77148cb69fd014004f..2191c01365317581e759d0c160524a7d85fc4ded
@@@ -1008,6 -1008,153 +1008,153 @@@ static void __init of_unittest_pci_dma_
        of_node_put(np);
  }
  
+ static void __init of_unittest_bus_ranges(void)
+ {
+       struct device_node *np;
+       struct of_range range;
+       struct of_range_parser parser;
+       struct resource res;
+       int ret, count, i = 0;
+       np = of_find_node_by_path("/testcase-data/address-tests");
+       if (!np) {
+               pr_err("missing testcase data\n");
+               return;
+       }
+       if (of_range_parser_init(&parser, np)) {
+               pr_err("missing ranges property\n");
+               return;
+       }
+       ret = of_range_to_resource(np, 1, &res);
+       unittest(!ret, "of_range_to_resource returned error (%d) node %pOF\n",
+               ret, np);
+       unittest(resource_type(&res) == IORESOURCE_MEM,
+               "of_range_to_resource wrong resource type on node %pOF res=%pR\n",
+               np, &res);
+       unittest(res.start == 0xd0000000,
+               "of_range_to_resource wrong resource start address on node %pOF res=%pR\n",
+               np, &res);
+       unittest(resource_size(&res) == 0x20000000,
+               "of_range_to_resource wrong resource start address on node %pOF res=%pR\n",
+               np, &res);
+       count = of_range_count(&parser);
+       unittest(count == 2,
+               "of_range_count wrong size on node %pOF count=%d\n",
+               np, count);
+       /*
+        * Get the "ranges" from the device tree
+        */
+       for_each_of_range(&parser, &range) {
+               unittest(range.flags == IORESOURCE_MEM,
+                       "for_each_of_range wrong flags on node %pOF flags=%x (expected %x)\n",
+                       np, range.flags, IORESOURCE_MEM);
+               if (!i) {
+                       unittest(range.size == 0x50000000,
+                                "for_each_of_range wrong size on node %pOF size=%llx\n",
+                                np, range.size);
+                       unittest(range.cpu_addr == 0x70000000,
+                                "for_each_of_range wrong CPU addr (%llx) on node %pOF",
+                                range.cpu_addr, np);
+                       unittest(range.bus_addr == 0x70000000,
+                                "for_each_of_range wrong bus addr (%llx) on node %pOF",
+                                range.pci_addr, np);
+               } else {
+                       unittest(range.size == 0x20000000,
+                                "for_each_of_range wrong size on node %pOF size=%llx\n",
+                                np, range.size);
+                       unittest(range.cpu_addr == 0xd0000000,
+                                "for_each_of_range wrong CPU addr (%llx) on node %pOF",
+                                range.cpu_addr, np);
+                       unittest(range.bus_addr == 0x00000000,
+                                "for_each_of_range wrong bus addr (%llx) on node %pOF",
+                                range.pci_addr, np);
+               }
+               i++;
+       }
+       of_node_put(np);
+ }
+ static void __init of_unittest_bus_3cell_ranges(void)
+ {
+       struct device_node *np;
+       struct of_range range;
+       struct of_range_parser parser;
+       int i = 0;
+       np = of_find_node_by_path("/testcase-data/address-tests/bus@a0000000");
+       if (!np) {
+               pr_err("missing testcase data\n");
+               return;
+       }
+       if (of_range_parser_init(&parser, np)) {
+               pr_err("missing ranges property\n");
+               return;
+       }
+       /*
+        * Get the "ranges" from the device tree
+        */
+       for_each_of_range(&parser, &range) {
+               if (!i) {
+                       unittest(range.flags == 0xf00baa,
+                                "for_each_of_range wrong flags on node %pOF flags=%x\n",
+                                np, range.flags);
+                       unittest(range.size == 0x100000,
+                                "for_each_of_range wrong size on node %pOF size=%llx\n",
+                                np, range.size);
+                       unittest(range.cpu_addr == 0xa0000000,
+                                "for_each_of_range wrong CPU addr (%llx) on node %pOF",
+                                range.cpu_addr, np);
+                       unittest(range.bus_addr == 0x0,
+                                "for_each_of_range wrong bus addr (%llx) on node %pOF",
+                                range.pci_addr, np);
+               } else {
+                       unittest(range.flags == 0xf00bee,
+                                "for_each_of_range wrong flags on node %pOF flags=%x\n",
+                                np, range.flags);
+                       unittest(range.size == 0x200000,
+                                "for_each_of_range wrong size on node %pOF size=%llx\n",
+                                np, range.size);
+                       unittest(range.cpu_addr == 0xb0000000,
+                                "for_each_of_range wrong CPU addr (%llx) on node %pOF",
+                                range.cpu_addr, np);
+                       unittest(range.bus_addr == 0x100000000,
+                                "for_each_of_range wrong bus addr (%llx) on node %pOF",
+                                range.pci_addr, np);
+               }
+               i++;
+       }
+       of_node_put(np);
+ }
+ static void __init of_unittest_reg(void)
+ {
+       struct device_node *np;
+       int ret;
+       u64 addr, size;
+       np = of_find_node_by_path("/testcase-data/address-tests/bus@80000000/device@1000");
+       if (!np) {
+               pr_err("missing testcase data\n");
+               return;
+       }
+       ret = of_property_read_reg(np, 0, &addr, &size);
+       unittest(!ret, "of_property_read_reg(%pOF) returned error %d\n",
+               np, ret);
+       unittest(addr == 0x1000, "of_property_read_reg(%pOF) untranslated address (%llx) incorrect\n",
+               np, addr);
+       of_node_put(np);
+ }
  static void __init of_unittest_parse_interrupts(void)
  {
        struct device_node *np;
@@@ -1529,12 -1676,13 +1676,12 @@@ static int unittest_probe(struct platfo
        return 0;
  }
  
 -static int unittest_remove(struct platform_device *pdev)
 +static void unittest_remove(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
  
        dev_dbg(dev, "%s for node @%pOF\n", __func__, np);
 -      return 0;
  }
  
  static const struct of_device_id unittest_match[] = {
  
  static struct platform_driver unittest_driver = {
        .probe                  = unittest_probe,
 -      .remove                 = unittest_remove,
 +      .remove_new             = unittest_remove,
        .driver = {
                .name           = "unittest",
                .of_match_table = of_match_ptr(unittest_match),
@@@ -1625,17 -1773,23 +1772,17 @@@ static int unittest_gpio_probe(struct p
        return ret;
  }
  
 -static int unittest_gpio_remove(struct platform_device *pdev)
 +static void unittest_gpio_remove(struct platform_device *pdev)
  {
        struct unittest_gpio_dev *devptr = platform_get_drvdata(pdev);
        struct device *dev = &pdev->dev;
  
        dev_dbg(dev, "%s for node @%pfw\n", __func__, devptr->chip.fwnode);
  
 -      if (!devptr)
 -              return -EINVAL;
 -
        if (devptr->chip.base != -1)
                gpiochip_remove(&devptr->chip);
  
 -      platform_set_drvdata(pdev, NULL);
        kfree(devptr);
 -
 -      return 0;
  }
  
  static const struct of_device_id unittest_gpio_id[] = {
  
  static struct platform_driver unittest_gpio_driver = {
        .probe  = unittest_gpio_probe,
 -      .remove = unittest_gpio_remove,
 +      .remove_new = unittest_gpio_remove,
        .driver = {
                .name           = "unittest-gpio",
                .of_match_table = of_match_ptr(unittest_gpio_id),
@@@ -2483,7 -2637,7 +2630,7 @@@ static int unittest_i2c_bus_probe(struc
        return 0;
  }
  
 -static int unittest_i2c_bus_remove(struct platform_device *pdev)
 +static void unittest_i2c_bus_remove(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
  
        dev_dbg(dev, "%s for node @%pOF\n", __func__, np);
        i2c_del_adapter(&std->adap);
 -
 -      return 0;
  }
  
  static const struct of_device_id unittest_i2c_bus_match[] = {
  
  static struct platform_driver unittest_i2c_bus_driver = {
        .probe                  = unittest_i2c_bus_probe,
 -      .remove                 = unittest_i2c_bus_remove,
 +      .remove_new             = unittest_i2c_bus_remove,
        .driver = {
                .name           = "unittest-i2c-bus",
                .of_match_table = of_match_ptr(unittest_i2c_bus_match),
@@@ -3635,6 -3791,9 +3782,9 @@@ static int __init of_unittest(void
        of_unittest_dma_get_max_cpu_address();
        of_unittest_parse_dma_ranges();
        of_unittest_pci_dma_ranges();
+       of_unittest_bus_ranges();
+       of_unittest_bus_3cell_ranges();
+       of_unittest_reg();
        of_unittest_match_node();
        of_unittest_platform_populate();
        of_unittest_overlay();
diff --combined drivers/opp/of.c
index 233eab70e15e3976ad00490d83a1f8d3eb259bed,63b126c6215eaff7829008d7c42a51cc865e8ca3..8246e9b7afe7f970e94946ec23c7530edee1d5f2
@@@ -13,7 -13,7 +13,7 @@@
  #include <linux/cpu.h>
  #include <linux/errno.h>
  #include <linux/device.h>
- #include <linux/of_device.h>
+ #include <linux/of.h>
  #include <linux/pm_domain.h>
  #include <linux/slab.h>
  #include <linux/export.h>
@@@ -196,8 -196,6 +196,8 @@@ static void _opp_table_alloc_required_t
        /* Let's do the linking later on */
        if (lazy)
                list_add(&opp_table->lazy, &lazy_opp_tables);
 +      else
 +              _update_set_required_opps(opp_table);
  
        goto put_np;
  
@@@ -226,7 -224,7 +226,7 @@@ void _of_init_opp_table(struct opp_tabl
        of_property_read_u32(np, "voltage-tolerance",
                             &opp_table->voltage_tolerance_v1);
  
 -      if (of_find_property(np, "#power-domain-cells", NULL))
 +      if (of_property_present(np, "#power-domain-cells"))
                opp_table->is_genpd = true;
  
        /* Get OPP table node */
@@@ -413,7 -411,6 +413,7 @@@ static void lazy_link_required_opp_tabl
  
                /* All required opp-tables found, remove from lazy list */
                if (!lazy) {
 +                      _update_set_required_opps(opp_table);
                        list_del_init(&opp_table->lazy);
  
                        list_for_each_entry(opp, &opp_table->opp_list, node)
@@@ -539,7 -536,7 +539,7 @@@ static bool _opp_is_supported(struct de
                 * an OPP then the OPP should not be enabled as there is
                 * no way to see if the hardware supports it.
                 */
 -              if (of_find_property(np, "opp-supported-hw", NULL))
 +              if (of_property_present(np, "opp-supported-hw"))
                        return false;
                else
                        return true;
index b9c96182a46a63a4be1d4127fae3923b79c4f4ea,1b7579a5bec609db8ad1158cc4020ace48b0a5b4..81585733c8a99401276db4858cd528efff580d09
@@@ -7,6 -7,7 +7,7 @@@
  #include <linux/bits.h>
  #include <linux/clk.h>
  #include <linux/completion.h>
+ #include <linux/cpu.h>
  #include <linux/cpuidle.h>
  #include <linux/debugfs.h>
  #include <linux/device.h>
@@@ -558,7 -559,7 +559,7 @@@ static int svs_adjust_pm_opp_volts(stru
        }
  
        /* Get thermal effect */
 -      if (svsb->phase == SVSB_PHASE_MON) {
 +      if (!IS_ERR_OR_NULL(svsb->tzd)) {
                ret = thermal_zone_get_temp(svsb->tzd, &tzone_temp);
                if (ret || (svsb->temp > SVSB_TEMP_UPPER_BOUND &&
                            svsb->temp < SVSB_TEMP_LOWER_BOUND)) {
                        temp_voffset += svsb->tzone_ltemp_voffset;
  
                /* 2-line bank update all opp volts when running mon mode */
 -              if (svsb->type == SVSB_HIGH || svsb->type == SVSB_LOW) {
 +              if (svsb->phase == SVSB_PHASE_MON && (svsb->type == SVSB_HIGH ||
 +                                                    svsb->type == SVSB_LOW)) {
                        opp_start = 0;
                        opp_stop = svsb->opp_count;
                }
                        /* do nothing */
                        goto unlock_mutex;
                case SVSB_PHASE_INIT02:
 -                      svsb_volt = max(svsb->volt[i], svsb->vmin);
 -                      opp_volt = svs_bank_volt_to_opp_volt(svsb_volt,
 -                                                           svsb->volt_step,
 -                                                           svsb->volt_base);
 -                      break;
                case SVSB_PHASE_MON:
                        svsb_volt = max(svsb->volt[i] + temp_voffset, svsb->vmin);
                        opp_volt = svs_bank_volt_to_opp_volt(svsb_volt,
@@@ -620,25 -625,6 +621,25 @@@ unlock_mutex
        return ret;
  }
  
 +static void svs_bank_disable_and_restore_default_volts(struct svs_platform *svsp,
 +                                                     struct svs_bank *svsb)
 +{
 +      unsigned long flags;
 +
 +      if (svsb->mode_support == SVSB_MODE_ALL_DISABLE)
 +              return;
 +
 +      spin_lock_irqsave(&svs_lock, flags);
 +      svsp->pbank = svsb;
 +      svs_switch_bank(svsp);
 +      svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
 +      svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
 +      spin_unlock_irqrestore(&svs_lock, flags);
 +
 +      svsb->phase = SVSB_PHASE_ERROR;
 +      svs_adjust_pm_opp_volts(svsb);
 +}
 +
  #ifdef CONFIG_DEBUG_FS
  static int svs_dump_debug_show(struct seq_file *m, void *p)
  {
@@@ -715,6 -701,7 +716,6 @@@ static ssize_t svs_enable_debug_write(s
  {
        struct svs_bank *svsb = file_inode(filp)->i_private;
        struct svs_platform *svsp = dev_get_drvdata(svsb->dev);
 -      unsigned long flags;
        int enabled, ret;
        char *buf = NULL;
  
                return ret;
  
        if (!enabled) {
 -              spin_lock_irqsave(&svs_lock, flags);
 -              svsp->pbank = svsb;
 +              svs_bank_disable_and_restore_default_volts(svsp, svsb);
                svsb->mode_support = SVSB_MODE_ALL_DISABLE;
 -              svs_switch_bank(svsp);
 -              svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
 -              svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
 -              spin_unlock_irqrestore(&svs_lock, flags);
 -
 -              svsb->phase = SVSB_PHASE_ERROR;
 -              svs_adjust_pm_opp_volts(svsb);
        }
  
        kfree(buf);
@@@ -1514,7 -1509,16 +1515,7 @@@ static int svs_init02(struct svs_platfo
  out_of_init02:
        for (idx = 0; idx < svsp->bank_max; idx++) {
                svsb = &svsp->banks[idx];
 -
 -              spin_lock_irqsave(&svs_lock, flags);
 -              svsp->pbank = svsb;
 -              svs_switch_bank(svsp);
 -              svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
 -              svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
 -              spin_unlock_irqrestore(&svs_lock, flags);
 -
 -              svsb->phase = SVSB_PHASE_ERROR;
 -              svs_adjust_pm_opp_volts(svsb);
 +              svs_bank_disable_and_restore_default_volts(svsp, svsb);
        }
  
        return ret;
@@@ -1560,12 -1564,23 +1561,12 @@@ static int svs_suspend(struct device *d
  {
        struct svs_platform *svsp = dev_get_drvdata(dev);
        struct svs_bank *svsb;
 -      unsigned long flags;
        int ret;
        u32 idx;
  
        for (idx = 0; idx < svsp->bank_max; idx++) {
                svsb = &svsp->banks[idx];
 -
 -              /* This might wait for svs_isr() process */
 -              spin_lock_irqsave(&svs_lock, flags);
 -              svsp->pbank = svsb;
 -              svs_switch_bank(svsp);
 -              svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
 -              svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
 -              spin_unlock_irqrestore(&svs_lock, flags);
 -
 -              svsb->phase = SVSB_PHASE_ERROR;
 -              svs_adjust_pm_opp_volts(svsb);
 +              svs_bank_disable_and_restore_default_volts(svsp, svsb);
        }
  
        ret = reset_control_assert(svsp->rst);
@@@ -1679,7 -1694,7 +1680,7 @@@ static int svs_bank_resource_setup(stru
                        }
                }
  
 -              if (svsb->mode_support & SVSB_MODE_MON) {
 +              if (!IS_ERR_OR_NULL(svsb->tzone_name)) {
                        svsb->tzd = thermal_zone_get_zone_by_name(svsb->tzone_name);
                        if (IS_ERR(svsb->tzd)) {
                                dev_err(svsb->dev, "cannot get \"%s\" thermal zone\n",
        return 0;
  }
  
 -static int svs_thermal_efuse_get_data(struct svs_platform *svsp)
 +static int svs_get_efuse_data(struct svs_platform *svsp,
 +                            const char *nvmem_cell_name,
 +                            u32 **svsp_efuse, size_t *svsp_efuse_max)
  {
        struct nvmem_cell *cell;
  
 -      /* Thermal efuse parsing */
 -      cell = nvmem_cell_get(svsp->dev, "t-calibration-data");
 -      if (IS_ERR_OR_NULL(cell)) {
 -              dev_err(svsp->dev, "no \"t-calibration-data\"? %ld\n", PTR_ERR(cell));
 +      cell = nvmem_cell_get(svsp->dev, nvmem_cell_name);
 +      if (IS_ERR(cell)) {
 +              dev_err(svsp->dev, "no \"%s\"? %ld\n",
 +                      nvmem_cell_name, PTR_ERR(cell));
                return PTR_ERR(cell);
        }
  
 -      svsp->tefuse = nvmem_cell_read(cell, &svsp->tefuse_max);
 -      if (IS_ERR(svsp->tefuse)) {
 -              dev_err(svsp->dev, "cannot read thermal efuse: %ld\n",
 -                      PTR_ERR(svsp->tefuse));
 +      *svsp_efuse = nvmem_cell_read(cell, svsp_efuse_max);
 +      if (IS_ERR(*svsp_efuse)) {
 +              dev_err(svsp->dev, "cannot read \"%s\" efuse: %ld\n",
 +                      nvmem_cell_name, PTR_ERR(*svsp_efuse));
                nvmem_cell_put(cell);
 -              return PTR_ERR(svsp->tefuse);
 +              return PTR_ERR(*svsp_efuse);
        }
  
 -      svsp->tefuse_max /= sizeof(u32);
 +      *svsp_efuse_max /= sizeof(u32);
        nvmem_cell_put(cell);
  
        return 0;
@@@ -1784,8 -1797,7 +1785,8 @@@ static bool svs_mt8192_efuse_parsing(st
                svsb->vmax += svsb->dvt_fixed;
        }
  
 -      ret = svs_thermal_efuse_get_data(svsp);
 +      ret = svs_get_efuse_data(svsp, "t-calibration-data",
 +                               &svsp->tefuse, &svsp->tefuse_max);
        if (ret)
                return false;
  
@@@ -1890,8 -1902,7 +1891,8 @@@ static bool svs_mt8183_efuse_parsing(st
                }
        }
  
 -      ret = svs_thermal_efuse_get_data(svsp);
 +      ret = svs_get_efuse_data(svsp, "t-calibration-data",
 +                               &svsp->tefuse, &svsp->tefuse_max);
        if (ret)
                return false;
  
@@@ -1993,6 -2004,32 +1994,6 @@@ remove_mt8183_svsb_mon_mode
        return true;
  }
  
 -static bool svs_is_efuse_data_correct(struct svs_platform *svsp)
 -{
 -      struct nvmem_cell *cell;
 -
 -      /* Get svs efuse by nvmem */
 -      cell = nvmem_cell_get(svsp->dev, "svs-calibration-data");
 -      if (IS_ERR(cell)) {
 -              dev_err(svsp->dev, "no \"svs-calibration-data\"? %ld\n",
 -                      PTR_ERR(cell));
 -              return false;
 -      }
 -
 -      svsp->efuse = nvmem_cell_read(cell, &svsp->efuse_max);
 -      if (IS_ERR(svsp->efuse)) {
 -              dev_err(svsp->dev, "cannot read svs efuse: %ld\n",
 -                      PTR_ERR(svsp->efuse));
 -              nvmem_cell_put(cell);
 -              return false;
 -      }
 -
 -      svsp->efuse_max /= sizeof(u32);
 -      nvmem_cell_put(cell);
 -
 -      return true;
 -}
 -
  static struct device *svs_get_subsys_device(struct svs_platform *svsp,
                                            const char *node_name)
  {
@@@ -2023,6 -2060,11 +2024,6 @@@ static struct device *svs_add_device_li
        struct device *dev;
        struct device_link *sup_link;
  
 -      if (!node_name) {
 -              dev_err(svsp->dev, "node name cannot be null\n");
 -              return ERR_PTR(-EINVAL);
 -      }
 -
        dev = svs_get_subsys_device(svsp, node_name);
        if (IS_ERR(dev))
                return dev;
@@@ -2118,7 -2160,6 +2119,7 @@@ static struct svs_bank svs_mt8192_banks
                .type                   = SVSB_LOW,
                .set_freq_pct           = svs_set_bank_freq_pct_v3,
                .get_volts              = svs_get_bank_volts_v3,
 +              .tzone_name             = "gpu1",
                .volt_flags             = SVSB_REMOVE_DVTFIXED_VOLT,
                .mode_support           = SVSB_MODE_INIT02,
                .opp_count              = MAX_OPP_ENTRIES,
                .core_sel               = 0x0fff0100,
                .int_st                 = BIT(0),
                .ctl0                   = 0x00540003,
 +              .tzone_htemp            = 85000,
 +              .tzone_htemp_voffset    = 0,
 +              .tzone_ltemp            = 25000,
 +              .tzone_ltemp_voffset    = 7,
        },
        {
                .sw_id                  = SVSB_GPU,
@@@ -2328,9 -2365,8 +2329,9 @@@ static int svs_probe(struct platform_de
        if (ret)
                return ret;
  
 -      if (!svs_is_efuse_data_correct(svsp)) {
 -              dev_notice(svsp->dev, "efuse data isn't correct\n");
 +      ret = svs_get_efuse_data(svsp, "svs-calibration-data",
 +                               &svsp->efuse, &svsp->efuse_max);
 +      if (ret) {
                ret = -EPERM;
                goto svs_probe_free_efuse;
        }
        if (!svsp_data->efuse_parsing(svsp)) {
                dev_err(svsp->dev, "efuse data parsing failed\n");
                ret = -EPERM;
 -              goto svs_probe_free_resource;
 +              goto svs_probe_free_tefuse;
        }
  
        ret = svs_bank_resource_setup(svsp);
        if (ret) {
                dev_err(svsp->dev, "svs bank resource setup fail: %d\n", ret);
 -              goto svs_probe_free_resource;
 +              goto svs_probe_free_tefuse;
        }
  
        svsp_irq = platform_get_irq(pdev, 0);
        if (svsp_irq < 0) {
                ret = svsp_irq;
 -              goto svs_probe_free_resource;
 +              goto svs_probe_free_tefuse;
        }
  
        svsp->main_clk = devm_clk_get(svsp->dev, "main");
                dev_err(svsp->dev, "failed to get clock: %ld\n",
                        PTR_ERR(svsp->main_clk));
                ret = PTR_ERR(svsp->main_clk);
 -              goto svs_probe_free_resource;
 +              goto svs_probe_free_tefuse;
        }
  
        ret = clk_prepare_enable(svsp->main_clk);
        if (ret) {
                dev_err(svsp->dev, "cannot enable main clk: %d\n", ret);
 -              goto svs_probe_free_resource;
 +              goto svs_probe_free_tefuse;
        }
  
        svsp->base = of_iomap(svsp->dev->of_node, 0);
@@@ -2404,7 -2440,7 +2405,7 @@@ svs_probe_iounmap
  svs_probe_clk_disable:
        clk_disable_unprepare(svsp->main_clk);
  
 -svs_probe_free_resource:
 +svs_probe_free_tefuse:
        if (!IS_ERR_OR_NULL(svsp->tefuse))
                kfree(svsp->tefuse);
  
diff --combined include/linux/cpufreq.h
index 541013487a0e287e5169b10532c58ce7146ee8de,3ac4a10d4651b7fb01e81c3628f1ccd3560d0b13..26e2eb3994841b28694640932c57b9d8e6edd1b3
@@@ -15,7 -15,6 +15,6 @@@
  #include <linux/kobject.h>
  #include <linux/notifier.h>
  #include <linux/of.h>
- #include <linux/of_device.h>
  #include <linux/pm_opp.h>
  #include <linux/pm_qos.h>
  #include <linux/spinlock.h>
@@@ -237,7 -236,6 +236,7 @@@ bool cpufreq_supports_freq_invariance(v
  struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy);
  void cpufreq_enable_fast_switch(struct cpufreq_policy *policy);
  void cpufreq_disable_fast_switch(struct cpufreq_policy *policy);
 +bool has_target_index(void);
  #else
  static inline unsigned int cpufreq_get(unsigned int cpu)
  {