* Re: [PATCH v2] pinctrl/meson: fix typo in PDM's pin name
From: Neil Armstrong @ 2024-03-25 13:59 UTC (permalink / raw)
To: Jan Dakinevich, Linus Walleij, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, linux-gpio, linux-arm-kernel, linux-amlogic,
linux-kernel
In-Reply-To: <20240325113058.248022-1-jan.dakinevich@salutedevices.com>
On 25/03/2024 12:30, Jan Dakinevich wrote:
> Other pins have _a or _x suffix, but this one doesn't have any. Most
> likely this is a typo.
>
> Fixes: dabad1ff8561 ("pinctrl: meson: add pinctrl driver support for Meson-A1 SoC")
> Signed-off-by: Jan Dakinevich <jan.dakinevich@salutedevices.com>
> ---
> Links:
>
> [1] https://lore.kernel.org/lkml/20240314232201.2102178-1-jan.dakinevich@salutedevices.com/
>
> Changes:
> v1 -> v2: Detached from v1's series (patch 15)
>
> drivers/pinctrl/meson/pinctrl-meson-a1.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pinctrl/meson/pinctrl-meson-a1.c b/drivers/pinctrl/meson/pinctrl-meson-a1.c
> index 79f5d753d7e1..50a87d9618a8 100644
> --- a/drivers/pinctrl/meson/pinctrl-meson-a1.c
> +++ b/drivers/pinctrl/meson/pinctrl-meson-a1.c
> @@ -250,7 +250,7 @@ static const unsigned int pdm_dclk_x_pins[] = { GPIOX_10 };
> static const unsigned int pdm_din2_a_pins[] = { GPIOA_6 };
> static const unsigned int pdm_din1_a_pins[] = { GPIOA_7 };
> static const unsigned int pdm_din0_a_pins[] = { GPIOA_8 };
> -static const unsigned int pdm_dclk_pins[] = { GPIOA_9 };
> +static const unsigned int pdm_dclk_a_pins[] = { GPIOA_9 };
>
> /* gen_clk */
> static const unsigned int gen_clk_x_pins[] = { GPIOX_7 };
> @@ -591,7 +591,7 @@ static struct meson_pmx_group meson_a1_periphs_groups[] = {
> GROUP(pdm_din2_a, 3),
> GROUP(pdm_din1_a, 3),
> GROUP(pdm_din0_a, 3),
> - GROUP(pdm_dclk, 3),
> + GROUP(pdm_dclk_a, 3),
> GROUP(pwm_c_a, 3),
> GROUP(pwm_b_a, 3),
>
> @@ -755,7 +755,7 @@ static const char * const spi_a_groups[] = {
>
> static const char * const pdm_groups[] = {
> "pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
> - "pdm_din1_a", "pdm_din0_a", "pdm_dclk",
> + "pdm_din1_a", "pdm_din0_a", "pdm_dclk_a",
> };
>
> static const char * const gen_clk_groups[] = {
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v6 04/16] dt-bindings: net: wireless: qcom,ath11k: describe the ath11k on QCA6390
From: Kalle Valo @ 2024-03-25 13:57 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Liam Girdwood, Mark Brown, Catalin Marinas, Will Deacon,
Bjorn Helgaas, Saravana Kannan, Geert Uytterhoeven, Arnd Bergmann,
Neil Armstrong, Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov, linux-bluetooth, netdev,
devicetree, linux-kernel, linux-wireless, linux-arm-msm,
linux-arm-kernel, linux-pci, linux-pm, Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-5-brgl@bgdev.pl>
Bartosz Golaszewski <brgl@bgdev.pl> writes:
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> Add a PCI compatible for the ATH11K module on QCA6390 and describe the
> power inputs from the PMU that it consumes.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
[...]
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: pci17cb,1101
> + then:
> + required:
> + - vddrfacmn-supply
> + - vddaon-supply
> + - vddwlcx-supply
> + - vddwlmx-supply
> + - vddrfa0p8-supply
> + - vddrfa1p2-supply
> + - vddrfa1p7-supply
> + - vddpcie0p9-supply
> + - vddpcie1p8-supply
I don't know DT well enough to know what the "required:" above means,
but does this take into account that there are normal "plug&play" type
of QCA6390 boards as well which don't need any DT settings?
--
https://patchwork.kernel.org/project/linux-wireless/list/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [WIP 0/3] Memory model and atomic API in Rust
From: Philipp Stanner @ 2024-03-25 13:56 UTC (permalink / raw)
To: Linus Torvalds, Kent Overstreet
Cc: Boqun Feng, rust-for-linux, linux-kernel, linux-arch, llvm,
Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Alan Stern, Andrea Parri, Will Deacon, Peter Zijlstra,
Nicholas Piggin, David Howells, Jade Alglave, Luc Maranget,
Paul E. McKenney, Akira Yokosawa, Daniel Lustig, Joel Fernandes,
Nathan Chancellor, Nick Desaulniers, kent.overstreet,
Greg Kroah-Hartman, elver, Mark Rutland, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
Catalin Marinas, linux-arm-kernel, linux-fsdevel
In-Reply-To: <CAHk-=whkQk=zq5XiMcaU3xj4v69+jyoP-y6Sywhq-TvxSSvfEA@mail.gmail.com>
On Fri, 2024-03-22 at 17:36 -0700, Linus Torvalds wrote:
> On Fri, 22 Mar 2024 at 17:21, Kent Overstreet
> <kent.overstreet@linux.dev> wrote:
> >
> > Besides that there's cross arch support to think about - it's hard
> > to
> > imagine us ever ditching our own atomics.
>
> > [... SNIP ...]
> >
> > I was thinking about something more incremental - just an optional
> > mode
> > where our atomics were C atomics underneath. It'd probably give the
> > compiler people a much more effective way to test their stuff than
> > anything they have now.
>
> I suspect it might be painful, and some compiler people would throw
> their hands up in horror, because the C++ atomics model is based
> fairly solidly on atomic types, and the kernel memory model is much
> more fluid.
>
> Boqun already mentioned the "mixing access sizes", which is actually
> quite fundamental in the kernel, where we play lots of games with
> that
> (typically around locking, where you find patterns line unlock
> writing
> a zero to a single byte, even though the whole lock data structure is
> a word). And sometimes the access size games are very explicit (eg
> lib/lockref.c).
>
> But it actually goes deeper than that. While we do have "atomic_t"
> etc
> for arithmetic atomics, and that probably would map fairly well to
> C++
> atomics, in other cases we simply base our atomics not on _types_,
> but
> on code.
>
> IOW, we do things like "cmpxchg()", and the target of that atomic
> access is just a regular data structure field.
>
> It's kind of like our "volatile" usage. If you read the C (and C++)
> standards, you'll find that you should use "volatile" on data types.
> That's almost *never* what the kernel does. The kernel uses
> "volatile"
> in _code_ (ie READ_ONCE() etc), and uses it by casting etc.
>
> Compiler people don't tend to really like those kinds of things.
Just for my understanding: Why don't they like it?
I guess since compiler people have to support volatile pointers
anyways, temporarily casting something to such a volatile pointer
shouldn't be a problem either – so they don't dislike it because it's
more difficult to implement, but because it's more difficult to verify
for correctness?
P.
>
> Linus
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v1 2/2] dt-bindings: clock: rockchip: Add support for clk input / output switch
From: Rob Herring @ 2024-03-25 13:55 UTC (permalink / raw)
To: Sugar Zhang
Cc: Stephen Boyd, Conor Dooley, linux-rockchip, linux-arm-kernel,
heiko, linux-clk, Michael Turquette, devicetree, linux-kernel,
Krzysztof Kozlowski
In-Reply-To: <1711340191-69588-2-git-send-email-sugar.zhang@rock-chips.com>
On Mon, 25 Mar 2024 12:16:30 +0800, Sugar Zhang wrote:
> This patch add support switch for clk-bidirection which located
> at GRF, such as SAIx_MCLK_{IN OUT} which share the same pin.
> and these config maybe located in many pieces of GRF,
> which hard to addressed in one single clk driver. so, we add
> this simple helper driver to address this situation.
>
> In order to simplify implement and usage, and also for safety
> clk usage (avoid high freq glitch), we set all clk out as disabled
> (which means Input default for clk-bidrection) in the pre-stage,
> such boot-loader or init by HW default. And then set a safety freq
> before enable clk-out, such as "assign-clock-rates" or clk_set_rate
> in drivers.
>
> e.g.
>
> 1. mclk{out,in}_sai0 define:
>
> mclkin_sai0: mclkin-sai0 {
> compatible = "fixed-clock";
> #clock-cells = <0>;
> clock-frequency = <12288000>;
> clock-output-names = "mclk_sai0_from_io";
> };
>
> mclkout_sai0: mclkout-sai0@ff040070 {
> compatible = "rockchip,clk-out";
> reg = <0 0xff040070 0 0x4>;
> clocks = <&cru MCLK_SAI0_OUT2IO>;
> #clock-cells = <0>;
> clock-output-names = "mclk_sai0_to_io";
> rockchip,bit-shift = <4>;
> //example with PD if reg access needed
> power-domains = <&power RK3562_PD_VO>;
> };
>
> Note:
>
> clock-output-names of mclkin_sai0 should equal to strings in drivers. such as:
>
> drivers/clk/rockchip/clk-rk3562.c:
> PNAME(clk_sai0_p) = { "clk_sai0_src", "clk_sai0_frac", "xin_osc0_half", "mclk_sai0_from_io" };
>
> 2. mclkout_sai0 usage:
>
> &ext_codec {
> clocks = <&mclkout_sai0>;
> clock-names = "mclk";
> assigned-clocks = <&mclkout_sai0>;
> assigned-clock-rates = <12288000>;
> pinctrl-names = "default";
> pinctrl-0 = <&i2s0m0_mclk>;
> };
>
> clk_summary on sai0 work:
>
> cat /sys/kernel/debug/clk/clk_summary | egrep "pll|sai0"
>
> clk_sai0_src 1 1 0 1188000000 0 0 50000
> clk_sai0_frac 1 1 0 12288000 0 0 50000
> clk_sai0 1 1 0 12288000 0 0 50000
> mclk_sai0 1 1 0 12288000 0 0 50000
> mclk_sai0_out2io 1 1 0 12288000 0 0 50000
> mclk_sai0_to_io 1 1 0 12288000 0 0 50000
>
> example with PD if reg access needed:
>
> * PD status when mclk_sai0_to_io on:
>
> cat /sys/kernel/debug/pm_genpd/pm_genpd_summary
>
> domain status children
> /device runtime status
> ----------------------------------------------------------------------
> ...
>
> vo on
> /devices/platform/clocks/ff040070.mclkout-sai0 active
> ...
>
> * PD status when mclk_sai0_to_io off:
>
> cat /sys/kernel/debug/pm_genpd/pm_genpd_summary
>
> domain status children
> /device runtime status
> ----------------------------------------------------------------------
> ...
>
> vo off-0
> /devices/platform/clocks/ff040070.mclkout-sai0 suspended
> ...
>
> 3. mclkin_sai0 usage:
>
> please override freq of mclkin as the real external clkin, such as:
>
> &mclkin_sai0 {
> clock-frequency = <24576000>;
> }
>
> &ext_codec {
> clocks = <&mclkin_sai0>;
> clock-names = "mclk";
> assigned-clocks = <&cru CLK_SAI0>;
> assigned-clock-parents = <&mclkin_sai0>;
> pinctrl-names = "default";
> pinctrl-0 = <&i2s0m0_mclk>;
> };
>
> clk_summary on sai0 work:
>
> cat /sys/kernel/debug/clk/clk_summary | egrep "pll|sai0"
>
> mclk_sai0_from_io 1 1 0 12288000 0 0 50000
> clk_sai0 1 1 0 12288000 0 0 50000
> mclk_sai0 1 1 0 12288000 0 0 50000
> mclk_sai0_out2io 0 0 0 12288000 0 0 50000
> mclk_sai0_to_io 0 0 0 12288000 0 0 50000
>
> Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
> ---
>
> .../bindings/clock/rockchip,clk-out.yaml | 107 +++++++++++++++++++++
> 1 file changed, 107 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/rockchip,clk-out.yaml
>
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/rockchip,clk-out.yaml: title: 'Rockchip Clock Out Control Module Binding' should not be valid under {'pattern': '([Bb]inding| [Ss]chema)'}
hint: Everything is a binding/schema, no need to say it. Describe what hardware the binding is for.
from schema $id: http://devicetree.org/meta-schemas/base.yaml#
Error: Documentation/devicetree/bindings/clock/rockchip,clk-out.example.dts:28.28-29 syntax error
FATAL ERROR: Unable to parse input tree
make[2]: *** [scripts/Makefile.lib:427: Documentation/devicetree/bindings/clock/rockchip,clk-out.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1430: dt_binding_check] Error 2
make: *** [Makefile:240: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/1711340191-69588-2-git-send-email-sugar.zhang@rock-chips.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: arm: qcom: Add Motorola Moto G (2013)
From: Rob Herring @ 2024-03-25 13:55 UTC (permalink / raw)
To: Stanislav Jakubek
Cc: Conor Dooley, Bjorn Andersson, linux-arm-kernel, linux-kernel,
phone-devel, linux-arm-msm, Krzysztof Kozlowski, Konrad Dybcio,
devicetree
In-Reply-To: <f5d4d71cd59f25b80889ef88fa044aa3a4268d46.1711288736.git.stano.jakubek@gmail.com>
On Sun, 24 Mar 2024 15:03:59 +0100, Stanislav Jakubek wrote:
> Document the Motorola Moto G (2013), which is a smartphone based
> on the Qualcomm MSM8226 SoC.
>
> Signed-off-by: Stanislav Jakubek <stano.jakubek@gmail.com>
> ---
> Documentation/devicetree/bindings/arm/qcom.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
My bot found new DTB warnings on the .dts files added or changed in this
series.
Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.
If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:
pip3 install dtschema --upgrade
New warnings running 'make CHECK_DTBS=y qcom/msm8226-motorola-falcon.dtb' for f5d4d71cd59f25b80889ef88fa044aa3a4268d46.1711288736.git.stano.jakubek@gmail.com:
arch/arm/boot/dts/qcom/msm8226-motorola-falcon.dtb: syscon@f9011000: compatible: 'anyOf' conditional failed, one must be fixed:
['syscon'] is too short
'syscon' is not one of ['allwinner,sun8i-a83t-system-controller', 'allwinner,sun8i-h3-system-controller', 'allwinner,sun8i-v3s-system-controller', 'allwinner,sun50i-a64-system-controller', 'amd,pensando-elba-syscon', 'brcm,cru-clkset', 'freecom,fsg-cs2-system-controller', 'fsl,imx93-aonmix-ns-syscfg', 'fsl,imx93-wakeupmix-syscfg', 'hisilicon,dsa-subctrl', 'hisilicon,hi6220-sramctrl', 'hisilicon,pcie-sas-subctrl', 'hisilicon,peri-subctrl', 'hpe,gxp-sysreg', 'intel,lgm-syscon', 'loongson,ls1b-syscon', 'loongson,ls1c-syscon', 'marvell,armada-3700-usb2-host-misc', 'mediatek,mt8135-pctl-a-syscfg', 'mediatek,mt8135-pctl-b-syscfg', 'mediatek,mt8365-syscfg', 'microchip,lan966x-cpu-syscon', 'microchip,sparx5-cpu-syscon', 'mstar,msc313-pmsleep', 'nuvoton,ma35d1-sys', 'nuvoton,wpcm450-shm', 'rockchip,px30-qos', 'rockchip,rk3036-qos', 'rockchip,rk3066-qos', 'rockchip,rk3128-qos', 'rockchip,rk3228-qos', 'rockchip,rk3288-qos', 'rockchip,rk3368-qos', 'rockchip,rk3399-qos', 'rockchip,rk3568-qos', '
rockchip,rk3588-qos', 'rockchip,rv1126-qos', 'starfive,jh7100-sysmain', 'ti,am62-usb-phy-ctrl', 'ti,am654-dss-oldi-io-ctrl', 'ti,am654-serdes-ctrl', 'ti,j784s4-pcie-ctrl']
from schema $id: http://devicetree.org/schemas/mfd/syscon.yaml#
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v11 0/7] drm/meson: add support for MIPI DSI Display
From: Rob Herring @ 2024-03-25 13:55 UTC (permalink / raw)
To: Neil Armstrong
Cc: David Airlie, linux-amlogic, linux-kernel, Conor Dooley,
Stephen Boyd, Thomas Zimmermann, devicetree, Krzysztof Kozlowski,
dri-devel, Conor Dooley, Daniel Vetter, Michael Turquette,
Nicolas Belin, Lukas F. Hartmann, Maxime Ripard,
Maarten Lankhorst, Jerome Brunet, Kevin Hilman,
Martin Blumenstingl, Jagan Teki, linux-clk, linux-arm-kernel
In-Reply-To: <20240325-amlogic-v6-4-upstream-dsi-ccf-vim3-v11-0-04f55de44604@linaro.org>
On Mon, 25 Mar 2024 12:09:46 +0100, Neil Armstrong wrote:
> The Amlogic G12A, G12B & SM1 SoCs embeds a Synopsys DW-MIPI-DSI transceiver (ver 1.21a),
> with a custom glue managing the IP resets, clock and data input similar to the DW-HDMI
> glue on the same Amlogic SoCs.
>
> This is a follow-up of v5 now the DRM patches are applied, the clk & DT changes
> remains for a full DSI support on G12A & SM1 platforms.
>
> The DW-MIPI-DSI transceiver + D-PHY are clocked by the GP0 PLL, and the ENCL encoder + VIU
> pixel reader by the VCLK2 clock using the HDMI PLL.
>
> The DW-MIPI-DSI transceiver gets this pixel stream as input clocked with the VCLK2 clock.
>
> An optional "MEAS" clock can be enabled to measure the delay between each vsync feeding the
> DW-MIPI-DSI transceiver.
>
> The clock setup has been redesigned to use CCF, a common PLL (GP0) and the VCLK2 clock
> path for DSI in preparation of full CCF support and possibly dual display with HDMI.
>
> The change from v5 is that now we use a "VCLK" driver instead of notifier and rely
> on CLK_SET_RATE_GATE to ensure the VCLK gate operation are called.
>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> Changes in v11:
> - Rebased on v6.9-rc1
> - Fixed overlay handling/creation
> - Link to v10: https://lore.kernel.org/r/20240205-amlogic-v6-4-upstream-dsi-ccf-vim3-v10-0-dc06073d5330@linaro.org
>
> Changes in v10:
> - Rename regmap_vclk to meson_clk and add _gate for the gate
> - Move COMMON_CLK_MESON_VCLK to following patch
> - Remove CLK_SET_RATE_PARENT from g12a_vclk2_sel, keep it only on mipi_dsi_pxclk_sel
> - Add more info on commit message to specify how clock setup is designed
> - Remove forgotten CLK_IGNORE_UNUSED on g12a_vclk2_input
> - Remove useless CLK_SET_RATE_PARENT on g12a_vclk2_div to stop propagatting rate _after_ vclk2_div
> - Remove invalid CLK_SET_RATE_GATE on g12a_vclk2 since it's not a divider...
> - Drop already applied patches
> - move Khadas TS050 changes as an overlay
> - Link to v9: https://lore.kernel.org/r/20231124-amlogic-v6-4-upstream-dsi-ccf-vim3-v9-0-95256ed139e6@linaro.org
>
> Changes in v9:
> - Colledte reviewed-bys
> - Fixed patches 2 & 4, commit messages and bindings format
> - Link to v8: https://lore.kernel.org/r/20231109-amlogic-v6-4-upstream-dsi-ccf-vim3-v8-0-81e4aeeda193@linaro.org
>
> Changes in v8:
> - Switch vclk clk driver to parm as requested by Jerome
> - Added bindings fixes to amlogic,meson-axg-mipi-pcie-analog & amlogic,g12a-mipi-dphy-analog
> - Fixed DT errors in vim3 example and MNT Reform DT
> - Rebased on next-20231107, successfully tested on VIM3L
> - Link to v7: https://lore.kernel.org/r/20230803-amlogic-v6-4-upstream-dsi-ccf-vim3-v7-0-762219fc5b28@linaro.org
>
> Changes in v7:
> - Added review tags
> - Fixed patch 5 thanks to George
> - Link to v6: https://lore.kernel.org/r/20230512-amlogic-v6-4-upstream-dsi-ccf-vim3-v6-0-fd2ac9845472@linaro.org
>
> Changes in v6:
> - dropped applied DRM patches
> - dropped clk private prefix patches
> - rebased on top of 20230607-topic-amlogic-upstream-clkid-public-migration-v2-0-38172d17c27a@linaro.org
> - re-ordered/cleaned ENCL patches to match clkid public migration
> - Added new "vclk" driver
> - uses vclk driver instead of notifier
> - cleaned VCLK2 clk flags
> - add px_clk gating from DSI driver
> - Link to v5: https://lore.kernel.org/r/20230512-amlogic-v6-4-upstream-dsi-ccf-vim3-v5-0-56eb7a4d5b8e@linaro.org
>
> Changes in v5:
> - Aded PRIV all the G12 internal clk IDS to simplify public exposing
> - Fixed the DSI bindings
> - Fixed the DSI HSYNC/VSYNC polarity handling
> - Fixed the DSI clock setup
> - Fixed the DSI phy timings
> - Dropped components for DSI, only keeping it for HDMI
> - Added MNT Reform 2 CM4 DT
> - Dropped already applied PHY fix
> - Link to v4: https://lore.kernel.org/r/20230512-amlogic-v6-4-upstream-dsi-ccf-vim3-v4-0-2592c29ea263@linaro.org
>
> Changes from v3 at [3]:
> - switched all clk setup via CCF
> - using single PLL for DSI controller & ENCL encoder
> - added ENCL clocks to CCF
> - make the VCLK2 clocks configuration by CCF
> - fixed probe/bind of DSI controller to work with panels & bridges
> - added bit_clk to controller to it can setup the BIT clock aswell
> - added fix for components unbind
> - added fix for analog phy setup value
> - added TS050 timings fix
> - dropped previous clk control patch
>
> Changes from v2 at [2]:
> - Fixed patch 3
> - Added reviews from Jagan
> - Rebased on v5.19-rc1
>
> Changes from v1 at [1]:
> - fixed DSI host bindings
> - add reviewed-by tags for bindings
> - moved magic values to defines thanks to Martin's searches
> - added proper prefixes to defines
> - moved phy_configure to phy_init() dw-mipi-dsi callback
> - moved phy_on to a new phy_power_on() dw-mipi-dsi callback
> - correctly return phy_init/configure errors to callback returns
>
> [1] https://lore.kernel.org/r/20200907081825.1654-1-narmstrong@baylibre.com
> [2] https://lore.kernel.org/r/20220120083357.1541262-1-narmstrong@baylibre.com
> [3] https://lore.kernel.org/r/20220617072723.1742668-1-narmstrong@baylibre.com
>
> ---
> Neil Armstrong (7):
> dt-bindings: arm: amlogic: Document the MNT Reform 2 CM4 adapter with a BPI-CM4 Module
> clk: meson: add vclk driver
> clk: meson: g12a: make VCLK2 and ENCL clock path configurable by CCF
> drm/meson: gate px_clk when setting rate
> arm64: meson: g12-common: add the MIPI DSI nodes
> arm64: meson: khadas-vim3l: add TS050 DSI panel overlay
> arm64: dts: amlogic: meson-g12b-bananapi-cm4: add support for MNT Reform2 with CM4 adaper
>
> Documentation/devicetree/bindings/arm/amlogic.yaml | 1 +
> arch/arm64/boot/dts/amlogic/Makefile | 5 +
> arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi | 70 ++++
> .../meson-g12b-bananapi-cm4-mnt-reform2.dts | 384 +++++++++++++++++++++
> .../boot/dts/amlogic/meson-khadas-vim3-ts050.dtso | 108 ++++++
> drivers/clk/meson/Kconfig | 5 +
> drivers/clk/meson/Makefile | 1 +
> drivers/clk/meson/g12a.c | 72 ++--
> drivers/clk/meson/vclk.c | 141 ++++++++
> drivers/clk/meson/vclk.h | 51 +++
> drivers/gpu/drm/meson/meson_dw_mipi_dsi.c | 7 +
> 11 files changed, 825 insertions(+), 20 deletions(-)
> ---
> base-commit: 4cece764965020c22cff7665b18a012006359095
> change-id: 20230512-amlogic-v6-4-upstream-dsi-ccf-vim3-b8e5217e1f4a
>
> Best regards,
> --
> Neil Armstrong <neil.armstrong@linaro.org>
>
>
>
My bot found new DTB warnings on the .dts files added or changed in this
series.
Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.
If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:
pip3 install dtschema --upgrade
New warnings running 'make CHECK_DTBS=y amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dtb' for 20240325-amlogic-v6-4-upstream-dsi-ccf-vim3-v11-0-04f55de44604@linaro.org:
arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dtb: /soc/bus@ff600000/bus@42000/clock-controller@0: failed to match any schema with compatible: ['amlogic,g12a-audio-clkc']
arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dtb: /soc/bus@ff600000/bus@42000/audio-controller@744: failed to match any schema with compatible: ['amlogic,g12a-tohdmitx']
arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dtb: sys-ctrl@0: '#address-cells', '#size-cells', 'ranges' do not match any of the regexes: 'pinctrl-[0-9]+'
from schema $id: http://devicetree.org/schemas/soc/amlogic/amlogic,meson-gx-hhi-sysctrl.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dtb: sound: Unevaluated properties are not allowed ('assigned-clock-parents', 'assigned-clock-rates', 'assigned-clocks' were unexpected)
from schema $id: http://devicetree.org/schemas/sound/amlogic,axg-sound-card.yaml#
arch/arm64/boot/dts/amlogic/meson-g12b-bananapi-cm4-mnt-reform2.dtb: sound: 'anyOf' conditional failed, one must be fixed:
'clocks' is a required property
'#clock-cells' is a required property
from schema $id: http://devicetree.org/schemas/clock/clock.yaml#
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] arm64: configs: enable REGULATOR_QCOM_USB_VBUS
From: Dmitry Baryshkov @ 2024-03-25 13:46 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Catalin Marinas, Will Deacon
Cc: linux-arm-msm, linux-arm-kernel, linux-kernel,
Bryan O'Donoghue, Dmitry Baryshkov
Enable the VBUS regulator used on Qualcomm platforms (RB1, RB2, RB5) to
supply VBUS voltage to the USB-C connector.
Reported-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 6c45a465a071..a86e94aea63e 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -772,6 +772,7 @@ CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_QCOM_RPMH=y
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
+CONFIG_REGULATOR_QCOM_USB_VBUS=m
CONFIG_REGULATOR_RAA215300=y
CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_S2MPS11=y
---
base-commit: 13ee4a7161b6fd938aef6688ff43b163f6d83e37
change-id: 20240325-arm64-config-usb-vbus-c0e0554df1e6
Best regards,
--
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v4] PCI: keystone: Fix pci_ops for AM654x SoC
From: Niklas Cassel @ 2024-03-25 13:45 UTC (permalink / raw)
To: Siddharth Vadapalli
Cc: lpieralisi, kw, robh, bhelgaas, manivannan.sadhasivam,
fancer.lancer, u.kleine-koenig, dlemoal, yoshihiro.shimoda.uh,
linux-pci, linux-kernel, linux-arm-kernel, srk
In-Reply-To: <ea0294d4-85d1-4784-acd7-dd247165f69b@ti.com>
Hello Siddharth,
On Mon, Mar 25, 2024 at 05:52:28PM +0530, Siddharth Vadapalli wrote:
> On Mon, Mar 25, 2024 at 12:23:05PM +0100, Niklas Cassel wrote:
> > On Mon, Mar 25, 2024 at 11:07:22AM +0530, Siddharth Vadapalli wrote:
> > > @@ -822,6 +788,23 @@ static int __init ks_pcie_host_init(struct dw_pcie_rp *pp)
> > > if (ret < 0)
> > > return ret;
> > >
> >
> > > + if (!ks_pcie->is_am6) {
> >
> > Perhaps add a comment here stating WHY this is needed for v3.65a (!is_am6).
> >
> > From reading the old threads, it appears that v3.65a:
> > -Has no support for iATUs. iATU-specific resource handling code is to be
> > bypassed for v3.65 h/w. Thus v3.65a has it's own .child_ops implementation,
> > so that pcie-designware-host.c does not configure the iATUs.
> > -v3.65a has it's own .msi_init implementation, so that pcie-designware-host.c
> > does not call dw_pcie_msi_host_init() to configure the MSI controller.
> >
> > While 4.90a:
> > -Does have iATU support.
> > -Does use the generic dw_pcie_msi_host_init().
> >
> > Considering the major differences (with v3.65a being the outlier) here,
> > I think it would have been a much wiser idea to have two different glue
> > drivers for these two compatibles (ti,keystone-pcie and ti,am654-pcie-rc).
> >
> > Right now the driver is quite hard to read, most of the functions in this
> > driver exist because v3.65a does not have an iATU and does not use the
> > generic DWC way to handle MSIs. Additionally, you have "if (!ks_pcie->is_am6)"
> > spread out all over the driver, to control quite major things, like if you
> > should overload .child_ops, or if you should set up inbound translation without
> > an iATU. This makes is even harder to see which code is actually used for
> > am654... like the fact that it actually uses the generic way to handle MSIs...
> >
> > The driver for am654 would be much nicer since many of the functions in
> > this driver would not be needed (and the fact that you have only implemented
> > EP support for am654 and not for v3.65a). All EP related stuff would be in
> > the am654 file/driver.
> > You could keep the quirky stuff for v3.65a in the existing pci-keystone.c
> > driver.
> >
> > (I guess if there is a function that is identical between the twos, you could
> > have a pci-keystone-common.{c,h} that can be used by both drivers, but from
> > the looks of it, they seem to share very little code.
>
> Thank you for reviewing the patch. I agree that two drivers will be
> better considering the !ks_pcie->is_am6 present throughout the driver.
> However, I hope you notice the fact that commit:
> 6ab15b5e7057 PCI: dwc: keystone: Convert .scan_bus() callback to use add_bus
> introduced a regression in a driver which was working prior to that
> commit for AM654. While there are flaws in the driver and it needs to be
> split to handle v3.65a and other versions in a cleaner manner, I am
> unable to understand why that is a precursor to fixing the regression.
>
> If splitting the driver is the only way to fix this regression, please
> let me know and I will work on that instead, though it will take up more
> time.
I think you are misunderstanding me.
I think this patch is fine, except for the comment that I gave:
"Perhaps add a comment here stating WHY this is needed for v3.65a (!is_am6)."
Like:
/*
* This is only needed for !am654 since it has its own msi_irq_chip
* implementation. (am654 uses the generic msi_irq_chip implementation.)
*/
if (!ks_pcie->is_am6) {
...
}
In fact, if you move this code to ks_pcie_msi_host_init(), instead of
ks_pcie_host_init(), you would not need a comment (or a if (!ks_pcie->is_am6)),
since ks_pcie_msi_host_init() is only executed by !am654.
My suggestion to split this driver to two different drivers is just because
I noticed how different they are (am654 has iATUs, uses generic msi_irq_chip
implementation and has EP-mode support. !am654 has no iATUs, its own MSI
implementation and no EP-mode support.)
So the am654 driver would look like most other DWC glue drivers.
The non-am654 driver would look mostly like it looks today, except you would
remove the EP-mode support.
However, this suggestion can of course be implemented sometime in the future
and should not be a blocker for the patch in $subject.
Kind regards,
Niklas
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: mailbox: arm,mhuv3: Add bindings
From: Rob Herring @ 2024-03-25 13:44 UTC (permalink / raw)
To: Cristian Marussi
Cc: linux-kernel, linux-arm-kernel, devicetree, sudeep.holla,
jassisinghbrar, krzysztof.kozlowski+dt, conor+dt
In-Reply-To: <20240325092808.117510-2-cristian.marussi@arm.com>
On Mon, Mar 25, 2024 at 4:28 AM Cristian Marussi
<cristian.marussi@arm.com> wrote:
>
> Add bindings for the ARM MHUv3 Mailbox controller.
>
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> ---
> .../bindings/mailbox/arm,mhuv3.yaml | 239 ++++++++++++++++++
> 1 file changed, 239 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mailbox/arm,mhuv3.yaml
>
> diff --git a/Documentation/devicetree/bindings/mailbox/arm,mhuv3.yaml b/Documentation/devicetree/bindings/mailbox/arm,mhuv3.yaml
> new file mode 100644
> index 000000000000..bfb8ec341d26
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/arm,mhuv3.yaml
> @@ -0,0 +1,239 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mailbox/arm,mhuv3.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: ARM MHUv3 Mailbox Controller
> +
> +maintainers:
> + - Sudeep Holla <sudeep.holla@arm.com>
> + - Cristian Marussi <cristian.marussi@arm.com>
> +
> +description: |
> + The Arm Message Handling Unit (MHU) Version 3 is a mailbox controller that
> + enables unidirectional communications with remote processors through various
> + possible transport protocols.
> + The controller can optionally support a varying number of extensions that, in
> + turn, enable different kinds of transport to be used for communication.
> + Number, type and characteristics of each supported extension can be discovered
> + dynamically at runtime.
> +
> + Given the unidirectional nature of the controller, an MHUv3 mailbox controller
> + is composed of a MHU Sender (MHUS) containing a PostBox (PBX) block and a MHU
> + Receiver (MHUR) containing a MailBox (MBX) block, where
> +
> + PBX is used to
> + - Configure the MHU
> + - Send Transfers to the Receiver
> + - Optionally receive acknowledgment of a Transfer from the Receiver
> +
> + MBX is used to
> + - Configure the MHU
> + - Receive Transfers from the Sender
> + - Optionally acknowledge Transfers sent by the Sender
> +
> + Both PBX and MBX need to be present and defined in the DT description if you
> + need to establish a bidirectional communication, since you will have to
> + acquire two distinct unidirectional channels, one for each block.
> +
> + As a consequence both blocks needs to be represented separately and specified
> + as distinct DT nodes in order to properly describe their resources.
> +
> + Note that, though, thanks to the runtime discoverability, there is no need to
> + identify the type of blocks with distinct compatibles.
> +
> + Following are the MHUv3 possible extensions.
> +
> + - Doorbell Extension (DBE): DBE defines a type of channel called a Doorbell
> + Channel (DBCH). DBCH enables a single bit Transfer to be sent from the
> + Sender to Receiver. The Transfer indicates that an event has occurred.
> + When DBE is implemented, the number of DBCHs implemented is between 1 and
> + 128, numbered starting from 0 in ascending order.
> + Each DBCH contains 32 individual fields, referred to as flags, each of which
> + can be used independently. It is possible for the Sender to send multiple
> + Transfers at once using a single DBCH, so long as each Transfer uses
> + a different flag in the DBCH.
> + Optionally, data may be transmitted through an out-of-band shared memory
> + region, wherein the MHU Doorbell is used strictly as an interrupt generation
> + mechanism, but this is out of the scope of these bindings.
> +
> + - FastChannel Extension (FCE): FCE defines a type of channel called a Fast
> + Channel (FCH). FCH is intended for lower overhead communication between
> + Sender and Receiver at the expense of determinism. An FCH allows the Sender
> + to update the channel value at any time, regardless of whether the previous
> + value has been seen by the Receiver. When the Receiver reads the channel's
> + content it gets the last value written to the channel.
> + FCH is considered lossy in nature, and means that the Sender has no way of
> + knowing if, or when, the Receiver will act on the Transfer.
> + FCHs are expected to behave as RAM which generates interrupts when writes
> + occur to the locations within the RAM.
> + When FCE is implemented, the number of FCH that an implementation of the MHU
> + can support is between 1-1024, if the Fast Channel word-size is 32-bits, or
> + between 1-512, when the Fast Channel word-size is 64-bits.
Be consistent: FastChannel
> + FCHs are numbered from 0 in ascending order.
> + Note that Fast Channel word-size is implementation defined, not configurable
> + but discoverable at run-time.
> + Optionally, data may be transmitted through an out-of-band shared memory
> + region, wherein the MHU FastChannel is used as an interrupt generation
> + mechanism which carries also a pointer to such out-of-band data, but this
> + is out of the scope of these bindings.
> +
> + - FIFO Extension (FE): FE defines a Channel type called a FIFO Channel (FFCH).
> + FFCH allows a Sender to send
> + - Multiple Transfer to the Receiver without having to wait for a previous
> + Transfer to be acknowledged by the Receiver, as long as the FIFO has
> + room for the Transfer.
> + - Transfers which require the Receiver to provide acknowledgment.
> + - Transfers which have in-band payload.
> + In all cases, the data is guaranteed to be observed by the Receiver in the
> + same order which the Sender sent it.
> + When FE is implemented, the number of FFCH an implementation of the MHU can
> + support is between 1 and 64, numbered starting from the 0 in ascending
> + order. The FIFO size is implementation defined and not configurable.
Size is discoverable or opaque to s/w?
> + Optionally, additional data may be transmitted through an out-of-band shared
> + memory region, wherein the MHU FIFO is used to transmit, in order, a small
> + part of the payload (like a header) and a reference to the shared memory
> + area holding the remaining, bigger, chunk of the payload, but this is out of
> + the scope of these bindings.
> +
> +properties:
> + compatible:
> + const: arm,mhuv3
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + minItems: 1
> + maxItems: 38
> +
> + interrupt-names:
> + description: |
> + The MHUv3 controller generates a number of events some of which are used
> + to generate interrupts; as a consequence it can expose a varying number of
> + optional PBX/MBX interrupts, representing the events generated during the
> + operation of the various transport protocols associated with different
> + extensions. All interrupts of the MHU are level-sensitive.
> + Some of these optional interrupts are defined per-channel, where the
> + number of channels effectively available is implementation defined and
> + run-time discoverable.
> + In the following, for sake of simplicity, only a limited number of
> + per-channel interrupt names are enumerated, out of all the possible
> + channels allowed by the specification for each extension type.
> +
> + - "combined": PBX/MBX Combined interrupt
> + - "combined-ffch": PBX/MBX FIFO Combined interrupt
> + - "ffch-low-tide-<N>": PBX/MBX FIFO Channel <N> Low Tide interrupt
> + - "ffch-high-tide-<N>": PBX/MBX FIFO Channel <N> High Tide interrupt
> + - "ffch-flush-<N>": PBX/MBX FIFO Channel <N> Flush interrupt
> + - "mbx-dbch-xfer-<N>": MBX Doorbell Channel <N> Transfer interrupt
> + - "mbx-fch-xfer-<N>": MBX Fast Channel <N> Transfer interrupt
> + - "mbx-fchgrp-xfer-<N>": MBX Fast Channel <N> Group Transfer interrupt
> + - "mbx-ffch-xfer-<N>": MBX FIFO Channel <N> Transfer interrupt
> + - "pbx-dbch-xfer-ack-<N>": PBX Doorbell Channel <N> Transfer Ack interrupt
> + - "pbx-ffch-xfer-ack-<N>": PBX FIFO Channel <N> Transfer Ack interrupt
It would be better to not define these strings twice. You can do
something like this:
items:
oneOf:
- const: combined
description: ...
- pattern: '^ffch-low-tide-[0-9]+$'
description: ...
And so on.
> +
> + The only mandatory interrupts on the MHU are:
> + - combined
> + - mbx-fch-xfer-<N> but only if mbx-fcgrp-xfer-<N> is not implemented.
> +
> + minItems: 1
> + maxItems: 38
Perhaps a comment on where 38 comes from. AIUI, this is a "should be
enough for now" value.
> + items:
> + enum:
> + - combined
> + - combined-ffch
> + - ffch-low-tide-0
> + - ffch-low-tide-1
> + - ffch-low-tide-2
> + - ffch-low-tide-3
> + - ffch-high-tide-0
> + - ffch-high-tide-1
> + - ffch-high-tide-2
> + - ffch-high-tide-3
> + - ffch-flush-0
> + - ffch-flush-1
> + - ffch-flush-2
> + - ffch-flush-3
> + - mbx-dbch-xfer-0
> + - mbx-dbch-xfer-1
> + - mbx-dbch-xfer-2
> + - mbx-dbch-xfer-3
> + - mbx-fch-xfer-0
> + - mbx-fch-xfer-1
> + - mbx-fch-xfer-2
> + - mbx-fch-xfer-3
> + - mbx-fchgrp-xfer-0
> + - mbx-fchgrp-xfer-1
> + - mbx-fchgrp-xfer-2
> + - mbx-fchgrp-xfer-3
> + - mbx-ffch-xfer-0
> + - mbx-ffch-xfer-1
> + - mbx-ffch-xfer-2
> + - mbx-ffch-xfer-3
> + - pbx-dbch-xfer-ack-0
> + - pbx-dbch-xfer-ack-1
> + - pbx-dbch-xfer-ack-2
> + - pbx-dbch-xfer-ack-3
> + - pbx-ffch-xfer-ack-0
> + - pbx-ffch-xfer-ack-1
> + - pbx-ffch-xfer-ack-2
> + - pbx-ffch-xfer-ack-3
> +
> + '#mbox-cells':
> + description: |
> + The first argument in the consumers 'mboxes' property represents the
> + extension type, the second is for the channel number while the third
> + depends on extension type.
> +
> + Extension type for DBE is 0 and the third parameter represents the
> + doorbell flag number to use.
> + Extension type for FCE is 1, third parameter unused.
> + Extension type for FE is 2, third parameter unused.
> +
> + mboxes = <&mhu 0 0 5>; // DBE, Doorbell Channel Window 0, doorbell flag 5.
> + mboxes = <&mhu 0 1 7>; // DBE, Doorbell Channel Window 1, doorbell flag 7.
> + mboxes = <&mhu 1 0 0>; // FCE, Fast Channel Window 0.
> + mboxes = <&mhu 1 3 0>; // FCE, Fast Channel Window 3.
> + mboxes = <&mhu 2 1 0>; // FE, FIFO Channel Window 1.
> + mboxes = <&mhu 2 7 0>; // FE, FIFO Channel Window 7.
> + const: 3
> +
> + clocks:
> + maxItems: 1
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - interrupt-names
> + - '#mbox-cells'
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + mhu_tx: mailbox@2aaa0000 {
Drop unused labels.
> + compatible = "arm,mhuv3";
> + #mbox-cells = <3>;
> + reg = <0 0x2aaa0000 0 0x10000>;
> + clocks = <&clock 0>;
> + interrupt-names = "combined", "pbx-dbch-xfer-ack-1",
> + "ffch-high-tide-0";
> + interrupts = <0 36 4>, <0 37 4>;
> + };
> +
> + mhu_rx: mailbox@2ab00000 {
> + compatible = "arm,mhuv3";
> + #mbox-cells = <3>;
> + reg = <0 0x2aab0000 0 0x10000>;
> + clocks = <&clock 0>;
> + interrupt-names = "combined", "mbx-dbch-xfer-1", "ffch-low-tide-0";
> + interrupts = <0 35 4>, <0 38 4>, <0 39 4>;
> + };
> + };
> --
> 2.34.1
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Potential bug of arm64 SMCCC call
From: 崇文 李 @ 2024-03-25 13:36 UTC (permalink / raw)
To: linux-arm-kernel@lists.infradead.org
Hello. I saw a potential bug when I was checking arm64 SMCCC call.
In arm-smccc.h [see link 0], from line 481 to line 497 resides the
definition of "__arm_smccc_1_1", which is in turn used to implement
the RMI interface in rmi_cmds.h [see link 1].
In the definition of "__arm_smccc_1_1", there is no clobbering of
registers x4 -- x17. However, according to Arm SMC Calling Convention
[see link 2, page 10 of 19], registers x4 -- x17 are scratch registers.
Upon returning from an arm64 smc instruction, x4 -- x17 registers may
be overwritten with mysterious values from the firmware.
So it is safer to mark x4--x17 registers as clobbered registers in the
"asm" statement inside the definition of "__arm_smccc_1_1", so the
compiler avoids using x4--x17 registers around arm64 smc instructions.
Best regards.
Links
============
[0] arm-smccc.h in arm's linux kernel repository
https://gitlab.arm.com/linux-arm/linux-cca/-/blob/cca-host/rmm-v1.0-eac5/include/linux/arm-smccc.h?ref_type=heads
[1] rmi_cmds.h in arm's linux kernel repository
https://gitlab.arm.com/linux-arm/linux-cca/-/blob/cca-host/rmm-v1.0-eac5/arch/arm64/include/asm/rmi_cmds.h?ref_type=heads
[2] Arm SMC Calling Convention
https://documentation-service.arm.com/static/5f8ea482f86e16515cdbe3c6?token=
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 4/4] arm64: dts: S32G3: Introduce device tree for S32G-VNP-RDB3
From: Ghennadi Procopciuc @ 2024-03-25 13:34 UTC (permalink / raw)
To: Wadim Mueller, Shawn Guo
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Ulf Hansson,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
NXP Linux Team, Greg Kroah-Hartman, Jiri Slaby, Chester Lin,
Andreas Färber, Matthias Brugger, NXP S32 Linux Team,
Tim Harvey, Marco Felsch, Marek Vasut, Gregor Herburger,
Hugo Villeneuve, Joao Paulo Goncalves, Markus Niebel,
Matthias Schiffer, Stefan Wahren, Bjorn Helgaas,
Philippe Schenker, Josua Mayer, Li Yang, devicetree, linux-kernel,
linux-mmc, linux-arm-kernel, linux-serial
In-Reply-To: <20240325132634.GA33097@bhlegrsu.conti.de>
On 3/25/24 15:26, Wadim Mueller wrote:
> On Mon, Mar 25, 2024 at 11:30:38AM +0200, Ghennadi Procopciuc wrote:
>> On 3/24/24 23:43, Wadim Mueller wrote:
>>> This commit adds device tree support for the NXP S32G3-based
>>> S32G-VNP-RDB3 Board [1].
>>>
>>> The S32G3 features an 8-core ARM Cortex-A53 based SoC developed by NXP.
>>>
>>> The device tree files are derived from the official NXP downstream
>>> Linux tree [2].
>>>
>>> This addition encompasses a limited selection of peripherals that
>>> are upstream-supported. Apart from the ARM System Modules
>>> (GIC, Generic Timer, etc.), the following IPs have been validated:
>>>
>>> * UART: fsl-linflexuart
>>> * SDHC: fsl-imx-esdhc
>>>
>>> Clock settings for the chip rely on ATF Firmware [3].
>>> Pin control integration into the device tree is pending and currently
>>> relies on Firmware/U-Boot settings [4].
>>>
>>> These changes were validated using BSP39 Firmware/U-Boot from NXP [5].
>>>
>>> The modifications enable booting the official Ubuntu 22.04 from NXP on
>>> the RDB3 with default settings from the SD card and eMMC.
>>>
>>> [1] https://www.nxp.com/design/design-center/designs/s32g3-vehicle-networking-reference-design:S32G-VNP-RDB3
>>> [2] https://github.com/nxp-auto-linux/linux
>>> [3] https://github.com/nxp-auto-linux/arm-trusted-firmware
>>> [4] https://github.com/nxp-auto-linux/u-boot
>>> [5] https://github.com/nxp-auto-linux/auto_yocto_bsp
>>>
>>> Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
>>> ---
>>
>> Thank you, Wadim, for bringing up the S32G3RDB3 board! The board boots
>> with all 8 cores. The log is attached below.
>>
>
> Thanks for testing Ghennadi, much appreciated.
>
> According to MAINTAINERS all "dts/freescale/" DTS files
> needs to go through the IMX/MXC tree?
> Is my understanding correct? Just asking whether I understand the file
> content correctly!
>
Indeed, everything should go through the IMX tree.
Here [0] you can find a long discussion about this.
[0]
https://lore.kernel.org/linux-arm-kernel/a5f7b53a-6b44-4f0b-83f2-b055b8aa3b2d@suse.com/
Regards,
Ghennadi
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 4/4] arm64: dts: S32G3: Introduce device tree for S32G-VNP-RDB3
From: Wadim Mueller @ 2024-03-25 13:26 UTC (permalink / raw)
To: Ghennadi Procopciuc
Cc: Wadim Mueller, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Ulf Hansson, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, NXP Linux Team, Greg Kroah-Hartman, Jiri Slaby,
Chester Lin, Andreas Färber, Matthias Brugger,
NXP S32 Linux Team, Tim Harvey, Marco Felsch, Marek Vasut,
Gregor Herburger, Hugo Villeneuve, Joao Paulo Goncalves,
Markus Niebel, Matthias Schiffer, Stefan Wahren, Bjorn Helgaas,
Philippe Schenker, Josua Mayer, Li Yang, devicetree, linux-kernel,
linux-mmc, linux-arm-kernel, linux-serial
In-Reply-To: <df6f2a09-8125-4c1a-9dfd-3217233dc076@oss.nxp.com>
On Mon, Mar 25, 2024 at 11:30:38AM +0200, Ghennadi Procopciuc wrote:
> On 3/24/24 23:43, Wadim Mueller wrote:
> > This commit adds device tree support for the NXP S32G3-based
> > S32G-VNP-RDB3 Board [1].
> >
> > The S32G3 features an 8-core ARM Cortex-A53 based SoC developed by NXP.
> >
> > The device tree files are derived from the official NXP downstream
> > Linux tree [2].
> >
> > This addition encompasses a limited selection of peripherals that
> > are upstream-supported. Apart from the ARM System Modules
> > (GIC, Generic Timer, etc.), the following IPs have been validated:
> >
> > * UART: fsl-linflexuart
> > * SDHC: fsl-imx-esdhc
> >
> > Clock settings for the chip rely on ATF Firmware [3].
> > Pin control integration into the device tree is pending and currently
> > relies on Firmware/U-Boot settings [4].
> >
> > These changes were validated using BSP39 Firmware/U-Boot from NXP [5].
> >
> > The modifications enable booting the official Ubuntu 22.04 from NXP on
> > the RDB3 with default settings from the SD card and eMMC.
> >
> > [1] https://www.nxp.com/design/design-center/designs/s32g3-vehicle-networking-reference-design:S32G-VNP-RDB3
> > [2] https://github.com/nxp-auto-linux/linux
> > [3] https://github.com/nxp-auto-linux/arm-trusted-firmware
> > [4] https://github.com/nxp-auto-linux/u-boot
> > [5] https://github.com/nxp-auto-linux/auto_yocto_bsp
> >
> > Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
> > ---
>
> Thank you, Wadim, for bringing up the S32G3RDB3 board! The board boots
> with all 8 cores. The log is attached below.
>
Thanks for testing Ghennadi, much appreciated.
According to MAINTAINERS all "dts/freescale/" DTS files
needs to go through the IMX/MXC tree?
Is my understanding correct? Just asking whether I understand the file
content correctly!
> Tested-by: Ghennadi Procopciuc <ghennadi.procopciuc@oss.nxp.com>
> Reviewed-by: Ghennadi Procopciuc <ghennadi.procopciuc@oss.nxp.com>
>
> Starting kernel ...
>
> [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
> [ 0.000000] Linux version 6.9.0-rc1-00004-gcb630dd69df3
> (nxa06643@lxl00026) (aarch64-linux-gnu-gcc (Linaro GCC 7.5-2019.12)
> 7.5.0, GNU ld (Linaro_Binutils-2019.12) 2.28.2.20170706) #21 SMP PREEMPT
> Mon Mar 25 10:50:16 EET 2024
> [ 0.000000] KASLR disabled due to lack of seed
> [ 0.000000] Machine model: NXP S32G3 Reference Design Board 3
> (S32G-VNP-RDB3)
> [ 0.000000] efi: UEFI not found.
> [ 0.000000] OF: reserved mem: 0x00000000d0000000..0x00000000d000007f
> (0 KiB) nomap non-reusable shm@d0000000
> [ 0.000000] OF: reserved mem: 0x00000000ff600000..0x00000000ff7fffff
> (2048 KiB) nomap non-reusable atf@ff600000
> [ 0.000000] earlycon: linflex0 at MMIO 0x00000000401c8000 (options
> '115200n8')
> [ 0.000000] printk: legacy bootconsole [linflex0] enabled
> [ 0.000000] NUMA: No NUMA configuration found
> [ 0.000000] NUMA: Faking a node at [mem
> 0x0000000080000000-0x00000008dfffffff]
> [ 0.000000] NUMA: NODE_DATA [mem 0x8df8ff9c0-0x8df901fff]
> [ 0.000000] Zone ranges:
> [ 0.000000] DMA [mem 0x0000000080000000-0x00000000ffffffff]
> [ 0.000000] DMA32 empty
> [ 0.000000] Normal [mem 0x0000000100000000-0x00000008dfffffff]
> [ 0.000000] Movable zone start for each node
> [ 0.000000] Early memory node ranges
> [ 0.000000] node 0: [mem 0x0000000080000000-0x00000000cfffffff]
> [ 0.000000] node 0: [mem 0x00000000d0001000-0x00000000ff5fffff]
> [ 0.000000] node 0: [mem 0x00000000ff600000-0x00000000ff7fffff]
> [ 0.000000] node 0: [mem 0x00000000ff800000-0x00000000ffffffff]
> [ 0.000000] node 0: [mem 0x0000000880000000-0x00000008dfffffff]
> [ 0.000000] Initmem setup node 0 [mem
> 0x0000000080000000-0x00000008dfffffff]
> [ 0.000000] On node 0, zone DMA: 1 pages in unavailable ranges
> [ 0.000000] cma: Reserved 32 MiB at 0x00000000fd600000 on node -1
> [ 0.000000] psci: probing for conduit method from DT.
> [ 0.000000] psci: PSCIv1.1 detected in firmware.
> [ 0.000000] psci: Using standard PSCI v0.2 function IDs
> [ 0.000000] psci: MIGRATE_INFO_TYPE not supported.
> [ 0.000000] psci: SMC Calling Convention v1.2
> [ 0.000000] percpu: Embedded 24 pages/cpu s57896 r8192 d32216 u98304
> [ 0.000000] Detected VIPT I-cache on CPU0
> [ 0.000000] CPU features: detected: GIC system register CPU interface
> [ 0.000000] CPU features: detected: ARM erratum 845719
> [ 0.000000] alternatives: applying boot alternatives
> [ 0.000000] Kernel command line: console=ttyLF0,115200
> root=/dev/mmcblk0p2 rootwait rw earlycon
> [ 0.000000] Dentry cache hash table entries: 524288 (order: 10,
> 4194304 bytes, linear)
> [ 0.000000] Inode-cache hash table entries: 262144 (order: 9, 2097152
> bytes, linear)
> [ 0.000000] Fallback order for Node 0: 0
> [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 903167
> [ 0.000000] Policy zone: Normal
> [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
> [ 0.000000] software IO TLB: area num 8.
> [ 0.000000] software IO TLB: mapped [mem
> 0x00000000f9600000-0x00000000fd600000] (64MB)
> [ 0.000000] Memory: 3451804K/3670012K available (17472K kernel code,
> 4790K rwdata, 11432K rodata, 9984K init, 754K bss, 185440K reserved,
> 32768K cma-reserved)
> [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=1
> [ 0.000000] rcu: Preemptible hierarchical RCU implementation.
> [ 0.000000] rcu: RCU event tracing is enabled.
> [ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=512 to
> nr_cpu_ids=8.
> [ 0.000000] Trampoline variant of Tasks RCU enabled.
> [ 0.000000] Tracing variant of Tasks RCU enabled.
> [ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay
> is 25 jiffies.
> [ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=8
> [ 0.000000] RCU Tasks: Setting shift to 3 and lim to 1
> rcu_task_cb_adjust=1.
> [ 0.000000] RCU Tasks Trace: Setting shift to 3 and lim to 1
> rcu_task_cb_adjust=1.
> [ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
> [ 0.000000] GICv3: 544 SPIs implemented
> [ 0.000000] GICv3: 0 Extended SPIs implemented
> [ 0.000000] Root IRQ handler: gic_handle_irq
> [ 0.000000] GICv3: GICv3 features: 16 PPIs
> [ 0.000000] GICv3: CPU0: found redistributor 0 region
> 0:0x0000000050900000
> [ 0.000000] ITS: No ITS available, not enabling LPIs
> [ 0.000000] rcu: srcu_init: Setting srcu_struct sizes based on
> contention.
> [ 0.000000] arch_timer: cp15 timer(s) running at 5.00MHz (virt).
> [ 0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff
> max_cycles: 0x127350b88, max_idle_ns: 440795202120 ns
> [ 0.000001] sched_clock: 56 bits at 5MHz, resolution 200ns, wraps
> every 4398046511100ns
> [ 0.008224] Console: colour dummy device 80x25
> [ 0.012493] Calibrating delay loop (skipped), value calculated using
> timer frequency.. 10.00 BogoMIPS (lpj=20000)
> [ 0.022661] pid_max: default: 32768 minimum: 301
> [ 0.027333] LSM: initializing lsm=capability
> [ 0.031604] Mount-cache hash table entries: 8192 (order: 4, 65536
> bytes, linear)
> [ 0.038904] Mountpoint-cache hash table entries: 8192 (order: 4,
> 65536 bytes, linear)
> [ 0.047831] cacheinfo: Unable to detect cache hierarchy for CPU 0
> [ 0.054481] rcu: Hierarchical SRCU implementation.
> [ 0.058926] rcu: Max phase no-delay instances is 1000.
> [ 0.064746] EFI services will not be available.
> [ 0.069258] smp: Bringing up secondary CPUs ...
> [ 0.073964] Detected VIPT I-cache on CPU1
> [ 0.074018] GICv3: CPU1: found redistributor 1 region
> 0:0x0000000050920000
> [ 0.074056] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
> [ 0.074630] Detected VIPT I-cache on CPU2
> [ 0.074662] GICv3: CPU2: found redistributor 2 region
> 0:0x0000000050940000
> [ 0.074682] CPU2: Booted secondary processor 0x0000000002 [0x410fd034]
> [ 0.075227] Detected VIPT I-cache on CPU3
> [ 0.075258] GICv3: CPU3: found redistributor 3 region
> 0:0x0000000050960000
> [ 0.075277] CPU3: Booted secondary processor 0x0000000003 [0x410fd034]
> [ 0.075831] Detected VIPT I-cache on CPU4
> [ 0.075885] GICv3: CPU4: found redistributor 100 region
> 0:0x0000000050980000
> [ 0.075917] CPU4: Booted secondary processor 0x0000000100 [0x410fd034]
> [ 0.076492] Detected VIPT I-cache on CPU5
> [ 0.076527] GICv3: CPU5: found redistributor 101 region
> 0:0x00000000509a0000
> [ 0.076547] CPU5: Booted secondary processor 0x0000000101 [0x410fd034]
> [ 0.077090] Detected VIPT I-cache on CPU6
> [ 0.077127] GICv3: CPU6: found redistributor 102 region
> 0:0x00000000509c0000
> [ 0.077147] CPU6: Booted secondary processor 0x0000000102 [0x410fd034]
> [ 0.077724] Detected VIPT I-cache on CPU7
> [ 0.077765] GICv3: CPU7: found redistributor 103 region
> 0:0x00000000509e0000
> [ 0.077785] CPU7: Booted secondary processor 0x0000000103 [0x410fd034]
> [ 0.077896] smp: Brought up 1 node, 8 CPUs
> [ 0.203873] SMP: Total of 8 processors activated.
> [ 0.208551] CPU: All CPU(s) started at EL1
> [ 0.212660] CPU features: detected: 32-bit EL0 Support
> [ 0.217751] CPU features: detected: 32-bit EL1 Support
> [ 0.222885] CPU features: detected: CRC32 instructions
> [ 0.228042] alternatives: applying system-wide alternatives
> [ 0.236019] devtmpfs: initialized
> [ 0.242628] clocksource: jiffies: mask: 0xffffffff max_cycles:
> 0xffffffff, max_idle_ns: 7645041785100000 ns
> [ 0.252037] futex hash table entries: 2048 (order: 5, 131072 bytes,
> linear)
> [ 0.260021] pinctrl core: initialized pinctrl subsystem
> [ 0.266046] DMI not present or invalid.
> [ 0.272094] NET: Registered PF_NETLINK/PF_ROUTE protocol family
> [ 0.278654] DMA: preallocated 512 KiB GFP_KERNEL pool for atomic
> allocations
> [ 0.285546] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA pool for
> atomic allocations
> [ 0.293318] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA32 pool for
> atomic allocations
> [ 0.301019] audit: initializing netlink subsys (disabled)
> [ 0.306513] audit: type=2000 audit(0.180:1): state=initialized
> audit_enabled=0 res=1
> [ 0.307304] thermal_sys: Registered thermal governor 'step_wise'
> [ 0.314096] thermal_sys: Registered thermal governor 'power_allocator'
> [ 0.320130] cpuidle: using governor menu
> [ 0.330730] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
> [ 0.337396] ASID allocator initialised with 65536 entries
> [ 0.344482] Serial: AMBA PL011 UART driver
> [ 0.350914] Modules: 21600 pages in range for non-PLT usage
> [ 0.350920] Modules: 513120 pages in range for PLT usage
> [ 0.356758] HugeTLB: registered 1.00 GiB page size, pre-allocated 0 pages
> [ 0.368493] HugeTLB: 0 KiB vmemmap can be freed for a 1.00 GiB page
> [ 0.374744] HugeTLB: registered 32.0 MiB page size, pre-allocated 0 pages
> [ 0.381511] HugeTLB: 0 KiB vmemmap can be freed for a 32.0 MiB page
> [ 0.387762] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
> [ 0.394531] HugeTLB: 0 KiB vmemmap can be freed for a 2.00 MiB page
> [ 0.400784] HugeTLB: registered 64.0 KiB page size, pre-allocated 0 pages
> [ 0.407551] HugeTLB: 0 KiB vmemmap can be freed for a 64.0 KiB page
> [ 0.414206] Demotion targets for Node 0: null
> [ 0.419168] ACPI: Interpreter disabled.
> [ 0.423692] iommu: Default domain type: Translated
> [ 0.428153] iommu: DMA domain TLB invalidation policy: strict mode
> [ 0.434805] SCSI subsystem initialized
> [ 0.438513] usbcore: registered new interface driver usbfs
> [ 0.443706] usbcore: registered new interface driver hub
> [ 0.448995] usbcore: registered new device driver usb
> [ 0.454351] pps_core: LinuxPPS API ver. 1 registered
> [ 0.458968] pps_core: Software ver. 5.3.6 - Copyright 2005-2007
> Rodolfo Giometti <giometti@linux.it>
> [ 0.468095] PTP clock support registered
> [ 0.472054] EDAC MC: Ver: 3.0.0
> [ 0.475481] scmi_core: SCMI protocol bus registered
> [ 0.480546] FPGA manager framework
> [ 0.483666] Advanced Linux Sound Architecture Driver Initialized.
> [ 0.490590] vgaarb: loaded
> [ 0.493333] clocksource: Switched to clocksource arch_sys_counter
> [ 0.499297] VFS: Disk quotas dquot_6.6.0
> [ 0.503017] VFS: Dquot-cache hash table entries: 512 (order 0, 4096
> bytes)
> [ 0.510017] pnp: PnP ACPI: disabled
> [ 0.519430] NET: Registered PF_INET protocol family
> [ 0.524185] IP idents hash table entries: 65536 (order: 7, 524288
> bytes, linear)
> [ 0.533803] tcp_listen_portaddr_hash hash table entries: 2048 (order:
> 3, 32768 bytes, linear)
> [ 0.542061] Table-perturb hash table entries: 65536 (order: 6, 262144
> bytes, linear)
> [ 0.549719] TCP established hash table entries: 32768 (order: 6,
> 262144 bytes, linear)
> [ 0.557803] TCP bind hash table entries: 32768 (order: 8, 1048576
> bytes, linear)
> [ 0.566154] TCP: Hash tables configured (established 32768 bind 32768)
> [ 0.572472] UDP hash table entries: 2048 (order: 4, 65536 bytes, linear)
> [ 0.579091] UDP-Lite hash table entries: 2048 (order: 4, 65536 bytes,
> linear)
> [ 0.586323] NET: Registered PF_UNIX/PF_LOCAL protocol family
> [ 0.592198] RPC: Registered named UNIX socket transport module.
> [ 0.597778] RPC: Registered udp transport module.
> [ 0.602457] RPC: Registered tcp transport module.
> [ 0.607143] RPC: Registered tcp-with-tls transport module.
> [ 0.612612] RPC: Registered tcp NFSv4.1 backchannel transport module.
> [ 0.619048] PCI: CLS 0 bytes, default 64
> [ 0.623428] kvm [1]: HYP mode not available
> [ 0.628384] Initialise system trusted keyrings
> [ 0.632632] workingset: timestamp_bits=42 max_order=20 bucket_order=0
> [ 0.639182] squashfs: version 4.0 (2009/01/31) Phillip Lougher
> [ 0.644948] NFS: Registering the id_resolver key type
> [ 0.649780] Key type id_resolver registered
> [ 0.653921] Key type id_legacy registered
> [ 0.657932] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
> [ 0.664597] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver
> Registering...
> [ 0.672111] 9p: Installing v9fs 9p2000 file system support
> [ 0.714617] Key type asymmetric registered
> [ 0.718368] Asymmetric key parser 'x509' registered
> [ 0.723278] Block layer SCSI generic (bsg) driver version 0.4 loaded
> (major 245)
> [ 0.730608] io scheduler mq-deadline registered
> [ 0.735119] io scheduler kyber registered
> [ 0.739144] io scheduler bfq registered
> [ 0.764751] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
> [ 0.773400] 401c8000.serial: ttyLF0 at MMIO 0x401c8000 (irq = 14,
> base_baud = 0) is a FSL_LINFLEX
> [ 0.783976] printk: legacy console [ttyLF0] enabled
> [ 0.783976] printk: legacy console [ttyLF0] enabled
> [ 0.793930] printk: legacy bootconsole [linflex0] disabled
> [ 0.793930] printk: legacy bootconsole [linflex0] disabled
> [ 0.809777] 401cc000.serial: ttyLF1 at MMIO 0x401cc000 (irq = 15,
> base_baud = 0) is a FSL_LINFLEX
> [ 0.819329] msm_serial: driver initialized
> [ 0.823695] SuperH (H)SCI(F) driver initialized
> [ 0.828378] STM32 USART driver initialized
> [ 0.840105] loop: module loaded
> [ 0.844169] megasas: 07.727.03.00-rc1
> [ 0.852986] tun: Universal TUN/TAP device driver, 1.6
> [ 0.858691] thunder_xcv, ver 1.0
> [ 0.862013] thunder_bgx, ver 1.0
> [ 0.865323] nicpf, ver 1.0
> [ 0.868818] hns3: Hisilicon Ethernet Network Driver for Hip08 Family
> - version
> [ 0.876179] hns3: Copyright (c) 2017 Huawei Corporation.
> [ 0.881621] hclge is initializing
> [ 0.885029] e1000: Intel(R) PRO/1000 Network Driver
> [ 0.889999] e1000: Copyright (c) 1999-2006 Intel Corporation.
> [ 0.895874] e1000e: Intel(R) PRO/1000 Network Driver
> [ 0.900932] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
> [ 0.906982] igb: Intel(R) Gigabit Ethernet Network Driver
> [ 0.912483] igb: Copyright (c) 2007-2014 Intel Corporation.
> [ 0.918195] igbvf: Intel(R) Gigabit Virtual Function Network Driver
> [ 0.924581] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
> [ 0.930796] sky2: driver version 1.30
> [ 0.935382] VFIO - User Level meta-driver version: 0.3
> [ 0.942227] usbcore: registered new interface driver usb-storage
> [ 0.950179] i2c_dev: i2c /dev entries driver
> [ 0.959203] sdhci: Secure Digital Host Controller Interface driver
> [ 0.965503] sdhci: Copyright(c) Pierre Ossman
> [ 0.970334] Synopsys Designware Multimedia Card Interface Driver
> [ 0.976987] sdhci-pltfm: SDHCI platform and OF driver helper
> [ 0.983975] ledtrig-cpu: registered to indicate activity on CPUs
> [ 0.990556] scmi_protocol scmi_dev.1: Enabled polling mode TX channel
> - prot_id:16
> [ 0.998513] arm-scmi firmware:scmi: SCMI Notifications - Core Enabled.
> [ 1.005209] arm-scmi firmware:scmi: SCMI Protocol v2.0 'NXP:S32G399A'
> Firmware version 0x0
> [ 1.014897] cpu cpu0: EM: only supports uW power values
> [ 1.025027] SMCCC: SOC_ID: ARCH_SOC_ID not implemented, skipping ....
> [ 1.032401] usbcore: registered new interface driver usbhid
> [ 1.038094] usbhid: USB HID core driver
> [ 1.044180] hw perfevents: enabled with armv8_cortex_a53 PMU driver,
> 7 counters available
> [ 1.056194] NET: Registered PF_PACKET protocol family
> [ 1.061445] 9pnet: Installing 9P2000 support
> [ 1.065867] Key type dns_resolver registered
> [ 1.079732] Timer migration: 1 hierarchy levels; 8 children per
> group; 1 crossnode level
> [ 1.088206] registered taskstats version 1
> [ 1.092820] Loading compiled-in X.509 certificates
> [ 1.115627] clk: Disabling unused clocks
> [ 1.117662] sdhci-esdhc-imx 402f0000.mmc: could not get pinctrl
> [ 1.119704] PM: genpd: Disabling unused power domains
> [ 1.130853] ALSA device list:
> [ 1.133886] No soundcards found.
> [ 1.157133] mmc0: SDHCI controller on 402f0000.mmc [402f0000.mmc]
> using ADMA
> [ 1.164512] Waiting for root device /dev/mmcblk0p2...
> [ 1.185787] mmc0: host does not support reading read-only switch,
> assuming write-enable
> [ 1.195000] mmc0: new high speed SDHC card at address 5048
> [ 1.201102] mmcblk0: mmc0:5048 SD32G 29.7 GiB
> [ 1.208397] mmcblk0: p1 p2
> [ 1.238459] EXT4-fs (mmcblk0p2): recovery complete
> [ 1.244613] EXT4-fs (mmcblk0p2): mounted filesystem
> 52830f5f-ab50-4125-a606-3c65100b7d4a r/w with ordered data mode. Quota
> mode: none.
> [ 1.257000] VFS: Mounted root (ext4 filesystem) on device 179:2.
> [ 1.264390] devtmpfs: mounted
> [ 1.271069] Freeing unused kernel memory: 9984K
> [ 1.275760] Run /sbin/init as init process
> [ 1.657291] systemd[1]: System time before build time, advancing clock.
> [ 1.714423] systemd[1]: systemd 250.5+ running in system mode (+PAM
> -AUDIT -SELINUX -APPARMOR +IMA -SMACK +SECCOMP -GCRYPT -GNUTLS -OPENSSL
> +ACL +BLKID -CURL -ELFUTILS -FIDO2 -IDN2 -IDN -IPTC +KMOD -LIBCRYPTSETUP
> +LIBFDISK -PCRE2 -PWQUALITY -P11KIT -QRENCODE -BZIP2 -LZ4 -XZ -ZLIB
> +ZSTD -BPF_FRAMEWORK +XKBCOMMON +UTMP +SYSVINIT default-hierarchy=hybrid)
> [ 1.746891] systemd[1]: Detected architecture arm64.
>
> Welcome to Auto Linux BSP develop (kirkstone)!
>
> [ 1.845928] systemd[1]: Hostname set to <s32g399ardb3>.
> [ 2.186158] systemd[1]: Binding to IPv6 address not available since
> kernel does not support IPv6.
> [ 2.195287] systemd[1]: Binding to IPv6 address not available since
> kernel does not support IPv6.
> [ 2.317364] systemd[1]: Queued start job for default target
> Multi-User System.
> [ 2.396694] systemd[1]: Created slice Slice /system/getty.
> [ OK ] Created slice Slice /system/getty.
> [ 2.410476] systemd[1]: Created slice Slice /system/modprobe.
> [ OK ] Created slice Slice /system/modprobe.
> [ 2.424209] systemd[1]: Created slice Slice /system/serial-getty.
> [ OK ] Created slice Slice /system/serial-getty.
> [ 2.438389] systemd[1]: Created slice User and Session Slice.
> [ OK ] Created slice User and Session Slice.
> [ 2.450954] systemd[1]: Started Dispatch Password Requests to Console
> Directory Watch.
> [ OK ] Started Dispatch Password …ts to Console Directory Watch.
> [ 2.467638] systemd[1]: Started Forward Password Requests to Wall
> Directory Watch.
> [ OK ] Started Forward Password R…uests to Wall Directory Watch.
> [ 2.484011] systemd[1]: Reached target Path Units.
> [ OK ] Reached target Path Units.
> [ 2.494464] systemd[1]: Reached target Remote File Systems.
> [ OK ] Reached target Remote File Systems.
> [ 2.506485] systemd[1]: Reached target Slice Units.
> [ OK ] Reached target Slice Units.
> [ 2.517119] systemd[1]: Reached target Swaps.
> [ OK ] Reached target Swaps.
> [ 2.586411] systemd[1]: Listening on RPCbind Server Activation Socket.
> [ OK ] Listening on RPCbind Server Activation Socket.
> [ 2.600701] systemd[1]: Reached target RPC Port Mapper.
> [ OK ] Reached target RPC Port Mapper.
> [ 2.612616] systemd[1]: Listening on Syslog Socket.
> [ OK ] Listening on Syslog Socket.
> [ 2.623452] systemd[1]: Listening on initctl Compatibility Named Pipe.
> [ OK ] Listening on initctl Compatibility Named Pipe.
> [ 2.637954] systemd[1]: Listening on Journal Audit Socket.
> [ OK ] Listening on Journal Audit Socket.
> [ 2.650037] systemd[1]: Listening on Journal Socket (/dev/log).
> [ OK ] Listening on Journal Socket (/dev/log).
> [ 2.663102] systemd[1]: Listening on Journal Socket.
> [ OK ] Listening on Journal Socket.
> [ 2.674363] systemd[1]: Listening on Network Service Netlink Socket.
> [ OK ] Listening on Network Service Netlink Socket.
> [ 2.688327] systemd[1]: Listening on udev Control Socket.
> [ OK ] Listening on udev Control Socket.
> [ 2.700193] systemd[1]: Listening on udev Kernel Socket.
> [ OK ] Listening on udev Kernel Socket.
> [ 2.711963] systemd[1]: Listening on User Database Manager Socket.
> [ OK ] Listening on User Database Manager Socket.
> [ 2.749696] systemd[1]: Mounting Huge Pages File System...
> Mounting Huge Pages File System...
> [ 2.764346] systemd[1]: Mounting POSIX Message Queue File System...
> Mounting POSIX Message Queue File System...
> [ 2.780591] systemd[1]: Mounting Kernel Debug File System...
> Mounting Kernel Debug File System...
> [ 2.792560] systemd[1]: Kernel Trace File System was skipped because
> of a failed condition check (ConditionPathExists=/sys/kernel/tracing).
> [ 2.805768] systemd[1]: Create List of Static Device Nodes was
> skipped because of a failed condition check
> (ConditionFileNotEmpty=/lib/modules/6.9.0-rc1-00004-gcb630dd69df3/modules.devname).
> [ 2.826957] systemd[1]: Starting Load Kernel Module configfs...
> Starting Load Kernel Module configfs...
> [ 2.842860] systemd[1]: Starting Load Kernel Module drm...
> Starting Load Kernel Module drm...
> [ 2.857874] systemd[1]: Starting Load Kernel Module fuse...
> Starting Load Kernel Module fuse...
> [ 2.879679] systemd[1]: Starting RPC Bind...
> Starting RPC Bind...
> [ 2.888514] systemd[1]: File System Check on Root Device was skipped
> because of a failed condition check (ConditionPathIsReadWrite=!/).
> [ 2.907067] systemd[1]: Starting Journal Service...
> Starting Journal Service...
> [ 2.925119] systemd[1]: Starting Load Kernel Modules...
> Starting Load Kernel Modules...
> [ 2.940298] systemd[1]: Starting Generate network units from Kernel
> command line...
> Starting Generate network …ts from Kernel command line...
> [ 2.959955] systemd[1]: Starting Remount Root and Kernel File Systems...
> Starting Remount Root and Kernel File Systems...
> [ 2.977958] systemd[1]: Starting Coldplug All udev Devices...
> Starting Coldplug All udev Devices...
> [ 2.995944] systemd[1]: Started RPC Bind.
> [ OK ] Started RPC Bind.
> [ 3.005902] systemd[1]: Mounted Huge Pages File System.
> [ OK ] Mounted Huge Pages File System.
> [ 3.018033] systemd[1]: Mounted POSIX Message Queue File System.
> [ OK ] Mounted POSIX Message Queue File System.[ 3.029658] EXT4-fs
> (mmcblk0p2): re-mounted 52830f5f-ab50-4125-a606-3c65100b7d4a r/w. Quota
> mode: none.
>
> [ 3.043175] systemd[1]: Started Journal Service.
> [ OK ] Started Journal Service.
> [ OK ] Mounted Kernel Debug File System.
> [ OK ] Finished Load Kernel Module configfs.
> [ OK ] Finished Load Kernel Module drm.
> [ OK ] Finished Load Kernel Module fuse.
> [FAILED] Failed to start Load Kernel Modules.
> See 'systemctl status systemd-modules-load.service' for details.
> [ OK ] Finished Generate network units from Kernel command line.
> [ OK ] Finished Remount Root and Kernel File Systems.
> Mounting Kernel Configuration File System...
> Starting Flush Journal to Persistent Storage...
> Starting Apply Kernel Variables...
> Starting Create Static Device Nodes in /dev...[ 3.206617]
> systemd-journald[124]: Received client request to flush runtime journal.
>
> [ OK ] Mounted Kernel Configuration File System.
> [ OK ] Finished Flush Journal to Persistent Storage.
> [ OK ] Finished Apply Kernel Variables.
> [ OK ] Finished Create Static Device Nodes in /dev.
> [ OK ] Reached target Preparation for Local File Systems.
> Mounting /tmp...
> Mounting /var/volatile...
> [ 3.338366] audit: type=1334 audit(1651167746.684:2): prog-id=5 op=LOAD
> [ 3.345166] audit: type=1334 audit(1651167746.688:3): prog-id=6 op=LOAD
> Starting Rule-based Manage…for Device Events and Files...
> [ OK ] Mounted /tmp.
> [ OK ] Mounted /var/volatile.
> Mounting /var/volatile/tmp...
> Starting Load/Save Random Seed...
> [ OK ] Mounted /var/volatile/tmp.
> [ OK ] Reached target Local File Systems.
> Starting Create Volatile Files and Directories...
> [ OK ] Finished Create Volatile Files and Directories.
> Starting Network Time Synchronization...
> Starting Record System Boot/Shutdown in UTMP...
> [ OK ] Started Rule-based Manager for Device Events and Files.
> [ OK ] Finished Coldplug All udev Devices.
> [ OK ] Finished Record System Boot/Shutdown in UTMP.
> [ OK ] Started Network Time Synchronization.
> [ OK ] Reached target System Initialization.
> [ OK ] Started Daily Cleanup of Temporary Directories.
> [ OK ] Reached target System Time Set.
> [ OK ] Started Daily rotation of log files.
> [ OK ] Reached target Timer Units.
> [ OK ] Listening on D-Bus System Message Bus Socket.
> Starting sshd.socket...
> [ OK ] Listening on sshd.socket.
> [ OK ] Reached target Socket Units.
> [ OK ] Reached target Basic System.
> [ OK ] Started Job spooling tools.
> [ OK ] Started Periodic Command Scheduler.
> Starting D-Bus System Message Bus...
> Starting IPv6 Packet Filtering Framework...
> Starting IPv4 Packet Filtering Framework...
> [ OK ] Started irqbalance daemon.
> [ OK ] Started Hardware RNG Entropy Gatherer Daemon.
> [ OK ] Started System Logging Service.
> Starting Resets System Activity Logs...
> [ 4.124453] audit: type=1334 audit(1651254541.860:4): prog-id=7 op=LOAD
> [ 4.131266] audit: type=1334 audit(1651254541.868:5): prog-id=8 op=LOAD
> Starting User Login Management...
> Starting OpenSSH Key Generation...
> [ OK ] Finished IPv6 Packet Filtering Framework.
> [ OK ] Finished IPv4 Packet Filtering Framework.
> [ OK ] Reached target Preparation for Network.
> Starting Network Configuration...
> [ OK ] Finished Resets System Activity Logs.
> [ OK ] Finished OpenSSH Key Generation.
> [ OK ] Started Network Configuration.
> Starting Network Name Resolution...
> [ OK ] Started Network Name Resolution.
> [ OK ] Reached target Network.
> [ OK ] Reached target Host and Network Name Lookups.
> [ OK ] Started Netperf Benchmark Server.
> [ OK ] Started NFS status monitor for NFSv2/3 locking..
> [ OK ] Started Respond to IPv6 Node Information Queries.
> [ OK ] Started Network Router Discovery Daemon.
> Starting Permit User Sessions...
> [ OK ] Started Xinetd A Powerful Replacement For Inetd.
> [ OK ] Finished Permit User Sessions.
> [ OK ] Started Getty on tty1.
> [ OK ] Started Serial Getty on ttyLF0.
> [ OK ] Reached target Login Prompts.
> [ OK ] Created slice Slice /system/systemd-fsck.
> [ OK ] Found device /dev/mmcblk0p1.
> Starting File System Check on /dev/mmcblk0p1...
> [ OK ] Finished File System Check on /dev/mmcblk0p1.
> Mounting /run/media/boot_s32g3-mmcblk0p1...
> [ OK ] Mounted /run/media/boot_s32g3-mmcblk0p1.
> [ OK ] Finished Load/Save Random Seed.
> [ OK ] Started D-Bus System Message Bus.
> [ OK ] Started User Login Management.
> [ OK ] Reached target Multi-User System.
> Starting Record Runlevel Change in UTMP...
> [ OK ] Finished Record Runlevel Change in UTMP.
>
>
> Regards,
> Ghennadi
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 3/4] dt-bindings: mmc: fsl-imx-esdhc: add NXP S32G3 support
From: Ulf Hansson @ 2024-03-25 13:19 UTC (permalink / raw)
To: Wadim Mueller
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
NXP Linux Team, Greg Kroah-Hartman, Jiri Slaby, Chester Lin,
Andreas Färber, Matthias Brugger, NXP S32 Linux Team,
Tim Harvey, Alexander Stein, Gregor Herburger, Marek Vasut,
Marco Felsch, Hugo Villeneuve, Markus Niebel, Matthias Schiffer,
Stefan Wahren, Bjorn Helgaas, Yannic Moog, Li Yang, devicetree,
linux-kernel, linux-mmc, linux-arm-kernel, linux-serial
In-Reply-To: <20240324214329.29988-4-wafgo01@gmail.com>
On Sun, 24 Mar 2024 at 22:44, Wadim Mueller <wafgo01@gmail.com> wrote:
>
> Add a compatible string for the SDHC binding of NXP S32G3 platforms. Here
> we use "nxp,s32g2-usdhc" as fallback since the s32g2-usdhc
> driver works also on S32G3 platforms.
>
> Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
Applied for next, thanks!
Kind regards
Uffe
> ---
> Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
> index 82eb7a24c857..466e7157308a 100644
> --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
> +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
> @@ -90,6 +90,9 @@ properties:
> - enum:
> - fsl,imxrt1170-usdhc
> - const: fsl,imxrt1050-usdhc
> + - items:
> + - const: nxp,s32g3-usdhc
> + - const: nxp,s32g2-usdhc
>
> reg:
> maxItems: 1
> --
> 2.25.1
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v1 1/1] mmc: mtk-sd: Remove unused of_gpio.h
From: Ulf Hansson @ 2024-03-25 13:18 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Axe Yang, linux-mmc, linux-kernel, linux-arm-kernel,
linux-mediatek, Chaotian Jing, Matthias Brugger,
AngeloGioacchino Del Regno
In-Reply-To: <20240307114348.3643034-1-andriy.shevchenko@linux.intel.com>
On Thu, 7 Mar 2024 at 12:43, Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> of_gpio.h is deprecated and subject to remove.
> The driver doesn't use it, simply remove the unused header.
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Applied for next, thanks!
Kind regards
Uffe
> ---
> drivers/mmc/host/mtk-sd.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index 1634b1f5d201..a94835b8ab93 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -13,7 +13,6 @@
> #include <linux/ioport.h>
> #include <linux/irq.h>
> #include <linux/of.h>
> -#include <linux/of_gpio.h>
> #include <linux/pinctrl/consumer.h>
> #include <linux/platform_device.h>
> #include <linux/pm.h>
> --
> 2.43.0.rc1.1.gbec44491f096
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] iommu/arm-smmu-v3: Fix access for STE.SHCFG
From: Jason Gunthorpe @ 2024-03-25 13:18 UTC (permalink / raw)
To: Mostafa Saleh
Cc: will, robin.murphy, linux-arm-kernel, iommu, linux-kernel, joro,
nicolinc, mshavit
In-Reply-To: <20240323134658.464743-1-smostafa@google.com>
On Sat, Mar 23, 2024 at 01:46:58PM +0000, Mostafa Saleh wrote:
> STE attributes(NSCFG, PRIVCFG, INSTCFG) use value 0 for "Use Icomming",
> for some reason SHCFG doesn't follow that, and it is defined as "0b01".
>
> Currently the driver sets SHCFG to Use Incoming for stage-2 and bypass
> domains.
>
> However according to the User Manual (ARM IHI 0070 F.b):
> When SMMU_IDR1.ATTR_TYPES_OVR == 0, this field is RES0 and the
> incoming Shareability attribute is used.
>
> This patch adds a condition for writing SHCFG to Use incoming to be
> compliant with the architecture, and defines ATTR_TYPE_OVR as a new
> feature discovered from IDR1.
> This also required to propagate the SMMU through some functions args.
>
> There is no need to add similar condition for the newly introduced function
> arm_smmu_get_ste_used() as the values of the STE are the same before and
> after any transition, so this will not trigger any change. (we already
> do the same for the VMID).
>
> Although this is a misconfiguration from the driver, this has been there
> for a long time, so probably no HW running Linux is affected by it.
>
> Reported-by: Will Deacon <will@kernel.org>
> Closes: https://lore.kernel.org/all/20240215134952.GA690@willie-the-truck/
> Signed-off-by: Mostafa Saleh <smostafa@google.com>
> ---
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 35 ++++++++++++++-------
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 2 ++
> 2 files changed, 25 insertions(+), 12 deletions(-)
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Thanks,
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v6 16/16] PCI/pwrctl: add a PCI power control driver for power sequenced devices
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Add a PCI power control driver that's capable of correctly powering up
devices using the power sequencing subsystem. The first user of this
driver is the ath11k module on QCA6390.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/pci/pwrctl/Kconfig | 9 +++
drivers/pci/pwrctl/Makefile | 2 +
drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 89 ++++++++++++++++++++++++++
3 files changed, 100 insertions(+)
create mode 100644 drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
diff --git a/drivers/pci/pwrctl/Kconfig b/drivers/pci/pwrctl/Kconfig
index 96195395af69..eb126225eb9f 100644
--- a/drivers/pci/pwrctl/Kconfig
+++ b/drivers/pci/pwrctl/Kconfig
@@ -5,4 +5,13 @@ menu "PCI Power control drivers"
config PCI_PWRCTL
tristate
+config PCI_PWRCTL_PWRSEQ
+ tristate "PCI Power Control driver using the Power Sequencing subsystem"
+ select POWER_SEQUENCING
+ select PCI_PWRCTL
+ default m if (ATH11K_PCI && ARCH_QCOM)
+ help
+ Enable support for the PCI power control driver for device
+ drivers using the Power Sequencing subsystem.
+
endmenu
diff --git a/drivers/pci/pwrctl/Makefile b/drivers/pci/pwrctl/Makefile
index 52ae0640ef7b..d308aae4800c 100644
--- a/drivers/pci/pwrctl/Makefile
+++ b/drivers/pci/pwrctl/Makefile
@@ -2,3 +2,5 @@
obj-$(CONFIG_PCI_PWRCTL) += pci-pwrctl-core.o
pci-pwrctl-core-y := core.o
+
+obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctl-pwrseq.o
diff --git a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
new file mode 100644
index 000000000000..c7a113a76c0c
--- /dev/null
+++ b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pci-pwrctl.h>
+#include <linux/platform_device.h>
+#include <linux/pwrseq/consumer.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+struct pci_pwrctl_pwrseq_data {
+ struct pci_pwrctl ctx;
+ struct pwrseq_desc *pwrseq;
+};
+
+static void devm_pci_pwrctl_pwrseq_power_off(void *data)
+{
+ struct pwrseq_desc *pwrseq = data;
+
+ pwrseq_power_off(pwrseq);
+}
+
+static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev)
+{
+ struct pci_pwrctl_pwrseq_data *data;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->pwrseq = devm_pwrseq_get(dev, of_device_get_match_data(dev));
+ if (IS_ERR(data->pwrseq))
+ return dev_err_probe(dev, PTR_ERR(data->pwrseq),
+ "Failed to get the power sequencer\n");
+
+ ret = pwrseq_power_on(data->pwrseq);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to power-on the device\n");
+
+ ret = devm_add_action_or_reset(dev, devm_pci_pwrctl_pwrseq_power_off,
+ data->pwrseq);
+ if (ret)
+ return ret;
+
+ data->ctx.dev = dev;
+
+ ret = devm_pci_pwrctl_device_set_ready(dev, &data->ctx);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register the pwrctl wrapper\n");
+
+ return 0;
+}
+
+static const struct of_device_id pci_pwrctl_pwrseq_of_match[] = {
+ {
+ /* ATH11K in QCA6390 package. */
+ .compatible = "pci17cb,1101",
+ .data = "wlan",
+ },
+ {
+ /* ATH12K in WCN7850 package. */
+ .compatible = "pci17cb,1107",
+ .data = "wlan",
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pci_pwrctl_pwrseq_of_match);
+
+static struct platform_driver pci_pwrctl_pwrseq_driver = {
+ .driver = {
+ .name = "pci-pwrctl-pwrseq",
+ .of_match_table = pci_pwrctl_pwrseq_of_match,
+ },
+ .probe = pci_pwrctl_pwrseq_probe,
+};
+module_platform_driver(pci_pwrctl_pwrseq_driver);
+
+MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
+MODULE_DESCRIPTION("Generic PCI Power Control module for power sequenced devices");
+MODULE_LICENSE("GPL");
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v6 13/16] power: sequencing: implement the pwrseq core
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Implement the power sequencing subsystem allowing devices to share
complex powering-up and down procedures. It's split into the consumer
and provider parts but does not implement any new DT bindings so that
the actual power sequencing is never revealed in the DT representation.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
MAINTAINERS | 8 +
drivers/power/Kconfig | 1 +
drivers/power/Makefile | 1 +
drivers/power/sequencing/Kconfig | 12 +
drivers/power/sequencing/Makefile | 4 +
drivers/power/sequencing/core.c | 1065 +++++++++++++++++++++++++++++
include/linux/pwrseq/consumer.h | 56 ++
include/linux/pwrseq/provider.h | 75 ++
8 files changed, 1222 insertions(+)
create mode 100644 drivers/power/sequencing/Kconfig
create mode 100644 drivers/power/sequencing/Makefile
create mode 100644 drivers/power/sequencing/core.c
create mode 100644 include/linux/pwrseq/consumer.h
create mode 100644 include/linux/pwrseq/provider.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 51d5a64a5a36..37039fa1b721 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17631,6 +17631,14 @@ F: include/linux/pm_*
F: include/linux/powercap.h
F: kernel/configs/nopm.config
+POWER SEQUENCING
+M: Bartosz Golaszewski <brgl@bgdev.pl>
+L: linux-pm@vger.kernel.org
+S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git
+F: drivers/power/sequencing/
+F: include/linux/pwrseq/
+
POWER STATE COORDINATION INTERFACE (PSCI)
M: Mark Rutland <mark.rutland@arm.com>
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 696bf77a7042..9a8e44ca9ae4 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
source "drivers/power/reset/Kconfig"
+source "drivers/power/sequencing/Kconfig"
source "drivers/power/supply/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index effbf0377f32..962a2cd30a51 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_POWER_RESET) += reset/
+obj-$(CONFIG_POWER_SEQUENCING) += sequencing/
obj-$(CONFIG_POWER_SUPPLY) += supply/
diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
new file mode 100644
index 000000000000..ba5732b1dbf8
--- /dev/null
+++ b/drivers/power/sequencing/Kconfig
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+menuconfig POWER_SEQUENCING
+ tristate "Power Sequencing support"
+ help
+ Say Y here to enable the Power Sequencing subsystem.
+
+ This subsystem is designed to control power to devices that share
+ complex resources and/or require specific power sequences to be run
+ during power-up.
+
+ If unsure, say no.
diff --git a/drivers/power/sequencing/Makefile b/drivers/power/sequencing/Makefile
new file mode 100644
index 000000000000..dcdf8c0c159e
--- /dev/null
+++ b/drivers/power/sequencing/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_POWER_SEQUENCING) += pwrseq-core.o
+pwrseq-core-y := core.o
diff --git a/drivers/power/sequencing/core.c b/drivers/power/sequencing/core.c
new file mode 100644
index 000000000000..f5f3dc9d2407
--- /dev/null
+++ b/drivers/power/sequencing/core.c
@@ -0,0 +1,1065 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <linux/bug.h>
+#include <linux/cleanup.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/idr.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/property.h>
+#include <linux/pwrseq/consumer.h>
+#include <linux/pwrseq/provider.h>
+#include <linux/radix-tree.h>
+#include <linux/rwsem.h>
+#include <linux/slab.h>
+
+/*
+ * Power-sequencing framework for linux.
+ *
+ * This subsystem allows power sequence providers to register a set of targets
+ * that consumers may request and power-up/down.
+ *
+ * Glossary:
+ *
+ * Unit - a unit is a discreet chunk of a power sequence. For instance one unit
+ * may enable a set of regulators, another may enable a specific GPIO. Units
+ * can define dependencies in the form of other units that must be enabled
+ * before it itself can be.
+ *
+ * Target - a target is a set of units (composed of the "final" unit and its
+ * dependencies) that a consumer selects by its name when requesting a handle
+ * to the power sequencer. Via the dependency system, multiple targets may
+ * share the same parts of a power sequence but ignore parts that are
+ * irrelevant.
+ *
+ * Descriptor - a handle passed by the pwrseq core to every consumer that
+ * serves as the entry point to the provider layer. It ensures coherence
+ * between different users and keeps reference counting consistent.
+ *
+ * Each provider must define a .match() callback whose role is to determine
+ * whether a potential consumer is in fact associated with this sequencer.
+ * This allows creating abstraction layers on top of regular device-tree
+ * resources like regulators, clocks and other nodes connected to the consumer
+ * via phandle.
+ */
+
+static DEFINE_IDA(pwrseq_ida);
+
+/*
+ * Protects the device list on the pwrseq bus from concurrent modifications
+ * but allows simultaneous read-only access.
+ */
+static DECLARE_RWSEM(pwrseq_sem);
+
+/**
+ * struct pwrseq_unit - Private power-sequence unit data.
+ * @ref: Reference count for this object. When it goes to 0, the object is
+ * destroyed.
+ * @name: Name of this target.
+ * @list: Link to siblings on the list of all units of a single sequencer.
+ * @deps: List of units on which this unit depends.
+ * @enable: Callback running the part of the power-on sequence provided by
+ * this unit.
+ * @disable: Callback running the part of the power-off sequence provided
+ * by this unit.
+ * @enable_count: Current number of users that enabled this unit. May be the
+ * consumer of the power sequencer or other units that depend
+ * on this one.
+ */
+struct pwrseq_unit {
+ struct kref ref;
+ const char *name;
+ struct list_head list;
+ struct list_head deps;
+ pwrseq_power_state_func enable;
+ pwrseq_power_state_func disable;
+ unsigned int enable_count;
+};
+
+static struct pwrseq_unit *pwrseq_unit_new(const struct pwrseq_unit_data *data)
+{
+ struct pwrseq_unit *unit;
+
+ unit = kzalloc(sizeof(*unit), GFP_KERNEL);
+ if (!unit)
+ return NULL;
+
+ unit->name = kstrdup_const(data->name, GFP_KERNEL);
+ if (!unit->name) {
+ kfree(unit);
+ return NULL;
+ }
+
+ kref_init(&unit->ref);
+ INIT_LIST_HEAD(&unit->deps);
+ unit->enable = data->enable;
+ unit->disable = data->disable;
+
+ return unit;
+}
+
+static struct pwrseq_unit *pwrseq_unit_incref(struct pwrseq_unit *unit)
+{
+ kref_get(&unit->ref);
+
+ return unit;
+}
+
+static void pwrseq_unit_release(struct kref *ref);
+
+static void pwrseq_unit_decref(struct pwrseq_unit *unit)
+{
+ kref_put(&unit->ref, pwrseq_unit_release);
+}
+
+/**
+ * struct pwrseq_unit_dep - Wrapper around a reference to the unit structure
+ * allowing to keep it on multiple dependency lists
+ * in different units.
+ * @list: Siblings on the list.
+ * @unit: Address of the referenced unit.
+ */
+struct pwrseq_unit_dep {
+ struct list_head list;
+ struct pwrseq_unit *unit;
+};
+
+static struct pwrseq_unit_dep *pwrseq_unit_dep_new(struct pwrseq_unit *unit)
+{
+ struct pwrseq_unit_dep *dep;
+
+ dep = kzalloc(sizeof(*dep), GFP_KERNEL);
+ if (!dep)
+ return NULL;
+
+ dep->unit = unit;
+
+ return dep;
+}
+
+static void pwrseq_unit_dep_free(struct pwrseq_unit_dep *ref)
+{
+ pwrseq_unit_decref(ref->unit);
+ kfree(ref);
+}
+
+static void pwrseq_unit_free_deps(struct list_head *list)
+{
+ struct pwrseq_unit_dep *dep, *next;
+
+ list_for_each_entry_safe(dep, next, list, list) {
+ list_del(&dep->list);
+ pwrseq_unit_dep_free(dep);
+ }
+}
+
+static void pwrseq_unit_release(struct kref *ref)
+{
+ struct pwrseq_unit *unit = container_of(ref, struct pwrseq_unit, ref);
+
+ pwrseq_unit_free_deps(&unit->deps);
+ list_del(&unit->list);
+ kfree_const(unit->name);
+ kfree(unit);
+}
+
+/**
+ * struct pwrseq_target - Private power-sequence target data.
+ * @list: Siblings on the list of all targets exposed by a power sequencer.
+ * @name: Name of the target.
+ * @unit: Final unit for this target.
+ * @post_enable: Callback run after the target unit has been enabled, *after*
+ * the state lock has been released. It's useful for implementing
+ * boot-up delays without blocking other users from powering up
+ * using the same power sequencer.
+ */
+struct pwrseq_target {
+ struct list_head list;
+ const char *name;
+ struct pwrseq_unit *unit;
+ pwrseq_power_state_func post_enable;
+};
+
+static struct pwrseq_target *
+pwrseq_target_new(const struct pwrseq_target_data *data)
+{
+ struct pwrseq_target *target;
+
+ target = kzalloc(sizeof(*target), GFP_KERNEL);
+ if (!target)
+ return NULL;
+
+ target->name = kstrdup_const(data->name, GFP_KERNEL);
+ if (!target->name) {
+ kfree(target);
+ return NULL;
+ }
+
+ target->post_enable = data->post_enable;
+
+ return target;
+}
+
+static void pwrseq_target_free(struct pwrseq_target *target)
+{
+ pwrseq_unit_decref(target->unit);
+ kfree_const(target->name);
+ kfree(target);
+}
+
+/**
+ * struct pwrseq_device - Private power sequencing data.
+ * @dev: Device struct associated with this sequencer.
+ * @id: Device ID.
+ * @owner: Prevents removal of active power sequencing providers.
+ * @rw_lock: Protects the device from being unregistered while in use.
+ * @state_lock: Prevents multiple users running the power sequence at the same
+ * time.
+ * @match: Power sequencer matching callback.
+ * @targets: List of targets exposed by this sequencer.
+ * @units: List of all units supported by this sequencer.
+ */
+struct pwrseq_device {
+ struct device dev;
+ int id;
+ struct module *owner;
+ struct rw_semaphore rw_lock;
+ struct mutex state_lock;
+ pwrseq_match_func match;
+ struct list_head targets;
+ struct list_head units;
+};
+
+static struct pwrseq_device *to_pwrseq_device(struct device *dev)
+{
+ return container_of(dev, struct pwrseq_device, dev);
+}
+
+static struct pwrseq_device *pwrseq_device_get(struct pwrseq_device *pwrseq)
+{
+ get_device(&pwrseq->dev);
+
+ return pwrseq;
+}
+
+static void pwrseq_device_put(struct pwrseq_device *pwrseq)
+{
+ put_device(&pwrseq->dev);
+}
+
+/**
+ * struct pwrseq_desc - Wraps access to the pwrseq_device and ensures that one
+ * user cannot break the reference counting for others.
+ * @pwrseq: Reference to the power sequencing device.
+ * @target: Reference to the target this descriptor allows to control.
+ * @powered_on: Power state set by the holder of the descriptor (not necessarily
+ * corresponding to the actual power state of the device).
+ */
+struct pwrseq_desc {
+ struct pwrseq_device *pwrseq;
+ struct pwrseq_target *target;
+ bool powered_on;
+};
+
+static const struct bus_type pwrseq_bus = {
+ .name = "pwrseq",
+};
+
+static void pwrseq_release(struct device *dev)
+{
+ struct pwrseq_device *pwrseq = to_pwrseq_device(dev);
+ struct pwrseq_target *target;
+
+ list_for_each_entry(target, &pwrseq->targets, list)
+ pwrseq_target_free(target);
+
+ mutex_destroy(&pwrseq->state_lock);
+ ida_free(&pwrseq_ida, pwrseq->id);
+ kfree(pwrseq);
+}
+
+static const struct device_type pwrseq_device_type = {
+ .name = "power_sequencer",
+ .release = pwrseq_release,
+};
+
+static int pwrseq_unit_setup_deps(const struct pwrseq_unit_data **data,
+ struct list_head *dep_list,
+ struct list_head *unit_list,
+ struct radix_tree_root *processed_units)
+{
+ const struct pwrseq_unit_data *pos;
+ struct pwrseq_unit_dep *dep;
+ struct pwrseq_unit *unit;
+ int ret, i;
+
+ for (i = 0; data[i]; i++) {
+ pos = data[i];
+
+ unit = radix_tree_lookup(processed_units, (unsigned long)pos);
+ if (unit) {
+ pwrseq_unit_incref(unit);
+ } else {
+ unit = pwrseq_unit_new(pos);
+ if (!unit)
+ return -ENOMEM;
+
+ if (pos->deps) {
+ ret = pwrseq_unit_setup_deps(pos->deps,
+ &unit->deps,
+ unit_list,
+ processed_units);
+ if (ret) {
+ pwrseq_unit_decref(unit);
+ return ret;
+ }
+ }
+
+ ret = radix_tree_insert(processed_units,
+ (unsigned long)pos, unit);
+ if (ret) {
+ pwrseq_unit_decref(unit);
+ return ret;
+ }
+
+ list_add_tail(&unit->list, unit_list);
+ }
+
+ dep = pwrseq_unit_dep_new(unit);
+ if (!dep) {
+ pwrseq_unit_decref(unit);
+ return -ENOMEM;
+ }
+
+ list_add_tail(&dep->list, dep_list);
+ }
+
+ return 0;
+}
+
+static int pwrseq_target_setup_unit(struct pwrseq_target *target,
+ const struct pwrseq_unit_data *data,
+ struct list_head *unit_list,
+ struct radix_tree_root *processed_units)
+{
+ struct pwrseq_unit *unit;
+ int ret;
+
+ unit = radix_tree_lookup(processed_units, (unsigned long)data);
+ if (unit) {
+ target->unit = pwrseq_unit_incref(unit);
+ return 0;
+ }
+
+ unit = pwrseq_unit_new(data);
+ if (!unit)
+ return -ENOMEM;
+
+ ret = pwrseq_unit_setup_deps(data->deps, &unit->deps, unit_list,
+ processed_units);
+ if (ret) {
+ pwrseq_unit_decref(unit);
+ return ret;
+ }
+
+ ret = radix_tree_insert(processed_units, (unsigned long)data, unit);
+ if (ret) {
+ pwrseq_unit_decref(unit);
+ return ret;
+ }
+
+ target->unit = unit;
+ list_add_tail(&unit->list, unit_list);
+
+ return 0;
+}
+
+static int pwrseq_do_setup_targets(const struct pwrseq_target_data **data,
+ struct pwrseq_device *pwrseq,
+ struct radix_tree_root *processed_units)
+{
+ const struct pwrseq_target_data *pos;
+ struct pwrseq_target *target;
+ int ret, i;
+
+ for (i = 0; data[i]; i++) {
+ pos = data[i];
+
+ target = pwrseq_target_new(pos);
+ if (!target)
+ return -ENOMEM;
+
+ ret = pwrseq_target_setup_unit(target, pos->unit,
+ &pwrseq->units,
+ processed_units);
+ if (ret) {
+ pwrseq_target_free(target);
+ return ret;
+ }
+
+ list_add_tail(&target->list, &pwrseq->targets);
+ }
+
+ return 0;
+}
+
+static int pwrseq_setup_targets(const struct pwrseq_target_data **targets,
+ struct pwrseq_device *pwrseq)
+{
+ struct radix_tree_root processed_units;
+ struct radix_tree_iter iter;
+ void __rcu **slot;
+ int ret;
+
+ INIT_RADIX_TREE(&processed_units, GFP_KERNEL);
+ ret = pwrseq_do_setup_targets(targets, pwrseq, &processed_units);
+ radix_tree_for_each_slot(slot, &processed_units, &iter, 0)
+ radix_tree_delete(&processed_units, iter.index);
+
+ return ret;
+}
+
+/**
+ * pwrseq_device_register() - Register a new power sequencer.
+ * @config: Configuration of the new power sequencing device.
+ *
+ * The config structure is only used during the call and can be freed after
+ * the function returns. The config structure *must* have the parent device
+ * as well as the match() callback and at least one target set.
+ *
+ * Returns:
+ * Returns the address of the new pwrseq device or ERR_PTR() on failure.
+ */
+struct pwrseq_device *
+pwrseq_device_register(const struct pwrseq_config *config)
+{
+ struct pwrseq_device *pwrseq;
+ int ret;
+
+ if (!config->parent || !config->match || !config->targets ||
+ !config->targets[0])
+ return ERR_PTR(-EINVAL);
+
+ pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);
+ if (!pwrseq)
+ return ERR_PTR(-ENOMEM);
+
+ pwrseq->dev.type = &pwrseq_device_type;
+ pwrseq->dev.bus = &pwrseq_bus;
+ pwrseq->dev.parent = config->parent;
+ device_set_node(&pwrseq->dev, dev_fwnode(config->parent));
+ dev_set_drvdata(&pwrseq->dev, config->drvdata);
+
+ pwrseq->id = ida_alloc(&pwrseq_ida, GFP_KERNEL);
+ if (pwrseq->id < 0) {
+ kfree(pwrseq);
+ return ERR_PTR(pwrseq->id);
+ }
+
+ /*
+ * From this point onwards the device's release() callback is
+ * responsible for freeing resources.
+ */
+ device_initialize(&pwrseq->dev);
+
+ ret = dev_set_name(&pwrseq->dev, "pwrseq.%d", pwrseq->id);
+ if (ret)
+ goto err_put_pwrseq;
+
+ pwrseq->owner = config->owner ?: THIS_MODULE;
+ pwrseq->match = config->match;
+
+ init_rwsem(&pwrseq->rw_lock);
+ mutex_init(&pwrseq->state_lock);
+ INIT_LIST_HEAD(&pwrseq->targets);
+ INIT_LIST_HEAD(&pwrseq->units);
+
+ ret = pwrseq_setup_targets(config->targets, pwrseq);
+ if (ret)
+ goto err_put_pwrseq;
+
+ scoped_guard(rwsem_write, &pwrseq_sem) {
+ ret = device_add(&pwrseq->dev);
+ if (ret)
+ goto err_put_pwrseq;
+ }
+
+ return pwrseq;
+
+err_put_pwrseq:
+ pwrseq_device_put(pwrseq);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(pwrseq_device_register);
+
+/**
+ * pwrseq_device_unregister() - Unregister the power sequencer.
+ * @pwrseq: Power sequencer to unregister.
+ */
+void pwrseq_device_unregister(struct pwrseq_device *pwrseq)
+{
+ struct device *dev = &pwrseq->dev;
+ struct pwrseq_target *target;
+
+ scoped_guard(mutex, &pwrseq->state_lock) {
+ guard(rwsem_write)(&pwrseq->rw_lock);
+
+ list_for_each_entry(target, &pwrseq->targets, list)
+ WARN_ONCE(target->unit->enable_count,
+ "REMOVING POWER SEQUENCER WITH ACTIVE USERS\n");
+
+ guard(rwsem_write)(&pwrseq_sem);
+
+ device_del(dev);
+ }
+
+ pwrseq_device_put(pwrseq);
+}
+EXPORT_SYMBOL_GPL(pwrseq_device_unregister);
+
+static void devm_pwrseq_device_unregister(void *data)
+{
+ struct pwrseq_device *pwrseq = data;
+
+ pwrseq_device_unregister(pwrseq);
+}
+
+/**
+ * devm_pwrseq_device_register() - Managed variant of pwrseq_device_register().
+ * @dev: Managing device.
+ * @config: Configuration of the new power sequencing device.
+ *
+ * Returns:
+ * Returns the address of the new pwrseq device or ERR_PTR() on failure.
+ */
+struct pwrseq_device *
+devm_pwrseq_device_register(struct device *dev,
+ const struct pwrseq_config *config)
+{
+ struct pwrseq_device *pwrseq;
+ int ret;
+
+ pwrseq = pwrseq_device_register(config);
+ if (IS_ERR(pwrseq))
+ return pwrseq;
+
+ ret = devm_add_action_or_reset(dev, devm_pwrseq_device_unregister,
+ pwrseq);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return pwrseq;
+}
+EXPORT_SYMBOL_GPL(devm_pwrseq_device_register);
+
+/**
+ * pwrseq_device_get_drvdata() - Get the driver private data associated with
+ * this sequencer.
+ * @pwrseq: Power sequencer object.
+ *
+ * Returns:
+ * Address of the private driver data.
+ */
+void *pwrseq_device_get_drvdata(struct pwrseq_device *pwrseq)
+{
+ return dev_get_drvdata(&pwrseq->dev);
+}
+EXPORT_SYMBOL_GPL(pwrseq_device_get_drvdata);
+
+struct pwrseq_match_data {
+ struct pwrseq_desc *desc;
+ struct device *dev;
+ const char *target;
+};
+
+static int pwrseq_match_device(struct device *pwrseq_dev, void *data)
+{
+ struct pwrseq_device *pwrseq = to_pwrseq_device(pwrseq_dev);
+ struct pwrseq_match_data *match_data = data;
+ struct pwrseq_target *target;
+ int ret;
+
+ guard(rwsem_read)(&pwrseq->rw_lock);
+ if (!device_is_registered(&pwrseq->dev))
+ return 0;
+
+ ret = pwrseq->match(pwrseq, match_data->dev);
+ if (ret <= 0)
+ return ret;
+
+ /* We got the matching device, let's find the right target. */
+ list_for_each_entry(target, &pwrseq->targets, list) {
+ if (strcmp(target->name, match_data->target))
+ continue;
+
+ match_data->desc->target = target;
+ }
+
+ /*
+ * This device does not have this target. No point in deferring as it
+ * will not get a new target dynamically later.
+ */
+ if (!match_data->desc->target)
+ return -ENOENT;
+
+ if (!try_module_get(pwrseq->owner))
+ return -EPROBE_DEFER;
+
+ match_data->desc->pwrseq = pwrseq_device_get(pwrseq);
+
+ return 1;
+}
+
+/**
+ * pwrseq_get() - Get the power sequencer associated with this device.
+ * @dev: Device for which to get the sequencer.
+ * @target: Name of the target exposed by the sequencer this device wants to
+ * reach.
+ *
+ * Returns:
+ * New power sequencer descriptor for use by the consumer driver or ERR_PTR()
+ * on failure.
+ */
+struct pwrseq_desc *pwrseq_get(struct device *dev, const char *target)
+{
+ struct pwrseq_match_data match_data;
+ int ret;
+
+ struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc),
+ GFP_KERNEL);
+ if (!desc)
+ return ERR_PTR(-ENOMEM);
+
+ match_data.desc = desc;
+ match_data.dev = dev;
+ match_data.target = target;
+
+ guard(rwsem_read)(&pwrseq_sem);
+
+ ret = bus_for_each_dev(&pwrseq_bus, NULL, &match_data,
+ pwrseq_match_device);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ if (ret == 0)
+ /* No device matched. */
+ return ERR_PTR(-EPROBE_DEFER);
+
+ return no_free_ptr(desc);
+}
+EXPORT_SYMBOL_GPL(pwrseq_get);
+
+/**
+ * pwrseq_put() - Release the power sequencer descriptor.
+ * @desc: Descriptor to release.
+ */
+void pwrseq_put(struct pwrseq_desc *desc)
+{
+ struct pwrseq_device *pwrseq;
+
+ if (!desc)
+ return;
+
+ pwrseq = desc->pwrseq;
+
+ if (desc->powered_on)
+ pwrseq_power_off(desc);
+
+ kfree(desc);
+ module_put(pwrseq->owner);
+ pwrseq_device_put(pwrseq);
+}
+EXPORT_SYMBOL_GPL(pwrseq_put);
+
+static void devm_pwrseq_put(void *data)
+{
+ struct pwrseq_desc *desc = data;
+
+ pwrseq_put(desc);
+}
+
+/**
+ * devm_pwrseq_get() - Managed variant of pwrseq_get().
+ * @dev: Device for which to get the sequencer and which also manages its
+ * lifetime.
+ * @target: Name of the target exposed by the sequencer this device wants to
+ * reach.
+ *
+ * Returns:
+ * New power sequencer descriptor for use by the consumer driver or ERR_PTR()
+ * on failure.
+ */
+struct pwrseq_desc *devm_pwrseq_get(struct device *dev, const char *target)
+{
+ struct pwrseq_desc *desc;
+ int ret;
+
+ desc = pwrseq_get(dev, target);
+ if (IS_ERR(desc))
+ return desc;
+
+ ret = devm_add_action_or_reset(dev, devm_pwrseq_put, desc);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return desc;
+}
+EXPORT_SYMBOL_GPL(devm_pwrseq_get);
+
+static int pwrseq_unit_enable(struct pwrseq_device *pwrseq,
+ struct pwrseq_unit *target);
+static int pwrseq_unit_disable(struct pwrseq_device *pwrseq,
+ struct pwrseq_unit *target);
+
+static int pwrseq_unit_enable_deps(struct pwrseq_device *pwrseq,
+ struct list_head *list)
+{
+ struct pwrseq_unit_dep *pos;
+ int ret = 0;
+
+ list_for_each_entry(pos, list, list) {
+ ret = pwrseq_unit_enable(pwrseq, pos->unit);
+ if (ret) {
+ list_for_each_entry_continue_reverse(pos, list, list)
+ pwrseq_unit_disable(pwrseq, pos->unit);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int pwrseq_unit_disable_deps(struct pwrseq_device *pwrseq,
+ struct list_head *list)
+{
+ struct pwrseq_unit_dep *pos;
+ int ret = 0;
+
+ list_for_each_entry_reverse(pos, list, list) {
+ ret = pwrseq_unit_disable(pwrseq, pos->unit);
+ if (ret) {
+ list_for_each_entry_continue(pos, list, list)
+ pwrseq_unit_enable(pwrseq, pos->unit);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int pwrseq_unit_enable(struct pwrseq_device *pwrseq,
+ struct pwrseq_unit *unit)
+{
+ int ret;
+
+ if (unit->enable_count != 0) {
+ unit->enable_count++;
+ return 0;
+ }
+
+ ret = pwrseq_unit_enable_deps(pwrseq, &unit->deps);
+ if (ret) {
+ dev_err(&pwrseq->dev,
+ "Failed to enable dependencies before power-on for target '%s': %d\n",
+ unit->name, ret);
+ return ret;
+ }
+
+ if (unit->enable) {
+ ret = unit->enable(pwrseq);
+ if (ret) {
+ dev_err(&pwrseq->dev,
+ "Failed to enable target '%s': %d\n",
+ unit->name, ret);
+ pwrseq_unit_disable_deps(pwrseq, &unit->deps);
+ return ret;
+ }
+ }
+
+ unit->enable_count++;
+
+ return 0;
+}
+
+static int pwrseq_unit_disable(struct pwrseq_device *pwrseq,
+ struct pwrseq_unit *unit)
+{
+ int ret;
+
+ if (unit->enable_count == 0) {
+ WARN_ONCE(1, "Unmatched power-off for target '%s'\n",
+ unit->name);
+ return -EBUSY;
+ }
+
+ if (unit->enable_count != 1) {
+ unit->enable_count--;
+ return 0;
+ }
+
+ if (unit->disable) {
+ ret = unit->disable(pwrseq);
+ if (ret) {
+ dev_err(&pwrseq->dev,
+ "Failed to disable target '%s': %d\n",
+ unit->name, ret);
+ return ret;
+ }
+ }
+
+ ret = pwrseq_unit_disable_deps(pwrseq, &unit->deps);
+ if (ret) {
+ dev_err(&pwrseq->dev,
+ "Failed to disable dependencies after power-off for target '%s': %d\n",
+ unit->name, ret);
+ if (unit->enable)
+ unit->enable(pwrseq);
+ return ret;
+ }
+
+ unit->enable_count--;
+
+ return 0;
+}
+
+/**
+ * pwrseq_power_on() - Issue a power-on request on behalf of the consumer
+ * device.
+ * @desc: Descriptor referencing the power sequencer.
+ *
+ * This function tells the power sequencer that the consumer wants to be
+ * powered-up. The sequencer may already have powered-up the device in which
+ * case the function returns 0. If the power-up sequence is already in
+ * progress, the function will block until it's done and return 0. If this is
+ * the first request, the device will be powered up.
+ *
+ * Returns:
+ * 0 on success, negative error number on failure.
+ */
+int pwrseq_power_on(struct pwrseq_desc *desc)
+{
+ struct pwrseq_device *pwrseq;
+ struct pwrseq_target *target;
+ struct pwrseq_unit *unit;
+ int ret;
+
+ might_sleep();
+
+ if (!desc || desc->powered_on)
+ return 0;
+
+ pwrseq = desc->pwrseq;
+ target = desc->target;
+ unit = target->unit;
+
+ guard(rwsem_read)(&pwrseq->rw_lock);
+ if (!device_is_registered(&pwrseq->dev))
+ return -ENODEV;
+
+ scoped_guard(mutex, &pwrseq->state_lock) {
+ ret = pwrseq_unit_enable(pwrseq, unit);
+ if (!ret)
+ desc->powered_on = true;
+ }
+
+ if (target->post_enable) {
+ ret = target->post_enable(pwrseq);
+ if (ret) {
+ pwrseq_unit_disable(pwrseq, unit);
+ desc->powered_on = false;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pwrseq_power_on);
+
+/**
+ * pwrseq_power_off() - Issue a power-off request on behalf of the consumer
+ * device.
+ * @desc: Descriptor referencing the power sequencer.
+ *
+ * This undoes the effects of pwrseq_power_on(). It issues a power-off request
+ * on behalf of the consumer and when the last remaining user does so, the
+ * power-down sequence will be started. If one is in progress, the function
+ * will block until it's complete and then return.
+ *
+ * Returns:
+ * 0 on success, negative error number on failure.
+ */
+int pwrseq_power_off(struct pwrseq_desc *desc)
+{
+ struct pwrseq_device *pwrseq;
+ struct pwrseq_unit *unit;
+ int ret;
+
+ might_sleep();
+
+ if (!desc || !desc->powered_on)
+ return 0;
+
+ pwrseq = desc->pwrseq;
+ unit = desc->target->unit;
+
+ guard(rwsem_read)(&pwrseq->rw_lock);
+ if (!device_is_registered(&pwrseq->dev))
+ return -ENODEV;
+
+ guard(mutex)(&pwrseq->state_lock);
+
+ ret = pwrseq_unit_disable(pwrseq, unit);
+ if (!ret)
+ desc->powered_on = false;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pwrseq_power_off);
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+
+struct pwrseq_debugfs_count_ctx {
+ struct device *dev;
+ loff_t index;
+};
+
+static int pwrseq_debugfs_seq_count(struct device *dev, void *data)
+{
+ struct pwrseq_debugfs_count_ctx *ctx = data;
+
+ ctx->dev = dev;
+
+ return ctx->index-- ? 0 : 1;
+}
+
+static void *pwrseq_debugfs_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct pwrseq_debugfs_count_ctx ctx;
+
+ ctx.dev = NULL;
+ ctx.index = *pos;
+
+ /*
+ * We're holding the lock for the entire printout so no need to fiddle
+ * with device reference count.
+ */
+ down_read(&pwrseq_sem);
+
+ bus_for_each_dev(&pwrseq_bus, NULL, &ctx, pwrseq_debugfs_seq_count);
+ if (!ctx.index)
+ return NULL;
+
+ return ctx.dev;
+}
+
+static void *pwrseq_debugfs_seq_next(struct seq_file *seq, void *data,
+ loff_t *pos)
+{
+ struct device *curr = data;
+
+ ++*pos;
+
+ struct device *next __free(put_device) =
+ bus_find_next_device(&pwrseq_bus, curr);
+ return next;
+}
+
+static void pwrseq_debugfs_seq_show_target(struct seq_file *seq,
+ struct pwrseq_target *target)
+{
+ seq_printf(seq, " target: [%s] (target unit: [%s])\n",
+ target->name, target->unit->name);
+}
+
+static void pwrseq_debugfs_seq_show_unit(struct seq_file *seq,
+ struct pwrseq_unit *unit)
+{
+ struct pwrseq_unit_dep *ref;
+
+ seq_printf(seq, " unit: [%s] - enable count: %u\n",
+ unit->name, unit->enable_count);
+
+ if (list_empty(&unit->deps))
+ return;
+
+ seq_puts(seq, " dependencies:\n");
+ list_for_each_entry(ref, &unit->deps, list)
+ seq_printf(seq, " [%s]\n", ref->unit->name);
+}
+
+static int pwrseq_debugfs_seq_show(struct seq_file *seq, void *data)
+{
+ struct device *dev = data;
+ struct pwrseq_device *pwrseq = to_pwrseq_device(dev);
+ struct pwrseq_target *target;
+ struct pwrseq_unit *unit;
+
+ seq_printf(seq, "%s:\n", dev_name(dev));
+
+ seq_puts(seq, " targets:\n");
+ list_for_each_entry(target, &pwrseq->targets, list)
+ pwrseq_debugfs_seq_show_target(seq, target);
+
+ seq_puts(seq, " units:\n");
+ list_for_each_entry(unit, &pwrseq->units, list)
+ pwrseq_debugfs_seq_show_unit(seq, unit);
+
+ return 0;
+}
+
+static void pwrseq_debugfs_seq_stop(struct seq_file *seq, void *data)
+{
+ up_read(&pwrseq_sem);
+}
+
+static const struct seq_operations pwrseq_debugfs_sops = {
+ .start = pwrseq_debugfs_seq_start,
+ .next = pwrseq_debugfs_seq_next,
+ .show = pwrseq_debugfs_seq_show,
+ .stop = pwrseq_debugfs_seq_stop,
+};
+DEFINE_SEQ_ATTRIBUTE(pwrseq_debugfs);
+
+static struct dentry *pwrseq_debugfs_dentry;
+
+#endif /* CONFIG_DEBUG_FS */
+
+static int __init pwrseq_init(void)
+{
+ int ret;
+
+ ret = bus_register(&pwrseq_bus);
+ if (ret) {
+ pr_err("Failed to register the power sequencer bus\n");
+ return ret;
+ }
+
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+ pwrseq_debugfs_dentry = debugfs_create_file("pwrseq", 0444, NULL, NULL,
+ &pwrseq_debugfs_fops);
+#endif /* CONFIG_DEBUG_FS */
+
+ return 0;
+}
+subsys_initcall(pwrseq_init);
+
+static void __exit pwrseq_exit(void)
+{
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+ debugfs_remove_recursive(pwrseq_debugfs_dentry);
+#endif /* CONFIG_DEBUG_FS */
+
+ bus_unregister(&pwrseq_bus);
+}
+module_exit(pwrseq_exit);
+
+MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
+MODULE_DESCRIPTION("Power Sequencing subsystem core");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/pwrseq/consumer.h b/include/linux/pwrseq/consumer.h
new file mode 100644
index 000000000000..7d583b4f266e
--- /dev/null
+++ b/include/linux/pwrseq/consumer.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#ifndef __POWER_SEQUENCING_CONSUMER_H__
+#define __POWER_SEQUENCING_CONSUMER_H__
+
+#include <linux/err.h>
+
+struct device;
+struct pwrseq_desc;
+
+#if IS_ENABLED(CONFIG_POWER_SEQUENCING)
+
+struct pwrseq_desc * __must_check
+pwrseq_get(struct device *dev, const char *target);
+void pwrseq_put(struct pwrseq_desc *desc);
+
+struct pwrseq_desc * __must_check
+devm_pwrseq_get(struct device *dev, const char *target);
+
+int pwrseq_power_on(struct pwrseq_desc *desc);
+int pwrseq_power_off(struct pwrseq_desc *desc);
+
+#else /* CONFIG_POWER_SEQUENCING */
+
+static inline struct pwrseq_desc * __must_check
+pwrseq_get(struct device *dev, const char *target)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void pwrseq_put(struct pwrseq_desc *desc)
+{
+}
+
+static inline struct pwrseq_desc * __must_check
+devm_pwrseq_get(struct device *dev, const char *target)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline int pwrseq_power_on(struct pwrseq_desc *desc)
+{
+ return -ENOSYS;
+}
+
+static inline int pwrseq_power_off(struct pwrseq_desc *desc)
+{
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_POWER_SEQUENCING */
+
+#endif /* __POWER_SEQUENCING_CONSUMER_H__ */
diff --git a/include/linux/pwrseq/provider.h b/include/linux/pwrseq/provider.h
new file mode 100644
index 000000000000..e627ed2f4d91
--- /dev/null
+++ b/include/linux/pwrseq/provider.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#ifndef __POWER_SEQUENCING_PROVIDER_H__
+#define __POWER_SEQUENCING_PROVIDER_H__
+
+struct device;
+struct module;
+struct pwrseq_device;
+
+typedef int (*pwrseq_power_state_func)(struct pwrseq_device *);
+typedef int (*pwrseq_match_func)(struct pwrseq_device *, struct device *);
+
+/**
+ * struct pwrseq_unit_data - Configuration of a single power sequencing
+ * unit.
+ * @name: Name of the unit.
+ * @deps: Units that must be enabled before this one and disabled after it
+ * in the order they come in this array.
+ * @enable: Callback running the part of the power-on sequence provided by
+ * this unit.
+ * @disable: Callback running the part of the power-off sequence provided
+ * by this unit.
+ */
+struct pwrseq_unit_data {
+ const char *name;
+ const struct pwrseq_unit_data **deps;
+ pwrseq_power_state_func enable;
+ pwrseq_power_state_func disable;
+};
+
+/**
+ * struct pwrseq_target_data - Configuration of a power sequencing target.
+ * @name: Name of the target.
+ * @unit: Final unit that this target must reach in order to be considered
+ * enabled.
+ * @post_enable: Callback run after the target unit has been enabled, *after*
+ * the state lock has been released. It's useful for implementing
+ * boot-up delays without blocking other users from powering up
+ * using the same power sequencer.
+ */
+struct pwrseq_target_data {
+ const char *name;
+ const struct pwrseq_unit_data *unit;
+ pwrseq_power_state_func post_enable;
+};
+
+/**
+ * struct pwrseq_config - Configuration used for registering a new provider.
+ * @parent: Parent device for the sequencer. Must be set.
+ * @owner: Module providing this device.
+ * @drvdata: Private driver data.
+ * @match: Provider callback used to match the consumer device to the sequencer.
+ * @targets: Array of targets for this power sequencer. Must be NULL-terminated.
+ */
+struct pwrseq_config {
+ struct device *parent;
+ struct module *owner;
+ void *drvdata;
+ pwrseq_match_func match;
+ const struct pwrseq_target_data **targets;
+};
+
+struct pwrseq_device *
+pwrseq_device_register(const struct pwrseq_config *config);
+void pwrseq_device_unregister(struct pwrseq_device *pwrseq);
+struct pwrseq_device *
+devm_pwrseq_device_register(struct device *dev,
+ const struct pwrseq_config *config);
+
+void *pwrseq_device_get_drvdata(struct pwrseq_device *pwrseq);
+
+#endif /* __POWER_SEQUENCING_PROVIDER_H__ */
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v6 15/16] Bluetooth: qca: use the power sequencer for QCA6390
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Use the pwrseq subsystem's consumer API to run the power-up sequence for
the Bluetooth module of the QCA6390 package.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/bluetooth/hci_qca.c | 74 +++++++++++++++++++++++++++++--------
1 file changed, 59 insertions(+), 15 deletions(-)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 8a60ad7acd70..d31dcea650c1 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -29,6 +29,7 @@
#include <linux/of.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
+#include <linux/pwrseq/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/serdev.h>
#include <linux/mutex.h>
@@ -215,6 +216,7 @@ struct qca_power {
struct regulator_bulk_data *vreg_bulk;
int num_vregs;
bool vregs_on;
+ struct pwrseq_desc *pwrseq;
};
struct qca_serdev {
@@ -1682,6 +1684,27 @@ static bool qca_wakeup(struct hci_dev *hdev)
return wakeup;
}
+static int qca_port_reopen(struct hci_uart *hu)
+{
+ int ret;
+
+ /* Now the device is in ready state to communicate with host.
+ * To sync host with device we need to reopen port.
+ * Without this, we will have RTS and CTS synchronization
+ * issues.
+ */
+ serdev_device_close(hu->serdev);
+ ret = serdev_device_open(hu->serdev);
+ if (ret) {
+ bt_dev_err(hu->hdev, "failed to open port");
+ return ret;
+ }
+
+ hci_uart_set_flow_control(hu, false);
+
+ return 0;
+}
+
static int qca_regulator_init(struct hci_uart *hu)
{
enum qca_btsoc_type soc_type = qca_soc_type(hu);
@@ -1750,21 +1773,7 @@ static int qca_regulator_init(struct hci_uart *hu)
break;
}
- /* Now the device is in ready state to communicate with host.
- * To sync host with device we need to reopen port.
- * Without this, we will have RTS and CTS synchronization
- * issues.
- */
- serdev_device_close(hu->serdev);
- ret = serdev_device_open(hu->serdev);
- if (ret) {
- bt_dev_err(hu->hdev, "failed to open port");
- return ret;
- }
-
- hci_uart_set_flow_control(hu, false);
-
- return 0;
+ return qca_port_reopen(hu);
}
static int qca_power_on(struct hci_dev *hdev)
@@ -1792,6 +1801,17 @@ static int qca_power_on(struct hci_dev *hdev)
ret = qca_regulator_init(hu);
break;
+ case QCA_QCA6390:
+ qcadev = serdev_device_get_drvdata(hu->serdev);
+ ret = pwrseq_power_on(qcadev->bt_power->pwrseq);
+ if (ret)
+ return ret;
+
+ ret = qca_port_reopen(hu);
+ if (ret)
+ return ret;
+ break;
+
default:
qcadev = serdev_device_get_drvdata(hu->serdev);
if (qcadev->bt_en) {
@@ -2170,6 +2190,10 @@ static void qca_power_shutdown(struct hci_uart *hu)
}
break;
+ case QCA_QCA6390:
+ pwrseq_power_off(qcadev->bt_power->pwrseq);
+ break;
+
default:
gpiod_set_value_cansleep(qcadev->bt_en, 0);
}
@@ -2308,12 +2332,25 @@ static int qca_serdev_probe(struct serdev_device *serdev)
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
+ case QCA_QCA6390:
qcadev->bt_power = devm_kzalloc(&serdev->dev,
sizeof(struct qca_power),
GFP_KERNEL);
if (!qcadev->bt_power)
return -ENOMEM;
+ break;
+ default:
+ break;
+ }
+ switch (qcadev->btsoc_type) {
+ case QCA_WCN3988:
+ case QCA_WCN3990:
+ case QCA_WCN3991:
+ case QCA_WCN3998:
+ case QCA_WCN6750:
+ case QCA_WCN6855:
+ case QCA_WCN7850:
qcadev->bt_power->dev = &serdev->dev;
err = qca_init_regulators(qcadev->bt_power, data->vregs,
data->num_vregs);
@@ -2354,6 +2391,13 @@ static int qca_serdev_probe(struct serdev_device *serdev)
}
break;
+ case QCA_QCA6390:
+ qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev,
+ "bluetooth");
+ if (IS_ERR(qcadev->bt_power->pwrseq))
+ return PTR_ERR(qcadev->bt_power->pwrseq);
+ fallthrough;
+
default:
qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
GPIOD_OUT_LOW);
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v6 14/16] power: pwrseq: add a driver for the PMU module on the QCom WCN chipsets
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This adds the power sequencing driver for the PMU modules present on the
Qualcomm WCN Bluetooth and Wifi chipsets. It uses the pwrseq subsystem
and knows how to match the sequencer to the consumer device by verifying
the relevant properties and DT layout.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/power/sequencing/Kconfig | 16 +
drivers/power/sequencing/Makefile | 2 +
drivers/power/sequencing/pwrseq-qcom-wcn.c | 336 +++++++++++++++++++++
3 files changed, 354 insertions(+)
create mode 100644 drivers/power/sequencing/pwrseq-qcom-wcn.c
diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
index ba5732b1dbf8..468d58fac07d 100644
--- a/drivers/power/sequencing/Kconfig
+++ b/drivers/power/sequencing/Kconfig
@@ -10,3 +10,19 @@ menuconfig POWER_SEQUENCING
during power-up.
If unsure, say no.
+
+if POWER_SEQUENCING
+
+config POWER_SEQUENCING_QCOM_WCN
+ tristate "Qualcomm WCN family PMU driver"
+ default m if ARCH_QCOM
+ help
+ Say U here to enable the power sequencing driver for Qualcomm
+ WCN Bluetooth/WLAN chipsets.
+
+ Typically, a package from the Qualcomm WCN family contains the BT
+ and WLAN modules whose power is controlled by the PMU module. As the
+ former two share the power-up sequence which is executed by the PMU,
+ this driver is needed for correct power control.
+
+endif
diff --git a/drivers/power/sequencing/Makefile b/drivers/power/sequencing/Makefile
index dcdf8c0c159e..2eec2df7912d 100644
--- a/drivers/power/sequencing/Makefile
+++ b/drivers/power/sequencing/Makefile
@@ -2,3 +2,5 @@
obj-$(CONFIG_POWER_SEQUENCING) += pwrseq-core.o
pwrseq-core-y := core.o
+
+obj-$(CONFIG_POWER_SEQUENCING_QCOM_WCN) += pwrseq-qcom-wcn.o
diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c
new file mode 100644
index 000000000000..380305227b3f
--- /dev/null
+++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/jiffies.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pwrseq/provider.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+struct pwrseq_qcom_wcn_pdata {
+ const char *const *vregs;
+ size_t num_vregs;
+ unsigned int pwup_delay_msec;
+ unsigned int gpio_enable_delay;
+};
+
+struct pwrseq_qcom_wcn_ctx {
+ struct pwrseq_device *pwrseq;
+ struct device_node *of_node;
+ const struct pwrseq_qcom_wcn_pdata *pdata;
+ struct regulator_bulk_data *regs;
+ struct gpio_desc *bt_gpio;
+ struct gpio_desc *wlan_gpio;
+ struct clk *clk;
+ unsigned long last_gpio_enable;
+};
+
+static void pwrseq_qcom_wcn_ensure_gpio_delay(struct pwrseq_qcom_wcn_ctx *ctx)
+{
+ unsigned long diff_jiffies;
+ unsigned int diff_msecs;
+
+ if (!ctx->pdata->gpio_enable_delay)
+ return;
+
+ diff_jiffies = jiffies - ctx->last_gpio_enable;
+ diff_msecs = jiffies_to_msecs(diff_jiffies);
+
+ if (diff_msecs < ctx->pdata->gpio_enable_delay)
+ msleep(ctx->pdata->gpio_enable_delay - diff_msecs);
+}
+
+static int pwrseq_qcom_wcn_vregs_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return regulator_bulk_enable(ctx->pdata->num_vregs, ctx->regs);
+}
+
+static int pwrseq_qcom_wcn_vregs_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return regulator_bulk_disable(ctx->pdata->num_vregs, ctx->regs);
+}
+
+static const struct pwrseq_unit_data pwrseq_qcom_wcn_vregs_unit_data = {
+ .name = "regulators-enable",
+ .enable = pwrseq_qcom_wcn_vregs_enable,
+ .disable = pwrseq_qcom_wcn_vregs_disable,
+};
+
+static int pwrseq_qcom_wcn_clk_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ return clk_prepare_enable(ctx->clk);
+}
+
+static int pwrseq_qcom_wcn_clk_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ clk_disable_unprepare(ctx->clk);
+
+ return 0;
+}
+
+static const struct pwrseq_unit_data pwrseq_qcom_wcn_clk_unit_data = {
+ .name = "clock-enable",
+ .enable = pwrseq_qcom_wcn_clk_enable,
+ .disable = pwrseq_qcom_wcn_clk_disable,
+};
+
+static const struct pwrseq_unit_data *pwrseq_qcom_wcn_unit_deps[] = {
+ &pwrseq_qcom_wcn_vregs_unit_data,
+ &pwrseq_qcom_wcn_clk_unit_data,
+ NULL
+};
+
+static int pwrseq_qcom_wcn_bt_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ pwrseq_qcom_wcn_ensure_gpio_delay(ctx);
+ gpiod_set_value_cansleep(ctx->bt_gpio, 1);
+ ctx->last_gpio_enable = jiffies;
+
+ return 0;
+}
+
+static int pwrseq_qcom_wcn_bt_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ gpiod_set_value_cansleep(ctx->bt_gpio, 0);
+
+ return 0;
+}
+
+static const struct pwrseq_unit_data pwrseq_qcom_wcn_bt_unit_data = {
+ .name = "bluetooth-enable",
+ .deps = pwrseq_qcom_wcn_unit_deps,
+ .enable = pwrseq_qcom_wcn_bt_enable,
+ .disable = pwrseq_qcom_wcn_bt_disable,
+};
+
+static int pwrseq_qcom_wcn_wlan_enable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ pwrseq_qcom_wcn_ensure_gpio_delay(ctx);
+ gpiod_set_value_cansleep(ctx->wlan_gpio, 1);
+ ctx->last_gpio_enable = jiffies;
+
+ return 0;
+}
+
+static int pwrseq_qcom_wcn_wlan_disable(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ gpiod_set_value_cansleep(ctx->wlan_gpio, 0);
+
+ return 0;
+}
+
+static const struct pwrseq_unit_data pwrseq_qcom_wcn_wlan_unit_data = {
+ .name = "wlan-enable",
+ .deps = pwrseq_qcom_wcn_unit_deps,
+ .enable = pwrseq_qcom_wcn_wlan_enable,
+ .disable = pwrseq_qcom_wcn_wlan_disable,
+};
+
+static int pwrseq_qcom_wcn_pwup_delay(struct pwrseq_device *pwrseq)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+
+ if (ctx->pdata->pwup_delay_msec)
+ msleep(ctx->pdata->pwup_delay_msec);
+
+ return 0;
+}
+
+static const struct pwrseq_target_data pwrseq_qcom_wcn_bt_target_data = {
+ .name = "bluetooth",
+ .unit = &pwrseq_qcom_wcn_bt_unit_data,
+ .post_enable = pwrseq_qcom_wcn_pwup_delay,
+};
+
+static const struct pwrseq_target_data pwrseq_qcom_wcn_wlan_target_data = {
+ .name = "wlan",
+ .unit = &pwrseq_qcom_wcn_wlan_unit_data,
+ .post_enable = pwrseq_qcom_wcn_pwup_delay,
+};
+
+static const struct pwrseq_target_data *pwrseq_qcom_wcn_targets[] = {
+ &pwrseq_qcom_wcn_bt_target_data,
+ &pwrseq_qcom_wcn_wlan_target_data,
+ NULL
+};
+
+static const char *const pwrseq_qca6390_vregs[] = {
+ "vddio",
+ "vddaon",
+ "vddpmu",
+ "vddrfa0p95",
+ "vddrfa1p3",
+ "vddrfa1p9",
+ "vddpcie1p3",
+ "vddpcie1p9",
+};
+
+static const struct pwrseq_qcom_wcn_pdata pwrseq_qca6390_of_data = {
+ .vregs = pwrseq_qca6390_vregs,
+ .num_vregs = ARRAY_SIZE(pwrseq_qca6390_vregs),
+ .pwup_delay_msec = 60,
+ .gpio_enable_delay = 100,
+};
+
+static const char *const pwrseq_wcn7850_vregs[] = {
+ "vdd",
+ "vddio",
+ "vddio1p2",
+ "vddaon",
+ "vdddig",
+ "vddrfa1p2",
+ "vddrfa1p8",
+};
+
+static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn7850_of_data = {
+ .vregs = pwrseq_wcn7850_vregs,
+ .num_vregs = ARRAY_SIZE(pwrseq_wcn7850_vregs),
+ .pwup_delay_msec = 50,
+};
+
+static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq,
+ struct device *dev)
+{
+ struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
+ struct device_node *dev_node = dev->of_node;
+
+ /*
+ * The PMU supplies power to the Bluetooth and WLAN modules. both
+ * consume the PMU AON output so check the presence of the
+ * 'vddaon-supply' property and whether it leads us to the right
+ * device.
+ */
+ if (!of_property_present(dev_node, "vddaon-supply"))
+ return 0;
+
+ struct device_node *reg_node __free(device_node) =
+ of_parse_phandle(dev_node, "vddaon-supply", 0);
+ if (!reg_node)
+ return 0;
+
+ /*
+ * `reg_node` is the PMU AON regulator, its parent is the `regulators`
+ * node and finally its grandparent is the PMU device node that we're
+ * looking for.
+ */
+ if (!reg_node->parent || !reg_node->parent->parent ||
+ reg_node->parent->parent != ctx->of_node)
+ return 0;
+
+ return 1;
+}
+
+static int pwrseq_qcom_wcn_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pwrseq_qcom_wcn_ctx *ctx;
+ struct pwrseq_config config;
+ int i, ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->of_node = dev->of_node;
+
+ ctx->pdata = of_device_get_match_data(dev);
+ if (!ctx->pdata)
+ return dev_err_probe(dev, -ENODEV,
+ "Failed to obtain platform data\n");
+
+ ctx->regs = devm_kcalloc(dev, ctx->pdata->num_vregs,
+ sizeof(*ctx->regs), GFP_KERNEL);
+ if (!ctx->regs)
+ return -ENOMEM;
+
+ for (i = 0; i < ctx->pdata->num_vregs; i++)
+ ctx->regs[i].supply = ctx->pdata->vregs[i];
+
+ ret = devm_regulator_bulk_get(dev, ctx->pdata->num_vregs, ctx->regs);
+ if (ret < 0)
+ return dev_err_probe(dev, PTR_ERR(ctx->regs),
+ "Failed to get all regulators\n");
+
+ ctx->bt_gpio = devm_gpiod_get_optional(dev, "bt-enable", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->bt_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->bt_gpio),
+ "Failed to get the Bluetooth enable GPIO\n");
+
+ ctx->wlan_gpio = devm_gpiod_get_optional(dev, "wlan-enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->wlan_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->wlan_gpio),
+ "Failed to get the WLAN enable GPIO\n");
+
+ ctx->clk = devm_clk_get_optional(dev, NULL);
+ if (IS_ERR(ctx->clk))
+ return dev_err_probe(dev, PTR_ERR(ctx->clk),
+ "Failed to get the reference clock\n");
+
+ memset(&config, 0, sizeof(config));
+
+ config.parent = dev;
+ config.owner = THIS_MODULE;
+ config.drvdata = ctx;
+ config.match = pwrseq_qcom_wcn_match;
+ config.targets = pwrseq_qcom_wcn_targets;
+
+ ctx->pwrseq = devm_pwrseq_device_register(dev, &config);
+ if (IS_ERR(ctx->pwrseq))
+ return dev_err_probe(dev, PTR_ERR(ctx->pwrseq),
+ "Failed to register the power sequencer\n");
+
+ return 0;
+}
+
+static const struct of_device_id pwrseq_qcom_wcn_of_match[] = {
+ {
+ .compatible = "qcom,qca6390-pmu",
+ .data = &pwrseq_qca6390_of_data,
+ },
+ {
+ .compatible = "qcom,wcn7850-pmu",
+ .data = &pwrseq_wcn7850_of_data,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pwrseq_qcom_wcn_of_match);
+
+static struct platform_driver pwrseq_qcom_wcn_driver = {
+ .driver = {
+ .name = "pwrseq-qcom_wcn",
+ .of_match_table = pwrseq_qcom_wcn_of_match,
+ },
+ .probe = pwrseq_qcom_wcn_probe,
+};
+module_platform_driver(pwrseq_qcom_wcn_driver);
+
+MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
+MODULE_DESCRIPTION("Qualcomm WCN PMU power sequencing driver");
+MODULE_LICENSE("GPL");
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v6 12/16] PCI/pwrctl: add PCI power control core code
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Some PCI devices must be powered-on before they can be detected on the
bus. Introduce a simple framework reusing the existing PCI OF
infrastructure.
The way this works is: a DT node representing a PCI device connected to
the port can be matched against its power control platform driver. If
the match succeeds, the driver is responsible for powering-up the device
and calling pcie_pwrctl_device_set_ready() which will trigger a PCI bus
rescan as well as subscribe to PCI bus notifications.
When the device is detected and created, we'll make it consume the same
DT node that the platform device did. When the device is bound, we'll
create a device link between it and the parent power control device.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/pci/Kconfig | 1 +
drivers/pci/Makefile | 1 +
drivers/pci/pwrctl/Kconfig | 8 +++
drivers/pci/pwrctl/Makefile | 4 ++
drivers/pci/pwrctl/core.c | 136 ++++++++++++++++++++++++++++++++++++
include/linux/pci-pwrctl.h | 51 ++++++++++++++
6 files changed, 201 insertions(+)
create mode 100644 drivers/pci/pwrctl/Kconfig
create mode 100644 drivers/pci/pwrctl/Makefile
create mode 100644 drivers/pci/pwrctl/core.c
create mode 100644 include/linux/pci-pwrctl.h
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index d35001589d88..aa4d1833f442 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -296,5 +296,6 @@ source "drivers/pci/hotplug/Kconfig"
source "drivers/pci/controller/Kconfig"
source "drivers/pci/endpoint/Kconfig"
source "drivers/pci/switch/Kconfig"
+source "drivers/pci/pwrctl/Kconfig"
endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 175302036890..8ddad57934a6 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_PCI) += access.o bus.o probe.o host-bridge.o \
obj-$(CONFIG_PCI) += msi/
obj-$(CONFIG_PCI) += pcie/
+obj-$(CONFIG_PCI) += pwrctl/
ifdef CONFIG_PCI
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/drivers/pci/pwrctl/Kconfig b/drivers/pci/pwrctl/Kconfig
new file mode 100644
index 000000000000..96195395af69
--- /dev/null
+++ b/drivers/pci/pwrctl/Kconfig
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+menu "PCI Power control drivers"
+
+config PCI_PWRCTL
+ tristate
+
+endmenu
diff --git a/drivers/pci/pwrctl/Makefile b/drivers/pci/pwrctl/Makefile
new file mode 100644
index 000000000000..52ae0640ef7b
--- /dev/null
+++ b/drivers/pci/pwrctl/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_PCI_PWRCTL) += pci-pwrctl-core.o
+pci-pwrctl-core-y := core.o
diff --git a/drivers/pci/pwrctl/core.c b/drivers/pci/pwrctl/core.c
new file mode 100644
index 000000000000..11bd19519841
--- /dev/null
+++ b/drivers/pci/pwrctl/core.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci-pwrctl.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+
+static int pci_pwrctl_notify(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct pci_pwrctl *pwrctl = container_of(nb, struct pci_pwrctl, nb);
+ struct device *dev = data;
+
+ if (dev_fwnode(dev) != dev_fwnode(pwrctl->dev))
+ return NOTIFY_DONE;
+
+ switch (action) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ /*
+ * We will have two struct device objects bound to two different
+ * drivers on different buses but consuming the same DT node. We
+ * must not bind the pins twice in this case but only once for
+ * the first device to be added.
+ *
+ * If we got here then the PCI device is the second after the
+ * power control platform device. Mark its OF node as reused.
+ */
+ dev->of_node_reused = true;
+ break;
+ case BUS_NOTIFY_BOUND_DRIVER:
+ pwrctl->link = device_link_add(dev, pwrctl->dev,
+ DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!pwrctl->link)
+ dev_err(pwrctl->dev, "Failed to add device link\n");
+ break;
+ case BUS_NOTIFY_UNBOUND_DRIVER:
+ if (pwrctl->link)
+ device_link_del(pwrctl->link);
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+/**
+ * pci_pwrctl_device_set_ready() - Notify the pwrctl subsystem that the PCI
+ * device is powered-up and ready to be detected.
+ *
+ * @pwrctl: PCI power control data
+ *
+ * Returns:
+ * 0 on success, negative error number on error.
+ *
+ * Note:
+ * This function returning 0 doesn't mean the device was detected. It means,
+ * that the bus rescan was successfully started. The device will get bound to
+ * its PCI driver asynchronously.
+ */
+int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl)
+{
+ int ret;
+
+ if (!pwrctl->dev)
+ return -ENODEV;
+
+ pwrctl->nb.notifier_call = pci_pwrctl_notify;
+ ret = bus_register_notifier(&pci_bus_type, &pwrctl->nb);
+ if (ret)
+ return ret;
+
+ pci_lock_rescan_remove();
+ pci_rescan_bus(to_pci_dev(pwrctl->dev->parent)->bus);
+ pci_unlock_rescan_remove();
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_pwrctl_device_set_ready);
+
+/**
+ * pci_pwrctl_device_unset_ready() - Notify the pwrctl subsystem that the PCI
+ * device is about to be powered-down.
+ *
+ * @pwrctl: PCI power control data
+ */
+void pci_pwrctl_device_unset_ready(struct pci_pwrctl *pwrctl)
+{
+ /*
+ * We don't have to delete the link here. Typically, this function
+ * is only called when the power control device is being detached. If
+ * it is being detached then the child PCI device must have already
+ * been unbound too or the device core wouldn't let us unbind.
+ */
+ bus_unregister_notifier(&pci_bus_type, &pwrctl->nb);
+}
+EXPORT_SYMBOL_GPL(pci_pwrctl_device_unset_ready);
+
+static void devm_pci_pwrctl_device_unset_ready(void *data)
+{
+ struct pci_pwrctl *pwrctl = data;
+
+ pci_pwrctl_device_set_ready(pwrctl);
+}
+
+/**
+ * devm_pci_pwrctl_device_set_ready - Managed variant of
+ * pci_pwrctl_device_set_ready().
+ *
+ * @pwrctl: PCI power control data
+ *
+ * Returns:
+ * 0 on success, negative error number on error.
+ */
+int devm_pci_pwrctl_device_set_ready(struct device *dev,
+ struct pci_pwrctl *pwrctl)
+{
+ int ret;
+
+ ret = pci_pwrctl_device_set_ready(pwrctl);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev,
+ devm_pci_pwrctl_device_unset_ready,
+ pwrctl);
+}
+EXPORT_SYMBOL_GPL(devm_pci_pwrctl_device_set_ready);
+
+MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
+MODULE_DESCRIPTION("PCI Device Power Control core driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/pci-pwrctl.h b/include/linux/pci-pwrctl.h
new file mode 100644
index 000000000000..ae8324ea7eeb
--- /dev/null
+++ b/include/linux/pci-pwrctl.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#ifndef __PCI_PWRCTL_H__
+#define __PCI_PWRCTL_H__
+
+#include <linux/notifier.h>
+
+struct device;
+struct device_link;
+
+/*
+ * This is a simple framework for solving the issue of PCI devices that require
+ * certain resources (regulators, GPIOs, clocks) to be enabled before the
+ * device can actually be detected on the PCI bus.
+ *
+ * The idea is to reuse the platform bus to populate OF nodes describing the
+ * PCI device and its resources, let these platform devices probe and enable
+ * relevant resources and then trigger a rescan of the PCI bus allowing for the
+ * same device (with a second associated struct device) to be registered with
+ * the PCI subsystem.
+ *
+ * To preserve a correct hierarchy for PCI power management and device reset,
+ * we create a device link between the power control platform device (parent)
+ * and the supplied PCI device (child).
+ */
+
+/**
+ * struct pci_pwrctl - PCI device power control context.
+ * @dev - Address of the power controlling device.
+ *
+ * An object of this type must be allocated by the PCI power control device and
+ * passed to the pwrctl subsystem to trigger a bus rescan and setup a device
+ * link with the device once it's up.
+ */
+struct pci_pwrctl {
+ struct device *dev;
+
+ /* Private, don't use. */
+ struct notifier_block nb;
+ struct device_link *link;
+};
+
+int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl);
+void pci_pwrctl_device_unset_ready(struct pci_pwrctl *pwrctl);
+int devm_pci_pwrctl_device_set_ready(struct device *dev,
+ struct pci_pwrctl *pwrctl);
+
+#endif /* __PCI_PWRCTL_H__ */
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v6 11/16] PCI/pwrctl: create platform devices for child OF nodes of the port node
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
In preparation for introducing PCI device power control - a set of
library functions that will allow powering-up of PCI devices before
they're detected on the PCI bus - we need to populate the devices
defined on the device-tree.
We are reusing the platform bus as it provides us with all the
infrastructure we need to match the pwrctl drivers against the
compatibles from OF nodes.
These platform devices will be probed by the driver core and bound to
the PCI pwrctl drivers we'll introduce later.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/pci/bus.c | 9 ++++++++-
drivers/pci/remove.c | 2 ++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 826b5016a101..17ab41094c4e 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -12,6 +12,7 @@
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
@@ -342,8 +343,14 @@ void pci_bus_add_device(struct pci_dev *dev)
*/
pcibios_bus_add_device(dev);
pci_fixup_device(pci_fixup_final, dev);
- if (pci_is_bridge(dev))
+ if (pci_is_bridge(dev)) {
of_pci_make_dev_node(dev);
+ retval = of_platform_populate(dev->dev.of_node, NULL, NULL,
+ &dev->dev);
+ if (retval)
+ pci_err(dev, "failed to populate child OF nodes (%d)\n",
+ retval);
+ }
pci_create_sysfs_dev_files(dev);
pci_proc_attach_device(dev);
pci_bridge_d3_update(dev);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index d749ea8250d6..fc9db2805888 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/of_platform.h>
#include "pci.h"
static void pci_free_resources(struct pci_dev *dev)
@@ -22,6 +23,7 @@ static void pci_stop_dev(struct pci_dev *dev)
device_release_driver(&dev->dev);
pci_proc_detach_device(dev);
pci_remove_sysfs_dev_files(dev);
+ of_platform_depopulate(&dev->dev);
of_pci_remove_node(dev);
pci_dev_assign_added(dev, false);
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v6 10/16] PCI/pwrctl: reuse the OF node for power controlled devices
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
With PCI power control we deal with two struct device objects bound to
two different drivers but consuming the same OF node. We must not bind
the pinctrl twice. To that end: before setting the OF node of the newly
instantiated PCI device, check if a platform device consuming the same
OF node doesn't already exist on the platform bus and - if so - mark the
PCI device as reusing the OF node.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/pci/of.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 51e3dd0ea5ab..b908fe1ae951 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -6,6 +6,7 @@
*/
#define pr_fmt(fmt) "PCI: OF: " fmt
+#include <linux/cleanup.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -13,6 +14,7 @@
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
+#include <linux/platform_device.h>
#include "pci.h"
#ifdef CONFIG_PCI
@@ -25,16 +27,20 @@
*/
int pci_set_of_node(struct pci_dev *dev)
{
- struct device_node *node;
-
if (!dev->bus->dev.of_node)
return 0;
- node = of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn);
+ struct device_node *node __free(device_node) =
+ of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn);
if (!node)
return 0;
- device_set_node(&dev->dev, of_fwnode_handle(node));
+ struct device *pdev __free(put_device) =
+ bus_find_device_by_of_node(&platform_bus_type, node);
+ if (pdev)
+ dev->bus->dev.of_node_reused = true;
+
+ device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node)));
return 0;
}
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v6 09/16] PCI: hold the rescan mutex when scanning for the first time
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
With the introduction of PCI device power control drivers that will be
able to trigger the port rescan when probing, we need to hold the rescan
mutex during the initial pci_host_probe() too or the two could get in
each other's way.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/pci/probe.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 1325fbae2f28..1802900328a0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -3066,7 +3066,9 @@ int pci_host_probe(struct pci_host_bridge *bridge)
struct pci_bus *bus, *child;
int ret;
+ pci_lock_rescan_remove();
ret = pci_scan_root_bus_bridge(bridge);
+ pci_unlock_rescan_remove();
if (ret < 0) {
dev_err(bridge->dev.parent, "Scanning root bridge failed");
return ret;
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v6 08/16] arm64: dts: qcom: qrb5165-rb5: add the Wifi node
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Add a node for the PMU module of the QCA6391 present on the RB5 board.
Assign its LDO power outputs to the existing Bluetooth module. Add a
node for the PCIe port to sm8250.dtsi and define the WLAN node on it in
the board's .dts and also make it consume the power outputs of the PMU.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 103 ++++++++++++++++++++---
arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 +++
2 files changed, 102 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
index cd0db4f31d4a..24f528fc741f 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -108,6 +108,67 @@ lt9611_3v3: lt9611-3v3 {
regulator-always-on;
};
+ qca6390-pmu {
+ compatible = "qcom,qca6390-pmu";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_en_state>, <&wlan_en_state>;
+
+ vddaon-supply = <&vreg_s6a_0p95>;
+ vddpmu-supply = <&vreg_s2f_0p95>;
+ vddrfa0p95-supply = <&vreg_s2f_0p95>;
+ vddrfa1p3-supply = <&vreg_s8c_1p3>;
+ vddrfa1p9-supply = <&vreg_s5a_1p9>;
+ vddpcie1p3-supply = <&vreg_s8c_1p3>;
+ vddpcie1p9-supply = <&vreg_s5a_1p9>;
+ vddio-supply = <&vreg_s4a_1p8>;
+
+ wlan-enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>;
+ bt-enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>;
+
+ regulators {
+ vreg_pmu_rfa_cmn: ldo0 {
+ regulator-name = "vreg_pmu_rfa_cmn";
+ };
+
+ vreg_pmu_aon_0p59: ldo1 {
+ regulator-name = "vreg_pmu_aon_0p59";
+ };
+
+ vreg_pmu_wlcx_0p8: ldo2 {
+ regulator-name = "vreg_pmu_wlcx_0p8";
+ };
+
+ vreg_pmu_wlmx_0p85: ldo3 {
+ regulator-name = "vreg_pmu_wlmx_0p85";
+ };
+
+ vreg_pmu_btcmx_0p85: ldo4 {
+ regulator-name = "vreg_pmu_btcmx_0p85";
+ };
+
+ vreg_pmu_rfa_0p8: ldo5 {
+ regulator-name = "vreg_pmu_rfa_0p8";
+ };
+
+ vreg_pmu_rfa_1p2: ldo6 {
+ regulator-name = "vreg_pmu_rfa_1p2";
+ };
+
+ vreg_pmu_rfa_1p7: ldo7 {
+ regulator-name = "vreg_pmu_rfa_1p7";
+ };
+
+ vreg_pmu_pcie_0p9: ldo8 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_pcie_1p8: ldo9 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+ };
+ };
+
thermal-zones {
conn-thermal {
polling-delay-passive = <0>;
@@ -734,6 +795,23 @@ &pcie0_phy {
vdda-pll-supply = <&vreg_l9a_1p2>;
};
+&pcieport0 {
+ wifi@0 {
+ compatible = "pci17cb,1101";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
+ vddaon-supply = <&vreg_pmu_aon_0p59>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p7-supply = <&vreg_pmu_rfa_1p7>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ };
+};
+
&pcie1 {
status = "okay";
};
@@ -1303,6 +1381,14 @@ sdc2_card_det_n: sd-card-det-n-state {
function = "gpio";
bias-pull-up;
};
+
+ wlan_en_state: wlan-default-state {
+ pins = "gpio20";
+ function = "gpio";
+ drive-strength = <16>;
+ output-low;
+ bias-pull-up;
+ };
};
&uart6 {
@@ -1311,17 +1397,12 @@ &uart6 {
bluetooth {
compatible = "qcom,qca6390-bt";
- pinctrl-names = "default";
- pinctrl-0 = <&bt_en_state>;
-
- enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>;
-
- vddio-supply = <&vreg_s4a_1p8>;
- vddpmu-supply = <&vreg_s2f_0p95>;
- vddaon-supply = <&vreg_s6a_0p95>;
- vddrfa0p9-supply = <&vreg_s2f_0p95>;
- vddrfa1p3-supply = <&vreg_s8c_1p3>;
- vddrfa1p9-supply = <&vreg_s5a_1p9>;
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
+ vddaon-supply = <&vreg_pmu_aon_0p59>;
+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p7-supply = <&vreg_pmu_rfa_1p7>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index 7f2333c9d17d..06decf15a2d3 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -2203,6 +2203,16 @@ pcie0: pcie@1c00000 {
dma-coherent;
status = "disabled";
+
+ pcieport0: pcie@0 {
+ device_type = "pci";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ bus-range = <0x01 0xff>;
+ };
};
pcie0_phy: phy@1c06000 {
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v6 07/16] arm64: dts: qcom: sm8650-qrd: add the Wifi node
From: Bartosz Golaszewski @ 2024-03-25 13:16 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Kalle Valo, Bjorn Andersson,
Konrad Dybcio, Liam Girdwood, Mark Brown, Catalin Marinas,
Will Deacon, Bjorn Helgaas, Bartosz Golaszewski, Saravana Kannan,
Geert Uytterhoeven, Arnd Bergmann, Neil Armstrong,
Marek Szyprowski, Alex Elder, Srini Kandagatla,
Greg Kroah-Hartman, Abel Vesa, Manivannan Sadhasivam,
Lukas Wunner, Dmitry Baryshkov
Cc: linux-bluetooth, netdev, devicetree, linux-kernel, linux-wireless,
linux-arm-msm, linux-arm-kernel, linux-pci, linux-pm,
Bartosz Golaszewski
In-Reply-To: <20240325131624.26023-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Describe the ath12k WLAN on-board the WCN7850 module present on the
board.
[Neil: authored the initial version of the change]
Co-developed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
arch/arm64/boot/dts/qcom/sm8650-qrd.dts | 89 +++++++++++++++++++++++++
arch/arm64/boot/dts/qcom/sm8650.dtsi | 10 +++
2 files changed, 99 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sm8650-qrd.dts b/arch/arm64/boot/dts/qcom/sm8650-qrd.dts
index b07cac2e5bc8..c87d21115716 100644
--- a/arch/arm64/boot/dts/qcom/sm8650-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8650-qrd.dts
@@ -203,6 +203,71 @@ wcd_codec_headset_in: endpoint {
};
};
};
+
+ wcn7850-pmu {
+ compatible = "qcom,wcn7850-pmu";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_en>;
+
+ wlan-enable-gpios = <&tlmm 16 GPIO_ACTIVE_HIGH>;
+ /*
+ * TODO Add bt-enable-gpios once the Bluetooth driver is
+ * converted to using the power sequencer.
+ */
+
+ vdd-supply = <&vreg_s4i_0p85>;
+ vddio-supply = <&vreg_l15b_1p8>;
+ vddio1p2-supply = <&vreg_l3c_1p2>;
+ vddaon-supply = <&vreg_s2c_0p8>;
+ vdddig-supply = <&vreg_s3c_0p9>;
+ vddrfa1p2-supply = <&vreg_s1c_1p2>;
+ vddrfa1p8-supply = <&vreg_s6c_1p8>;
+
+ clocks = <&rpmhcc RPMH_RF_CLK1>;
+
+ regulators {
+ vreg_pmu_rfa_cmn: ldo0 {
+ regulator-name = "vreg_pmu_rfa_cmn";
+ };
+
+ vreg_pmu_aon_0p59: ldo1 {
+ regulator-name = "vreg_pmu_aon_0p59";
+ };
+
+ vreg_pmu_wlcx_0p8: ldo2 {
+ regulator-name = "vreg_pmu_wlcx_0p8";
+ };
+
+ vreg_pmu_wlmx_0p85: ldo3 {
+ regulator-name = "vreg_pmu_wlmx_0p85";
+ };
+
+ vreg_pmu_btcmx_0p85: ldo4 {
+ regulator-name = "vreg_pmu_btcmx_0p85";
+ };
+
+ vreg_pmu_rfa_0p8: ldo5 {
+ regulator-name = "vreg_pmu_rfa_0p8";
+ };
+
+ vreg_pmu_rfa_1p2: ldo6 {
+ regulator-name = "vreg_pmu_rfa_1p2";
+ };
+
+ vreg_pmu_rfa_1p8: ldo7 {
+ regulator-name = "vreg_pmu_rfa_1p8";
+ };
+
+ vreg_pmu_pcie_0p9: ldo8 {
+ regulator-name = "vreg_pmu_pcie_0p9";
+ };
+
+ vreg_pmu_pcie_1p8: ldo9 {
+ regulator-name = "vreg_pmu_pcie_1p8";
+ };
+ };
+ };
};
&apps_rsc {
@@ -845,6 +910,23 @@ &pcie0 {
status = "okay";
};
+&pcieport0 {
+ wifi@0 {
+ compatible = "pci17cb,1107";
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+
+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn>;
+ vddaon-supply = <&vreg_pmu_aon_0p59>;
+ vddwlcx-supply = <&vreg_pmu_wlcx_0p8>;
+ vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
+ vddrfa0p8-supply = <&vreg_pmu_rfa_0p8>;
+ vddrfa1p2-supply = <&vreg_pmu_rfa_1p2>;
+ vddrfa1p8-supply = <&vreg_pmu_rfa_1p8>;
+ vddpcie0p9-supply = <&vreg_pmu_pcie_0p9>;
+ vddpcie1p8-supply = <&vreg_pmu_pcie_1p8>;
+ };
+};
+
&pcie0_phy {
vdda-phy-supply = <&vreg_l1i_0p88>;
vdda-pll-supply = <&vreg_l3i_1p2>;
@@ -1139,6 +1221,13 @@ wcd_default: wcd-reset-n-active-state {
bias-disable;
output-low;
};
+
+ wlan_en: wlan-en-state {
+ pins = "gpio16";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-down;
+ };
};
&uart14 {
diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
index 78757f01a7d8..693857905fe9 100644
--- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
@@ -2293,6 +2293,16 @@ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
dma-coherent;
status = "disabled";
+
+ pcieport0: pcie@0 {
+ device_type = "pci";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ bus-range = <0x01 0xff>;
+ };
};
pcie0_phy: phy@1c06000 {
--
2.40.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox