* [PATCH 1/2] soc: rockchip: add driver for rockchip io domains
2022-09-05 14:52 [PATCH 0/2] soc: rockchip: add driver for rockchip io domains Michael Riesch
@ 2022-09-05 14:52 ` Michael Riesch
2022-09-05 14:52 ` [PATCH 2/2] arm: rockchip: radxa-rock3: remove io domain configuration Michael Riesch
2022-09-19 9:01 ` [PATCH 0/2] soc: rockchip: add driver for rockchip io domains Sascha Hauer
2 siblings, 0 replies; 5+ messages in thread
From: Michael Riesch @ 2022-09-05 14:52 UTC (permalink / raw)
To: barebox; +Cc: Frank Wunderlich, Michael Riesch
The IO domains on Rockchip SoCs need to be configured to the correct
bank voltage. In Linux this is achieved by means of a platform driver
that reads the voltage value of the supplies and configures the bits
in the general register file (GRF) accordingly. Port this driver to
barebox to provide support for the Rockchip RK356x SoCs.
Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
---
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/rockchip/Kconfig | 17 +++
drivers/soc/rockchip/Makefile | 6 +
drivers/soc/rockchip/io-domain.c | 223 +++++++++++++++++++++++++++++++
5 files changed, 248 insertions(+)
create mode 100644 drivers/soc/rockchip/Kconfig
create mode 100644 drivers/soc/rockchip/Makefile
create mode 100644 drivers/soc/rockchip/io-domain.c
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 54b69cc42e..c0fe214429 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,5 +2,6 @@ menu "SoC drivers"
source "drivers/soc/imx/Kconfig"
source "drivers/soc/kvx/Kconfig"
+source "drivers/soc/rockchip/Kconfig"
endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index a23e81ffb3..9bff737b78 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,5 +2,6 @@
obj-$(CONFIG_ARCH_IMX) += imx/
obj-$(CONFIG_KVX) += kvx/
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_CPU_SIFIVE) += sifive/
obj-$(CONFIG_SOC_STARFIVE) += starfive/
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
new file mode 100644
index 0000000000..3484b37e22
--- /dev/null
+++ b/drivers/soc/rockchip/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if ARCH_ROCKCHIP || COMPILE_TEST
+
+menu "Rockchip SoC drivers"
+
+config ROCKCHIP_IODOMAIN
+ tristate "Rockchip IO domain support"
+ depends on OFDEVICE
+ help
+ Say y here to enable support io domains on Rockchip SoCs. It is
+ necessary for the io domain setting of the SoC to match the
+ voltage supplied by the regulators.
+
+endmenu
+
+endif
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
new file mode 100644
index 0000000000..104fad968e
--- /dev/null
+++ b/drivers/soc/rockchip/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Rockchip Soc drivers
+#
+
+obj-$(CONFIG_ROCKCHIP_IODOMAIN) += io-domain.o
diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c
new file mode 100644
index 0000000000..ac5724c0e7
--- /dev/null
+++ b/drivers/soc/rockchip/io-domain.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Rockchip IO Voltage Domain driver
+ *
+ * Copyright 2014 MundoReader S.L.
+ * Copyright 2014 Google, Inc.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <linux/err.h>
+#include <mfd/syscon.h>
+#include <regmap.h>
+#include <regulator.h>
+
+#define MAX_SUPPLIES 16
+
+/*
+ * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
+ * "Recommended Operating Conditions" for "Digital GPIO". When the typical
+ * is 3.3V the max is 3.6V. When the typical is 1.8V the max is 1.98V.
+ *
+ * They are used like this:
+ * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
+ * SoC we're at 3.3.
+ * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
+ * that to be an error.
+ */
+#define MAX_VOLTAGE_1_8 1980000
+#define MAX_VOLTAGE_3_3 3600000
+
+#define RK3568_PMU_GRF_IO_VSEL0 (0x0140)
+#define RK3568_PMU_GRF_IO_VSEL1 (0x0144)
+#define RK3568_PMU_GRF_IO_VSEL2 (0x0148)
+
+struct rockchip_iodomain;
+
+struct rockchip_iodomain_supply {
+ struct rockchip_iodomain *iod;
+ struct regulator *reg;
+ int idx;
+};
+
+struct rockchip_iodomain_soc_data {
+ int grf_offset;
+ const char *supply_names[MAX_SUPPLIES];
+ void (*init)(struct rockchip_iodomain *iod);
+ int (*write)(struct rockchip_iodomain_supply *supply, int uV);
+};
+
+struct rockchip_iodomain {
+ struct device_d *dev;
+ struct regmap *grf;
+ const struct rockchip_iodomain_soc_data *soc_data;
+ struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
+ int (*write)(struct rockchip_iodomain_supply *supply, int uV);
+};
+
+static int rk3568_iodomain_write(struct rockchip_iodomain_supply *supply,
+ int uV)
+{
+ struct rockchip_iodomain *iod = supply->iod;
+ u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
+ u32 val0, val1;
+ int b;
+
+ dev_dbg(iod->dev, "set domain %d to %d uV\n", supply->idx, uV);
+
+ switch (supply->idx) {
+ case 0: /* pmuio1 */
+ break;
+ case 1: /* pmuio2 */
+ b = supply->idx;
+ val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
+ b = supply->idx + 4;
+ val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
+
+ regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val0);
+ regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val1);
+ break;
+ case 3: /* vccio2 */
+ break;
+ case 2: /* vccio1 */
+ case 4: /* vccio3 */
+ case 5: /* vccio4 */
+ case 6: /* vccio5 */
+ case 7: /* vccio6 */
+ case 8: /* vccio7 */
+ b = supply->idx - 1;
+ val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
+ val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
+
+ regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL0, val0);
+ regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL1, val1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
+ .grf_offset = 0x140,
+ .supply_names = {
+ "pmuio1",
+ "pmuio2",
+ "vccio1",
+ "vccio2",
+ "vccio3",
+ "vccio4",
+ "vccio5",
+ "vccio6",
+ "vccio7",
+ },
+ .write = rk3568_iodomain_write,
+};
+
+static const struct of_device_id rockchip_iodomain_match[] = {
+ { .compatible = "rockchip,rk3568-pmu-io-voltage-domain",
+ .data = &soc_data_rk3568_pmu },
+ { /* sentinel */ },
+};
+
+static int rockchip_iodomain_probe(struct device_d *dev)
+{
+ struct device_node *np = dev->device_node, *parent;
+ struct rockchip_iodomain *iod;
+ int i, ret = 0;
+
+ if (!np)
+ return -ENODEV;
+
+ iod = xzalloc(sizeof(*iod));
+ iod->dev = dev;
+ iod->soc_data = device_get_match_data(dev);
+
+ if (iod->soc_data->write)
+ iod->write = iod->soc_data->write;
+
+ parent = of_get_parent(np);
+ if (parent) {
+ iod->grf = syscon_node_to_regmap(parent);
+ } else {
+ dev_dbg(dev, "falling back to old binding\n");
+ iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+ }
+
+ if (IS_ERR(iod->grf)) {
+ dev_err(dev, "couldn't find grf regmap\n");
+ return PTR_ERR(iod->grf);
+ }
+
+ for (i = 0; i < MAX_SUPPLIES; i++) {
+ const char *supply_name = iod->soc_data->supply_names[i];
+ struct rockchip_iodomain_supply *supply = &iod->supplies[i];
+ struct regulator *reg;
+ int uV;
+
+ if (!supply_name)
+ continue;
+
+ reg = regulator_get(dev, supply_name);
+ if (IS_ERR(reg)) {
+ ret = PTR_ERR(reg);
+
+ /* If a supply wasn't specified, that's OK */
+ if (ret == -ENODEV)
+ continue;
+ else if (ret != -EPROBE_DEFER)
+ dev_err(dev, "couldn't get regulator %s\n",
+ supply_name);
+ goto out;
+ }
+
+ /* set initial correct value */
+ uV = regulator_get_voltage(reg);
+
+ /* must be a regulator we can get the voltage of */
+ if (uV < 0) {
+ dev_err(dev, "Can't determine voltage: %s\n",
+ supply_name);
+ ret = uV;
+ goto out;
+ }
+
+ if (uV > MAX_VOLTAGE_3_3) {
+ dev_crit(dev, "%d uV is too high. May damage SoC!\n",
+ uV);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* setup our supply */
+ supply->idx = i;
+ supply->iod = iod;
+ supply->reg = reg;
+
+ ret = iod->write(supply, uV);
+ if (ret) {
+ supply->reg = NULL;
+ goto out;
+ }
+ }
+
+ if (iod->soc_data->init)
+ iod->soc_data->init(iod);
+
+ ret = 0;
+out:
+ return ret;
+}
+
+static struct driver_d rockchip_iodomain_driver = {
+ .name = "rockchip-iodomain",
+ .probe = rockchip_iodomain_probe,
+ .of_compatible = rockchip_iodomain_match,
+};
+coredevice_platform_driver(rockchip_iodomain_driver);
--
2.30.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] soc: rockchip: add driver for rockchip io domains
2022-09-05 14:52 [PATCH 0/2] soc: rockchip: add driver for rockchip io domains Michael Riesch
2022-09-05 14:52 ` [PATCH 1/2] " Michael Riesch
2022-09-05 14:52 ` [PATCH 2/2] arm: rockchip: radxa-rock3: remove io domain configuration Michael Riesch
@ 2022-09-19 9:01 ` Sascha Hauer
2022-09-19 9:50 ` Michael Riesch
2 siblings, 1 reply; 5+ messages in thread
From: Sascha Hauer @ 2022-09-19 9:01 UTC (permalink / raw)
To: Michael Riesch; +Cc: barebox, Frank Wunderlich
On Mon, Sep 05, 2022 at 04:52:12PM +0200, Michael Riesch wrote:
> Hi all,
>
> The IO domains on Rockchip SoCs need to be configured to the correct
> bank voltage. In Linux this is achieved by means of a platform driver
> that reads the voltage value of the supplies and configures the bits
> in the general register file (GRF) accordingly.
>
> This series ports this driver to barebox to provide support for the
> Rockchip RK356x SoCs. Please note that I could only test the changes
> on RK3568 boards, so I left out the parts for the other SoCs supported
> by the Linux driver. Also, it should be noted that the Linux driver
> uses notifiers to react to voltage changes. This is not supported by
> this barebox driver.
>
> WARNING: Use those patches with care as they have the potential to
> fry up your board. That said, testers are very welcome ;-)
You are frightening me.
I would apply this series, but given you warn about its usage I'm not
sure what I should do with it. I could give it a test on the RK3568-EVB
once it returned back in our remote lab, but I neither have a Pine64 nor
a BananaPi R2 Pro.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 5+ messages in thread