linux-sunxi.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/4] regulator: Add support for Allwinner D1 system LDOs
@ 2022-12-08  8:41 Samuel Holland
  2022-12-08  8:41 ` [PATCH v5 1/4] regulator: dt-bindings: Add " Samuel Holland
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Samuel Holland @ 2022-12-08  8:41 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown
  Cc: Chen-Yu Tsai, Krzysztof Kozlowski, Andre Przywara, linux-kernel,
	devicetree, Jernej Skrabec, Rob Herring, linux-sunxi,
	linux-arm-kernel, Samuel Holland, Andrew Lunn, Heiko Stuebner,
	Maxime Ripard

This series adds the binding and driver for one of the two pairs of LDOs
inside the Allwinner D1 SoC. I am splitting up the two pairs of LDOs to
unblock merging the SoC devicetree; the analog LDOs depend on the audio
codec binding, but they are not required to boot.

A binding and driver change is required for the SRAM controller, to
accept the regulators device as its child node.

The example for the regulator device binding is in SRAM controller
binding document, per Rob's request to keep MFD examples in one place.

Because of this, at least the first 3 patches need to be taken together
through the regulator tree, though it should be fine to merge the whole
series that way.

Changes in v5:
 - Correct the voltage calculation for the non-linearity around 1.6 V.

Changes in v4:
 - Fix the order of the maintainer/description sections
 - Replace unevaluatedProperties with "additionalProperties: false"
 - Drop the analog LDOs until the codec binding is ready
 - Drop the analog LDOs until the codec binding is ready
 - Remove unevaluatedProperties from regulators schema reference
 - Check the compatible string instead of the node name

Changes in v3:
 - Add "reg" property to bindings
 - Add "unevaluatedProperties: true" to regulator nodes
 - Minor changes to regulator node name patterns
 - Remove system-ldos example (now added in the parent binding)
 - Adjust control flow in sun20i_regulator_get_regmap() for clarity
 - Require the regulators node to have a unit address
 - Reference the regulator schema from the SRAM controller schema
 - Move the system LDOs example to the SRAM controller schema
 - Reorder the patches so the example passes validation

Changes in v2:
 - Remove syscon property from bindings
 - Update binding examples to fix warnings and provide context
 - Use decimal numbers for .n_voltages instead of field widths
 - Get the regmap from the parent device instead of a property/phandle

Samuel Holland (4):
  regulator: dt-bindings: Add Allwinner D1 system LDOs
  regulator: sun20i: Add Allwinner D1 LDOs driver
  dt-bindings: sram: sunxi-sram: Add regulators child
  soc: sunxi: sram: Only iterate over SRAM children

 .../allwinner,sun20i-d1-system-ldos.yaml      |  37 +++++
 .../allwinner,sun4i-a10-system-control.yaml   |  28 ++++
 drivers/regulator/Kconfig                     |   8 +
 drivers/regulator/Makefile                    |   1 +
 drivers/regulator/sun20i-regulator.c          | 156 ++++++++++++++++++
 drivers/soc/sunxi/sunxi_sram.c                |   3 +
 6 files changed, 233 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml
 create mode 100644 drivers/regulator/sun20i-regulator.c

-- 
2.37.4


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v5 1/4] regulator: dt-bindings: Add Allwinner D1 system LDOs
  2022-12-08  8:41 [PATCH v5 0/4] regulator: Add support for Allwinner D1 system LDOs Samuel Holland
@ 2022-12-08  8:41 ` Samuel Holland
  2022-12-08  8:41 ` [PATCH v5 2/4] regulator: sun20i: Add Allwinner D1 LDOs driver Samuel Holland
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Samuel Holland @ 2022-12-08  8:41 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown
  Cc: Chen-Yu Tsai, Krzysztof Kozlowski, Andre Przywara, linux-kernel,
	devicetree, Jernej Skrabec, Rob Herring, linux-sunxi,
	linux-arm-kernel, Samuel Holland, Andrew Lunn, Heiko Stuebner,
	Maxime Ripard, Krzysztof Kozlowski

The Allwinner D1 SoC contains two pairs of in-package LDOs. The pair of
"system" LDOs is for general purpose use. LDOA generally powers the
board's 1.8 V rail. LDOB powers the in-package DRAM, where applicable.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---

(no changes since v4)

Changes in v4:
 - Fix the order of the maintainer/description sections
 - Replace unevaluatedProperties with "additionalProperties: false"
 - Drop the analog LDOs until the codec binding is ready

Changes in v3:
 - Add "reg" property to bindings
 - Add "unevaluatedProperties: true" to regulator nodes
 - Minor changes to regulator node name patterns
 - Remove system-ldos example (now added in the parent binding)

Changes in v2:
 - Remove syscon property from bindings
 - Update binding examples to fix warnings and provide context

 .../allwinner,sun20i-d1-system-ldos.yaml      | 37 +++++++++++++++++++
 1 file changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml

diff --git a/Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml b/Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml
new file mode 100644
index 000000000000..ec6695c8d2e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/allwinner,sun20i-d1-system-ldos.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner D1 System LDOs
+
+maintainers:
+  - Samuel Holland <samuel@sholland.org>
+
+description:
+  Allwinner D1 contains a pair of general-purpose LDOs which are designed to
+  supply power inside and outside the SoC. They are controlled by a register
+  within the system control MMIO space.
+
+properties:
+  compatible:
+    enum:
+      - allwinner,sun20i-d1-system-ldos
+
+  reg:
+    maxItems: 1
+
+patternProperties:
+  "^ldo[ab]$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+...
-- 
2.37.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 2/4] regulator: sun20i: Add Allwinner D1 LDOs driver
  2022-12-08  8:41 [PATCH v5 0/4] regulator: Add support for Allwinner D1 system LDOs Samuel Holland
  2022-12-08  8:41 ` [PATCH v5 1/4] regulator: dt-bindings: Add " Samuel Holland
