[PATCH v2 4/5] rockchip: Port IO-domain driver for RK3568 from linux

Kever Yang kever.yang at rock-chips.com
Wed Sep 27 04:50:01 CEST 2023


On 2023/8/22 06:30, Jonas Karlman wrote:
> Port the Rockchip IO-domain driver for RK3568 from linux.
>
> The driver auto probe after bind to configure IO-domain based on the
> regulator voltage. Compared to the linux driver this driver is not
> notified about regulator voltage changes and only configure IO-domain
> based on the initial voltage autoset by the regulator.
>
> It is not recommended to enable MMC_IO_VOLTAGE or the mmc signal voltage
> and IO-domain may end up out of sync.
>
> Based on the linux commit 28b05a64e47c ("soc: rockchip: io-domain: add
> rk3568 support").
>
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
> Reviewed-by: Simon Glass <sjg at chromium.org>
> ---
> Cc: Jianqun Xu <jay.xu at rock-chips.com>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: Doug Anderson <dianders at chromium.org>
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>

Thanks,
- Kever
> ---
> v2:
> - Add probe after bind comment
> - Drop parenthesis
> - Collect r-b tag
>
>   drivers/misc/Kconfig              |   9 ++
>   drivers/misc/Makefile             |   1 +
>   drivers/misc/rockchip-io-domain.c | 167 ++++++++++++++++++++++++++++++
>   3 files changed, 177 insertions(+)
>   create mode 100644 drivers/misc/rockchip-io-domain.c
>
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index b9f5c7a37aed..d160ce693939 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -101,6 +101,15 @@ config ROCKCHIP_OTP
>   	  addressing and a length or through child-nodes that are generated
>   	  based on the e-fuse map retrieved from the DTS.
>   
> +config ROCKCHIP_IODOMAIN
> +	bool "Rockchip IO-domain driver support"
> +	depends on DM_REGULATOR && ARCH_ROCKCHIP
> +	default y if ROCKCHIP_RK3568
> +	help
> +	  Enable support for IO-domains in Rockchip SoCs. It is necessary
> +	  for the IO-domain setting of the SoC to match the voltage supplied
> +	  by the regulators.
> +
>   config SIFIVE_OTP
>   	bool "SiFive eMemory OTP driver"
>   	depends on MISC
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index fd8805f34bd9..b67b82358a6c 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_SANDBOX) += qfw_sandbox.o
>   endif
>   obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o
>   obj-$(CONFIG_ROCKCHIP_OTP) += rockchip-otp.o
> +obj-$(CONFIG_$(SPL_TPL_)ROCKCHIP_IODOMAIN) += rockchip-io-domain.o
>   obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o
>   obj-$(CONFIG_SIFIVE_OTP) += sifive-otp.o
>   obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o
> diff --git a/drivers/misc/rockchip-io-domain.c b/drivers/misc/rockchip-io-domain.c
> new file mode 100644
> index 000000000000..3f6227f993f9
> --- /dev/null
> +++ b/drivers/misc/rockchip-io-domain.c
> @@ -0,0 +1,167 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Rockchip IO Voltage Domain driver
> + *
> + * Ported from linux drivers/soc/rockchip/io-domain.c
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/device_compat.h>
> +#include <regmap.h>
> +#include <syscon.h>
> +#include <power/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_soc_data {
> +	int grf_offset;
> +	const char *supply_names[MAX_SUPPLIES];
> +	int (*write)(struct regmap *grf, int idx, int uV);
> +};
> +
> +static int rk3568_iodomain_write(struct regmap *grf, int idx, int uV)
> +{
> +	u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
> +	u32 val0, val1;
> +	int b;
> +
> +	switch (idx) {
> +	case 0: /* pmuio1 */
> +		break;
> +	case 1: /* pmuio2 */
> +		b = idx;
> +		val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
> +		b = idx + 4;
> +		val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
> +
> +		regmap_write(grf, RK3568_PMU_GRF_IO_VSEL2, val0);
> +		regmap_write(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 = idx - 1;
> +		val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
> +		val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
> +
> +		regmap_write(grf, RK3568_PMU_GRF_IO_VSEL0, val0);
> +		regmap_write(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 = {
> +		NULL,
> +		"pmuio2-supply",
> +		"vccio1-supply",
> +		NULL,
> +		"vccio3-supply",
> +		"vccio4-supply",
> +		"vccio5-supply",
> +		"vccio6-supply",
> +		"vccio7-supply",
> +	},
> +	.write = rk3568_iodomain_write,
> +};
> +
> +static const struct udevice_id rockchip_iodomain_ids[] = {
> +	{
> +		.compatible = "rockchip,rk3568-pmu-io-voltage-domain",
> +		.data = (ulong)&soc_data_rk3568_pmu,
> +	},
> +	{ }
> +};
> +
> +static int rockchip_iodomain_bind(struct udevice *dev)
> +{
> +	/*
> +	 * According to the Hardware Design Guide, IO-domain configuration must
> +	 * be consistent with the power supply voltage (1.8V or 3.3V).
> +	 * Probe after bind to configure IO-domain voltage early during boot.
> +	 */
> +	dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
> +
> +	return 0;
> +}
> +
> +static int rockchip_iodomain_probe(struct udevice *dev)
> +{
> +	struct rockchip_iodomain_soc_data *soc_data =
> +		(struct rockchip_iodomain_soc_data *)dev_get_driver_data(dev);
> +	struct regmap *grf;
> +	int ret;
> +
> +	grf = syscon_get_regmap(dev_get_parent(dev));
> +	if (IS_ERR(grf))
> +		return PTR_ERR(grf);
> +
> +	for (int i = 0; i < MAX_SUPPLIES; i++) {
> +		const char *supply_name = soc_data->supply_names[i];
> +		struct udevice *reg;
> +		int uV;
> +
> +		if (!supply_name)
> +			continue;
> +
> +		ret = device_get_supply_regulator(dev, supply_name, &reg);
> +		if (ret)
> +			continue;
> +
> +		ret = regulator_autoset(reg);
> +		if (ret && ret != -EALREADY && ret != -EMEDIUMTYPE &&
> +		    ret != -ENOSYS)
> +			continue;
> +
> +		uV = regulator_get_value(reg);
> +		if (uV <= 0)
> +			continue;
> +
> +		if (uV > MAX_VOLTAGE_3_3) {
> +			dev_crit(dev, "%s: %d uV is too high. May damage SoC!\n",
> +				 supply_name, uV);
> +			continue;
> +		}
> +
> +		soc_data->write(grf, i, uV);
> +	}
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(rockchip_iodomain) = {
> +	.name = "rockchip_iodomain",
> +	.id = UCLASS_NOP,
> +	.of_match = rockchip_iodomain_ids,
> +	.bind = rockchip_iodomain_bind,
> +	.probe = rockchip_iodomain_probe,
> +};


More information about the U-Boot mailing list