android_kernel_msm-6.1_noth.../drivers/soc
Brian Norris defec178df soc: rockchip: power-domain: Manage resource conflicts with firmware
On RK3399 platforms, power domains are managed mostly by the kernel
(drivers/soc/rockchip/pm_domains.c), but there are a few exceptions
where ARM Trusted Firmware has to be involved:

(1) system suspend/resume
(2) DRAM DVFS (a.k.a., "ddrfreq")

Exception (1) does not cause much conflict, since the kernel has
quiesced itself by the time we make the relevant PSCI call.

Exception (2) can cause conflict, because of two actions:

(a) ARM Trusted Firmware needs to read/modify/write the PMU_BUS_IDLE_REQ
    register to idle the memory controller domain; the kernel driver
    also has to touch this register for other domains.
(b) ARM Trusted Firmware needs to manage the clocks associated with
    these domains.

To elaborate on (b): idling a power domain has always required ungating
an array of clocks; see this old explanation from Rockchip:
https://lore.kernel.org/linux-arm-kernel/54503C19.9060607@rock-chips.com/

Historically, ARM Trusted Firmware has avoided this issue by using a
special PMU_CRU_GATEDIS_CON0 register -- this register ungates all the
necessary clocks -- when idling the memory controller. Unfortunately,
we've found that this register is not 100% sufficient; it does not turn
the relevant PLLs on [0].

So it's possible to trigger issues with something like the following:

1. enable a power domain (e.g., RK3399_PD_VDU) -- kernel will
   temporarily enable relevant clocks/PLLs, then turn them back off
   2. a PLL (e.g., PLL_NPLL) is part of the clock tree for
      RK3399_PD_VDU's clocks but otherwise unused; NPLL is disabled
3. perform a ddrfreq transition (rk3399_dmcfreq_target() -> ...
   drivers/clk/rockchip/clk-ddr.c / ROCKCHIP_SIP_DRAM_FREQ)
   4. ARM Trusted Firmware unagates VDU clocks (via PMU_CRU_GATEDIS_CON0)
   5. ARM Trusted firmware idles the memory controller domain
   6. Step 5 waits on the VDU domain/clocks, but NPLL is still off

i.e., we hang the system.

So for (b), we need to at a minimum manage the relevant PLLs on behalf
of firmware. It's easier to simply manage the whole clock tree, in a
similar way we do in rockchip_pd_power().

For (a), we need to provide mutual exclusion betwen rockchip_pd_power()
and firmware. To resolve that, we simply grab the PMU mutex and release
it when ddrfreq is done.

The Chromium OS kernel has been carrying versions of part of this hack
for a while, based on some new custom notifiers [1]. I've rewritten as a
simple function call between the drivers, which is OK because:

 * the PMU driver isn't enabled, and we don't have this problem at all
   (the firmware should have left us in an OK state, and there are no
   runtime conflicts); or
 * the PMU driver is present, and is a single instance.

And the power-domain driver cannot be removed, so there's no lifetime
management to worry about.

For completeness, there's a 'dmc_pmu_mutex' to guard (likely
theoretical?) probe()-time races. It's OK for the memory controller
driver to start running before the PMU, because the PMU will avoid any
critical actions during the block() sequence.

[0] The RK3399 TRM for PMU_CRU_GATEDIS_CON0 only talks about ungating
    clocks. Based on experimentation, we've found that it does not power
    up the necessary PLLs.

[1] CHROMIUM: soc: rockchip: power-domain: Add notifier to dmc driver
    https://chromium-review.googlesource.com/q/I242dbd706d352f74ff706f5cbf42ebb92f9bcc60
    Notably, the Chromium solution only handled conflict (a), not (b).
    In practice, item (b) wasn't a problem in many cases because we
    never managed to fully power off PLLs. Now that the (upstream) video
    decoder driver performs runtime clock management, we often power off
    NPLL.

Signed-off-by: Brian Norris <briannorris@chromium.org>
Tested-by: Peter Geis <pgwipeout@gmail.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
2022-05-09 03:36:52 +09:00
..
actions
amlogic soc: s4: Add support for power domains controller 2022-03-07 09:40:39 +01:00
apple soc: apple: apple-pmgr-pwrstate: Do not build as a module 2021-12-15 20:36:05 +09:00
aspeed soc: aspeed: lpc-ctrl: Block error printing on probe defer cases 2022-02-08 09:52:59 +01:00
atmel ARM: at91: add support in soc driver for new SAMA5D29 2022-03-04 12:49:22 +01:00
bcm soc: bcm: brcmstb: Add of_node_put() in pm-mips 2021-11-15 09:57:14 -08:00
canaan riscv: canaan: remove useless select of non-existing config SYSCON 2022-01-20 09:35:11 -08:00
dove
fsl Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net 2022-03-03 11:55:12 -08:00
gemini
imx ARM driver updates for 5.18 2022-03-23 18:23:13 -07:00
ixp4xx soc: ixp4xx-npe: Access syscon regs using regmap 2022-02-12 18:20:03 +01:00
lantiq
litex drivers/soc/litex: remove 8-bit subregister option 2021-06-11 04:35:40 +09:00
mediatek ARM driver updates for 5.18 2022-03-23 18:23:13 -07:00
microchip ARM driver updates for 5.18 2022-03-23 18:23:13 -07:00
qcom soc: qcom: rpmpd: Add MSM8226 support 2022-02-24 14:12:34 -06:00
renesas soc: renesas: Kconfig: Introduce ARCH_RZG2L config option 2022-02-24 13:53:25 +01:00
rockchip soc: rockchip: power-domain: Manage resource conflicts with firmware 2022-05-09 03:36:52 +09:00
samsung MAINTAINERS: update Krzysztof Kozlowski's email 2022-03-07 23:46:03 +01:00
sifive RISC-V: sifive_l2_cache: Update L2 cache driver to support SiFive FU740 2021-01-07 17:28:27 -08:00
sunxi soc: sunxi_sram: Make use of the helper function devm_platform_ioremap_resource() 2021-09-13 09:04:05 +02:00
tegra soc/tegra: pmc: Add Tegra234 wake events 2022-02-25 14:08:46 +01:00
ti soc: ti: k3-socinfo: Add AM62x JTAG ID 2022-02-28 05:35:19 -06:00
ux500
versatile
xilinx Char/Misc and other driver changes for 5.17-rc1 2022-01-14 16:02:28 +01:00
Kconfig soc: add microchip polarfire soc system controller 2022-02-25 12:50:59 +01:00
Makefile soc: add microchip polarfire soc system controller 2022-02-25 12:50:59 +01:00