@ 2022-12-08  8:41 ` Samuel Holland
  2023-01-12 23:50   ` Andre Przywara
  2023-01-13  5:08   ` Jernej Škrabec
  2022-12-08  8:41 ` [PATCH v5 3/4] dt-bindings: sram: sunxi-sram: Add regulators child Samuel Holland
  2022-12-08  8:41 ` [PATCH v5 4/4] soc: sunxi: sram: Only iterate over SRAM children Samuel Holland
  3 siblings, 2 replies; 8+ messages in thread
From: Samuel Holland @ 2022-12-08  8:41 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown
  Cc: Chen-Yu Tsai, Krzysztof Kozlowski, Andre Przywara, linux-kernel,
	devicetree, Jernej Skrabec, Rob Herring, linux-sunxi,
	linux-arm-kernel, Samuel Holland, Andrew Lunn, Heiko Stuebner,
	Maxime Ripard

D1 contains two pairs of LDOs, "analog" LDOs and "system" LDOs. They are
similar and can share a driver, but only the system LDOs have a DT
binding defined so far.

The system LDOs have a single linear range. The voltage step is not an
integer, so a custom .list_voltage is needed to get the rounding right.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

Changes in v5:
 - Correct the voltage calculation for the non-linearity around 1.6 V.

Changes in v4:
 - Drop the analog LDOs until the codec binding is ready

Changes in v3:
 - Adjust control flow in sun20i_regulator_get_regmap() for clarity

Changes in v2:
 - Use decimal numbers for .n_voltages instead of field widths
 - Get the regmap from the parent device instead of a property/phandle

 drivers/regulator/Kconfig            |   8 ++
 drivers/regulator/Makefile           |   1 +
 drivers/regulator/sun20i-regulator.c | 156 +++++++++++++++++++++++++++
 3 files changed, 165 insertions(+)
 create mode 100644 drivers/regulator/sun20i-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 070e4403c6c2..8480532114c1 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1280,6 +1280,14 @@ config REGULATOR_STW481X_VMMC
 	  This driver supports the internal VMMC regulator in the STw481x
 	  PMIC chips.
 
+config REGULATOR_SUN20I
+	tristate "Allwinner D1 internal LDOs"
+	depends on ARCH_SUNXI || COMPILE_TEST
+	select MFD_SYSCON
+	default ARCH_SUNXI
+	help
+	  This driver supports the internal LDOs in the Allwinner D1 SoC.
+
 config REGULATOR_SY7636A
 	tristate "Silergy SY7636A voltage regulator"
 	depends on MFD_SY7636A
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 5962307e1130..8e9b5a21123d 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -150,6 +150,7 @@ obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
 obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
 obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o
 obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
+obj-$(CONFIG_REGULATOR_SUN20I) += sun20i-regulator.o
 obj-$(CONFIG_REGULATOR_SY7636A) += sy7636a-regulator.o
 obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
 obj-$(CONFIG_REGULATOR_SY8824X) += sy8824x.o
diff --git a/drivers/regulator/sun20i-regulator.c b/drivers/regulator/sun20i-regulator.c
new file mode 100644
index 000000000000..8af6b8037ee0
--- /dev/null
+++ b/drivers/regulator/sun20i-regulator.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
+//
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define SUN20I_SYS_LDO_CTRL_REG		0x150
+
+struct sun20i_regulator_data {
+	const struct regulator_desc	*descs;
+	unsigned int			ndescs;
+};
+
+/* regulator_list_voltage_linear() modified for the non-integral uV_step. */
+static int sun20i_d1_system_ldo_list_voltage(struct regulator_dev *rdev,
+					     unsigned int selector)
+{
+	const struct regulator_desc *desc = rdev->desc;
+	unsigned int fraction, uV;
+
+	if (selector >= desc->n_voltages)
+		return -EINVAL;
+
+	uV = desc->min_uV + (desc->uV_step * selector);
+	fraction = selector + (desc->min_uV % 4);
+
+	if (uV > 1606667)
+		uV += 6667;
+	else
+		fraction++;
+
+	/* Produce correctly-rounded absolute voltages. */
+	return uV + (fraction / 3);
+}
+
+static const struct regulator_ops sun20i_d1_system_ldo_ops = {
+	.list_voltage		= sun20i_d1_system_ldo_list_voltage,
+	.map_voltage		= regulator_map_voltage_ascend,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_desc sun20i_d1_system_ldo_descs[] = {
+	{
+		.name		= "ldoa",
+		.supply_name	= "ldo-in",
+		.of_match	= "ldoa",
+		.ops		= &sun20i_d1_system_ldo_ops,
+		.type		= REGULATOR_VOLTAGE,
+		.owner		= THIS_MODULE,
+		.n_voltages	= 32,
+		.min_uV		= 1593333,
+		.uV_step	= 13333, /* repeating */
+		.vsel_reg	= SUN20I_SYS_LDO_CTRL_REG,
+		.vsel_mask	= GENMASK(7, 0),
+	},
+	{
+		.name		= "ldob",
+		.supply_name	= "ldo-in",
+		.of_match	= "ldob",
+		.ops		= &sun20i_d1_system_ldo_ops,
+		.type		= REGULATOR_VOLTAGE,
+		.owner		= THIS_MODULE,
+		.n_voltages	= 64,
+		.min_uV		= 1166666,
+		.uV_step	= 13333, /* repeating */
+		.vsel_reg	= SUN20I_SYS_LDO_CTRL_REG,
+		.vsel_mask	= GENMASK(15, 8),
+	},
+};
+
+static const struct sun20i_regulator_data sun20i_d1_system_ldos = {
+	.descs	= sun20i_d1_system_ldo_descs,
+	.ndescs	= ARRAY_SIZE(sun20i_d1_system_ldo_descs),
+};
+
+static struct regmap *sun20i_regulator_get_regmap(struct device *dev)
+{
+	struct regmap *regmap;
+
+	/*
+	 * First try the syscon interface. The system control device is not
+	 * compatible with "syscon", so fall back to getting the regmap from
+	 * its platform device. This is ugly, but required for devicetree
+	 * backward compatibility.
+	 */
+	regmap = syscon_node_to_regmap(dev->parent->of_node);
+	if (!IS_ERR(regmap))
+		return regmap;
+
+	regmap = dev_get_regmap(dev->parent, NULL);
+	if (regmap)
+		return regmap;
+
+	return ERR_PTR(-EPROBE_DEFER);
+}
+
+static int sun20i_regulator_probe(struct platform_device *pdev)
+{
+	const struct sun20i_regulator_data *data;
+	struct device *dev = &pdev->dev;
+	struct regulator_config config;
+	struct regmap *regmap;
+
+	data = of_device_get_match_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	regmap = sun20i_regulator_get_regmap(dev);
+	if (IS_ERR(regmap))
+		return dev_err_probe(dev, PTR_ERR(regmap), "Failed to get regmap\n");
+
+	config = (struct regulator_config) {
+		.dev	= dev,
+		.regmap	= regmap,
+	};
+
+	for (unsigned int i = 0; i < data->ndescs; ++i) {
+		const struct regulator_desc *desc = &data->descs[i];
+		struct regulator_dev *rdev;
+
+		rdev = devm_regulator_register(dev, desc, &config);
+		if (IS_ERR(rdev))
+			return PTR_ERR(rdev);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id sun20i_regulator_of_match[] = {
+	{
+		.compatible = "allwinner,sun20i-d1-system-ldos",
+		.data = &sun20i_d1_system_ldos,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, sun20i_regulator_of_match);
+
+static struct platform_driver sun20i_regulator_driver = {
+	.probe	= sun20i_regulator_probe,
+	.driver	= {
+		.name		= "sun20i-regulator",
+		.of_match_table	= sun20i_regulator_of_match,
+	},
+};
+module_platform_driver(sun20i_regulator_driver);
+
+MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
+MODULE_DESCRIPTION("Allwinner D1 internal LDO driver");
+MODULE_LICENSE("GPL");
-- 
2.37.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 3/4] dt-bindings: sram: sunxi-sram: Add regulators child
  2022-12-08  8:41 [PATCH v5 0/4] regulator: Add support for Allwinner D1 system LDOs Samuel Holland
  2022-12-08  8:41 ` [PATCH v5 1/4] regulator: dt-bindings: Add " Samuel Holland
  2022-12-08  8:41 ` [PATCH v5 2/4] regulator: sun20i: Add Allwinner D1 LDOs driver Samuel Holland
@ 2022-12-08  8:41 ` Samuel Holland
  2022-12-08  8:41 ` [PATCH v5 4/4] soc: sunxi: sram: Only iterate over SRAM children Samuel Holland
  3 siblings, 0 replies; 8+ messages in thread
From: Samuel Holland @ 2022-12-08  8:41 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown
  Cc: Chen-Yu Tsai, Krzysztof Kozlowski, Andre Przywara, linux-kernel,
	devicetree, Jernej Skrabec, Rob Herring, linux-sunxi,
	linux-arm-kernel, Samuel Holland, Andrew Lunn, Heiko Stuebner,
	Maxime Ripard, Krzysztof Kozlowski

Some sunxi SoCs have in-package regulators controlled by a register in
the system control MMIO block. Allow a child node for this regulator
device in addition to SRAM child nodes.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---

(no changes since v4)

Changes in v4:
 - Remove unevaluatedProperties from regulators schema reference

Changes in v3:
 - Require the regulators node to have a unit address
 - Reference the regulator schema from the SRAM controller schema
 - Move the system LDOs example to the SRAM controller schema
 - Reorder the patches so the example passes validation

Changes in v2:
 - New patch for v2

 .../allwinner,sun4i-a10-system-control.yaml   | 28 +++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
index 98a7dc7f467d..c487ac9521e9 100644
--- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
+++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
@@ -56,6 +56,9 @@ properties:
   ranges: true
 
 patternProperties:
+  "^regulators@[0-9a-f]+$":
+    $ref: /schemas/regulator/allwinner,sun20i-d1-system-ldos.yaml#
+
   "^sram@[a-z0-9]+":
     type: object
 
@@ -130,3 +133,28 @@ examples:
         };
       };
     };
+
+  - |
+    syscon@3000000 {
+      compatible = "allwinner,sun20i-d1-system-control";
+      reg = <0x3000000 0x1000>;
+      ranges;
+      #address-cells = <1>;
+      #size-cells = <1>;
+
+      regulators@3000150 {
+        compatible = "allwinner,sun20i-d1-system-ldos";
+        reg = <0x3000150 0x4>;
+
+        reg_ldoa: ldoa {
+          regulator-min-microvolt = <1800000>;
+          regulator-max-microvolt = <1800000>;
+        };
+
+        reg_ldob: ldob {
+          regulator-name = "vcc-dram";
+          regulator-min-microvolt = <1500000>;
+          regulator-max-microvolt = <1500000>;
+        };
+      };
+    };
-- 
2.37.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 4/4] soc: sunxi: sram: Only iterate over SRAM children
  2022-12-08  8:41 [PATCH v5 0/4] regulator: Add support for Allwinner D1 system LDOs Samuel Holland
                   ` (2 preceding siblings ...)
  2022-12-08  8:41 ` [PATCH v5 3/4] dt-bindings: sram: sunxi-sram: Add regulators child Samuel Holland
@ 2022-12-08  8:41 ` Samuel Holland
  2023-01-12 17:31   ` Jernej Škrabec
  3 siblings, 1 reply; 8+ messages in thread
From: Samuel Holland @ 2022-12-08  8:41 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown
  Cc: Chen-Yu Tsai, Krzysztof Kozlowski, Andre Przywara, linux-kernel,
	devicetree, Jernej Skrabec, Rob Herring, linux-sunxi,
	linux-arm-kernel, Samuel Holland, Andrew Lunn, Heiko Stuebner,
	Maxime Ripard

Now that a regulators child is accepted by the controller binding, the
debugfs show routine must be explicitly limited to mmio-sram children.

Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Samuel Holland <samuel@sholland.org>
---

(no changes since v4)

Changes in v4:
 - Check the compatible string instead of the node name

Changes in v2:
 - New patch for v2

 drivers/soc/sunxi/sunxi_sram.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index 92f9186c1c42..f09918c59042 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -120,6 +120,9 @@ static int sunxi_sram_show(struct seq_file *s, void *data)
 	seq_puts(s, "--------------------\n\n");
 
 	for_each_child_of_node(sram_dev->of_node, sram_node) {
+		if (!of_device_is_compatible(sram_node, "mmio-sram"))
+			continue;
+
 		sram_addr_p = of_get_address(sram_node, 0, NULL, NULL);
 
 		seq_printf(s, "sram@%08x\n",
-- 
2.37.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 4/4] soc: sunxi: sram: Only iterate over SRAM children
  2022-12-08  8:41 ` [PATCH v5 4/4] soc: sunxi: sram: Only iterate over SRAM children Samuel Holland
@ 2023-01-12 17:31   ` Jernej Škrabec
  0 siblings, 0 replies; 8+ messages in thread
From: Jernej Škrabec @ 2023-01-12 17:31 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Samuel Holland
  Cc: Chen-Yu Tsai, Krzysztof Kozlowski, Andre Przywara, linux-kernel,
	devicetree, Rob Herring, linux-sunxi, linux-arm-kernel,
	Samuel Holland, Andrew Lunn, Heiko Stuebner, Maxime Ripard

Dne četrtek, 08. december 2022 ob 09:41:27 CET je Samuel Holland napisal(a):
> Now that a regulators child is accepted by the controller binding, the
> debugfs show routine must be explicitly limited to mmio-sram children.
> 
> Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
> Signed-off-by: Samuel Holland <samuel@sholland.org>

Merged, thanks!

Best regards,
Jernej



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 2/4] regulator: sun20i: Add Allwinner D1 LDOs driver
  2022-12-08  8:41 ` [PATCH v5 2/4] regulator: sun20i: Add Allwinner D1 LDOs driver Samuel Holland
@ 2023-01-12 23:50   ` Andre Przywara
  2023-01-13  5:08   ` Jernej Škrabec
  1 sibling, 0 replies; 8+ messages in thread
From: Andre Przywara @ 2023-01-12 23:50 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Liam Girdwood, Mark Brown, Chen-Yu Tsai, Krzysztof Kozlowski,
	linux-kernel, devicetree, Jernej Skrabec, Rob Herring,
	linux-sunxi, linux-arm-kernel, Andrew Lunn, Heiko Stuebner,
	Maxime Ripard

