public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Andre Przywara <andre.przywara@arm.com>
To: Andrey Skvortsov <andrej.skvortzov@gmail.com>
Cc: Jagan Teki <jagan@amarulasolutions.com>,
	Hans de Goede <hdegoede@redhat.com>,
	u-boot@lists.denx.de, Samuel Holland <samuel@sholland.org>,
	Jarrah Gosbell <kernel@undef.tools>
Subject: Re: [PATCH] sunxi: board: provide CPU idle states to loaded OS
Date: Tue, 5 Sep 2023 09:27:12 +0100	[thread overview]
Message-ID: <20230905092712.6ba245bb@donnerap.manchester.arm.com> (raw)
In-Reply-To: <20230904205430.1647654-1-andrej.skvortzov@gmail.com>

On Mon,  4 Sep 2023 23:54:30 +0300
Andrey Skvortsov <andrej.skvortzov@gmail.com> wrote:

Hi Andrey,

> When using SCPI as the PSCI backend, firmware can wake up the CPUs and
> cluster from sleep, so CPU idle states are available for loaded OS to
> use. TF-A modifies DTB to advertise available CPU idle states, when
> SCPI is detected. This change copies nodes added by TF-A to any new
> dtb that is used for loaded OS.

Why do you need that, exactly? Why not just use $fdtcontroladdr for the
kernel? We now keep the U-Boot copy of the .dts files in sync with the
kernel. If you need to modify the DT in U-Boot, for instance by applying
overlays, you can copy that DTB into a better suitable location first:
=> fdt move $fdtcontroladdr $fdt_addr_r

In any case, there shall be only one DT, that one in the U-Boot image. Why
do you need to load another one for the kernel?

Cheers,
Andre

> Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>

> ---
>  board/sunxi/board.c | 120 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 120 insertions(+)
> 
> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> index f321cd58a6..e88bd11a99 100644
> --- a/board/sunxi/board.c
> +++ b/board/sunxi/board.c
> @@ -870,6 +870,125 @@ int board_late_init(void)
>  	return 0;
>  }
>  
> +static int cpuidle_dt_fixup_copy_node(ofnode src, int dst_offset, void *dst_blob,
> +				      u32 *count, u32 *phandle)
> +{
> +	int offs, len, ret;
> +	struct ofprop prop;
> +	ofnode subnode;
> +
> +	ofnode_for_each_prop(prop, src) {
> +		const char *name;
> +		const char *val;
> +
> +		val = ofprop_get_property(&prop, &name, &len);
> +		if (!val)
> +			return -EINVAL;
> +		if (!strcmp(name, "phandle")) {
> +			if (ofnode_device_is_compatible(src, "arm,idle-state")) {
> +				fdt_setprop_u32(dst_blob, dst_offset, name, *phandle);
> +				(*phandle)++;
> +				(*count)++;
> +			} else {
> +				log_err("Unexpected phandle node: %s\n", name);
> +				return -EINVAL;
> +			}
> +		} else {
> +			ret = fdt_setprop(dst_blob, dst_offset, name, val, len);
> +			if (ret < 0)
> +				return ret;
> +		}
> +	}
> +
> +	ofnode_for_each_subnode(subnode, src) {
> +		const char *name = ofnode_get_name(subnode);
> +
> +		if (!name)
> +			return -EINVAL;
> +		offs = fdt_add_subnode(dst_blob, dst_offset, name);
> +		if (offs < 0)
> +			return offs;
> +		ret = cpuidle_dt_fixup_copy_node(subnode, offs, dst_blob, count, phandle);
> +		if (ret < 0)
> +			return ret;
> +	}
> +	return 0;
> +}
> +
> +static int cpuidle_dt_fixup(void *blob)
> +{
> +	ofnode idle_states_node;
> +	ofnode subnode;
> +	u32 count, phandle;
> +	const struct property *prop;
> +	int offs, len, ret;
> +
> +	idle_states_node = ofnode_path("/cpus/idle-states");
> +	if (!ofnode_valid(idle_states_node)) {
> +		log_err("No idle-states node in old fdt, nothing to do");
> +		return 0;
> +	}
> +
> +	/*
> +	 * Do not proceed if the target dt already has an idle-states node.
> +	 * In this case assume that the system knows better somehow,
> +	 * so do not interfere.
> +	 */
> +	if (fdt_path_offset(blob, "/cpus/idle-states") >= 0) {
> +		log_err("idle-states node already exists in target");
> +		return 0;
> +	}
> +
> +	offs = fdt_path_offset(blob, "/cpus");
> +	if (offs < 0)
> +		return offs;
> +
> +	offs = fdt_add_subnode(blob, offs, "idle-states");
> +	if (offs < 0)
> +		return offs;
> +
> +	/* copy "/cpus/idle-states" node to destination fdt */
> +	ret = fdt_find_max_phandle(blob, &phandle);
> +	if (ret < 0)
> +		return ret;
> +	phandle++;
> +	count = 0;
> +	ret =  cpuidle_dt_fixup_copy_node(idle_states_node, offs, blob, &count, &phandle);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* copy "cpu-idle-state" property for all cpus */
> +	ofnode_for_each_subnode(subnode, ofnode_path("/cpus")) {
> +		char path[32];
> +		fdt32_t *value;
> +
> +		prop = ofnode_get_property(subnode, "cpu-idle-states", &len);
> +		if (!prop)
> +			continue;
> +
> +		/* find the same node in a new device-tree */
> +		ret = ofnode_get_path(subnode, path, sizeof(path));
> +		if (ret)
> +			return ret;
> +
> +		offs = fdt_path_offset(blob, path);
> +		if (offs < 0)
> +			return offs;
> +
> +		/* Allocate space for the list of phandles. */
> +		ret = fdt_setprop_placeholder(blob, offs, "cpu-idle-states",
> +					      count * sizeof(phandle),
> +					      (void **)&value);
> +		if (ret < 0)
> +			return ret;
> +
> +		/* Fill in the phandles of the idle state nodes. */
> +		for (u32 i = 0U; i < count; ++i)
> +			value[i] = cpu_to_fdt32(phandle - count + i);
> +	}
> +	return 0;
> +}
> +
>  static void bluetooth_dt_fixup(void *blob)
>  {
>  	/* Some devices ship with a Bluetooth controller default address.
> @@ -914,6 +1033,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
>  	setup_environment(blob);
>  	fdt_fixup_ethernet(blob);
>  
> +	cpuidle_dt_fixup(blob);
>  	bluetooth_dt_fixup(blob);
>  
>  #ifdef CONFIG_VIDEO_DT_SIMPLEFB


  reply	other threads:[~2023-09-05  8:27 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-04 20:54 [PATCH] sunxi: board: provide CPU idle states to loaded OS Andrey Skvortsov
2023-09-05  8:27 ` Andre Przywara [this message]
2023-09-05  8:37   ` Andrey Skvortsov
2023-09-06  0:12     ` Andre Przywara
2023-09-06 20:53       ` Andrey Skvortsov
2023-09-11 22:15         ` Andre Przywara
2023-09-14 20:22           ` Andrey Skvortsov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230905092712.6ba245bb@donnerap.manchester.arm.com \
    --to=andre.przywara@arm.com \
    --cc=andrej.skvortzov@gmail.com \
    --cc=hdegoede@redhat.com \
    --cc=jagan@amarulasolutions.com \
    --cc=kernel@undef.tools \
    --cc=samuel@sholland.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox