RE: [PATCH V6 03/12] clk: imx: scu: add two cells binding support
From: Aisheng Dong <aisheng.dong@nxp.com>
Date: 2020-06-19 16:34:22
Also in:
linux-clk
From: Stephen Boyd <sboyd@kernel.org> Sent: Friday, June 19, 2020 12:05 AM Quoting Aisheng Dong (2020-06-01 07:28:57)quoted
quoted
From: Stephen Boyd <sboyd@kernel.org> Sent: Wednesday, May 27, 2020 4:34 PM Quoting Aisheng Dong (2020-05-05 06:47:02)quoted
Hi Stephen, Thanks for the review.quoted
From: Stephen Boyd <sboyd@kernel.org> Sent: Tuesday, May 5, 2020 1:08 PM Quoting Dong Aisheng (2020-03-15 06:43:47)quoted
This patch implements the new two cells binding for SCU clocks. The usage is as follows: clocks = <&uart0_clk IMX_SC_R_UART_0 IMX_SC_PM_CLK_PER> Due to each SCU clock is associated with a power domain, without power on the domain, the SCU clock can't work. So we create platform devices for each domain clock respectively and manually attach the required domain before register the clock devices, then we can register clocks in the clock platform driveraccordingly.quoted
quoted
quoted
quoted
That's odd. See below.quoted
Note because we do not have power domain info in device tree and the SCU resource ID is the same for power domain and clock, so we use resource ID to find power domains. Later, we will also use this clock platform driver to support suspend/resume and runtime pm. Cc: Stephen Boyd <sboyd@kernel.org> Cc: Shawn Guo <shawnguo@kernel.org> Cc: Sascha Hauer <kernel@pengutronix.de> Cc: Michael Turquette <mturquette@baylibre.com> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> ---[...]quoted
diff --git a/drivers/clk/imx/clk-scu.cb/drivers/clk/imx/clk-scu.c index b8b2072742a5..4fadff14d8b2 100644--- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.cquoted
quoted
+ return -EINVAL; + + if (clk_cells == 2) { + for (i = 0; i < IMX_SC_R_LAST; i++) + INIT_LIST_HEAD(&imx_scu_clks[i]); + + pd_np = of_find_compatible_node(NULL, NULL,"fsl,scu-pd");quoted
+ pd_dev = of_find_device_by_node(pd_np); + if (!pd_dev || !device_is_bound(&pd_dev->dev)) + {What is device_is_bound() check for? Add a comment?Yes, I can add a comment in the code. It is because SCU clock driver depends on SCU power domain to be readyfirst.quoted
quoted
Does EPROBE_DEFER not kick in automatically in that case?No, there're no power domains under scu clock node in dts. So can't use PROBE_DEFER automatically.Why isn't the scu clock node using power domains?
We have tried this in several ways before but finally didn't go that way
due to various reasons.
e.g.
Method 1:
conn-scu-clock-controller {
compatible = "fsl,imx8qxp-clk", "fsl,scu-clk";
#address-cells = <1>;
#size-cells = <0>;
uart0_clk: clock-scu@57 {
reg = <57>;
#clock-cells = <1>;
clock-indices = <IMX_SC_PM_CLK_PER>;
clock-output-names = "uart0_clk";
power-domains = <&pd IMX_SC_R_UART_0>;
};
...
}
Method 2:
#define IMX_SCU_CLK_ID(rsrc, type) (type << 16 | rsrc)
scu_clk: scu-clock-controller {
compatible = "fsl,imx8qxp-scu-clk", "fsl,scu-clk";
#clock-cells = <1>;
clock-indices = <IMX_SCU_CLK_ID(IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER)>,
<IMX_SCU_CLK_ID(IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS)>,
<IMX_SCU_CLK_ID(IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0)>,
<IMX_SCU_CLK_ID(IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER)>,
...
clock-output-names = "enet0_clk",
"enet0_bypass_clk",
"enet0_rgmii_clk",
"uart0_clk",
...
power-domains = <&pd IMX_SC_R_ENET_0>,
<&pd IMX_SC_R_ENET_0>,
<&pd IMX_SC_R_ENET_0>,
<&pd IMX_SC_R_UART_0>,
...
};
See details here:
https://spinics.net/lists/devicetree/msg298642.html
quoted
quoted
quoted
quoted
quoted
+ + pdev->driver_override = "imx-scu-clk"; + + ret = imx_clk_scu_attach_pd(&pdev->dev, rsrc_id);Why do we have to allocate a device for each power domain?This is mainly for each clock runtime pm and suspend/resume support as they're independent with each other.quoted
Is this because we don't have support for one device being in multiple power domains? That is supported now as far as I recall, by basically making dummy platform devices like this.I know kernel supports multi power domains, but I didn't realize it could be used for our case.quoted
So maybe this code isn't necessary and we can have one platform device for the clk controller and then have it control certain power domains manually from runtime PM callbacks? It's possible the runtime PM callbacks are too simple for this case and we need to tell clk providers what clk is having runtime PM enabled for it.To make sure I understand correctly, do you mean we use only one general clk controllerTypically I see HW designers make one hardware block for a certain group of clks, like general purpose IO hardware, multimedia hardware, DSPhardware, etc.quoted
quoted
That isn't always true though. Sometimes I see the hardware designers decide to stamp down the same hard macro for a clk in every IP block they develop in the SoC. It gets interesting when they have to integrate with a third party core like dwc3. Usually they look to see if they can add some vendor specific register to the IP blockor make a wrapper around the IP block with the SoC glue bits.quoted
quoted
This usually happens when the clk hard macro library is used by all the hardware designers. Instead of consolidating that library into a hardware IP block that gets delivered for the particular SoC they just spread the hardware block around the system and hope that softwarewill figure it out.quoted
quoted
I suspect hardware blocks are given certain addresses on the MMIO bus because ARM's AMBA/AHB spec mandated that a "device" starts at a 1Kaligned address.quoted
quoted
This probably forced SoC hardware engineers to split their hardware blocks up into different pieces that they could then plug into the bus and easily route CPU addresses to different slaves on the bus. What's the situation here? I thought that this was a firmware interface that logically combines all the hardware block clk controllers. The firmware interface doesn't do everything though because it seems we still have to power on power domains to use variousclks?quoted
Yes, it is. For MX8QM/QXP, the whole SoC is comprised of a few HW Subsystems. Those HW Subsystems are independent with each other as they have separate power/clock Controllers. Within each subsystem, there's a DSC (distributed slave controller) acting as a standard interface to System Controller (SCU) to providepower/clock/reset and some other misc control functions. If it's a few then there are maybe 5 SCUs in the SoC?
There's only one SCU in the SoC running on a dedicated M4 core. SCU communicated with each Subsystem via standard DSC interface to provide centralized clock/power/reset/pinctrl/resource management/misc services.
quoted
quoted
quoted
Runtime pm callback to handle all clocks runtime pm status manually? If doing that, how do we handle different clocks pm requirements with only one device runtime pm status (clock controller)? e.g. One Clock Provider Consumer A -> Clock A -> Clock Provider resumed -> Clock A resumed Consumer B -> Clock B (Since Clock Provided is already resumed, no chance torun callback to resume Clock B now).quoted
(Note: assume all clocks need runtime pm enabled for i.MX case) Or you mean we simply resume all clocks? but that seems lose the granularity and possibly have no chance to enter runtime suspend anymoreonce there was one clock in use.quoted
Not sure if I missed something. Please help clarify a bit more. Right now, I'm a bit afraid this may make things a bit complicated as we have ~150 clocks and ~150 power domains. Putting them all under oneclock controller node in DT may scare people.quoted
And even we did not create platform devices for each clock in the clock driver, using multi-pd will still result in creating dummy platform devices for each clock automatically by power domainframework.quoted
quoted
That means we didn't save any platform devices. What software entity is providing the power domains? I wonder if things are going about all wrong and the power domains are provided by the same piece of code that's managing the clks?There's a separate power domain driver based on SCU protocol for only powercontrol.quoted
This power control is a lit complicated as it supports multi low power states. When power is completely gated, the HW state will be lost and need restoreby SW.quoted
Some of those features are still not upstreamed.quoted
If so, why can't we control the power domains directly from the clk code without having to go through runtime PM layer or genpd?It's probably hard to do that because: 1. power domain supports multiple low power states for different purpose. Now genpd seems a better place to handle it 2. Not all power domains associated with a clock.quoted
Or to flip it the other way, why do we need clk control for enable/disable in that case? Can we just expose rate control for the clks and then let genpd handle turning clks on an off if they're associated with that power domain?I wonder this way might also lose the granularity control capability. For a simple device with only one clock, we might be able to do it at mosttimes.quoted
But for some complicated devices with multiple clocks and which clocks to use depends on the real user cases, simply enable all clocks when PD is UPseems not very suitable.quoted
For MX8, it's a complicated systems and some device resources may have multi clocks, especially for Audio, Video IO, Display related cases.Do they have multiple clks and multiple power domains for one device, like Audio or Video? Is it 1:1 between some number of clks and some power domain?
For simple devices with only one clock, it might be 1:1. But for complicated devices with multiple clocks, it's usually not 1:1. e.g. AUDIO_PLL_0 PLL User programmable PLL AUDIO_PLL_0 MISC0 Audio PLL div 0 AUDIO_PLL_0 MISC1 Audio rec 0 DC_0 MISC0 Display 0 DC_0 MISC1 Display 1 MIPI_0 BYPASS Bypass MIPI_0 SLV_BUS DSI rx escape MIPI_0 MST_BUS DSI tx escape MIPI_0 PHY DPHY PLL ref MIPI_0 PER DPI - pixel
quoted
quoted
quoted
quoted
Maybe we can adjust the core clk framework to introduce a callback for the clk that is runtime PM enabling and put the logic there about what todo?quoted
That may help. Since we still only have one device for runtime pm state management, Still not understand how to do it as it may mix the usagewith the runtime pm framework.quoted
Right. I'm thinking that we may need a clk_op that is called when a clk is runtime PM enabled so the device driver that provides that clk can decide what genpds to manually enable. This would only be used in the case where the clks are provided by a clk controller that exists in multiple power domains. I'm not super clear on multi-pd and how it interacts with runtime PM but I assume that it doesn't actually turn on any genpd when the consumer device is runtimePM active. Instead the consumer driver has to figure out what to power on by itself.quoted
quoted
The callback would do this similarly from the CCF so that the manual steps could be done again.After more thinking, I guess we probably don't need a clk_op if we register the correct struct device (abstract clk provider) to clk register API. E.g.clk_hw_register(dev, hw).quoted
That abstract struct dev could be the virtual power domain device created and returned by PD framework when calling multi PD APIs. This can make us be able to fully reuse all the current rumtime PM support in CCF. Nothing else special need to care. (synchronization work with rpm/genpd framework)Whatever 'dev' is used to register the clk is presumed to be the device that is the clk provider. If 'dev' isn't the one that's matched to the device node in DT the CCF will become confused about what parent clks are supposed to be. That's one problem but it may not be a problem here because this is just one big DT node?quoted
See: multi pd API will create a virtual PD device to be associated with that PDfor later RPM usages.quoted
struct device *dev_pm_domain_attach_by_name(struct device *dev, const char *name) { if (dev->pm_domain) return ERR_PTR(-EEXIST); return genpd_dev_pm_attach_by_name(dev, name); } EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name); However, I'm still a bit feeling this probably could work for a clock controllersimply with <10 PDs.quoted
But not very suitable for MX8QM/QXP as it has 150+ PDs. Defining them all will make DT looks terrible and drivers slightly a bit complicated to fetch those PDs efficiently from DT for each clock, also make the futuremaintain work a bit harder when adding new clocks.quoted
Not sure whether it's worth to do that as compared with current approach, it really does not Improve too much as multi pd also need createvirtual devices if the virtual devices are the only concern.quoted
In contrast, it might increase, probably unnecessary complexities.Either way there are going to be 150+ devices for the 150+ power domains in the system. Why are there so many power domains? That seems like the problem. I doubt there are 150 devices in the SoC, or even 75 of them.
It's abstract power domain concept introduced by SCU firmware that each device Is associated with a power domain. In real HW, many devices within the same Subsystem might share one of the same HW power domain. But SCU firmware hides those internal details completely to users. So users are unaware of it. Additionally, power domain are also associated with device resource management by xRDC (Resource Domain Controller) component for security reasons. Without enable the resource power by SCU firmware, one SW execution environment (e.g. OS/ATF/OPTEE/VM) can't access those resource like registers, clocks and etc.
quoted
How would you suggest? Do you think if we should continue to investigate this Or if we can make the function work first as this improvement work does not affect users? Currently as this patch is a very fundamental change which blocks a lot otherdrivers upstream work.quoted
If you want to go ahead with this patch I guess I will stop caring.
Thanks a lot
Just be aware that needing to make virtual devices to fit this into the kernel looks wrong. I'd like to see one device node for the firmware interface of clks, and one struct device for said firmware interface that attaches to one struct driver for that firmware interface.
So far, I'm still no sure if we can finally archive that due to complexities of various requirements in MX8. Personally i feel a bit risky and trying it definitely need lot more time to ensure it can meet all of our feature requirements on MX8. But I did understand your concern. Anyway, I will continue to investigate. However, if you do not mind too much, I'd treat it as a continued improvement work in order to not block the whole MX8 upstream work too long. (dt binding part of users won't change) The current approach has been verified working well in NXP official released 5.4 kernel and can meet various product requirements. Probably could be a good start point for the reset drivers upstreaming work first.
Connecting that to genpd for proper power domain management is another issue. If the core clk framework needs to be multi-device power domain aware so that various clks can turn on along with the power domain that's needed to operate them then we'll need to add that in the core framework.
Yes. I guess the problem for MX8 is how to co-work with the exist power domain driver. For MX8, there're also more issues because MX8 power domain supports multiple lower power States. And we need a genpd governer to help choose a state. That's the future work we may do In the next step. If we power up clock power in CCF, we need think how to do It well by co-exist with genpd framework.
I'm amazed that the firmware interface doesn't handle the requirement that genpds need to be powered on to control the clks. I'd think the firmware would be happy to turn on power domains so that it can go poke clk registers.
I guess one reason may be SCU support multiple low power states. It wants user to choose which one to enter. /* * Defines for SC PM Power Mode */ #define IMX_SC_PM_PW_MODE_OFF 0 /* Power off */ #define IMX_SC_PM_PW_MODE_STBY 1 /* Power in standby */ #define IMX_SC_PM_PW_MODE_LP 2 /* Power in low-power */ #define IMX_SC_PM_PW_MODE_ON 3 /* Power on */ Regards Aisheng _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel