OPP: decouple dt properties in opp_parse_supplies()
Commit Message
The opp-microwatt property was added with the intention of providing
platforms a way to specify a precise value for the power consumption
of a device at a given OPP to enable better energy-aware scheduling
decisions by informing the kernel of the total static and dynamic
power of a device at a given OPP, removing the reliance on the EM
subsystem's often flawed estimations. This property is parsed by
opp_parse_supplies(), which creates a hard dependency on the
opp-microvolt property.
Some platforms, such as Apple Silicon, do not describe their devices'
voltage regulators in the DT as they cannot be controlled by the kernel
and/or rely on opaque firmware algorithms to control their voltage and
current characteristics at runtime. We can, however, experimentally
determine the power consumption of a given device at a given OPP, taking
advantage of opp-microwatt to provide EAS on such devices as was initially
intended.
Allow platforms to specify and consume any subset of opp-microvolt,
opp-microamp, or opp-microwatt without a hard dependency on opp-microvolt
to enable this functionality on such platforms.
Fixes: 4f9a7a1dc2a2 ("OPP: Add "opp-microwatt" supporting code")
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
drivers/opp/of.c | 198 +++++++++++++++++++++++++----------------------
1 file changed, 104 insertions(+), 94 deletions(-)
Comments
Hi James,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.1-rc2 next-20221028]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/James-Calligeros/OPP-decouple-dt-properties-in-opp_parse_supplies/20221030-114618
patch link: https://lore.kernel.org/r/20221030034414.24672-1-jcalligeros99%40gmail.com
patch subject: [PATCH] OPP: decouple dt properties in opp_parse_supplies()
config: arc-randconfig-r043-20221030
compiler: arceb-elf-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/c88dea73d372f38c7f3ab19f688cf210d49481ea
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review James-Calligeros/OPP-decouple-dt-properties-in-opp_parse_supplies/20221030-114618
git checkout c88dea73d372f38c7f3ab19f688cf210d49481ea
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arc SHELL=/bin/bash drivers/opp/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
drivers/opp/of.c: In function 'opp_parse_supplies':
>> drivers/opp/of.c:739:20: error: 'struct dev_pm_opp' has no member named 'regulator_count'
739 | opp->regulator_count = 0;
| ^~
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for VIDEO_MEDIATEK_VPU
Depends on [n]: MEDIA_SUPPORT [=y] && MEDIA_PLATFORM_SUPPORT [=y] && MEDIA_PLATFORM_DRIVERS [=y] && V4L_MEM2MEM_DRIVERS [=n] && VIDEO_DEV [=y] && (ARCH_MEDIATEK || COMPILE_TEST [=y])
Selected by [y]:
- VIDEO_MEDIATEK_MDP3 [=y] && MEDIA_SUPPORT [=y] && MEDIA_PLATFORM_SUPPORT [=y] && MEDIA_PLATFORM_DRIVERS [=y] && (MTK_IOMMU [=n] || COMPILE_TEST [=y]) && VIDEO_DEV [=y] && (ARCH_MEDIATEK || COMPILE_TEST [=y]) && HAS_DMA [=y] && REMOTEPROC [=y]
vim +739 drivers/opp/of.c
580
581 static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
582 struct opp_table *opp_table)
583 {
584 u32 *microvolt = NULL, *microamp = NULL, *microwatt = NULL;
585 int supplies = opp_table->regulator_count;
586 int vcount, icount, pcount, ret, i, j;
587 struct property *prop_mv = NULL, *prop_ma = NULL, *prop_mw = NULL;
588 char name[NAME_MAX];
589
590 /* Search for "opp-microvolt-<name>" */
591 if (opp_table->prop_name) {
592 snprintf(name, sizeof(name), "opp-microvolt-%s",
593 opp_table->prop_name);
594 prop_mv = of_find_property(opp->np, name, NULL);
595 }
596
597 if (!prop_mv) {
598 /* Search for "opp-microvolt" */
599 sprintf(name, "opp-microvolt");
600 prop_mv = of_find_property(opp->np, name, NULL);
601
602 }
603
604 if (prop_mv) {
605 vcount = of_property_count_u32_elems(opp->np, name);
606 if (unlikely(supplies == -1))
607 supplies = opp_table->regulator_count = vcount;
608 } else {
609 prop_mv = NULL;
610 vcount = 0;
611 }
612
613 if (vcount < 0) {
614 dev_err(dev, "%s: Invalid %s property (%d)\n",
615 __func__, name, vcount);
616 return vcount;
617 }
618
619 if (vcount) {
620 /* There can be one or three elements per supply */
621 if (vcount != supplies && vcount != supplies * 3) {
622 dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
623 __func__, name, vcount, supplies);
624 return -EINVAL;
625 }
626
627 microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
628 if (!microvolt)
629 return -ENOMEM;
630
631 ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
632 if (ret) {
633 dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
634 ret = -EINVAL;
635 goto free_microvolt;
636 }
637 }
638
639 /* Search for "opp-microamp-<name>" */
640 if (opp_table->prop_name) {
641 snprintf(name, sizeof(name), "opp-microamp-%s",
642 opp_table->prop_name);
643 prop_ma = of_find_property(opp->np, name, NULL);
644 }
645
646 if (!prop_ma) {
647 /* Search for "opp-microamp" */
648 sprintf(name, "opp-microamp");
649 prop_ma = of_find_property(opp->np, name, NULL);
650
651 }
652
653 if (prop_ma) {
654 icount = of_property_count_u32_elems(opp->np, name);
655 if (unlikely(supplies == -1))
656 supplies = opp_table->regulator_count = icount;
657 } else {
658 prop_ma = NULL;
659 icount = 0;
660 }
661
662 if (icount < 0) {
663 dev_err(dev, "%s: Invalid %s property (%d)\n",
664 __func__, name, icount);
665 return icount;
666 }
667
668 if (icount) {
669 /* There can be one or three elements per supply */
670 if (icount != supplies && icount != supplies * 3) {
671 dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
672 __func__, name, icount, supplies);
673 return -EINVAL;
674 }
675
676 microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL);
677 if (!microamp)
678 return -ENOMEM;
679
680 ret = of_property_read_u32_array(opp->np, name, microamp, icount);
681 if (ret) {
682 dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
683 ret = -EINVAL;
684 goto free_microamp;
685 }
686 }
687
688 /* Search for "opp-microwatt-<name>" */
689 if (opp_table->prop_name) {
690 snprintf(name, sizeof(name), "opp-microwatt-%s",
691 opp_table->prop_name);
692 prop_mw = of_find_property(opp->np, name, NULL);
693 }
694
695 if (!prop_mw) {
696 /* Search for "opp-microwatt" */
697 sprintf(name, "opp-microwatt");
698 prop_mw = of_find_property(opp->np, name, NULL);
699
700 }
701
702 if (prop_mw) {
703 pcount = of_property_count_u32_elems(opp->np, name);
704 if (unlikely(supplies == -1))
705 supplies = opp_table->regulator_count = pcount;
706 } else {
707 prop_mw = NULL;
708 pcount = 0;
709 }
710
711 if (pcount < 0) {
712 dev_err(dev, "%s: Invalid %s property (%d)\n",
713 __func__, name, pcount);
714 return pcount;
715 }
716
717 if (pcount) {
718 /* There can be one or three elements per supply */
719 if (pcount != supplies && pcount != supplies * 3) {
720 dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
721 __func__, name, pcount, supplies);
722 return -EINVAL;
723 }
724
725 microwatt = kmalloc_array(pcount, sizeof(*microwatt), GFP_KERNEL);
726 if (!microwatt)
727 return -ENOMEM;
728
729 ret = of_property_read_u32_array(opp->np, name, microwatt, pcount);
730 if (ret) {
731 dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
732 ret = -EINVAL;
733 goto free_microwatt;
734 }
735 }
736
737 /* No supplies associated with the OPP */
738 if (unlikely(supplies == -1)) {
> 739 opp->regulator_count = 0;
740 return 0;
741 }
742
743 for (i = 0, j = 0; i < supplies; i++) {
744 if (microvolt) {
745 opp->supplies[i].u_volt = microvolt[j++];
746
747 if (vcount == supplies) {
748 opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
749 opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
750 } else {
751 opp->supplies[i].u_volt_min = microvolt[j++];
752 opp->supplies[i].u_volt_max = microvolt[j++];
753 }
754 }
755
756 if (microamp)
757 opp->supplies[i].u_amp = microamp[i];
758
759 if (microwatt)
760 opp->supplies[i].u_watt = microwatt[i];
761 }
762
763 free_microwatt:
764 kfree(microwatt);
765 free_microamp:
766 kfree(microamp);
767 free_microvolt:
768 kfree(microvolt);
769
770 return ret;
771 }
772
Hi James,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.1-rc2 next-20221028]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/James-Calligeros/OPP-decouple-dt-properties-in-opp_parse_supplies/20221030-114618
patch link: https://lore.kernel.org/r/20221030034414.24672-1-jcalligeros99%40gmail.com
patch subject: [PATCH] OPP: decouple dt properties in opp_parse_supplies()
config: riscv-randconfig-r042-20221030
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 791a7ae1ba3efd6bca96338e10ffde557ba83920)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install riscv cross compiling tool for clang build
# apt-get install binutils-riscv64-linux-gnu
# https://github.com/intel-lab-lkp/linux/commit/c88dea73d372f38c7f3ab19f688cf210d49481ea
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review James-Calligeros/OPP-decouple-dt-properties-in-opp_parse_supplies/20221030-114618
git checkout c88dea73d372f38c7f3ab19f688cf210d49481ea
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash drivers/opp/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
>> drivers/opp/of.c:739:8: error: no member named 'regulator_count' in 'struct dev_pm_opp'
opp->regulator_count = 0;
~~~ ^
1 error generated.
vim +739 drivers/opp/of.c
580
581 static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
582 struct opp_table *opp_table)
583 {
584 u32 *microvolt = NULL, *microamp = NULL, *microwatt = NULL;
585 int supplies = opp_table->regulator_count;
586 int vcount, icount, pcount, ret, i, j;
587 struct property *prop_mv = NULL, *prop_ma = NULL, *prop_mw = NULL;
588 char name[NAME_MAX];
589
590 /* Search for "opp-microvolt-<name>" */
591 if (opp_table->prop_name) {
592 snprintf(name, sizeof(name), "opp-microvolt-%s",
593 opp_table->prop_name);
594 prop_mv = of_find_property(opp->np, name, NULL);
595 }
596
597 if (!prop_mv) {
598 /* Search for "opp-microvolt" */
599 sprintf(name, "opp-microvolt");
600 prop_mv = of_find_property(opp->np, name, NULL);
601
602 }
603
604 if (prop_mv) {
605 vcount = of_property_count_u32_elems(opp->np, name);
606 if (unlikely(supplies == -1))
607 supplies = opp_table->regulator_count = vcount;
608 } else {
609 prop_mv = NULL;
610 vcount = 0;
611 }
612
613 if (vcount < 0) {
614 dev_err(dev, "%s: Invalid %s property (%d)\n",
615 __func__, name, vcount);
616 return vcount;
617 }
618
619 if (vcount) {
620 /* There can be one or three elements per supply */
621 if (vcount != supplies && vcount != supplies * 3) {
622 dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
623 __func__, name, vcount, supplies);
624 return -EINVAL;
625 }
626
627 microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
628 if (!microvolt)
629 return -ENOMEM;
630
631 ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
632 if (ret) {
633 dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
634 ret = -EINVAL;
635 goto free_microvolt;
636 }
637 }
638
639 /* Search for "opp-microamp-<name>" */
640 if (opp_table->prop_name) {
641 snprintf(name, sizeof(name), "opp-microamp-%s",
642 opp_table->prop_name);
643 prop_ma = of_find_property(opp->np, name, NULL);
644 }
645
646 if (!prop_ma) {
647 /* Search for "opp-microamp" */
648 sprintf(name, "opp-microamp");
649 prop_ma = of_find_property(opp->np, name, NULL);
650
651 }
652
653 if (prop_ma) {
654 icount = of_property_count_u32_elems(opp->np, name);
655 if (unlikely(supplies == -1))
656 supplies = opp_table->regulator_count = icount;
657 } else {
658 prop_ma = NULL;
659 icount = 0;
660 }
661
662 if (icount < 0) {
663 dev_err(dev, "%s: Invalid %s property (%d)\n",
664 __func__, name, icount);
665 return icount;
666 }
667
668 if (icount) {
669 /* There can be one or three elements per supply */
670 if (icount != supplies && icount != supplies * 3) {
671 dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
672 __func__, name, icount, supplies);
673 return -EINVAL;
674 }
675
676 microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL);
677 if (!microamp)
678 return -ENOMEM;
679
680 ret = of_property_read_u32_array(opp->np, name, microamp, icount);
681 if (ret) {
682 dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
683 ret = -EINVAL;
684 goto free_microamp;
685 }
686 }
687
688 /* Search for "opp-microwatt-<name>" */
689 if (opp_table->prop_name) {
690 snprintf(name, sizeof(name), "opp-microwatt-%s",
691 opp_table->prop_name);
692 prop_mw = of_find_property(opp->np, name, NULL);
693 }
694
695 if (!prop_mw) {
696 /* Search for "opp-microwatt" */
697 sprintf(name, "opp-microwatt");
698 prop_mw = of_find_property(opp->np, name, NULL);
699
700 }
701
702 if (prop_mw) {
703 pcount = of_property_count_u32_elems(opp->np, name);
704 if (unlikely(supplies == -1))
705 supplies = opp_table->regulator_count = pcount;
706 } else {
707 prop_mw = NULL;
708 pcount = 0;
709 }
710
711 if (pcount < 0) {
712 dev_err(dev, "%s: Invalid %s property (%d)\n",
713 __func__, name, pcount);
714 return pcount;
715 }
716
717 if (pcount) {
718 /* There can be one or three elements per supply */
719 if (pcount != supplies && pcount != supplies * 3) {
720 dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
721 __func__, name, pcount, supplies);
722 return -EINVAL;
723 }
724
725 microwatt = kmalloc_array(pcount, sizeof(*microwatt), GFP_KERNEL);
726 if (!microwatt)
727 return -ENOMEM;
728
729 ret = of_property_read_u32_array(opp->np, name, microwatt, pcount);
730 if (ret) {
731 dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
732 ret = -EINVAL;
733 goto free_microwatt;
734 }
735 }
736
737 /* No supplies associated with the OPP */
738 if (unlikely(supplies == -1)) {
> 739 opp->regulator_count = 0;
740 return 0;
741 }
742
743 for (i = 0, j = 0; i < supplies; i++) {
744 if (microvolt) {
745 opp->supplies[i].u_volt = microvolt[j++];
746
747 if (vcount == supplies) {
748 opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
749 opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
750 } else {
751 opp->supplies[i].u_volt_min = microvolt[j++];
752 opp->supplies[i].u_volt_max = microvolt[j++];
753 }
754 }
755
756 if (microamp)
757 opp->supplies[i].u_amp = microamp[i];
758
759 if (microwatt)
760 opp->supplies[i].u_watt = microwatt[i];
761 }
762
763 free_microwatt:
764 kfree(microwatt);
765 free_microamp:
766 kfree(microamp);
767 free_microvolt:
768 kfree(microvolt);
769
770 return ret;
771 }
772
@@ -581,166 +581,176 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
struct opp_table *opp_table)
{
- u32 *microvolt, *microamp = NULL, *microwatt = NULL;
+ u32 *microvolt = NULL, *microamp = NULL, *microwatt = NULL;
int supplies = opp_table->regulator_count;
int vcount, icount, pcount, ret, i, j;
- struct property *prop = NULL;
+ struct property *prop_mv = NULL, *prop_ma = NULL, *prop_mw = NULL;
char name[NAME_MAX];
/* Search for "opp-microvolt-<name>" */
if (opp_table->prop_name) {
snprintf(name, sizeof(name), "opp-microvolt-%s",
opp_table->prop_name);
- prop = of_find_property(opp->np, name, NULL);
+ prop_mv = of_find_property(opp->np, name, NULL);
}
- if (!prop) {
+ if (!prop_mv) {
/* Search for "opp-microvolt" */
sprintf(name, "opp-microvolt");
- prop = of_find_property(opp->np, name, NULL);
-
- /* Missing property isn't a problem, but an invalid entry is */
- if (!prop) {
- if (unlikely(supplies == -1)) {
- /* Initialize regulator_count */
- opp_table->regulator_count = 0;
- return 0;
- }
+ prop_mv = of_find_property(opp->np, name, NULL);
- if (!supplies)
- return 0;
-
- dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n",
- __func__);
- return -EINVAL;
- }
}
- if (unlikely(supplies == -1)) {
- /* Initialize regulator_count */
- supplies = opp_table->regulator_count = 1;
- } else if (unlikely(!supplies)) {
- dev_err(dev, "%s: opp-microvolt wasn't expected\n", __func__);
- return -EINVAL;
+ if (prop_mv) {
+ vcount = of_property_count_u32_elems(opp->np, name);
+ if (unlikely(supplies == -1))
+ supplies = opp_table->regulator_count = vcount;
+ } else {
+ prop_mv = NULL;
+ vcount = 0;
}
- vcount = of_property_count_u32_elems(opp->np, name);
if (vcount < 0) {
dev_err(dev, "%s: Invalid %s property (%d)\n",
__func__, name, vcount);
return vcount;
}
- /* There can be one or three elements per supply */
- if (vcount != supplies && vcount != supplies * 3) {
- dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
- __func__, name, vcount, supplies);
- return -EINVAL;
- }
+ if (vcount) {
+ /* There can be one or three elements per supply */
+ if (vcount != supplies && vcount != supplies * 3) {
+ dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
+ __func__, name, vcount, supplies);
+ return -EINVAL;
+ }
- microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
- if (!microvolt)
- return -ENOMEM;
+ microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
+ if (!microvolt)
+ return -ENOMEM;
- ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
- if (ret) {
- dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
- ret = -EINVAL;
- goto free_microvolt;
+ ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
+ if (ret) {
+ dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
+ ret = -EINVAL;
+ goto free_microvolt;
+ }
}
/* Search for "opp-microamp-<name>" */
- prop = NULL;
if (opp_table->prop_name) {
snprintf(name, sizeof(name), "opp-microamp-%s",
opp_table->prop_name);
- prop = of_find_property(opp->np, name, NULL);
+ prop_ma = of_find_property(opp->np, name, NULL);
}
- if (!prop) {
+ if (!prop_ma) {
/* Search for "opp-microamp" */
sprintf(name, "opp-microamp");
- prop = of_find_property(opp->np, name, NULL);
+ prop_ma = of_find_property(opp->np, name, NULL);
+
}
- if (prop) {
+ if (prop_ma) {
icount = of_property_count_u32_elems(opp->np, name);
- if (icount < 0) {
- dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
- name, icount);
- ret = icount;
- goto free_microvolt;
- }
+ if (unlikely(supplies == -1))
+ supplies = opp_table->regulator_count = icount;
+ } else {
+ prop_ma = NULL;
+ icount = 0;
+ }
- if (icount != supplies) {
+ if (icount < 0) {
+ dev_err(dev, "%s: Invalid %s property (%d)\n",
+ __func__, name, icount);
+ return icount;
+ }
+
+ if (icount) {
+ /* There can be one or three elements per supply */
+ if (icount != supplies && icount != supplies * 3) {
dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
__func__, name, icount, supplies);
- ret = -EINVAL;
- goto free_microvolt;
+ return -EINVAL;
}
microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL);
- if (!microamp) {
- ret = -EINVAL;
- goto free_microvolt;
- }
+ if (!microamp)
+ return -ENOMEM;
- ret = of_property_read_u32_array(opp->np, name, microamp,
- icount);
+ ret = of_property_read_u32_array(opp->np, name, microamp, icount);
if (ret) {
- dev_err(dev, "%s: error parsing %s: %d\n", __func__,
- name, ret);
+ dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
ret = -EINVAL;
goto free_microamp;
}
}
- /* Search for "opp-microwatt" */
- sprintf(name, "opp-microwatt");
- prop = of_find_property(opp->np, name, NULL);
+ /* Search for "opp-microwatt-<name>" */
+ if (opp_table->prop_name) {
+ snprintf(name, sizeof(name), "opp-microwatt-%s",
+ opp_table->prop_name);
+ prop_mw = of_find_property(opp->np, name, NULL);
+ }
+
+ if (!prop_mw) {
+ /* Search for "opp-microwatt" */
+ sprintf(name, "opp-microwatt");
+ prop_mw = of_find_property(opp->np, name, NULL);
- if (prop) {
+ }
+
+ if (prop_mw) {
pcount = of_property_count_u32_elems(opp->np, name);
- if (pcount < 0) {
- dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
- name, pcount);
- ret = pcount;
- goto free_microamp;
- }
+ if (unlikely(supplies == -1))
+ supplies = opp_table->regulator_count = pcount;
+ } else {
+ prop_mw = NULL;
+ pcount = 0;
+ }
+
+ if (pcount < 0) {
+ dev_err(dev, "%s: Invalid %s property (%d)\n",
+ __func__, name, pcount);
+ return pcount;
+ }
- if (pcount != supplies) {
+ if (pcount) {
+ /* There can be one or three elements per supply */
+ if (pcount != supplies && pcount != supplies * 3) {
dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
__func__, name, pcount, supplies);
- ret = -EINVAL;
- goto free_microamp;
+ return -EINVAL;
}
- microwatt = kmalloc_array(pcount, sizeof(*microwatt),
- GFP_KERNEL);
- if (!microwatt) {
- ret = -EINVAL;
- goto free_microamp;
- }
+ microwatt = kmalloc_array(pcount, sizeof(*microwatt), GFP_KERNEL);
+ if (!microwatt)
+ return -ENOMEM;
- ret = of_property_read_u32_array(opp->np, name, microwatt,
- pcount);
+ ret = of_property_read_u32_array(opp->np, name, microwatt, pcount);
if (ret) {
- dev_err(dev, "%s: error parsing %s: %d\n", __func__,
- name, ret);
+ dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
ret = -EINVAL;
goto free_microwatt;
}
}
- for (i = 0, j = 0; i < supplies; i++) {
- opp->supplies[i].u_volt = microvolt[j++];
+ /* No supplies associated with the OPP */
+ if (unlikely(supplies == -1)) {
+ opp->regulator_count = 0;
+ return 0;
+ }
- if (vcount == supplies) {
- opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
- opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
- } else {
- opp->supplies[i].u_volt_min = microvolt[j++];
- opp->supplies[i].u_volt_max = microvolt[j++];
+ for (i = 0, j = 0; i < supplies; i++) {
+ if (microvolt) {
+ opp->supplies[i].u_volt = microvolt[j++];
+
+ if (vcount == supplies) {
+ opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
+ opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
+ } else {
+ opp->supplies[i].u_volt_min = microvolt[j++];
+ opp->supplies[i].u_volt_max = microvolt[j++];
+ }
}
if (microamp)