power: sequencing: implement the subsystem and add first users
Subsystems (8)
cover power: sequencing: implement the subsystem and add first users
From: Bartosz Golaszewski <[email protected]>
I'd like to preface the cover letter by saying right away that this series is not complete. It's an RFC that presents my approach and is sent to the list for discussion. There are no DT bindings nor docs in Documentation/ yet. Please review it as an RFC and not an upstreambound series. If the approach is accepted as correct, I'll add missing bits.
The RFC[1] presenting my proposed device-tree representation of the QCA6391 package present on the RB5 board - while not really officially accepted - was not outright rejected which is a good sign.
This series incorporates it and builds a proposed power sequencing subsystem together with the first dedicated driver around it. Then it adds first two users: the Bluetooth and WLAN modules of the QCA6391.
The Bluetooth part is pretty straightforward. The WLAN however is a PCIe device and as such needs to be powered-up *before* it's detected on the PCI bus. To that end, we modify the PCI core to instantiate platform devices for existing DT child nodes of the PCIe ports. For those nodes for which a power-sequencing driver exists, we bind it and let it probe. The driver then triggers a rescan of the PCI bus with the aim of detecting the now powered-on device. The device will consume the same DT node as the platform, power-sequencing device. We use device links to make the latter become the parent of the former.
The main advantage of the above approach (both for PCI as well as generic power sequencers) is that we don't introduce significant changes in DT bindings and don't introduce new properties. We merely define new resources.
Bartosz Golaszewski (9):
of: provide a cleanup helper for OF nodes
arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
power: sequencing: new subsystem
power: pwrseq: add a driver for the QCA6390 PMU module
Bluetooth: qca: use the power sequencer for QCA6390
PCI: create platform devices for child OF nodes of the port node
PCI: hold the rescan mutex when scanning for the first time PCI/pwrctl: add PCI power control core code
PCI/pwrctl: add a PCI power control driver for power sequenced devices
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 128 +++++- arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 + drivers/bluetooth/hci_qca.c | 30 ++ drivers/pci/Kconfig | 1 + drivers/pci/Makefile | 1 + drivers/pci/bus.c | 9 +- drivers/pci/probe.c | 2 + drivers/pci/pwrctl/Kconfig | 17 + drivers/pci/pwrctl/Makefile | 4 + drivers/pci/pwrctl/core.c | 82 ++++ drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 83 ++++ drivers/pci/remove.c | 2 + drivers/power/Kconfig | 1 + drivers/power/Makefile | 1 + drivers/power/sequencing/Kconfig | 28 ++ drivers/power/sequencing/Makefile | 6 + drivers/power/sequencing/core.c | 482 ++++++++++++++++++++++ drivers/power/sequencing/pwrseq-qca6390.c | 232 +++++++++++ include/linux/of.h | 4 + include/linux/pci-pwrctl.h | 24 ++ include/linux/pwrseq/consumer.h | 53 +++ include/linux/pwrseq/provider.h | 41 ++ 22 files changed, 1229 insertions(+), 12 deletions(-) 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 drivers/pci/pwrctl/pci-pwrctl-pwrseq.c 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 drivers/power/sequencing/pwrseq-qca6390.c create mode 100644 include/linux/pci-pwrctl.h create mode 100644 include/linux/pwrseq/consumer.h create mode 100644 include/linux/pwrseq/provider.h
Signature · 1 line
2.40.1
RFC 1/9 of: provide a cleanup helper for OF nodes
From: Bartosz Golaszewski <[email protected]>
Allow to use __free() to automatically put references to OF nodes.
--- include/linux/of.h | 4 ++++ 1 file changed, 4 insertions(+)
include/linux/of.h +4 -0
@@ -11,6 +11,8 @@* Updates for SPARC64 by David S. Miller * Derived from PowerPC and Sparc prom.h files by Stephen Rothwell, IBM Corp. */ + +#include <linux/cleanup.h> #include <linux/types.h> #include <linux/bitops.h> #include <linux/errno.h>
@@ -887,6 +889,8 @@ static inline const void *of_device_get_match_data(const struct device *dev)#define of_match_node (_matches, _node) NULL#endif /* CONFIG_OF */ +DEFINE_FREE(of_node, struct device_node *, if (_T) of_node_put(_T)) + /* Default string compare functions, Allow arch asm/prom.h to override */#if !defined(of_compat_cmp)#define of_compat_cmp (s1, s2, l) strcasecmp((s1), (s2))
Signature · 1 line
2.40.1
This is an automated email and please do not reply to this email.
Dear Submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.
----- Output -----
error: patch failed: arch/arm64/boot/dts/qcom/qrb5165-rb5.dts:1303
error: arch/arm64/boot/dts/qcom/qrb5165-rb5.dts: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch
Please resolve the issue and submit the patches again.
---
Regards,
Linux Bluetooth
Rob Herring
maintainerRe: [RFC 1/9] of: provide a cleanup helper for OF nodes
In reply to Bartosz GolaszewskiQuoted 4 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
Allow to use
__free()to automatically put references to OF nodes.
Jonathan has already been working on this[1].
Rob
Re: [RFC 1/9] of: provide a cleanup helper for OF nodes
Quoted 5 lines · Rob Herring
Quoted 3 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
Quoted 7 lines
Quoted 1 line
Allow to use
__free()to automatically put references to OF nodes.Jonathan has already been working on this[1].
Rob
Thanks, I will watch this but for now I'll have to stick to carrying it in my series until it gets upstream.
Bart
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=822186
---Test result---
Test Summary:
CheckPatch FAIL 11.15 seconds GitLint PASS 3.00 seconds SubjectPrefix FAIL 1.39 seconds BuildKernel PASS 27.79 seconds CheckAllWarning PASS 30.75 seconds CheckSparse PASS 37.46 seconds CheckSmatch PASS 99.82 seconds BuildKernel32 PASS 27.11 seconds TestRunnerSetup PASS 499.56 seconds TestRunner_l2cap-tester PASS 17.17 seconds TestRunner_iso-tester PASS 28.35 seconds TestRunner_bnep-tester PASS 4.85 seconds TestRunner_mgmt-tester FAIL 106.30 seconds TestRunner_rfcomm-tester PASS 7.42 seconds TestRunner_sco-tester PASS 13.23 seconds TestRunner_ioctl-tester PASS 7.87 seconds TestRunner_mesh-tester PASS 5.92 seconds TestRunner_smp-tester PASS 6.90 seconds TestRunner_userchan-tester PASS 5.00 seconds IncrementalBuild PASS 60.54 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[RFC,2/9] arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
WARNING: DT compatible string "qcom,qca6390-pmu" appears un-documented -- check ./Documentation/devicetree/bindings/ #138: FILE: arch/arm64/boot/dts/qcom/qrb5165-rb5.dts:112:
+ compatible = "qcom,qca6390-pmu";
WARNING: DT compatible string "pci17cb,1101" appears un-documented -- check ./Documentation/devicetree/bindings/ #227: FILE: arch/arm64/boot/dts/qcom/qrb5165-rb5.dts:820:
+ compatible = "pci17cb,1101";
WARNING: DT compatible string vendor "pci17cb" appears un-documented -- check ./Documentation/devicetree/bindings/vendor-prefixes.yaml #227: FILE: arch/arm64/boot/dts/qcom/qrb5165-rb5.dts:820:
+ compatible = "pci17cb,1101";
total: 0 errors, 3 warnings, 168 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/src/13541336.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[RFC,3/9] power: sequencing: new subsystem
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? #158:
new file mode 100644
WARNING: ENOSYS means 'invalid syscall nr' and nothing else #706: FILE: include/linux/pwrseq/consumer.h:28:
+ return ERR_PTR(-ENOSYS);
WARNING: ENOSYS means 'invalid syscall nr' and nothing else #716: FILE: include/linux/pwrseq/consumer.h:38:
+ return ERR_PTR(-ENOSYS);
WARNING: ENOSYS means 'invalid syscall nr' and nothing else #721: FILE: include/linux/pwrseq/consumer.h:43:
+ return -ENOSYS;
WARNING: ENOSYS means 'invalid syscall nr' and nothing else #726: FILE: include/linux/pwrseq/consumer.h:48:
+ return -ENOSYS;
total: 0 errors, 5 warnings, 600 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/src/13541337.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[RFC,4/9] power: pwrseq: add a driver for the QCA6390 PMU module
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? #165:
new file mode 100644
WARNING: DT compatible string "qcom,qca6390-pmu" appears un-documented -- check ./Documentation/devicetree/bindings/ #383: FILE: drivers/power/sequencing/pwrseq-qca6390.c:214:
+ .compatible = "qcom,qca6390-pmu",
total: 0 errors, 2 warnings, 256 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/src/13541338.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[RFC,8/9] PCI/pwrctl: add PCI power control core code
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? #170:
new file mode 100644
total: 0 errors, 1 warnings, 130 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/src/13541342.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[RFC,9/9] PCI/pwrctl: add a PCI power control driver for power sequenced devices
WARNING: please write a help paragraph that fully describes the config symbol #139: FILE: drivers/pci/pwrctl/Kconfig:8:
+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.
+
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? #159:
new file mode 100644
WARNING: DT compatible string "pci17cb,1101" appears un-documented -- check ./Documentation/devicetree/bindings/ #229: FILE: drivers/pci/pwrctl/pci-pwrctl-pwrseq.c:66:
+ .compatible = "pci17cb,1101",
WARNING: DT compatible string vendor "pci17cb" appears un-documented -- check ./Documentation/devicetree/bindings/vendor-prefixes.yaml #229: FILE: drivers/pci/pwrctl/pci-pwrctl-pwrseq.c:66:
+ .compatible = "pci17cb,1101",
total: 0 errors, 4 warnings, 100 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/src/13541343.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
##############################
Test: SubjectPrefix - FAIL
Desc: Check subject contains "Bluetooth" prefix Output:
"Bluetooth: " prefix is not specified in the subject "Bluetooth: " prefix is not specified in the subject "Bluetooth: " prefix is not specified in the subject "Bluetooth: " prefix is not specified in the subject "Bluetooth: " prefix is not specified in the subject "Bluetooth: " prefix is not specified in the subject "Bluetooth: " prefix is not specified in the subject "Bluetooth: " prefix is not specified in the subject
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner Output:
Total: 497, Passed: 486 (97.8%), Failed: 5, Not Run: 6
Failed Test Cases
Read Ext Controller Info 1 Failed 0.083 seconds Read Ext Controller Info 2 Failed 0.089 seconds Read Ext Controller Info 3 Failed 0.092 seconds Read Ext Controller Info 4 Failed 0.085 seconds Read Ext Controller Info 5 Failed 0.104 seconds
---
Regards,
Linux Bluetooth
RFC 2/9 arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
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.
--- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 128 +++++++++++++++++++++-- arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 ++ 2 files changed, 127 insertions(+), 11 deletions(-)
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +117 -11
@@ -108,6 +108,87 @@ lt9611_3v3: lt9611-3v3 { regulator-always-on; }; + qca6390_pmu: pmu@0 { + 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>; + vddrfa1-supply = <&vreg_s2f_0p95>; + vddrfa2-supply = <&vreg_s8c_1p3>; + vddrfa3-supply = <&vreg_s5a_1p9>; + vddpcie1-supply = <&vreg_s8c_1p3>; + vddpcie2-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"; + regulator-min-microvolt = <760000>; + regulator-max-microvolt = <840000>; + }; + + vreg_pmu_aon_0p59: ldo1 { + regulator-name = "vreg_pmu_aon_0p59"; + regulator-min-microvolt = <540000>; + regulator-max-microvolt = <840000>; + }; + + vreg_pmu_wlcx_0p8: ldo2 { + regulator_name = "vreg_pmu_wlcx_0p8"; + regulator-min-microvolt = <760000>; + regulator-max-microvolt = <840000>; + }; + + vreg_pmu_wlmx_0p85: ldo3 { + regulator-name = "vreg_pmu_wlmx_0p85"; + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <890000>; + }; + + vreg_pmu_btcmx_0p85: ldo4 { + regulator-name = "vreg_pmu_btcmx_0p85"; + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <890000>; + }; + + vreg_pmu_rfa_0p8: ldo5 { + regulator-name = "vreg_pmu_rfa_0p8"; + regulator-min-microvolt = <760000>; + regulator-max-microvolt = <840000>; + }; + + vreg_pmu_rfa_1p2: ldo6 { + regulator-name = "vreg_pmu_rfa_1p2"; + regulator-min-microvolt = <1187000>; + regulator-max-microvolt = <1313000>; + }; + + vreg_pmu_rfa_1p7: ldo7 { + regulator_name = "vreg_pmu_rfa_1p7"; + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <1890000>; + }; + + vreg_pmu_pcie_0p9: ldo8 { + regulator_name = "vreg_pmu_pcie_0p9"; + regulator-min-microvolt = <870000>; + regulator-max-microvolt = <970000>; + }; + + vreg_pmu_pcie_1p8: ldo9 { + regulator_name = "vreg_pmu_pcie_1p8"; + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <1890000>; + }; + }; + }; + thermal-zones { conn-thermal { polling-delay-passive = <0>;
@@ -734,6 +815,24 @@ &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>; + vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1-supply = <&vreg_pmu_rfa_1p2>; + vddrfa2-supply = <&vreg_pmu_rfa_1p7>; + vddpcie0-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1-supply = <&vreg_pmu_pcie_1p8>; + }; +}; + &pcie1 { status = "okay"; };
@@ -1303,6 +1402,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 +1418,16 @@ &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>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1-supply = <&vreg_pmu_rfa_1p2>; + vddrfa2-supply = <&vreg_pmu_rfa_1p7>; + vddpcie0-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1-supply = <&vreg_pmu_pcie_1p8>; }; };
arch/arm64/boot/dts/qcom/sm8250.dtsi +10 -0
@@ -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 {
Signature · 1 line
2.40.1
Bjorn Andersson
maintainerRe: [RFC 2/9] arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
Quoted 34 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
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.dtsiand 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 <[email protected]>--- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 128 +++++++++++++++++++++-- arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 ++ 2 files changed, 127 insertions(+), 11 deletions(-)arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +13
-0@@ -108,6 +108,87 @@ lt9611_3v3: lt9611-3v3 { regulator-always-on; }; + qca6390_pmu: pmu@0 { + 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>; + vddrfa1-supply = <&vreg_s2f_0p95>; + vddrfa2-supply = <&vreg_s8c_1p3>; + vddrfa3-supply = <&vreg_s5a_1p9>; + vddpcie1-supply = <&vreg_s8c_1p3>; + vddpcie2-supply = <&vreg_s5a_1p9>;
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts lt9611_3v3: lt9611-3v3 { · line 133
Quoted 10 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +10
-0+ 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"; + regulator-min-microvolt = <760000>; + regulator-max-microvolt = <840000>;
I'm still not convinced that the PMU has a set of LDOs, and looking at your implementation you neither register these with the regulator framework, nor provide any means of controlling the state or voltage of these "regulators".
[..]
Quoted 17 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +0
-11&uart6 {@@ -1311,17 +1418,16 @@ &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>;
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts &uart6 { · line 1430
Quoted 10 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +10
-0+ vddrfacmn-supply = <&vreg_pmu_rfa_cmn>; + vddaon-supply = <&vreg_pmu_aon_0p59>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1-supply = <&vreg_pmu_rfa_1p2>; + vddrfa2-supply = <&vreg_pmu_rfa_1p7>; + vddpcie0-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1-supply = <&vreg_pmu_pcie_1p8>;
As I asked before, why does bluetooth suddenly care about PCIe supplies?
Regards,
Bjorn
Quoted 27 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +0
-0}; };arch/arm64/boot/dts/qcom/sm8250.dtsi +10
-0@@ -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 {Signature · 1 line
2.40.1
Re: [RFC 2/9] arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
Quoted 43 lines · Bjorn Andersson
Quoted 41 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
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.dtsiand 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 <[email protected]>--- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 128 +++++++++++++++++++++-- arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 ++ 2 files changed, 127 insertions(+), 11 deletions(-)arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +20
-0@@ -108,6 +108,87 @@ lt9611_3v3: lt9611-3v3 { regulator-always-on; }; + qca6390_pmu: pmu@0 { + 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>; + vddrfa1-supply = <&vreg_s2f_0p95>; + vddrfa2-supply = <&vreg_s8c_1p3>; + vddrfa3-supply = <&vreg_s5a_1p9>; + vddpcie1-supply = <&vreg_s8c_1p3>; + vddpcie2-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 {
Quoted 8 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts lt9611_3v3: lt9611-3v3 { · line 133
Quoted 3 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +3
-0+ regulator-name = "vreg_pmu_rfa_cmn"; + regulator-min-microvolt = <760000>; + regulator-max-microvolt = <840000>;I'm still not convinced that the PMU has a set of LDOs, and looking at your implementation you neither register these with the regulator framework, nor provide any means of controlling the state or voltage of these "regulators".
Please take a look at the description of VDD08_PMU_RFA_CMN and VDD_PMU_AON_I pins in the spec (80-WL522-1, page 25). I'm not sure if I'm allowed to quote it, so I won't. But the spec clearly describes VDD_PMU_AON_I as 0.95V LDO input and VDD08_PMU_RFA_CMN as 0.8 LDO output generated using that input. I think this proves that the on-chip PMU has actual LDOs.
I must admit, I find this representation very verbose, but on the other hand Bartosz is right, it represents actual hardware. Maybe we can drop some of the properties of corresponding regulator blocks, as we don't actually need them and they are internal properties of the hardware.
Quoted 23 lines
[..]
Quoted 21 lines
&uart6 {
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +4
-11@@ -1311,17 +1418,16 @@ &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>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
Quoted 8 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts &pcie0_phy { · line 832
Quoted 6 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +6
-0+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1-supply = <&vreg_pmu_rfa_1p2>; + vddrfa2-supply = <&vreg_pmu_rfa_1p7>; + vddpcie0-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1-supply = <&vreg_pmu_pcie_1p8>;As I asked before, why does bluetooth suddenly care about PCIe supplies?
Power sequencing in the same spec describes that PCIe voltages should be up even if only BT is being brought up. PMU itself handles distributing voltages according to the actual load needs.
Quoted 32 lines
Regards,
BjornQuoted 27 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +0
-0}; };arch/arm64/boot/dts/qcom/sm8250.dtsi +10
-1@@ -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
Signature · 2 lines
With best wishes Dmitry
Bjorn Andersson
maintainerRe: Re: [RFC 2/9] arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
Quoted 53 lines · Dmitry Baryshkov
Quoted 43 lines · Bjorn Andersson
Quoted 41 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
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.dtsiand 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 <[email protected]>--- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 128 +++++++++++++++++++++-- arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 ++ 2 files changed, 127 insertions(+), 11 deletions(-)arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +20
-0@@ -108,6 +108,87 @@ lt9611_3v3: lt9611-3v3 { regulator-always-on; }; + qca6390_pmu: pmu@0 { + 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>; + vddrfa1-supply = <&vreg_s2f_0p95>; + vddrfa2-supply = <&vreg_s8c_1p3>; + vddrfa3-supply = <&vreg_s5a_1p9>; + vddpcie1-supply = <&vreg_s8c_1p3>; + vddpcie2-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 {Quoted 8 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts lt9611_3v3: lt9611-3v3 { · line 133
Quoted 3 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +3
-0+ regulator-name = "vreg_pmu_rfa_cmn"; + regulator-min-microvolt = <760000>; + regulator-max-microvolt = <840000>;I'm still not convinced that the PMU has a set of LDOs, and looking at your implementation you neither register these with the regulator framework, nor provide any means of controlling the state or voltage of these "regulators".
Quoted 7 lines
Please take a look at the description of
VDD08_PMU_RFA_CMNandVDD_PMU_AON_Ipins in the spec (80-WL522-1, page 25). I'm not sure if I'm allowed to quote it, so I won't. But the spec clearly describesVDD_PMU_AON_Ias 0.95V LDO input andVDD08_PMU_RFA_CMNas 0.8 LDO output generated using that input. I think this proves that the on-chip PMU has actual LDOs.
You're correct, thank you for the pointer and clarification. I now agree with you, the PMU consumes what I saw as the chip input supplies, and based on WL_EN and BT_EN will provide power on pads, which are then externally routed to respective block.
Quoted 2 lines
I must admit, I find this representation very verbose, but on the other hand Bartosz is right, it represents actual hardware.
I agree, this is actual hardware.
Quoted 5 lines
Maybe we
can drop some of the properties of corresponding regulator blocks, as we don't actually need them and they are internal properties of the hardware.
To me this really looks like a fancy "regulator-fixed" with multiple inputs, two gpios and multiple outputs.
This would also imply that we don't need to invent the power sequence framework to tie WiFi and BT to the PMU's state.
The PMU is a thing, so we can represent that in DeviceTree, it consumes M input power rails, and two gpios, it provides N WiFi supplies and O BT supplies (with some overlap between N and O). The WiFi node consumes its N supplies, the BT node consumes its O supplies.
If any of the N regulators are requested enabled the qca6390-pmu driver enables all M input rails, then enables WL_EN. If any of the O BT regulators are requested enabled, the driver enables all M input rails, then enables BT_EN.
Quoted 32 lines
Quoted 23 lines
[..]
Quoted 21 lines
&uart6 {
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +4
-11@@ -1311,17 +1418,16 @@ &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>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;Quoted 8 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts &pcie0_phy { · line 832
Quoted 6 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +6
-0+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1-supply = <&vreg_pmu_rfa_1p2>; + vddrfa2-supply = <&vreg_pmu_rfa_1p7>; + vddpcie0-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1-supply = <&vreg_pmu_pcie_1p8>;As I asked before, why does bluetooth suddenly care about PCIe supplies?
Quoted 4 lines
Power sequencing in the same spec describes that PCIe voltages should be up even if only BT is being brought up. PMU itself handles distributing voltages according to the actual load needs.
You're right, the power sequence diagram in the docs do indicate that VDD13_PMU_PCIE_I and VDD19_PMU_PCIE_I should be enabled before either WL_EN or BT_EN are driven high.
But I don't see anything stating that the output from the PMU (VDD09_PMU_PCIE) in turn is fed to the bluetooth block.
Regards,
Bjorn
Quoted 37 lines
Quoted 32 lines
Regards,
BjornQuoted 27 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +0
-0}; };arch/arm64/boot/dts/qcom/sm8250.dtsi +10
-1@@ -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
Signature · 2 lines
With best wishes Dmitry
Re: [RFC 2/9] arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
In reply to Bjorn AnderssonQuoted 1 line · Bjorn Andersson
[snip]
Quoted 6 lines
Quoted 6 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +6
-0+ + wlan-enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + bt-enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; + + regulators { + vreg_pmu_rfa_cmn: ldo0 {
Quoted 9 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts lt9611_3v3: lt9611-3v3 { · line 133
Quoted 3 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +3
-0+ regulator-name = "vreg_pmu_rfa_cmn"; + regulator-min-microvolt = <760000>; + regulator-max-microvolt = <840000>;I'm still not convinced that the PMU has a set of LDOs, and looking at your implementation you neither register these with the regulator framework, nor provide any means of controlling the state or voltage of these "regulators".
Why are you so fixated on the driver implementation matching the device-tree 1:1? I asked that question before - what does it matter if we use the regulator subsystem or not? This is just what HW there is. What we do with that knowledge in C is irrelevant. Yes, I don't use the regulator subsystem because it's unnecessary and would actually get in the way of the power sequencing. But it doesn't change the fact that the regulators *are* there so let's show them.
What isn't there is a "power sequencer device". This was the main concern about Dmitry's implementation before. We must not have "bt-pwrseq = <&...>;" -like properties in device-tree because there is no device that this would represent. But there *are* LDO outputs of the PMU which can be modelled and then used in C to retrieve the power sequencer and this is what I'm proposing.
Bartosz
Quoted 22 lines
[..]
Quoted 21 lines
&uart6 {
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +4
-11@@ -1311,17 +1418,16 @@ &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>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;
Quoted 9 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts &pcie0_phy { · line 832
Quoted 6 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +6
-0+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1-supply = <&vreg_pmu_rfa_1p2>; + vddrfa2-supply = <&vreg_pmu_rfa_1p7>; + vddpcie0-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1-supply = <&vreg_pmu_pcie_1p8>;As I asked before, why does bluetooth suddenly care about PCIe supplies?
Yes, I forgot to remove it, I'll do it next time.
Bartosz
[snip]
Bjorn Andersson
maintainerRe: Re: [RFC 2/9] arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
Quoted 21 lines · Bartosz Golaszewski
Quoted 1 line · Bjorn Andersson
[snip]
Quoted 6 lines
Quoted 6 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +6
-0+ + wlan-enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + bt-enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; + + regulators { + vreg_pmu_rfa_cmn: ldo0 {Quoted 9 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts lt9611_3v3: lt9611-3v3 { · line 133
Quoted 3 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +3
-0+ regulator-name = "vreg_pmu_rfa_cmn"; + regulator-min-microvolt = <760000>; + regulator-max-microvolt = <840000>;I'm still not convinced that the PMU has a set of LDOs, and looking at your implementation you neither register these with the regulator framework, nor provide any means of controlling the state or voltage of these "regulators".
Quoted 3 lines
Why are you so fixated on the driver implementation matching the device-tree 1:1? I asked that question before - what does it matter if we use the regulator subsystem or not?
I'm sorry, I must have missed this question. I'm not questioning why the DT needs to match the Linux implementation, I was really questioning if the hardware you describe here existed.
Quoted 4 lines
This is just what HW there is.
What we do with that knowledge in C is irrelevant. Yes, I don't use the regulator subsystem because it's unnecessary and would actually get in the way of the power sequencing.
Then describe that in your commit messages.
Quoted 5 lines
But it doesn't change the fact
that the regulators *are* there so let's show them.What isn't there is a "power sequencer device". This was the main concern about Dmitry's implementation before.
I don't agree. The concerns that I saw being raised with Dmitry's proposed design was that he used connected the WiFi controller to the QCA6391 using power-domains, etc.
Quoted 6 lines
We must not have
"bt-pwrseq = <&...>;" -like properties in device-tree because there is no device that this would represent. But there *are* LDO outputs of the PMU which can be modelled and then used in C to retrieve the power sequencer and this is what I'm proposing.
Performing device-specific power sequences is extremely common, but we so far don't have a separate abstraction of this because it's generally not an matter external to any given device.
If we're going to introduce a power sequence framework, it needs to be made very clear that it is there to solve the problem that you have devices on separate busses that need to share that sequence.
This also implies that for most examples out there where we have a need for doing "PCI power sequencing", I don't think we would use the power-sequence framework.
Regards,
Bjorn
Quoted 39 lines
Bartosz
Quoted 22 lines
[..]
Quoted 21 lines
&uart6 {
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +4
-11@@ -1311,17 +1418,16 @@ &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>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>;Quoted 9 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts &pcie0_phy { · line 832
Quoted 6 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +6
-0+ vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1-supply = <&vreg_pmu_rfa_1p2>; + vddrfa2-supply = <&vreg_pmu_rfa_1p7>; + vddpcie0-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1-supply = <&vreg_pmu_pcie_1p8>;As I asked before, why does bluetooth suddenly care about PCIe supplies?
Yes, I forgot to remove it, I'll do it next time.
Bartosz
[snip]
Bjorn Andersson
maintainerRe: [RFC 2/9] arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
In reply to Bartosz GolaszewskiQuoted 18 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
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.dtsiand 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 <[email protected]>--- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 128 +++++++++++++++++++++-- arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 ++ 2 files changed, 127 insertions(+), 11 deletions(-)arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +0
-0
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts lt9611_3v3: lt9611-3v3 { · line 111
Quoted 4 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +1
-0@@ -108,6 +108,87 @@ lt9611_3v3: lt9611-3v3 { regulator-always-on; }; + qca6390_pmu: pmu@0 {
The node doesn't have an address, so why does it have a unit address? Also, the node isn't referenced, so please skip the label.
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts lt9611_3v3: lt9611-3v3 { · line 124
Quoted 13 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +13
-0+ 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>; + vddrfa1-supply = <&vreg_s2f_0p95>; + vddrfa2-supply = <&vreg_s8c_1p3>; + vddrfa3-supply = <&vreg_s5a_1p9>; + vddpcie1-supply = <&vreg_s8c_1p3>; + vddpcie2-supply = <&vreg_s5a_1p9>; + vddio-supply = <&vreg_s4a_1p8>;
So, after studying the datasheet for this. The names of the pins seems to come from the existing binding(s). As you're introducing a new binding (and driver) for qcom,qca6390-pmu, please use the pad names from qca6390.
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts lt9611_3v3: lt9611-3v3 { · line 133
Quoted 9 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +9
-0+ + 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"; + regulator-min-microvolt = <760000>; + regulator-max-microvolt = <840000>;
The min/max operating range of the regulator is something we provide in the implementation, in DeviceTree you should specify the expected operating voltage. Based on the TYP value this should be regulator-min-microvolt = regulator-max-microvolt = 0.8V.
Quoted 7 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +7
-0+ }; + + vreg_pmu_aon_0p59: ldo1 { + regulator-name = "vreg_pmu_aon_0p59"; + regulator-min-microvolt = <540000>; + regulator-max-microvolt = <840000>; + };
[..]
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts sdc2_card_det_n: sd-card-det-n-state { · line 1410
Quoted 10 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +6
-0@@ -1303,6 +1402,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;
Please omit output-low here.
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts sdc2_card_det_n: sd-card-det-n-state { · line 1411
Quoted 1 line
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +1
-0+ bias-pull-up;
Why do you drive it low and pull it high? bias-disable sounds more appropriate.
Regards,
Bjorn
Quoted 56 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +11
-11+ }; }; &uart6 {@@ -1311,17 +1418,16 @@ &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>; + vddwlcx-supply = <&vreg_pmu_wlcx_0p8>; + vddwlmx-supply = <&vreg_pmu_wlmx_0p85>; + vddbtcmx-supply = <&vreg_pmu_btcmx_0p85>; + vddrfa0-supply = <&vreg_pmu_rfa_0p8>; + vddrfa1-supply = <&vreg_pmu_rfa_1p2>; + vddrfa2-supply = <&vreg_pmu_rfa_1p7>; + vddpcie0-supply = <&vreg_pmu_pcie_0p9>; + vddpcie1-supply = <&vreg_pmu_pcie_1p8>; }; };arch/arm64/boot/dts/qcom/sm8250.dtsi +10
-0@@ -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 {Signature · 1 line
2.40.1
Re: [RFC 2/9] arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
In reply to Bartosz GolaszewskiQuoted 18 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
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.dtsiand 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 <[email protected]>--- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 128 +++++++++++++++++++++-- arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 ++ 2 files changed, 127 insertions(+), 11 deletions(-)arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +0
-0
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts lt9611_3v3: lt9611-3v3 { · line 111
Quoted 4 lines
arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +1
-0@@ -108,6 +108,87 @@ lt9611_3v3: lt9611-3v3 { regulator-always-on; }; + qca6390_pmu: pmu@0 {
It does not look like you tested the DTS against bindings. Please run make dtbs_check W=1 (see Documentation/devicetree/bindings/writing-schema.rst or
https://www.linaro.org/blog/tips-and-tricks-for-validating-devicetree-sources-with-the-devicetree-schema/
for instructions).
Best regards,
Krzysztof
RFC 3/9 power: sequencing: new subsystem
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
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.
--- drivers/power/Kconfig | 1 + drivers/power/Makefile | 1 + drivers/power/sequencing/Kconfig | 12 + drivers/power/sequencing/Makefile | 4 + drivers/power/sequencing/core.c | 482 ++++++++++++++++++++++++++++++ include/linux/pwrseq/consumer.h | 53 ++++ include/linux/pwrseq/provider.h | 41 +++ 7 files changed, 594 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
drivers/power/Kconfig +1 -0
@@ -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"
drivers/power/Makefile +1 -0
@@ -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/
drivers/power/sequencing/Kconfig new file +12 -0
@@ -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.
drivers/power/sequencing/Makefile new file +4 -0
@@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_POWER_SEQUENCING) += pwrseq-core.o +pwrseq-core-y := core.o
drivers/power/sequencing/core.c new file +482 -0
482 lines not on this page · raw message
include/linux/pwrseq/consumer.h new file +53 -0
53 lines not on this page · raw message
include/linux/pwrseq/provider.h new file +41 -0
41 lines not on this page · raw message
Signature · 1 line
2.40.1
Rob Herring
maintainerRe: [RFC 3/9] power: sequencing: new subsystem
Quoted 21 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
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 <[email protected]>+++ b/drivers/power/sequencing/Kconfig
drivers/power/sequencing/Kconfig new file +1
-0@@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-onlydrivers/power/sequencing/Makefile new file +0
-0
drivers/power/sequencing/Makefile line 1
Quoted 1 line
drivers/power/sequencing/Makefile new file +1
-0@@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0
GPL-2.0-only to be consistent.
drivers/power/sequencing/core.c line 1
Quoted 10 lines
drivers/power/sequencing/Makefile new file +3
-0+ +obj-$(CONFIG_POWER_SEQUENCING) += pwrseq-core.o +pwrseq-core-y := core.odrivers/power/sequencing/core.c new file +1
-0@@ -0,0 +1,482 @@ +// SPDX-License-Identifier: GPL-2.0-or-later
Why the deviation from the kernel's default license?
Rob
kernel test robot
build botRe: [RFC 3/9] power: sequencing: new subsystem
In reply to Bartosz Golaszewskikernel test robot noticed the following build errors:
Hi Bartosz,
[This is a private test report for your RFC patch.] kernel test robot noticed the following build errors:
[auto build test ERROR on pci/next]
[also build test ERROR on pci/for-linus robh/for-next bluetooth-next/master bluetooth/master linus/master v6.8-rc2 next-20240202] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Bartosz-Golaszewski/of-provide-a-cleanup-helper-for-OF-nodes/20240202-000307 base: https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git next patch link: https://lore.kernel.org/r/20240201155532.49707-4-brgl%40bgdev.pl patch subject: [RFC 3/9] power: sequencing: new subsystem config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20240203/[email protected]/config) compiler: m68k-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240203/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All error/warnings (new ones prefixed by >>):
drivers/power/sequencing/core.c: In function 'pwrseq_release':
>> drivers/power/sequencing/core.c:91:9: error: implicit declaration of function 'kfree'; did you mean 'kvfree'? [-Werror=implicit-function-declaration]
91 | kfree(pwrseq);
| ^~~~~
| kvfree
drivers/power/sequencing/core.c: In function 'pwrseq_device_register':
>> drivers/power/sequencing/core.c:123:18: error: implicit declaration of function 'kzalloc' [-Werror=implicit-function-declaration]
123 | pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);
| ^~~~~~~
>> drivers/power/sequencing/core.c:123:16: warning: assignment to 'struct pwrseq_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
123 | pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);
| ^
drivers/power/sequencing/core.c: In function 'pwrseq_get':
>> drivers/power/sequencing/core.c:280:16: error: cleanup argument not a function
280 | struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc),
| ^~~~~~~~~~~
>> drivers/power/sequencing/core.c:280:50: warning: initialization of 'struct pwrseq_desc *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 280 | struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc),
| ^~~~~~~
cc1: some warnings being treated as errors
vim +91 drivers/power/sequencing/core.c
84
85 static void pwrseq_release(struct device *dev)
86 {
87 struct pwrseq_device *pwrseq = to_pwrseq_device(dev);
88
89 mutex_destroy(&pwrseq->state_lock);
90 ida_free(&pwrseq_ida, pwrseq->id);
> 91 kfree(pwrseq);
92 }
93
94 static const struct device_type pwrseq_device_type = {
95 .name = "power_sequencer",
96 .release = pwrseq_release,
97 };
98
99 /**
100 * pwrseq_device_register() - Register a new power sequencer.
101 * @config: Configuration of the new power sequencing device.
102 *
103 * The config structure is only used during the call and can be freed after
104 * the function returns. The config structure *must* have the parent device
105 * as well as the match(), power_on() and power_off() callbacks registered.
106 *
107 * Returns:
108 * Returns the address of the new pwrseq device or ERR_PTR() on failure.
109 */
110 struct pwrseq_device *pwrseq_device_register(struct pwrseq_config *config)
111 {
112 struct pwrseq_device *pwrseq;
113 int ret;
114
115 /*
116 * Power sequencer must have a parent device and at least the power-on,
117 * power-off and match callbacks.
118 */
119 if (!config->parent || !config->match || !config->power_on ||
120 !config->power_off)
121 return ERR_PTR(-EINVAL);
122
> 123 pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);
124 if (!pwrseq)
125 return ERR_PTR(-ENOMEM);
126
127 pwrseq->dev.type = &pwrseq_device_type;
128 pwrseq->dev.bus = &pwrseq_bus;
129 pwrseq->dev.parent = config->parent;
130 device_set_node(&pwrseq->dev, dev_fwnode(config->parent));
131
132 pwrseq->id = ida_alloc(&pwrseq_ida, GFP_KERNEL);
133 if (pwrseq->id < 0) {
134 kfree(pwrseq);
135 return ERR_PTR(pwrseq->id);
136 }
137
138 /*
139 * From this point onwards the device's release() callback is
140 * responsible for freeing resources.
141 */
142 device_initialize(&pwrseq->dev);
143
144 ret = dev_set_name(&pwrseq->dev, "pwrseq.%d", pwrseq->id);
145 if (ret)
146 goto err_put_pwrseq;
147
148 pwrseq->owner = config->owner ?: THIS_MODULE;
149 pwrseq->drvdata = config->drvdata;
150 pwrseq->match = config->match;
151 pwrseq->power_on = config->power_on;
152 pwrseq->power_off = config->power_off;
153
154 init_rwsem(&pwrseq->dev_sem);
155 mutex_init(&pwrseq->state_lock);
156
157 scoped_guard(rwsem_write, &pwrseq_sem) {
158 ret = device_add(&pwrseq->dev);
159 if (ret)
160 goto err_put_pwrseq;
161 }
162
163 return pwrseq;
164
165 err_put_pwrseq:
166 pwrseq_device_put(pwrseq);
167 return ERR_PTR(ret);
168 }
169 EXPORT_SYMBOL_GPL(pwrseq_device_register);
170
171 /**
172 * pwrseq_device_unregister() - Unregister the power sequencer.
173 * @pwrseq: Power sequencer to unregister.
174 */
175 void pwrseq_device_unregister(struct pwrseq_device *pwrseq)
176 {
177 struct device *dev = &pwrseq->dev;
178
179 scoped_guard(mutex, &pwrseq->state_lock) {
180 WARN_ONCE(pwrseq->pwrup_count > 0,
181 "%s: UNREGISTERING POWER SEQUENCER WITH ACTIVE USERS\n",
182 dev_name(&pwrseq->dev));
183
184 scoped_guard(rwsem_write, &pwrseq_sem) {
185 scoped_guard(rwsem_write, &pwrseq->dev_sem)
186 device_del(dev);
187 }
188 }
189
190 pwrseq_device_put(pwrseq);
191 }
192 EXPORT_SYMBOL_GPL(pwrseq_device_unregister);
193
194 static void devm_pwrseq_device_unregister(void *data)
195 {
196 struct pwrseq_device *pwrseq = data;
197
198 pwrseq_device_unregister(pwrseq);
199 }
200
201 /**
202 * devm_pwrseq_device_register() - Managed variant of pwrseq_device_register().
203 * @dev: Managing device.
204 * @config: Configuration of the new power sequencing device.
205 *
206 * Returns:
207 * Returns the address of the new pwrseq device or ERR_PTR() on failure.
208 */
209 struct pwrseq_device *
210 devm_pwrseq_device_register(struct device *dev, struct pwrseq_config *config)
211 {
212 struct pwrseq_device *pwrseq;
213 int ret;
214
215 pwrseq = pwrseq_device_register(config);
216 if (IS_ERR(pwrseq))
217 return pwrseq;
218
219 ret = devm_add_action_or_reset(dev, devm_pwrseq_device_unregister,
220 pwrseq);
221 if (ret)
222 return ERR_PTR(ret);
223
224 return pwrseq;
225 }
226 EXPORT_SYMBOL_GPL(devm_pwrseq_device_register);
227
228 /**
229 * pwrseq_device_get_data() - Get the driver private data associated with this
230 * sequencer.
231 * @pwrseq: Power sequencer object.
232 *
233 * Returns:
234 * Address of the private driver data.
235 */
236 void *pwrseq_device_get_data(struct pwrseq_device *pwrseq)
237 {
238 return pwrseq->drvdata;
239 }
240 EXPORT_SYMBOL_GPL(pwrseq_device_get_data);
241
242 struct pwrseq_match_data {
243 struct pwrseq_device *matched;
244 struct device *dev;
245 };
246
247 static int pwrseq_match_device(struct device *pwrseq_dev, void *data)
248 {
249 struct pwrseq_device *pwrseq = to_pwrseq_device(pwrseq_dev);
250 struct pwrseq_match_data *match_data = data;
251 int ret;
252
253 guard(rwsem_read)(&pwrseq->dev_sem);
254 if (!device_is_registered(&pwrseq->dev))
255 return 0;
256
257 ret = pwrseq->match(pwrseq, match_data->dev);
258 if (ret <= 0)
259 return ret;
260
261 match_data->matched = pwrseq;
262
263 return 1;
264 }
265
266 /**
267 * pwrseq_get() - Get the power sequencer associated with this device.
268 * @dev: Device for which to get the sequencer.
269 *
270 * Returns:
271 * New power sequencer descriptor for use by the consumer driver or ERR_PTR()
272 * on failure.
273 */
274 struct pwrseq_desc *pwrseq_get(struct device *dev)
275 {
276 struct pwrseq_match_data match_data;
277 struct pwrseq_device *pwrseq;
278 int ret;
279
> 280 struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc), 281 GFP_KERNEL);
282 if (!desc)
283 return ERR_PTR(-ENOMEM);
284
285 match_data.matched = NULL;
286 match_data.dev = dev;
287
288 guard(rwsem_read)(&pwrseq_sem);
289
290 ret = bus_for_each_dev(&pwrseq_bus, NULL, &match_data,
291 pwrseq_match_device);
292 if (ret < 0)
293 return ERR_PTR(ret);
294 if (ret == 0)
295 /* No device matched. */
296 return ERR_PTR(-EPROBE_DEFER);
297
298 pwrseq = match_data.matched;
299
300 if (!try_module_get(pwrseq->owner))
301 return ERR_PTR(-EPROBE_DEFER);
302
303 desc->pwrseq = pwrseq_device_get(pwrseq);
304
305 return no_free_ptr(desc);
306 }
307 EXPORT_SYMBOL_GPL(pwrseq_get);
308
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
kernel test robot
build botRe: [RFC 3/9] power: sequencing: new subsystem
In reply to Bartosz Golaszewskikernel test robot noticed the following build warnings:
Hi Bartosz,
[This is a private test report for your RFC patch.] kernel test robot noticed the following build warnings:
[auto build test WARNING on pci/next]
[also build test WARNING on pci/for-linus robh/for-next bluetooth-next/master bluetooth/master linus/master v6.8-rc2 next-20240202] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Bartosz-Golaszewski/of-provide-a-cleanup-helper-for-OF-nodes/20240202-000307 base: https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git next patch link: https://lore.kernel.org/r/20240201155532.49707-4-brgl%40bgdev.pl patch subject: [RFC 3/9] power: sequencing: new subsystem config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20240204/[email protected]/config) compiler: loongarch64-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240204/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All warnings (new ones prefixed by >>):
>> drivers/power/sequencing/core.c:50: warning: Function parameter or struct member 'dev_sem' not described in 'pwrseq_device' >> drivers/power/sequencing/core.c:50: warning: Function parameter or struct member 'state_lock' not described in 'pwrseq_device' >> drivers/power/sequencing/core.c:50: warning: Excess struct member 'sem' description in 'pwrseq_device'
vim +50 drivers/power/sequencing/core.c
26
27 /**
28 * struct pwrseq_device - Private power sequencing data.
29 * @dev: Device struct associated with this sequencer.
30 * @id: Device ID.
31 * @owner: Prevents removal of active power sequencing providers.
32 * @pwrup_count: Keeps track of power state change requests.
33 * @sem: Protects the device against being unregistered while in use.
34 * @drvdata: Provider driver private data.
35 * @match: Power sequencer matching callback.
36 * @power_on: Power-on callback.
37 * @power_off: Power-off callback.
38 */
39 struct pwrseq_device {
40 struct device dev;
41 int id;
42 struct module *owner;
43 unsigned int pwrup_count;
44 struct rw_semaphore dev_sem;
45 struct mutex state_lock;
46 void *drvdata;
47 pwrseq_match_func match;
48 pwrseq_power_state_func power_on;
49 pwrseq_power_state_func power_off;
> 50 };
51 Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
kernel test robot
build botRe: [RFC 3/9] power: sequencing: new subsystem
In reply to Bartosz Golaszewskikernel test robot noticed the following build errors:
Hi Bartosz,
[This is a private test report for your RFC patch.] kernel test robot noticed the following build errors:
[auto build test ERROR on pci/next]
[also build test ERROR on pci/for-linus robh/for-next bluetooth-next/master bluetooth/master linus/master v6.8-rc2 next-20240202] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Bartosz-Golaszewski/of-provide-a-cleanup-helper-for-OF-nodes/20240202-000307 base: https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git next patch link: https://lore.kernel.org/r/20240201155532.49707-4-brgl%40bgdev.pl patch subject: [RFC 3/9] power: sequencing: new subsystem config: powerpc-allyesconfig (https://download.01.org/0day-ci/archive/20240204/[email protected]/config) compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project 7dd790db8b77c4a833c06632e903dc4f13877a64) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240204/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
>> drivers/power/sequencing/core.c:91:2: error: call to undeclared function 'kfree'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
91 | kfree(pwrseq);
| ^
>> drivers/power/sequencing/core.c:123:11: error: call to undeclared function 'kzalloc'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
123 | pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);
| ^
>> drivers/power/sequencing/core.c:123:9: error: incompatible integer to pointer conversion assigning to 'struct pwrseq_device *' from 'int' [-Wint-conversion]
123 | pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/power/sequencing/core.c:134:3: error: call to undeclared function 'kfree'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
134 | kfree(pwrseq);
| ^
>> drivers/power/sequencing/core.c:280:27: error: use of undeclared identifier '__free_kfree'; did you mean '__free_pages'?
280 | struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc),
| ^
include/linux/cleanup.h:64:33: note: expanded from macro '__free'
64 | #define __free(_name) __cleanup(__free_##_name)
| ^
<scratch space>:13:1: note: expanded from here
13 | __free_kfree
| ^
include/linux/gfp.h:310:13: note: '__free_pages' declared here
310 | extern void __free_pages(struct page *page, unsigned int order);
| ^
>> drivers/power/sequencing/core.c:280:27: error: 'cleanup' function '__free_pages' must take 1 parameter
280 | struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc),
| ^
include/linux/cleanup.h:64:33: note: expanded from macro '__free'
64 | #define __free(_name) __cleanup(__free_##_name)
| ^
<scratch space>:13:1: note: expanded from here
13 | __free_kfree
| ^
drivers/power/sequencing/core.c:280:43: error: call to undeclared function 'kzalloc'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
280 | struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc),
| ^
>> drivers/power/sequencing/core.c:280:22: error: incompatible integer to pointer conversion initializing 'struct pwrseq_desc *' with an expression of type 'int' [-Wint-conversion]
280 | struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc),
| ^ ~~~~~~~~~~~~~~~~~~~~~~
281 | GFP_KERNEL);
| ~~~~~~~~~~~
drivers/power/sequencing/core.c:325:2: error: call to undeclared function 'kfree'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
325 | kfree(desc);
| ^9 errors generated.
vim +/kfree +91 drivers/power/sequencing/core.c
84
85 static void pwrseq_release(struct device *dev)
86 {
87 struct pwrseq_device *pwrseq = to_pwrseq_device(dev);
88
89 mutex_destroy(&pwrseq->state_lock);
90 ida_free(&pwrseq_ida, pwrseq->id);
> 91 kfree(pwrseq);
92 }
93
94 static const struct device_type pwrseq_device_type = {
95 .name = "power_sequencer",
96 .release = pwrseq_release,
97 };
98
99 /**
100 * pwrseq_device_register() - Register a new power sequencer.
101 * @config: Configuration of the new power sequencing device.
102 *
103 * The config structure is only used during the call and can be freed after
104 * the function returns. The config structure *must* have the parent device
105 * as well as the match(), power_on() and power_off() callbacks registered.
106 *
107 * Returns:
108 * Returns the address of the new pwrseq device or ERR_PTR() on failure.
109 */
110 struct pwrseq_device *pwrseq_device_register(struct pwrseq_config *config)
111 {
112 struct pwrseq_device *pwrseq;
113 int ret;
114
115 /*
116 * Power sequencer must have a parent device and at least the power-on,
117 * power-off and match callbacks.
118 */
119 if (!config->parent || !config->match || !config->power_on ||
120 !config->power_off)
121 return ERR_PTR(-EINVAL);
122
> 123 pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);
124 if (!pwrseq)
125 return ERR_PTR(-ENOMEM);
126
127 pwrseq->dev.type = &pwrseq_device_type;
128 pwrseq->dev.bus = &pwrseq_bus;
129 pwrseq->dev.parent = config->parent;
130 device_set_node(&pwrseq->dev, dev_fwnode(config->parent));
131
132 pwrseq->id = ida_alloc(&pwrseq_ida, GFP_KERNEL);
133 if (pwrseq->id < 0) {
134 kfree(pwrseq);
135 return ERR_PTR(pwrseq->id);
136 }
137
138 /*
139 * From this point onwards the device's release() callback is
140 * responsible for freeing resources.
141 */
142 device_initialize(&pwrseq->dev);
143
144 ret = dev_set_name(&pwrseq->dev, "pwrseq.%d", pwrseq->id);
145 if (ret)
146 goto err_put_pwrseq;
147
148 pwrseq->owner = config->owner ?: THIS_MODULE;
149 pwrseq->drvdata = config->drvdata;
150 pwrseq->match = config->match;
151 pwrseq->power_on = config->power_on;
152 pwrseq->power_off = config->power_off;
153
154 init_rwsem(&pwrseq->dev_sem);
155 mutex_init(&pwrseq->state_lock);
156
157 scoped_guard(rwsem_write, &pwrseq_sem) {
158 ret = device_add(&pwrseq->dev);
159 if (ret)
160 goto err_put_pwrseq;
161 }
162
163 return pwrseq;
164
165 err_put_pwrseq:
166 pwrseq_device_put(pwrseq);
167 return ERR_PTR(ret);
168 }
169 EXPORT_SYMBOL_GPL(pwrseq_device_register);
170
171 /**
172 * pwrseq_device_unregister() - Unregister the power sequencer.
173 * @pwrseq: Power sequencer to unregister.
174 */
175 void pwrseq_device_unregister(struct pwrseq_device *pwrseq)
176 {
177 struct device *dev = &pwrseq->dev;
178
179 scoped_guard(mutex, &pwrseq->state_lock) {
180 WARN_ONCE(pwrseq->pwrup_count > 0,
181 "%s: UNREGISTERING POWER SEQUENCER WITH ACTIVE USERS\n",
182 dev_name(&pwrseq->dev));
183
184 scoped_guard(rwsem_write, &pwrseq_sem) {
185 scoped_guard(rwsem_write, &pwrseq->dev_sem)
186 device_del(dev);
187 }
188 }
189
190 pwrseq_device_put(pwrseq);
191 }
192 EXPORT_SYMBOL_GPL(pwrseq_device_unregister);
193
194 static void devm_pwrseq_device_unregister(void *data)
195 {
196 struct pwrseq_device *pwrseq = data;
197
198 pwrseq_device_unregister(pwrseq);
199 }
200
201 /**
202 * devm_pwrseq_device_register() - Managed variant of pwrseq_device_register().
203 * @dev: Managing device.
204 * @config: Configuration of the new power sequencing device.
205 *
206 * Returns:
207 * Returns the address of the new pwrseq device or ERR_PTR() on failure.
208 */
209 struct pwrseq_device *
210 devm_pwrseq_device_register(struct device *dev, struct pwrseq_config *config)
211 {
212 struct pwrseq_device *pwrseq;
213 int ret;
214
215 pwrseq = pwrseq_device_register(config);
216 if (IS_ERR(pwrseq))
217 return pwrseq;
218
219 ret = devm_add_action_or_reset(dev, devm_pwrseq_device_unregister,
220 pwrseq);
221 if (ret)
222 return ERR_PTR(ret);
223
224 return pwrseq;
225 }
226 EXPORT_SYMBOL_GPL(devm_pwrseq_device_register);
227
228 /**
229 * pwrseq_device_get_data() - Get the driver private data associated with this
230 * sequencer.
231 * @pwrseq: Power sequencer object.
232 *
233 * Returns:
234 * Address of the private driver data.
235 */
236 void *pwrseq_device_get_data(struct pwrseq_device *pwrseq)
237 {
238 return pwrseq->drvdata;
239 }
240 EXPORT_SYMBOL_GPL(pwrseq_device_get_data);
241
242 struct pwrseq_match_data {
243 struct pwrseq_device *matched;
244 struct device *dev;
245 };
246
247 static int pwrseq_match_device(struct device *pwrseq_dev, void *data)
248 {
249 struct pwrseq_device *pwrseq = to_pwrseq_device(pwrseq_dev);
250 struct pwrseq_match_data *match_data = data;
251 int ret;
252
253 guard(rwsem_read)(&pwrseq->dev_sem);
254 if (!device_is_registered(&pwrseq->dev))
255 return 0;
256
257 ret = pwrseq->match(pwrseq, match_data->dev);
258 if (ret <= 0)
259 return ret;
260
261 match_data->matched = pwrseq;
262
263 return 1;
264 }
265
266 /**
267 * pwrseq_get() - Get the power sequencer associated with this device.
268 * @dev: Device for which to get the sequencer.
269 *
270 * Returns:
271 * New power sequencer descriptor for use by the consumer driver or ERR_PTR()
272 * on failure.
273 */
274 struct pwrseq_desc *pwrseq_get(struct device *dev)
275 {
276 struct pwrseq_match_data match_data;
277 struct pwrseq_device *pwrseq;
278 int ret;
279
> 280 struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc), 281 GFP_KERNEL);
282 if (!desc)
283 return ERR_PTR(-ENOMEM);
284
285 match_data.matched = NULL;
286 match_data.dev = dev;
287
288 guard(rwsem_read)(&pwrseq_sem);
289
290 ret = bus_for_each_dev(&pwrseq_bus, NULL, &match_data,
291 pwrseq_match_device);
292 if (ret < 0)
293 return ERR_PTR(ret);
294 if (ret == 0)
295 /* No device matched. */
296 return ERR_PTR(-EPROBE_DEFER);
297
298 pwrseq = match_data.matched;
299
300 if (!try_module_get(pwrseq->owner))
301 return ERR_PTR(-EPROBE_DEFER);
302
303 desc->pwrseq = pwrseq_device_get(pwrseq);
304
305 return no_free_ptr(desc);
306 }
307 EXPORT_SYMBOL_GPL(pwrseq_get);
308
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
RFC 4/9 power: pwrseq: add a driver for the QCA6390 PMU module
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
This adds the power sequencing driver for the QCA6390's PMU module. It uses the pwrseq subsystem and knows how to match the sequencer to the consumer device by verifying the relevant properties and DT layout.
--- drivers/power/sequencing/Kconfig | 16 ++ drivers/power/sequencing/Makefile | 2 + drivers/power/sequencing/pwrseq-qca6390.c | 232 ++++++++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 drivers/power/sequencing/pwrseq-qca6390.c
drivers/power/sequencing/Kconfig +16 -0
@@ -10,3 +10,19 @@ menuconfig POWER_SEQUENCING during power-up. If unsure, say no. + +if POWER_SEQUENCING + +config POWER_SEQUENCING_QCA6390 + tristate "QCA6390 PMU driver" + default m if ARCH_QCOM + help + Say U here to enable the power sequencing driver for Qualcomm + QCA6390. + + The QCA6390 package 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
drivers/power/sequencing/Makefile +2 -0
@@ -2,3 +2,5 @@ obj-$(CONFIG_POWER_SEQUENCING) += pwrseq-core.o pwrseq-core-y := core.o + +obj-$(CONFIG_POWER_SEQUENCING_QCA6390) += pwrseq-qca6390.o
drivers/power/sequencing/pwrseq-qca6390.c new file +232 -0
232 lines not on this page · raw message
Signature · 1 line
2.40.1
Bjorn Andersson
maintainerRe: [RFC 4/9] power: pwrseq: add a driver for the QCA6390 PMU module
Quoted 1 line · Bartosz Golaszewski
drivers/power/sequencing/pwrseq-qca6390.c +0
-0
[..]
drivers/power/sequencing/pwrseq-qca6390.c line 89
Quoted 11 lines
drivers/power/sequencing/pwrseq-qca6390.c +11
-0+static int pwrseq_qca6390_power_on (struct pwrseq_device *pwrseq) +{ +struct pwrseq_qca6390_ctx *ctx =pwrseq_device_get_data (pwrseq); +int ret; + + ret =regulator_bulk_enable (ctx->pdata->num_vregs, ctx->regs); +if (ret) +return ret; + +gpiod_set_value_cansleep (ctx->bt_gpio,1 ); +gpiod_set_value_cansleep (ctx->wlan_gpio,1 );
So it's no longer possible to power these independently?
Quoted 4 lines
drivers/power/sequencing/pwrseq-qca6390.c +4
-0+ +if (ctx->pdata->pwup_delay_msec) +msleep (ctx->pdata->pwup_delay_msec); +
drivers/power/sequencing/pwrseq-qca6390.c line 103
Quoted 10 lines
drivers/power/sequencing/pwrseq-qca6390.c +10
-0+return 0 ; +} + +static int pwrseq_qca6390_power_off (struct pwrseq_device *pwrseq) +{ +struct pwrseq_qca6390_ctx *ctx =pwrseq_device_get_data (pwrseq); + +gpiod_set_value_cansleep (ctx->bt_gpio,0 ); +gpiod_set_value_cansleep (ctx->wlan_gpio,0 ); +
The answer that was provided recently was that the WiFi and BT modules absolutely must be modelled together, because there must be a 100ms delay between bt_gpio going low and wlan_gpio going high.
If you're not going to address that concern, then I fail to see the reason for adding the power sequence framework - just let the BT and PCI power control (WiFi) do their thing independently.
Quoted 21 lines
drivers/power/sequencing/pwrseq-qca6390.c +21
-0+return regulator_bulk_disable (ctx->pdata->num_vregs, ctx->regs); +} + +static int pwrseq_qca6390_match (struct pwrseq_device *pwrseq, +struct device *dev) +{ +struct pwrseq_qca6390_ctx *ctx =pwrseq_device_get_data (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(of_node) = +of_parse_phandle (dev_node,"vddaon-supply" ,0 ); +if (!reg_node)
drivers/power/sequencing/pwrseq-qca6390.c line 134
Quoted 10 lines
drivers/power/sequencing/pwrseq-qca6390.c +10
-0+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 ;
Your DeviceTree example gives a sense that a set of supplies feeds the PMU, which then supplies power to the BT and WiFi nodes through some entity that can switch power on and off, and adjust the voltage level.
Then comes this function, which indicates that the DeviceTree model was just for show.
Quoted 40 lines
drivers/power/sequencing/pwrseq-qca6390.c +40
-0+ +return 1 ; +} + +static int pwrseq_qca6390_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct pwrseq_qca6390_ctx *ctx; +struct pwrseq_config config; +int ret, i; + + 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" ); + +if (ctx->pdata->vregs) { + 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].name; + + ret =devm_regulator_bulk_get (dev, ctx->pdata->num_vregs, + ctx->regs); +if (ret <0 ) +return dev_err_probe (dev, ret, +"Failed to get all regulators\n" ); + +for (i =0 ; i < ctx->pdata->num_vregs; i++) { +if (!ctx->pdata->vregs[1 ].load_uA) +continue ;
drivers/power/sequencing/pwrseq-qca6390.c line 184
Quoted 10 lines
drivers/power/sequencing/pwrseq-qca6390.c +10
-0+ + ret =regulator_set_load (ctx->regs[i].consumer, + ctx->pdata->vregs[i].load_uA); +if (ret) +return dev_err_probe (dev, ret, +"Failed to set vreg load\n" ); + } + } + + ctx->bt_gpio =devm_gpiod_get_optional (dev,"bt-enable" ,GPIOD_OUT_LOW );
Why are these optional? Does it make sense to have a qca6390 without both of these gpios connected?
Regards,
Bjorn
Quoted 51 lines
drivers/power/sequencing/pwrseq-qca6390.c +48
-0+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" ); + +memset (&config,0 ,sizeof (config)); + + config.parent = dev; + config.owner =THIS_MODULE ; + config.drvdata = ctx; + config.match = pwrseq_qca6390_match; + config.power_on = pwrseq_qca6390_power_on; + config.power_off = pwrseq_qca6390_power_off; + + 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_qca6390_of_match[] = { + { + .compatible ="qcom,qca6390-pmu" , + .data = &pwrseq_qca6390_of_data, + }, + { } +}; +MODULE_DEVICE_TABLE (of, pwrseq_qca6390_of_match); + +static struct platform_driver pwrseq_qca6390_driver = { + .driver = { + .name ="pwrseq-qca6390" , + .of_match_table = pwrseq_qca6390_of_match, + }, + .probe = pwrseq_qca6390_probe, +}; +module_platform_driver (pwrseq_qca6390_driver); + +MODULE_AUTHOR ("Bartosz Golaszewski <[email protected]>" ); +MODULE_DESCRIPTION ("QCA6390 PMU power sequencing driver" ); +MODULE_LICENSE ("GPL" );Signature · 1 line
2.40.1
Re: [RFC 4/9] power: pwrseq: add a driver for the QCA6390 PMU module
Quoted 4 lines · Bjorn Andersson
Quoted 1 line · Bartosz Golaszewski
drivers/power/sequencing/pwrseq-qca6390.c +0
-0[..]
Quoted 13 lines
drivers/power/sequencing/pwrseq-qca6390.c line 89
Quoted 11 lines
drivers/power/sequencing/pwrseq-qca6390.c +11
-0+static int pwrseq_qca6390_power_on (struct pwrseq_device *pwrseq) +{ +struct pwrseq_qca6390_ctx *ctx =pwrseq_device_get_data (pwrseq); +int ret; + + ret =regulator_bulk_enable (ctx->pdata->num_vregs, ctx->regs); +if (ret) +return ret; + +gpiod_set_value_cansleep (ctx->bt_gpio,1 ); +gpiod_set_value_cansleep (ctx->wlan_gpio,1 );So it's no longer possible to power these independently?
I'd second this, there must be a way to power them on and off separately. In the end, this provides a good way to restart the BT core if it gets sick.
Quoted 11 lines
Quoted 11 lines
drivers/power/sequencing/pwrseq-qca6390.c +10
-0+ +if (ctx->pdata->pwup_delay_msec) +msleep (ctx->pdata->pwup_delay_msec); + +return 0 ; +} + +static int pwrseq_qca6390_power_off (struct pwrseq_device *pwrseq) +{ +struct pwrseq_qca6390_ctx *ctx =pwrseq_device_get_data (pwrseq);
Quoted 8 lines
drivers/power/sequencing/pwrseq-qca6390.c line 103
Quoted 4 lines
drivers/power/sequencing/pwrseq-qca6390.c +4
-0+ +gpiod_set_value_cansleep (ctx->bt_gpio,0 ); +gpiod_set_value_cansleep (ctx->wlan_gpio,0 ); +The answer that was provided recently was that the WiFi and BT modules absolutely must be modelled together, because there must be a 100ms delay between
bt_gpiogoing low andwlan_gpiogoing high.
For the reference, it was for the QCA6490 (not QCA6390, next revision), which maps to WCN6855.
Quoted 144 lines
If you're not going to address that concern, then I fail to see the reason for adding the power sequence framework - just let the BT and PCI power control (WiFi) do their thing independently.
Quoted 21 lines
drivers/power/sequencing/pwrseq-qca6390.c +21
-0+return regulator_bulk_disable (ctx->pdata->num_vregs, ctx->regs); +} + +static int pwrseq_qca6390_match (struct pwrseq_device *pwrseq, +struct device *dev) +{ +struct pwrseq_qca6390_ctx *ctx =pwrseq_device_get_data (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(of_node) = +of_parse_phandle (dev_node,"vddaon-supply" ,0 ); +if (!reg_node)drivers/power/sequencing/pwrseq-qca6390.c line 134
Quoted 10 lines
drivers/power/sequencing/pwrseq-qca6390.c +10
-0+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 ;Your DeviceTree example gives a sense that a set of supplies feeds the PMU, which then supplies power to the BT and WiFi nodes through some entity that can switch power on and off, and adjust the voltage level.
Then comes this function, which indicates that the DeviceTree model was just for show.
Quoted 40 lines
drivers/power/sequencing/pwrseq-qca6390.c +40
-0+ +return 1 ; +} + +static int pwrseq_qca6390_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct pwrseq_qca6390_ctx *ctx; +struct pwrseq_config config; +int ret, i; + + 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" ); + +if (ctx->pdata->vregs) { + 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].name; + + ret =devm_regulator_bulk_get (dev, ctx->pdata->num_vregs, + ctx->regs); +if (ret <0 ) +return dev_err_probe (dev, ret, +"Failed to get all regulators\n" ); + +for (i =0 ; i < ctx->pdata->num_vregs; i++) { +if (!ctx->pdata->vregs[1 ].load_uA) +continue ;drivers/power/sequencing/pwrseq-qca6390.c line 184
Quoted 10 lines
drivers/power/sequencing/pwrseq-qca6390.c +10
-0+ + ret =regulator_set_load (ctx->regs[i].consumer, + ctx->pdata->vregs[i].load_uA); +if (ret) +return dev_err_probe (dev, ret, +"Failed to set vreg load\n" ); + } + } + + ctx->bt_gpio =devm_gpiod_get_optional (dev,"bt-enable" ,GPIOD_OUT_LOW );Why are these optional? Does it make sense to have a qca6390 without both of these gpios connected?
Regards,
BjornQuoted 43 lines
drivers/power/sequencing/pwrseq-qca6390.c +43
-0+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" ); + +memset (&config,0 ,sizeof (config)); + + config.parent = dev; + config.owner =THIS_MODULE ; + config.drvdata = ctx; + config.match = pwrseq_qca6390_match; + config.power_on = pwrseq_qca6390_power_on; + config.power_off = pwrseq_qca6390_power_off; + + 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_qca6390_of_match[] = { + { + .compatible ="qcom,qca6390-pmu" , + .data = &pwrseq_qca6390_of_data, + }, + { } +}; +MODULE_DEVICE_TABLE (of, pwrseq_qca6390_of_match); + +static struct platform_driver pwrseq_qca6390_driver = { + .driver = { + .name ="pwrseq-qca6390" , + .of_match_table = pwrseq_qca6390_of_match, + }, + .probe = pwrseq_qca6390_probe, +};
Quoted 9 lines
Quoted 8 lines
drivers/power/sequencing/pwrseq-qca6390.c +5
-1+module_platform_driver (pwrseq_qca6390_driver); + +MODULE_AUTHOR ("Bartosz Golaszewski <[email protected]>" ); +MODULE_DESCRIPTION ("QCA6390 PMU power sequencing driver" ); +MODULE_LICENSE ("GPL" ); --2.40.1
--
With best wishes
Dmitry
Re: [RFC 4/9] power: pwrseq: add a driver for the QCA6390 PMU module
Quoted 20 lines · Dmitry Baryshkov
Quoted 4 lines · Bjorn Andersson
Quoted 1 line · Bartosz Golaszewski
drivers/power/sequencing/pwrseq-qca6390.c +0
-0[..]
Quoted 13 lines
drivers/power/sequencing/pwrseq-qca6390.c line 89
Quoted 11 lines
drivers/power/sequencing/pwrseq-qca6390.c +11
-0+static int pwrseq_qca6390_power_on (struct pwrseq_device *pwrseq) +{ +struct pwrseq_qca6390_ctx *ctx =pwrseq_device_get_data (pwrseq); +int ret; + + ret =regulator_bulk_enable (ctx->pdata->num_vregs, ctx->regs); +if (ret) +return ret; + +gpiod_set_value_cansleep (ctx->bt_gpio,1 ); +gpiod_set_value_cansleep (ctx->wlan_gpio,1 );So it's no longer possible to power these independently?
Quoted 4 lines
I'd second this, there must be a way to power them on and off separately. In the end, this provides a good way to restart the BT core if it gets sick.
Makes sense, I'll think about it. I'm thinking about adding a flags argument for this kind of switching.
Quoted 20 lines
Quoted 11 lines
Quoted 11 lines
drivers/power/sequencing/pwrseq-qca6390.c +10
-0+ +if (ctx->pdata->pwup_delay_msec) +msleep (ctx->pdata->pwup_delay_msec); + +return 0 ; +} + +static int pwrseq_qca6390_power_off (struct pwrseq_device *pwrseq) +{ +struct pwrseq_qca6390_ctx *ctx =pwrseq_device_get_data (pwrseq);Quoted 8 lines
drivers/power/sequencing/pwrseq-qca6390.c line 103
Quoted 4 lines
drivers/power/sequencing/pwrseq-qca6390.c +4
-0+ +gpiod_set_value_cansleep (ctx->bt_gpio,0 ); +gpiod_set_value_cansleep (ctx->wlan_gpio,0 ); +The answer that was provided recently was that the WiFi and BT modules absolutely must be modelled together, because there must be a 100ms delay between
bt_gpiogoing low andwlan_gpiogoing high.
Quoted 3 lines
For the reference, it was for the QCA6490 (not QCA6390, next revision), which maps to WCN6855.
The docs for QCA6390 also mention the 100ms delay but it doesn't seem to be necessary. But yes, this was done after Dmitry raised concerns about the QCA6490.
Bart
Quoted 159 lines
Quoted 145 lines
If you're not going to address that concern, then I fail to see the reason for adding the power sequence framework - just let the BT and PCI power control (WiFi) do their thing independently.
Quoted 21 lines
drivers/power/sequencing/pwrseq-qca6390.c +21
-0+return regulator_bulk_disable (ctx->pdata->num_vregs, ctx->regs); +} + +static int pwrseq_qca6390_match (struct pwrseq_device *pwrseq, +struct device *dev) +{ +struct pwrseq_qca6390_ctx *ctx =pwrseq_device_get_data (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(of_node) = +of_parse_phandle (dev_node,"vddaon-supply" ,0 ); +if (!reg_node)drivers/power/sequencing/pwrseq-qca6390.c line 134
Quoted 10 lines
drivers/power/sequencing/pwrseq-qca6390.c +10
-0+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 ;Your DeviceTree example gives a sense that a set of supplies feeds the PMU, which then supplies power to the BT and WiFi nodes through some entity that can switch power on and off, and adjust the voltage level.
Then comes this function, which indicates that the DeviceTree model was just for show.
Quoted 40 lines
drivers/power/sequencing/pwrseq-qca6390.c +40
-0+ +return 1 ; +} + +static int pwrseq_qca6390_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct pwrseq_qca6390_ctx *ctx; +struct pwrseq_config config; +int ret, i; + + 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" ); + +if (ctx->pdata->vregs) { + 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].name; + + ret =devm_regulator_bulk_get (dev, ctx->pdata->num_vregs, + ctx->regs); +if (ret <0 ) +return dev_err_probe (dev, ret, +"Failed to get all regulators\n" ); + +for (i =0 ; i < ctx->pdata->num_vregs; i++) { +if (!ctx->pdata->vregs[1 ].load_uA) +continue ;drivers/power/sequencing/pwrseq-qca6390.c line 184
Quoted 10 lines
drivers/power/sequencing/pwrseq-qca6390.c +10
-0+ + ret =regulator_set_load (ctx->regs[i].consumer, + ctx->pdata->vregs[i].load_uA); +if (ret) +return dev_err_probe (dev, ret, +"Failed to set vreg load\n" ); + } + } + + ctx->bt_gpio =devm_gpiod_get_optional (dev,"bt-enable" ,GPIOD_OUT_LOW );Why are these optional? Does it make sense to have a qca6390 without both of these gpios connected?
Regards,
BjornQuoted 43 lines
drivers/power/sequencing/pwrseq-qca6390.c +43
-0+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" ); + +memset (&config,0 ,sizeof (config)); + + config.parent = dev; + config.owner =THIS_MODULE ; + config.drvdata = ctx; + config.match = pwrseq_qca6390_match; + config.power_on = pwrseq_qca6390_power_on; + config.power_off = pwrseq_qca6390_power_off; + + 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_qca6390_of_match[] = { + { + .compatible ="qcom,qca6390-pmu" , + .data = &pwrseq_qca6390_of_data, + }, + { } +}; +MODULE_DEVICE_TABLE (of, pwrseq_qca6390_of_match); + +static struct platform_driver pwrseq_qca6390_driver = { + .driver = { + .name ="pwrseq-qca6390" , + .of_match_table = pwrseq_qca6390_of_match, + }, + .probe = pwrseq_qca6390_probe, +};Quoted 9 lines
Quoted 8 lines
drivers/power/sequencing/pwrseq-qca6390.c +5
-1+module_platform_driver (pwrseq_qca6390_driver); + +MODULE_AUTHOR ("Bartosz Golaszewski <[email protected]>" ); +MODULE_DESCRIPTION ("QCA6390 PMU power sequencing driver" ); +MODULE_LICENSE ("GPL" ); --2.40.1
--
With best wishes
Dmitry
RFC 5/9 Bluetooth: qca: use the power sequencer for QCA6390
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
Use the pwrseq subsystem's consumer API to run the power-up sequence for the Bluetooth module of the QCA6390 package.
--- drivers/bluetooth/hci_qca.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
drivers/bluetooth/hci_qca.c +30 -0
@@ -28,6 +28,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>
@@ -214,6 +215,7 @@ struct qca_power {struct regulator_bulk_data *vreg_bulk;int num_vregs;bool vregs_on; +struct pwrseq_desc *pwrseq; };struct qca_serdev {
@@ -1791,6 +1793,11 @@ 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); +break ; +default : qcadev =serdev_device_get_drvdata (hu->serdev);if (qcadev->bt_en) {
@@ -2160,6 +2167,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 ); }
@@ -2298,12 +2309,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);
@@ -2344,6 +2368,12 @@ static int qca_serdev_probe(struct serdev_device *serdev) }break ; +case QCA_QCA6390 : + qcadev->bt_power->pwrseq =devm_pwrseq_get (&serdev->dev); +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 );
Signature · 1 line
2.40.1
RFC 6/9 PCI: create platform devices for child OF nodes of the port node
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
In order to introduce PCI power-sequencing, we need to create platform devices for child nodes of the port node. They will get matched against the pwrseq drivers (if one exists) and then the actual PCI device will reuse the node once it's detected on the bus.
--- drivers/pci/bus.c | 9 ++++++++- drivers/pci/remove.c | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-)
drivers/pci/bus.c +8 -1
@@ -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);
drivers/pci/remove.c +2 -0
@@ -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);
Signature · 1 line
2.40.1
Bjorn Andersson
maintainerRe: [RFC 6/9] PCI: create platform devices for child OF nodes of the port node
Quoted 3 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
In order to introduce PCI power-sequencing,
Please provide a proper problem description.
Quoted 1 line
we need to create platform
And properly express why this is a "need".
Quoted 2 lines
devices for child nodes of the port node. They will get matched against the pwrseq drivers
That's not what happens in your code, the child nodes of the bridge node in DeviceTree will match against arbitrary platform_drivers.
I also would like this commit message to express that the job of the matched device is to:
1) power up said device, followed by triggering a scan on the parent PCI bus during it's probe function.
2) power down said device, during its remove function.
Quoted 2 lines
(if one exists) and then the actual PCI device will reuse the node once it's detected on the bus.
I think the "reuse" deserves to be clarified as there will be both a pci and a platform device associated with the same of_node.
Quoted 20 lines
Signed-off-by Bartosz Golaszewski <[email protected]>--- drivers/pci/bus.c | 9 ++++++++- drivers/pci/remove.c | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-)drivers/pci/bus.c +1
-0@@ -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>
drivers/pci/bus.c void pci_bus_add_device(struct pci_dev *dev) · line 349
Quoted 8 lines
drivers/pci/bus.c +3
-1@@ -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);
I'm not familiar enough with the ins and outs of the PCI code. Can you confirm that there are no problems with this (possibly) calling pci_rescan_bus() before the bridge device is fully initialized below?
Regards,
Bjorn
Quoted 30 lines
drivers/pci/bus.c +4
-0+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);drivers/pci/remove.c +2
-0@@ -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);Signature · 1 line
2.40.1
Re: [RFC 6/9] PCI: create platform devices for child OF nodes of the port node
Quoted 24 lines · Bjorn Andersson
Quoted 3 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
In order to introduce PCI power-sequencing,
Please provide a proper problem description.
Quoted 1 line
we need to create platform
And properly express why this is a "need".
Quoted 2 lines
devices for child nodes of the port node. They will get matched against the pwrseq drivers
That's not what happens in your code, the child nodes of the bridge node in DeviceTree will match against arbitrary
platform_drivers.I also would like this commit message to express that the job of the matched device is to:
1) power up said device, followed by triggering a scan on the parent PCI bus during it's probe function.
Quoted 8 lines
2) power down said device, during its remove function.
Quoted 2 lines
(if one exists) and then the actual PCI device will reuse the node once it's detected on the bus.
I think the "reuse" deserves to be clarified as there will be both a pci and a platform device associated with the same
of_node.
Noted all of the above. Thanks!
Quoted 19 lines
Quoted 19 lines
Signed-off-by Bartosz Golaszewski <[email protected]>--- drivers/pci/bus.c | 9 ++++++++- drivers/pci/remove.c | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-)drivers/pci/bus.c +1
-0@@ -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>
Quoted 14 lines
drivers/pci/bus.c void pci_bus_add_device(struct pci_dev *dev) · line 349
Quoted 9 lines
drivers/pci/bus.c +3
-1@@ -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);I'm not familiar enough with the ins and outs of the PCI code. Can you confirm that there are no problems with this (possibly) calling
pci_rescan_bus()before the bridge device is fully initialized below?
I'll clarify that. I'm not that well versed with PCI code either but will get help from the right people.
Bart
Quoted 33 lines
Regards,
BjornQuoted 30 lines
drivers/pci/bus.c +4
-0+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);drivers/pci/remove.c +2
-1@@ -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
RFC 7/9 PCI: hold the rescan mutex when scanning for the first time
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
With the introduction of the power sequencing drivers that will be able to trigger the port rescan, we need to hold the rescan mutex during the initial pci_host_probe() too or the two could get in each other's way.
--- drivers/pci/probe.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/pci/probe.c +2 -0
@@ -3122,7 +3122,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;
Signature · 1 line
2.40.1
RFC 8/9 PCI/pwrctl: add PCI power control core code
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
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_enable() 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.
--- drivers/pci/Kconfig | 1 + drivers/pci/Makefile | 1 + drivers/pci/pwrctl/Kconfig | 8 ++++ drivers/pci/pwrctl/Makefile | 3 ++ drivers/pci/pwrctl/core.c | 82 +++++++++++++++++++++++++++++++++++++ include/linux/pci-pwrctl.h | 24 +++++++++++ 6 files changed, 119 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
drivers/pci/Kconfig +1 -0
@@ -291,5 +291,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
drivers/pci/Makefile +1 -0
@@ -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
drivers/pci/pwrctl/Kconfig new file +8 -0
@@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 + +menu "PCI Power control drivers" + +config PCI_PWRCTL + bool + +endmenu
drivers/pci/pwrctl/Makefile new file +3 -0
@@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_PCI_PWRCTL) += core.o
drivers/pci/pwrctl/core.c new file +82 -0
82 lines not on this page · raw message
include/linux/pci-pwrctl.h new file +24 -0
@@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* +* Copyright (C) 2024 Linaro Ltd. +*/ + +#ifndef __PCI_PWRCTL_H__ +#define __PCI_PWRCTL_H__ + +#include <linux/notifier.h> + +struct device ; + +struct pci_pwrctl { +struct notifier_block nb; +struct device *dev; +struct device_link *link; +}; + +int pci_pwrctl_device_enable (struct pci_pwrctl *pwrctl); +void pci_pwrctl_device_disable (struct pci_pwrctl *pwrctl); +int devm_pci_pwrctl_device_enable (struct device *dev, +struct pci_pwrctl *pwrctl); + +#endif /* __PCI_PWRCTL_H__ */
Signature · 1 line
2.40.1
Bjorn Andersson
maintainerRe: [RFC 8/9] PCI/pwrctl: add PCI power control core code
Quoted 97 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
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_enable()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 <[email protected]>--- drivers/pci/Kconfig | 1 + drivers/pci/Makefile | 1 + drivers/pci/pwrctl/Kconfig | 8 ++++ drivers/pci/pwrctl/Makefile | 3 ++ drivers/pci/pwrctl/core.c | 82 +++++++++++++++++++++++++++++++++++++ include/linux/pci-pwrctl.h | 24 +++++++++++ 6 files changed, 119 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.hdrivers/pci/Kconfig +1
-0@@ -291,5 +291,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" endifdrivers/pci/Makefile +1
-0@@ -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.odrivers/pci/pwrctl/Kconfig new file +8
-0@@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 + +menu "PCI Power control drivers" + +config PCI_PWRCTL + bool + +endmenudrivers/pci/pwrctl/Makefile new file +3
-0@@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_PCI_PWRCTL) += core.odrivers/pci/pwrctl/core.c new file +15
-0@@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* 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)
drivers/pci/pwrctl/core.c line 25
Quoted 10 lines
drivers/pci/pwrctl/core.c new file +10
-0+{ + 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 : +device_set_of_node_from_dev (dev, pwrctl->dev);
What happens if the bootloader left the power on, and the of_platform_populate() got probe deferred because the pwrseq wasn't ready, so this happens after pci_set_of_node() has been called?
(I think dev->of_node will be put, then get and then node_reused assigned...but I'm not entirely sure)
drivers/pci/pwrctl/core.c line 34
Quoted 9 lines
drivers/pci/pwrctl/core.c new file +9
-0+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 : +device_link_del (pwrctl->link);
This might however become a NULL-pointer dereference, if dev was bound to its driver before the pci_pwrctl_notify() was registered for the pwrctl and then the PCI device is unbound.
This would also happen if device_link_add() failed when the PCI device was bound...
drivers/pci/pwrctl/core.c line 41
Quoted 7 lines
drivers/pci/pwrctl/core.c new file +7
-0+break ; + } + +return NOTIFY_DONE ; +} + +int pci_pwrctl_device_enable (struct pci_pwrctl *pwrctl)
This function doesn't really "enable the device", looking at the example driver it's rather "device_enabled" than "device_enable"...
Quoted 6 lines
drivers/pci/pwrctl/core.c new file +6
-0+{ +if (!pwrctl->dev) +return -ENODEV ; + + pwrctl->nb.notifier_call = pci_pwrctl_notify; +bus_register_notifier (&pci_bus_type, &pwrctl->nb);
drivers/pci/pwrctl/core.c line 57
Quoted 10 lines
drivers/pci/pwrctl/core.c new file +10
-0+ +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_enable); + +void pci_pwrctl_device_disable (struct pci_pwrctl *pwrctl)
Similarly this doesn't disable the device, the code calling this is doing so...
Regards,
Bjorn
Quoted 58 lines
drivers/pci/pwrctl/core.c new file +25
-0+{ +bus_unregister_notifier (&pci_bus_type, &pwrctl->nb); +} +EXPORT_SYMBOL_GPL (pci_pwrctl_device_disable); + +static void devm_pci_pwrctl_device_disable (void *data) +{ +struct pci_pwrctl *pwrctl = data; + +pci_pwrctl_device_disable (pwrctl); +} + +int devm_pci_pwrctl_device_enable (struct device *dev, +struct pci_pwrctl *pwrctl) +{ +int ret; + + ret =pci_pwrctl_device_enable (pwrctl); +if (ret) +return ret; + +return devm_add_action_or_reset (dev, devm_pci_pwrctl_device_disable, + pwrctl); +} +EXPORT_SYMBOL_GPL (devm_pci_pwrctl_device_enable);include/linux/pci-pwrctl.h new file +24
-0@@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* +* Copyright (C) 2024 Linaro Ltd. +*/ + +#ifndef __PCI_PWRCTL_H__ +#define __PCI_PWRCTL_H__ + +#include <linux/notifier.h> + +struct device ; + +struct pci_pwrctl { +struct notifier_block nb; +struct device *dev; +struct device_link *link; +}; + +int pci_pwrctl_device_enable (struct pci_pwrctl *pwrctl); +void pci_pwrctl_device_disable (struct pci_pwrctl *pwrctl); +int devm_pci_pwrctl_device_enable (struct device *dev, +struct pci_pwrctl *pwrctl); + +#endif /* __PCI_PWRCTL_H__ */ Signature · 1 line
2.40.1
Re: [RFC 8/9] PCI/pwrctl: add PCI power control core code
Quoted 1 line · Bjorn Andersson
[snip]
Quoted 18 lines
drivers/pci/pwrctl/core.c line 25
Quoted 13 lines
drivers/pci/pwrctl/core.c new file +13
-0+ +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 : +device_set_of_node_from_dev (dev, pwrctl->dev);What happens if the bootloader left the power on, and the
of_platform_populate()got probe deferred because the pwrseq wasn't ready, so this happens afterpci_set_of_node()has been called?
Quoted 2 lines
(I think
dev->of_nodewill be put, then get and thennode_reusedassigned...but I'm not entirely sure)
That's exactly what will happen and the end result will be the same.
Quoted 11 lines
drivers/pci/pwrctl/core.c line 34
Quoted 10 lines
drivers/pci/pwrctl/core.c new file +9
-0+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 : +device_link_del (pwrctl->link);
Quoted 7 lines
This might however become a NULL-pointer dereference, if dev was bound to its driver before the
pci_pwrctl_notify()was registered for the pwrctl and then the PCI device is unbound.This would also happen if
device_link_add()failed when the PCI device was bound...
Yes, I'll address it.
Quoted 11 lines
drivers/pci/pwrctl/core.c line 41
Quoted 7 lines
drivers/pci/pwrctl/core.c new file +7
-0+break ; + } + +return NOTIFY_DONE ; +} + +int pci_pwrctl_device_enable (struct pci_pwrctl *pwrctl)This function doesn't really "enable the device", looking at the example driver it's rather "
device_enabled" than "device_enable"...
I was also thinking about pci_pwrctl_device_ready() or pci_pwrctl_device_prepared().
Bart
[snip!]
Bjorn Andersson
maintainerRe: Re: [RFC 8/9] PCI/pwrctl: add PCI power control core code
Quoted 1 line · Bartosz Golaszewski
On Fri, Feb 2, 2024 at 4:53 AM Bjorn Andersson <[email protected]> wrote:
[..]
Quoted 12 lines
Quoted 11 lines
drivers/pci/pwrctl/core.c line 41
Quoted 7 lines
drivers/pci/pwrctl/core.c new file +7
-0+break ; + } + +return NOTIFY_DONE ; +} + +int pci_pwrctl_device_enable (struct pci_pwrctl *pwrctl)This function doesn't really "enable the device", looking at the example driver it's rather "
device_enabled" than "device_enable"...
Quoted 2 lines
I was also thinking about
pci_pwrctl_device_ready()orpci_pwrctl_device_prepared().
I like both of these.
I guess the bigger question is how the flow would look like in the event that we need to power-cycle the attached PCIe device, e.g. because firmware has gotten into a really bad state.
Will we need an operation that removes the device first, and then cut the power, or do we cut the power and then call unprepared()?
Regards,
Bjorn
Quoted 4 lines
Bart
[snip!]
Re: Re: [RFC 8/9] PCI/pwrctl: add PCI power control core code
Quoted 19 lines · Bjorn Andersson
Quoted 1 line · Bartosz Golaszewski
On Fri, Feb 2, 2024 at 4:53 AM Bjorn Andersson <[email protected]> wrote:
[..]
Quoted 12 lines
Quoted 11 lines
drivers/pci/pwrctl/core.c line 41
Quoted 7 lines
drivers/pci/pwrctl/core.c new file +7
-0+break ; + } + +return NOTIFY_DONE ; +} + +int pci_pwrctl_device_enable (struct pci_pwrctl *pwrctl)This function doesn't really "enable the device", looking at the example driver it's rather "
device_enabled" than "device_enable"...Quoted 2 lines
I was also thinking about
pci_pwrctl_device_ready()orpci_pwrctl_device_prepared().
Quoted 9 lines
I like both of these.
I guess the bigger question is how the flow would look like in the event that we need to power-cycle the attached PCIe device, e.g. because firmware has gotten into a really bad state.
Will we need an operation that removes the device first, and then cut the power, or do we cut the power and then call
unprepared()?
How would the core be notified about this power-cycle from the PCI subsystem? I honestly don't know. Is there a notifier we could subscribe to? Is the device unbound and rebound in such case?
Bart
Re: Re: [RFC 8/9] PCI/pwrctl: add PCI power control core code
Quoted 11 lines · Bartosz Golaszewski
Quoted 10 lines · On Fri, Feb 2, 2024 at 5:52???PM Bjorn Andersson <[email protected]> wrote:
Quoted 2 lines · Bartosz Golaszewski
I was also thinking about
pci_pwrctl_device_ready()orpci_pwrctl_device_prepared().I like both of these.
I guess the bigger question is how the flow would look like in the event that we need to power-cycle the attached PCIe device, e.g. because firmware has gotten into a really bad state.
Quoted 6 lines
Quoted 2 lines
Will we need an operation that removes the device first, and then cut the power, or do we cut the power and then call
unprepared()?How would the core be notified about this power-cycle from the PCI subsystem? I honestly don't know. Is there a notifier we could subscribe to? Is the device unbound and rebound in such case?
To power-manage the PCI device for runtime PM (suspend to D3cold) or system sleep, you need to amend:
platform_pci_power_manageable()
platform_pci_set_power_state()
platform_pci_get_power_state()
platform_pci_refresh_power_state()
platform_pci_choose_state()
E.g. platform_pci_power_manageable() would check for presence of a regulator in the DT and platform_pci_set_power_state() would disable or enable the regulator.
To reset the device by power cycling it, amend pci_reset_fn_methods[] to provide a reset method which disables and re-enables the regulator. Then you can choose that reset method via sysfs and power-cycle the device. The PCI core will also automatically use that reset method if there's nothing else available (e.g. if no Secondary Bus Reset is available because the device has siblings or children, or if FLR is not supported).
Thanks,
Lukas
Re: Re: [RFC 8/9] PCI/pwrctl: add PCI power control core code
Quoted 28 lines · Lukas Wunner
Quoted 11 lines · Bartosz Golaszewski
Quoted 10 lines · On Fri, Feb 2, 2024 at 5:52???PM Bjorn Andersson <[email protected]> wrote:
Quoted 2 lines · Bartosz Golaszewski
I was also thinking about
pci_pwrctl_device_ready()orpci_pwrctl_device_prepared().I like both of these.
I guess the bigger question is how the flow would look like in the event that we need to power-cycle the attached PCIe device, e.g. because firmware has gotten into a really bad state.
Quoted 6 lines
Quoted 2 lines
Will we need an operation that removes the device first, and then cut the power, or do we cut the power and then call
unprepared()?How would the core be notified about this power-cycle from the PCI subsystem? I honestly don't know. Is there a notifier we could subscribe to? Is the device unbound and rebound in such case?
To power-manage the PCI device for runtime PM (suspend to D3cold) or system sleep, you need to amend:
platform_pci_power_manageable()
platform_pci_set_power_state()
platform_pci_get_power_state()
platform_pci_refresh_power_state()
platform_pci_choose_state()
Quoted 4 lines
E.g.
platform_pci_power_manageable()would check for presence of a regulator in the DT andplatform_pci_set_power_state()would disable or enable the regulator.
This will work if the sole control of the resources lies in these platform_*() APIs. But in reality, the controller drivers are the ones controlling the power supply to the devices and with this series, the control would be shifted partly to pwrctl driver.
I think what we need is to call in the callbacks of the drivers in a hierarchial order.
- Mani
Quoted 11 lines
To reset the device by power cycling it, amend pci_reset_fn_methods[] to provide a reset method which disables and re-enables the regulator. Then you can choose that reset method via sysfs and power-cycle the device. The PCI core will also automatically use that reset method if there's nothing else available (e.g. if no Secondary Bus Reset is available because the device has siblings or children, or if FLR is not supported).
Thanks,
Lukas
Signature · 1 line
மணிவண்ணன் சதாசிவம்
Re: Re: [RFC 8/9] PCI/pwrctl: add PCI power control core code
In reply to Bjorn AnderssonQuoted 18 lines · Bjorn Andersson
Quoted 1 line · Bartosz Golaszewski
On Fri, Feb 2, 2024 at 4:53 AM Bjorn Andersson <[email protected]> wrote:
[..]
Quoted 12 lines
Quoted 11 lines
drivers/pci/pwrctl/core.c line 41
Quoted 7 lines
drivers/pci/pwrctl/core.c new file +7
-0+break ; + } + +return NOTIFY_DONE ; +} + +int pci_pwrctl_device_enable (struct pci_pwrctl *pwrctl)This function doesn't really "enable the device", looking at the example driver it's rather "
device_enabled" than "device_enable"...Quoted 2 lines
I was also thinking about
pci_pwrctl_device_ready()orpci_pwrctl_device_prepared().
Quoted 9 lines
I like both of these.
I guess the bigger question is how the flow would look like in the event that we need to power-cycle the attached PCIe device, e.g. because firmware has gotten into a really bad state.
Will we need an operation that removes the device first, and then cut the power, or do we cut the power and then call
unprepared()?
Currently, we don't power cycle while resetting the devices. Most of the drivers just do a software reset using some register writes. Part of the reason for that is, the drivers themselves don't control the power to the devices and there would be no way to let the parent know about the firmware crash.
- Mani
Signature · 1 line
மணிவண்ணன் சதாசிவம்
Bjorn Andersson
maintainerRe: Re: Re: [RFC 8/9] PCI/pwrctl: add PCI power control core code
Quoted 25 lines · Manivannan Sadhasivam
Quoted 24 lines · Bjorn Andersson
Quoted 1 line · Bartosz Golaszewski
On Fri, Feb 2, 2024 at 4:53 AM Bjorn Andersson <[email protected]> wrote:
[..]
Quoted 12 lines
Quoted 11 lines
drivers/pci/pwrctl/core.c line 41
Quoted 7 lines
drivers/pci/pwrctl/core.c new file +7
-0+break ; + } + +return NOTIFY_DONE ; +} + +int pci_pwrctl_device_enable (struct pci_pwrctl *pwrctl)This function doesn't really "enable the device", looking at the example driver it's rather "
device_enabled" than "device_enable"...Quoted 2 lines
I was also thinking about
pci_pwrctl_device_ready()orpci_pwrctl_device_prepared().I like both of these.
I guess the bigger question is how the flow would look like in the event that we need to power-cycle the attached PCIe device, e.g. because firmware has gotten into a really bad state.
Quoted 9 lines
Quoted 3 lines
Will we need an operation that removes the device first, and then cut the power, or do we cut the power and then call
unprepared()?Currently, we don't power cycle while resetting the devices. Most of the drivers just do a software reset using some register writes. Part of the reason for that is, the drivers themselves don't control the power to the devices and there would be no way to let the parent know about the firmware crash.
I don't know what the appropriate design for this is, but we do have a need for being able to recover from this state by the means of power-cycling the device.
If it's not possible to let the device do it (in any fashion), then perhaps a user-space-assisted model is needed?
Turning on power is an important first step, but please do consider the full scope of the known problem space.
Regards,
Bjorn
Re: Re: Re: [RFC 8/9] PCI/pwrctl: add PCI power control core code
Quoted 40 lines · Bjorn Andersson
Quoted 25 lines · Manivannan Sadhasivam
Quoted 24 lines · Bjorn Andersson
Quoted 1 line · Bartosz Golaszewski
On Fri, Feb 2, 2024 at 4:53 AM Bjorn Andersson <[email protected]> wrote:
[..]
Quoted 12 lines
Quoted 11 lines
drivers/pci/pwrctl/core.c line 41
Quoted 7 lines
drivers/pci/pwrctl/core.c new file +7
-0+break ; + } + +return NOTIFY_DONE ; +} + +int pci_pwrctl_device_enable (struct pci_pwrctl *pwrctl)This function doesn't really "enable the device", looking at the example driver it's rather "
device_enabled" than "device_enable"...Quoted 2 lines
I was also thinking about
pci_pwrctl_device_ready()orpci_pwrctl_device_prepared().I like both of these.
I guess the bigger question is how the flow would look like in the event that we need to power-cycle the attached PCIe device, e.g. because firmware has gotten into a really bad state.
Quoted 9 lines
Quoted 3 lines
Will we need an operation that removes the device first, and then cut the power, or do we cut the power and then call
unprepared()?Currently, we don't power cycle while resetting the devices. Most of the drivers just do a software reset using some register writes. Part of the reason for that is, the drivers themselves don't control the power to the devices and there would be no way to let the parent know about the firmware crash.
I don't know what the appropriate design for this is, but we do have a need for being able to recover from this state by the means of power-cycling the device.
Quoted 6 lines
If it's not possible to let the device do it (in any fashion), then perhaps a user-space-assisted model is needed?
Turning on power is an important first step, but please do consider the full scope of the known problem space.
Agree. I'm not ignoring this issue, but this is a separate topic IMO (or an incremental change). Because, power cycling the device in the event of a firmware crash or even upon receiving AER Fatal errors is valid for platforms not making use of this driver and an existing issue.
For sure we can accomodate that functionality in this series itself, but that's going to drag this series to many releases (you already know how long it took for us to get to the current state). Instead, I'd recommend to merge it in its current form and have Bartosz or someone work on incremental features such as:
1. Runtime/System PM
2. Resetting the device in the event of fw crash etc...
Wdyt?
- Mani
Signature · 1 line
மணிவண்ணன் சதாசிவம்
Re: [RFC 8/9] PCI/pwrctl: add PCI power control core code
In reply to Bjorn AnderssonQuoted 1 line · Bjorn Andersson
[snip]
Quoted 11 lines
drivers/pci/pwrctl/core.c line 34
Quoted 10 lines
drivers/pci/pwrctl/core.c new file +9
-0+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 : +device_link_del (pwrctl->link);
Quoted 4 lines
This might however become a NULL-pointer dereference, if dev was bound to its driver before the
pci_pwrctl_notify()was registered for the pwrctl and then the PCI device is unbound.
Right. And it also makes me think that right after registering with the notifier, we should iterate over the PCI bus devices and see if the relevant one is already there.
Quoted 3 lines
This would also happen if
device_link_add()failed when the PCI device was bound...
Right.
Bart
[snip]
RFC 9/9 PCI/pwrctl: add a PCI power control driver for power sequenced devices
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
Add a PCI power control driver that's capable of correctly powering up devices using the power sequencing subsystem. For now we support the ath11k module on QCA6390.
--- drivers/pci/pwrctl/Kconfig | 9 +++ drivers/pci/pwrctl/Makefile | 1 + drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 83 ++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
drivers/pci/pwrctl/Kconfig +9 -0
@@ -5,4 +5,13 @@ menu "PCI Power control drivers" config PCI_PWRCTL bool +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
drivers/pci/pwrctl/Makefile +1 -0
@@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_PCI_PWRCTL) += core.o +obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctl-pwrseq.o
drivers/pci/pwrctl/pci-pwrctl-pwrseq.c new file +83 -0
83 lines not on this page · raw message
Signature · 1 line
2.40.1
Bjorn Andersson
maintainerRe: [RFC 9/9] PCI/pwrctl: add a PCI power control driver for power sequenced devices
Quoted 6 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
Add a PCI power control driver that's capable of correctly powering up devices using the power sequencing subsystem. For now we support the ath11k module on QCA6390.
For a PCI device which doesn't share resources with something on another bus, the whole power sequencing would be implemented in a driver like this - without the involvement of the power sequence framework.
I think it would be nice to see this series introduce a simple pci_pwrctl driver, and then (in the same series) introduce the power sequence framework and your PMU driver.
One case where such model would be appropriate is the XHCI controller (uPD720201) on db845c. Today we describe vddpe-3p3-supply as a supply on the PCI controller, but it should have been vdd33-supply, vdd10-supply, avdd33-supply on the PCI device.
That would provide an example for how a simple PCI power control driver can/should look like, and we can discuss the PCI pieces separate from the introduction of the new power sequence framework (which is unrelated to PCI).
Regards,
Bjorn
Quoted 127 lines
Signed-off-by Bartosz Golaszewski <[email protected]>--- drivers/pci/pwrctl/Kconfig | 9 +++ drivers/pci/pwrctl/Makefile | 1 + drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 83 ++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 drivers/pci/pwrctl/pci-pwrctl-pwrseq.cdrivers/pci/pwrctl/Kconfig +9
-0@@ -5,4 +5,13 @@ menu "PCI Power control drivers" config PCI_PWRCTL bool +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. + endmenudrivers/pci/pwrctl/Makefile +1
-0@@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_PCI_PWRCTL) += core.o +obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctl-pwrseq.odrivers/pci/pwrctl/pci-pwrctl-pwrseq.c new file +83
-0@@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Copyright (C) 2023-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); +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_enable (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" , + }, + { } +}; +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 <[email protected]>" ); +MODULE_DESCRIPTION ("Generic PCI Power Control module for power sequenced devices" ); +MODULE_LICENSE ("GPL" );Signature · 1 line
2.40.1
Re: [RFC 9/9] PCI/pwrctl: add a PCI power control driver for power sequenced devices
Quoted 4 lines · Bjorn Andersson
Quoted 2 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
Quoted 9 lines
Quoted 4 lines
Add a PCI power control driver that's capable of correctly powering up devices using the power sequencing subsystem. For now we support the ath11k module on QCA6390.
For a PCI device which doesn't share resources with something on another bus, the whole power sequencing would be implemented in a driver like this - without the involvement of the power sequence framework.
Yes, this is what I did in the previous incarnation of this code[1].
(I know, I should have linked it here. My bad, I will do it next time).
Quoted 4 lines
I think it would be nice to see this series introduce a simple
pci_pwrctldriver, and then (in the same series) introduce the power sequence framework and your PMU driver.
I disagree. I was initially annoyed by Dmitry asking me to do a lot more work than anticipated but he's right after all. WLAN and BT consuming what is really the PMU's inputs is simply not the actual representation. That's why we should make it a pwrseq user IMO.
Quoted 4 lines
One case where such model would be appropriate is the XHCI controller (uPD720201) on db845c. Today we describe vddpe-3p3-supply as a supply on the PCI controller, but it should have been vdd33-supply, vdd10-supply, avdd33-supply on the PCI device.
Sounds like a good second user then!
Quoted 5 lines
That would provide an example for how a simple PCI power control driver can/should look like, and we can discuss the PCI pieces separate from the introduction of the new power sequence framework (which is unrelated to PCI).
I agree it's unrelated and it could possibly go upstream separately but the particular use-case on RB5 (and other Qcom platforms) requires both the PCI and generic power sequencing to be addressed.
Bart
[snip]
[1] https://lore.kernel.org/netdev/[email protected]/T/#m72f52254a52fcb8a8a44de0702cad1087d4bcfa1
Bjorn Andersson
maintainerRe: Re: [RFC 9/9] PCI/pwrctl: add a PCI power control driver for power sequenced devices
Quoted 24 lines · Bartosz Golaszewski
Quoted 4 lines · Bjorn Andersson
Quoted 2 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
Quoted 9 lines
Quoted 4 lines
Add a PCI power control driver that's capable of correctly powering up devices using the power sequencing subsystem. For now we support the ath11k module on QCA6390.
For a PCI device which doesn't share resources with something on another bus, the whole power sequencing would be implemented in a driver like this - without the involvement of the power sequence framework.
Yes, this is what I did in the previous incarnation of this code[1].
(I know, I should have linked it here. My bad, I will do it next time).
Quoted 4 lines
I think it would be nice to see this series introduce a simple
pci_pwrctldriver, and then (in the same series) introduce the power sequence framework and your PMU driver.
Quoted 5 lines
I disagree. I was initially annoyed by Dmitry asking me to do a lot more work than anticipated but he's right after all. WLAN and BT consuming what is really the PMU's inputs is simply not the actual representation. That's why we should make it a pwrseq user IMO.
If the PMU registers the "internal" output regulators, then PCI device would consume the PCI outputs of the PMU, the BT device would consume the BT outputs of the PMU. The PMU requests inputs enabled and drives BT_EN and WLAN_EN according to which subset of these output regulators are enabled.
Pretty much exactly as "regulator-fixes" isn't a pwrseq device.
Regards,
Bjorn
Quoted 22 lines
Quoted 4 lines
One case where such model would be appropriate is the XHCI controller (uPD720201) on db845c. Today we describe vddpe-3p3-supply as a supply on the PCI controller, but it should have been vdd33-supply, vdd10-supply, avdd33-supply on the PCI device.
Sounds like a good second user then!
Quoted 5 lines
That would provide an example for how a simple PCI power control driver can/should look like, and we can discuss the PCI pieces separate from the introduction of the new power sequence framework (which is unrelated to PCI).
I agree it's unrelated and it could possibly go upstream separately but the particular use-case on RB5 (and other Qcom platforms) requires both the PCI and generic power sequencing to be addressed.
Bart
[snip]
[1] https://lore.kernel.org/netdev/[email protected]/T/#m72f52254a52fcb8a8a44de0702cad1087d4bcfa1
Bjorn Andersson
maintainerQuoted 2 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
We now have 3 RFC and 1 PATCH versions of these patches on the list in under a month. Please at least add a version to your subject...
Quoted 24 lines
I'd like to preface the cover letter by saying right away that this series is not complete. It's an RFC that presents my approach and is sent to the list for discussion. There are no DT bindings nor docs in
Documentation/yet. Please review it as an RFC and not an upstreambound series. If the approach is accepted as correct, I'll add missing bits.The RFC[1] presenting my proposed device-tree representation of the QCA6391 package present on the RB5 board - while not really officially accepted - was not outright rejected which is a good sign.
This series incorporates it and builds a proposed power sequencing subsystem together with the first dedicated driver around it. Then it adds first two users: the Bluetooth and WLAN modules of the QCA6391.
The Bluetooth part is pretty straightforward. The WLAN however is a PCIe device and as such needs to be powered-up *before* it's detected on the PCI bus. To that end, we modify the PCI core to instantiate platform devices for existing DT child nodes of the PCIe ports. For those nodes for which a power-sequencing driver exists, we bind it and let it probe. The driver then triggers a rescan of the PCI bus with the aim of detecting the now powered-on device. The device will consume the same DT node as the platform, power-sequencing device. We use device links to make the latter become the parent of the former.
Quoted 5 lines
The main advantage of the above approach (both for PCI as well as generic power sequencers) is that we don't introduce significant changes in DT bindings and don't introduce new properties. We merely define new resources.
How can we tell? There are still no Documentation/dt-bindings changes in your series.
Regards,
Bjorn
Quoted 51 lines
Bartosz Golaszewski (9):
of: provide a cleanup helper for OF nodes
arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
power: sequencing: new subsystem
power: pwrseq: add a driver for the QCA6390 PMU module
Bluetooth: qca: use the power sequencer for QCA6390
PCI: create platform devices for child OF nodes of the port node
PCI: hold the rescan mutex when scanning for the first time PCI/pwrctl: add PCI power control core code
PCI/pwrctl: add a PCI power control driver for power sequenced devicesarch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 128 +++++- arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 + drivers/bluetooth/hci_qca.c | 30 ++ drivers/pci/Kconfig | 1 + drivers/pci/Makefile | 1 + drivers/pci/bus.c | 9 +- drivers/pci/probe.c | 2 + drivers/pci/pwrctl/Kconfig | 17 + drivers/pci/pwrctl/Makefile | 4 + drivers/pci/pwrctl/core.c | 82 ++++ drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 83 ++++ drivers/pci/remove.c | 2 + drivers/power/Kconfig | 1 + drivers/power/Makefile | 1 + drivers/power/sequencing/Kconfig | 28 ++ drivers/power/sequencing/Makefile | 6 + drivers/power/sequencing/core.c | 482 ++++++++++++++++++++++ drivers/power/sequencing/pwrseq-qca6390.c | 232 +++++++++++ include/linux/of.h | 4 + include/linux/pci-pwrctl.h | 24 ++ include/linux/pwrseq/consumer.h | 53 +++ include/linux/pwrseq/provider.h | 41 ++ 22 files changed, 1229 insertions(+), 12 deletions(-) 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 drivers/pci/pwrctl/pci-pwrctl-pwrseq.c 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 drivers/power/sequencing/pwrseq-qca6390.c create mode 100644 include/linux/pci-pwrctl.h create mode 100644 include/linux/pwrseq/consumer.h create mode 100644 include/linux/pwrseq/provider.hSignature · 1 line
2.40.1
Quoted 8 lines · Bjorn Andersson
Quoted 2 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
We now have 3 RFC and 1 PATCH versions of these patches on the list in under a month. Please at least add a version to your subject...
So there was an RFC for the PCI power sequencing (now renamed to PCI power control - pci_pwrctl), then a proper series for it (with changes listed). Then an RFC with just proposed DT changes (sent mostly to DT maintainers to clear it with them) and now an RFC with power sequencing + PCI power control. Hard to figure out how to version it if these are pretty much separate developments.
I'll provide links to everything next time.
Quoted 24 lines
Quoted 24 lines
I'd like to preface the cover letter by saying right away that this series is not complete. It's an RFC that presents my approach and is sent to the list for discussion. There are no DT bindings nor docs in
Documentation/yet. Please review it as an RFC and not an upstreambound series. If the approach is accepted as correct, I'll add missing bits.The RFC[1] presenting my proposed device-tree representation of the QCA6391 package present on the RB5 board - while not really officially accepted - was not outright rejected which is a good sign.
This series incorporates it and builds a proposed power sequencing subsystem together with the first dedicated driver around it. Then it adds first two users: the Bluetooth and WLAN modules of the QCA6391.
The Bluetooth part is pretty straightforward. The WLAN however is a PCIe device and as such needs to be powered-up *before* it's detected on the PCI bus. To that end, we modify the PCI core to instantiate platform devices for existing DT child nodes of the PCIe ports. For those nodes for which a power-sequencing driver exists, we bind it and let it probe. The driver then triggers a rescan of the PCI bus with the aim of detecting the now powered-on device. The device will consume the same DT node as the platform, power-sequencing device. We use device links to make the latter become the parent of the former.
Quoted 8 lines
Quoted 5 lines
The main advantage of the above approach (both for PCI as well as generic power sequencers) is that we don't introduce significant changes in DT bindings and don't introduce new properties. We merely define new resources.
How can we tell? There are still no
Documentation/dt-bindingschanges in your series.
Noted.
Bartosz
Quoted 55 lines
Regards,
BjornQuoted 51 lines
Bartosz Golaszewski (9):
of: provide a cleanup helper for OF nodes
arm64: dts: qcom: qrb5165-rb5: model the PMU of the QCA6391
power: sequencing: new subsystem
power: pwrseq: add a driver for the QCA6390 PMU module
Bluetooth: qca: use the power sequencer for QCA6390
PCI: create platform devices for child OF nodes of the port node
PCI: hold the rescan mutex when scanning for the first time PCI/pwrctl: add PCI power control core code
PCI/pwrctl: add a PCI power control driver for power sequenced devicesarch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 128 +++++- arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 + drivers/bluetooth/hci_qca.c | 30 ++ drivers/pci/Kconfig | 1 + drivers/pci/Makefile | 1 + drivers/pci/bus.c | 9 +- drivers/pci/probe.c | 2 + drivers/pci/pwrctl/Kconfig | 17 + drivers/pci/pwrctl/Makefile | 4 + drivers/pci/pwrctl/core.c | 82 ++++ drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 83 ++++ drivers/pci/remove.c | 2 + drivers/power/Kconfig | 1 + drivers/power/Makefile | 1 + drivers/power/sequencing/Kconfig | 28 ++ drivers/power/sequencing/Makefile | 6 + drivers/power/sequencing/core.c | 482 ++++++++++++++++++++++ drivers/power/sequencing/pwrseq-qca6390.c | 232 +++++++++++ include/linux/of.h | 4 + include/linux/pci-pwrctl.h | 24 ++ include/linux/pwrseq/consumer.h | 53 +++ include/linux/pwrseq/provider.h | 41 ++ 22 files changed, 1229 insertions(+), 12 deletions(-) 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 drivers/pci/pwrctl/pci-pwrctl-pwrseq.c 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 drivers/power/sequencing/pwrseq-qca6390.c create mode 100644 include/linux/pci-pwrctl.h create mode 100644 include/linux/pwrseq/consumer.h create mode 100644 include/linux/pwrseq/provider.h--
2.40.1
Bjorn Andersson
maintainerQuoted 26 lines · Bartosz Golaszewski
From: Bartosz Golaszewski <[email protected]>
I'd like to preface the cover letter by saying right away that this series is not complete. It's an RFC that presents my approach and is sent to the list for discussion. There are no DT bindings nor docs in
Documentation/yet. Please review it as an RFC and not an upstreambound series. If the approach is accepted as correct, I'll add missing bits.The RFC[1] presenting my proposed device-tree representation of the QCA6391 package present on the RB5 board - while not really officially accepted - was not outright rejected which is a good sign.
This series incorporates it and builds a proposed power sequencing subsystem together with the first dedicated driver around it. Then it adds first two users: the Bluetooth and WLAN modules of the QCA6391.
The Bluetooth part is pretty straightforward. The WLAN however is a PCIe device and as such needs to be powered-up *before* it's detected on the PCI bus. To that end, we modify the PCI core to instantiate platform devices for existing DT child nodes of the PCIe ports. For those nodes for which a power-sequencing driver exists, we bind it and let it probe. The driver then triggers a rescan of the PCI bus with the aim of detecting the now powered-on device. The device will consume the same DT node as the platform, power-sequencing device. We use device links to make the latter become the parent of the former.
Quoted 6 lines
The main advantage of the above approach (both for PCI as well as generic power sequencers) is that we don't introduce significant changes in DT bindings and don't introduce new properties. We merely define new resources.
FWIW, booting RB5 with this patch series does give me working working WiFI. But I do see the following splat during boot:
[ 5.880411] sysfs: cannot create duplicate filename '/devices/platform/soc@0/1c00000.pcie/pci0000:00/0000:00:00.0/resource0' [ 5.891938] CPU: 5 PID: 68 Comm: kworker/u16:4 Not tainted 6.8.0-rc2-next-20240131-00009-g079fdad54c8f #199 [ 5.901927] Hardware name: Qualcomm Technologies, Inc. Robotics RB5 (DT) [ 5.908808] Workqueue: events_unbound async_run_entry_fn [ 5.914274] Call trace: [ 5.916794] dump_backtrace+0xec/0x108 [ 5.920649] show_stack+0x18/0x24 [ 5.924062] dump_stack_lvl+0x50/0x68 [ 5.927826] dump_stack+0x18/0x24 [ 5.931238] sysfs_warn_dup+0x64/0x80 [ 5.935004] sysfs_create_bin_file+0xf4/0x130 [ 5.939480] pci_create_attr+0x100/0x168 [ 5.943509] pci_create_sysfs_dev_files+0x6c/0xc0 [ 5.948337] pci_bus_add_device+0x60/0x114 [ 5.952551] pci_bus_add_devices+0x4c/0x7c [ 5.956762] pci_host_probe+0x138/0x188 [ 5.960700] dw_pcie_host_init+0x290/0x334 [ 5.964914] qcom_pcie_probe+0x1f8/0x23c [ 5.968942] platform_probe+0xa8/0xd0 [ 5.972707] really_probe+0x130/0x2e4 [ 5.976469] __driver_probe_device+0xa0/0x128 [ 5.980944] driver_probe_device+0x3c/0x1f8 [ 5.985245] __device_attach_driver+0x118/0x140 [ 5.989897] bus_for_each_drv+0xf4/0x14c [ 5.993923] __device_attach_async_helper+0x78/0xd0 [ 5.998937] async_run_entry_fn+0x24/0xdc [ 6.003051] process_scheduled_works+0x210/0x328 [ 6.007793] worker_thread+0x28c/0x450 [ 6.011642] kthread+0xfc/0x184 [ 6.014865] ret_from_fork+0x10/0x20 [ 6.018572] ------------[ cut here ]------------ [ 6.023339] proc_dir_entry '0000:00/00.0' already registered
Regards,
Bjorn