On Thu,  8 Dec 2022 02:41:25 -0600
Samuel Holland <samuel@sholland.org> wrote:

> D1 contains two pairs of LDOs, "analog" LDOs and "system" LDOs. They are
> similar and can share a driver, but only the system LDOs have a DT
> binding defined so far.
> 
> The system LDOs have a single linear range. The voltage step is not an
> integer, so a custom .list_voltage is needed to get the rounding right.
> 

I put sun20i_d1_system_ldo_list_voltage() into a userland program, and
compared the full generated list with the manual: they fully match now.
The formula looks mind-boggling, but works: well done!
I have no real experience with the regulator boilerplate, but it looks
alright, and the register offset and masks also match: 

> Signed-off-by: Samuel Holland <samuel@sholland.org>

Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Cheers,
Andre

> ---
> 
> Changes in v5:
>  - Correct the voltage calculation for the non-linearity around 1.6 V.
> 
> Changes in v4:
>  - Drop the analog LDOs until the codec binding is ready
> 
> Changes in v3:
>  - Adjust control flow in sun20i_regulator_get_regmap() for clarity
> 
> Changes in v2:
>  - Use decimal numbers for .n_voltages instead of field widths
>  - Get the regmap from the parent device instead of a property/phandle
> 
>  drivers/regulator/Kconfig            |   8 ++
>  drivers/regulator/Makefile           |   1 +
>  drivers/regulator/sun20i-regulator.c | 156 +++++++++++++++++++++++++++
>  3 files changed, 165 insertions(+)
>  create mode 100644 drivers/regulator/sun20i-regulator.c
> 
> diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
> index 070e4403c6c2..8480532114c1 100644
> --- a/drivers/regulator/Kconfig
> +++ b/drivers/regulator/Kconfig
> @@ -1280,6 +1280,14 @@ config REGULATOR_STW481X_VMMC
>  	  This driver supports the internal VMMC regulator in the STw481x
>  	  PMIC chips.
>  
> +config REGULATOR_SUN20I
> +	tristate "Allwinner D1 internal LDOs"
> +	depends on ARCH_SUNXI || COMPILE_TEST
> +	select MFD_SYSCON
> +	default ARCH_SUNXI
> +	help
> +	  This driver supports the internal LDOs in the Allwinner D1 SoC.
> +
>  config REGULATOR_SY7636A
>  	tristate "Silergy SY7636A voltage regulator"
>  	depends on MFD_SY7636A
> diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
> index 5962307e1130..8e9b5a21123d 100644
> --- a/drivers/regulator/Makefile
> +++ b/drivers/regulator/Makefile
> @@ -150,6 +150,7 @@ obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
>  obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
>  obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o
>  obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
> +obj-$(CONFIG_REGULATOR_SUN20I) += sun20i-regulator.o
>  obj-$(CONFIG_REGULATOR_SY7636A) += sy7636a-regulator.o
>  obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
>  obj-$(CONFIG_REGULATOR_SY8824X) += sy8824x.o
> diff --git a/drivers/regulator/sun20i-regulator.c b/drivers/regulator/sun20i-regulator.c
> new file mode 100644
> index 000000000000..8af6b8037ee0
> --- /dev/null
> +++ b/drivers/regulator/sun20i-regulator.c
> @@ -0,0 +1,156 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +//
> +// Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
> +//
> +
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/driver.h>
> +
> +#define SUN20I_SYS_LDO_CTRL_REG		0x150
> +
> +struct sun20i_regulator_data {
> +	const struct regulator_desc	*descs;
> +	unsigned int			ndescs;
> +};
> +
> +/* regulator_list_voltage_linear() modified for the non-integral uV_step. */
> +static int sun20i_d1_system_ldo_list_voltage(struct regulator_dev *rdev,
> +					     unsigned int selector)
> +{
> +	const struct regulator_desc *desc = rdev->desc;
> +	unsigned int fraction, uV;
> +
> +	if (selector >= desc->n_voltages)
> +		return -EINVAL;
> +
> +	uV = desc->min_uV + (desc->uV_step * selector);
> +	fraction = selector + (desc->min_uV % 4);
> +
> +	if (uV > 1606667)
> +		uV += 6667;
> +	else
> +		fraction++;
> +
> +	/* Produce correctly-rounded absolute voltages. */
> +	return uV + (fraction / 3);
> +}
> +
> +static const struct regulator_ops sun20i_d1_system_ldo_ops = {
> +	.list_voltage		= sun20i_d1_system_ldo_list_voltage,
> +	.map_voltage		= regulator_map_voltage_ascend,
> +	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
> +	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
> +};
> +
> +static const struct regulator_desc sun20i_d1_system_ldo_descs[] = {
> +	{
> +		.name		= "ldoa",
> +		.supply_name	= "ldo-in",
> +		.of_match	= "ldoa",
> +		.ops		= &sun20i_d1_system_ldo_ops,
> +		.type		= REGULATOR_VOLTAGE,
> +		.owner		= THIS_MODULE,
> +		.n_voltages	= 32,
> +		.min_uV		= 1593333,
> +		.uV_step	= 13333, /* repeating */
> +		.vsel_reg	= SUN20I_SYS_LDO_CTRL_REG,
> +		.vsel_mask	= GENMASK(7, 0),
> +	},
> +	{
> +		.name		= "ldob",
> +		.supply_name	= "ldo-in",
> +		.of_match	= "ldob",
> +		.ops		= &sun20i_d1_system_ldo_ops,
> +		.type		= REGULATOR_VOLTAGE,
> +		.owner		= THIS_MODULE,
> +		.n_voltages	= 64,
> +		.min_uV		= 1166666,
> +		.uV_step	= 13333, /* repeating */
> +		.vsel_reg	= SUN20I_SYS_LDO_CTRL_REG,
> +		.vsel_mask	= GENMASK(15, 8),
> +	},
> +};
> +
> +static const struct sun20i_regulator_data sun20i_d1_system_ldos = {
> +	.descs	= sun20i_d1_system_ldo_descs,
> +	.ndescs	= ARRAY_SIZE(sun20i_d1_system_ldo_descs),
> +};
> +
> +static struct regmap *sun20i_regulator_get_regmap(struct device *dev)
> +{
> +	struct regmap *regmap;
> +
> +	/*
> +	 * First try the syscon interface. The system control device is not
> +	 * compatible with "syscon", so fall back to getting the regmap from
> +	 * its platform device. This is ugly, but required for devicetree
> +	 * backward compatibility.
> +	 */
> +	regmap = syscon_node_to_regmap(dev->parent->of_node);
> +	if (!IS_ERR(regmap))
> +		return regmap;
> +
> +	regmap = dev_get_regmap(dev->parent, NULL);
> +	if (regmap)
> +		return regmap;
> +
> +	return ERR_PTR(-EPROBE_DEFER);
> +}
> +
> +static int sun20i_regulator_probe(struct platform_device *pdev)
> +{
> +	const struct sun20i_regulator_data *data;
> +	struct device *dev = &pdev->dev;
> +	struct regulator_config config;
> +	struct regmap *regmap;
> +
> +	data = of_device_get_match_data(dev);
> +	if (!data)
> +		return -EINVAL;
> +
> +	regmap = sun20i_regulator_get_regmap(dev);
> +	if (IS_ERR(regmap))
> +		return dev_err_probe(dev, PTR_ERR(regmap), "Failed to get regmap\n");
> +
> +	config = (struct regulator_config) {
> +		.dev	= dev,
> +		.regmap	= regmap,
> +	};
> +
> +	for (unsigned int i = 0; i < data->ndescs; ++i) {
> +		const struct regulator_desc *desc = &data->descs[i];
> +		struct regulator_dev *rdev;
> +
> +		rdev = devm_regulator_register(dev, desc, &config);
> +		if (IS_ERR(rdev))
> +			return PTR_ERR(rdev);
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id sun20i_regulator_of_match[] = {
> +	{
> +		.compatible = "allwinner,sun20i-d1-system-ldos",
> +		.data = &sun20i_d1_system_ldos,
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, sun20i_regulator_of_match);
> +
> +static struct platform_driver sun20i_regulator_driver = {
> +	.probe	= sun20i_regulator_probe,
> +	.driver	= {
> +		.name		= "sun20i-regulator",
> +		.of_match_table	= sun20i_regulator_of_match,
> +	},
> +};
> +module_platform_driver(sun20i_regulator_driver);
> +
> +MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
> +MODULE_DESCRIPTION("Allwinner D1 internal LDO driver");
> +MODULE_LICENSE("GPL");


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 2/4] regulator: sun20i: Add Allwinner D1 LDOs driver
  2022-12-08  8:41 ` [PATCH v5 2/4] regulator: sun20i: Add Allwinner D1 LDOs driver Samuel Holland
  2023-01-12 23:50   ` Andre Przywara
@ 2023-01-13  5:08   ` Jernej Škrabec
  1 sibling, 0 replies; 8+ messages in thread
From: Jernej Škrabec @ 2023-01-13  5:08 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Samuel Holland
  Cc: Chen-Yu Tsai, Krzysztof Kozlowski, Andre Przywara, linux-kernel,
	devicetree, Rob Herring, linux-sunxi, linux-arm-kernel,
	Samuel Holland, Andrew Lunn, Heiko Stuebner, Maxime Ripard

Dne četrtek, 08. december 2022 ob 09:41:25 CET je Samuel Holland napisal(a):
> D1 contains two pairs of LDOs, "analog" LDOs and "system" LDOs. They are
> similar and can share a driver, but only the system LDOs have a DT
> binding defined so far.
> 
> The system LDOs have a single linear range. The voltage step is not an
> integer, so a custom .list_voltage is needed to get the rounding right.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Best regards,
Jernej



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2023-01-13  5:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-08  8:41 [PATCH v5 0/4] regulator: Add support for Allwinner D1 system LDOs Samuel Holland
2022-12-08  8:41 ` [PATCH v5 1/4] regulator: dt-bindings: Add " Samuel Holland
2022-12-08  8:41 ` [PATCH v5 2/4] regulator: sun20i: Add Allwinner D1 LDOs driver Samuel Holland
2023-01-12 23:50   ` Andre Przywara
2023-01-13  5:08   ` Jernej Škrabec
2022-12-08  8:41 ` [PATCH v5 3/4] dt-bindings: sram: sunxi-sram: Add regulators child Samuel Holland
2022-12-08  8:41 ` [PATCH v5 4/4] soc: sunxi: sram: Only iterate over SRAM children Samuel Holland
2023-01-12 17:31   ` Jernej Škrabec

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).