From 120e2a8109065fed116667238dec3b3dccc030c0 Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Mon, 27 May 2019 13:01:36 +0300 Subject: interconnect: Add bulk API helpers There are drivers which just need to get multiple interconnect paths, request some predefined amounts of bandwidth and then just toggle the paths between enabled/disabled state. The aim of this patch is simplify the above and to allow drivers to put all the path names and bandwidth data into a single static icc_bulk_data table and call the icc_bulk_* functions on that table in order to scale all the interconnect paths in parallel. Suggested-by: Evan Green Suggested-by: Bjorn Andersson Signed-off-by: Georgi Djakov --- drivers/interconnect/Makefile | 2 +- drivers/interconnect/bulk.c | 119 ++++++++++++++++++++++++++++++++++++++++++ include/linux/interconnect.h | 22 ++++++++ 3 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 drivers/interconnect/bulk.c diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile index 4825c287ca13..d203520b0a56 100644 --- a/drivers/interconnect/Makefile +++ b/drivers/interconnect/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 CFLAGS_core.o := -I$(src) -icc-core-objs := core.o +icc-core-objs := core.o bulk.o obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_IMX) += imx/ diff --git a/drivers/interconnect/bulk.c b/drivers/interconnect/bulk.c new file mode 100644 index 000000000000..9bd418594665 --- /dev/null +++ b/drivers/interconnect/bulk.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +/** + * of_icc_bulk_get - get interconnect paths + * @dev: the device requesting the path + * @num_paths: the number of icc_bulk_data + * @paths: the table with the paths we want to get + * + * Returns 0 on success or -EERROR otherwise. + */ +int __must_check of_icc_bulk_get(struct device *dev, int num_paths, + struct icc_bulk_data *paths) +{ + int ret, i; + + for (i = 0; i < num_paths; i++) { + paths[i].path = of_icc_get(dev, paths[i].name); + if (IS_ERR(paths[i].path)) { + ret = PTR_ERR(paths[i].path); + dev_err(dev, "of_icc_get() failed on path %s (%d)\n", + paths[i].name, ret); + paths[i].path = NULL; + goto err; + } + } + + return 0; + +err: + icc_bulk_put(i, paths); + + return ret; +} +EXPORT_SYMBOL_GPL(of_icc_bulk_get); + +/** + * icc_bulk_put - put a list of interconnect paths + * @num_paths: the number of icc_bulk_data + * @paths: the icc_bulk_data table with the paths being put + */ +void icc_bulk_put(int num_paths, struct icc_bulk_data *paths) +{ + while (--num_paths >= 0) { + icc_put(paths[num_paths].path); + paths[num_paths].path = NULL; + } +} +EXPORT_SYMBOL_GPL(icc_bulk_put); + +/** + * icc_bulk_set - set bandwidth to a set of paths + * @num_paths: the number of icc_bulk_data + * @paths: the icc_bulk_data table containing the paths and bandwidth + * + * Returns 0 on success or -EERROR otherwise. + */ +int icc_bulk_set_bw(int num_paths, const struct icc_bulk_data *paths) +{ + int ret = 0; + int i; + + for (i = 0; i < num_paths; i++) { + ret = icc_set_bw(paths[i].path, paths[i].avg_bw, + paths[i].peak_bw); + if (ret) { + pr_err("icc_set_bw() failed on path %s (%d)\n", + paths[i].name, ret); + return ret; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(icc_bulk_set_bw); + +/** + * icc_bulk_enable - enable a previously disabled set of paths + * @num_paths: the number of icc_bulk_data + * @paths: the icc_bulk_data table containing the paths and bandwidth + * + * Returns 0 on success or -EERROR otherwise. + */ +int icc_bulk_enable(int num_paths, const struct icc_bulk_data *paths) +{ + int ret, i; + + for (i = 0; i < num_paths; i++) { + ret = icc_enable(paths[i].path); + if (ret) { + pr_err("icc_enable() failed on path %s (%d)\n", + paths[i].name, ret); + goto err; + } + } + + return 0; + +err: + icc_bulk_disable(i, paths); + + return ret; +} +EXPORT_SYMBOL_GPL(icc_bulk_enable); + +/** + * icc_bulk_disable - disable a set of interconnect paths + * @num_paths: the number of icc_bulk_data + * @paths: the icc_bulk_data table containing the paths and bandwidth + */ +void icc_bulk_disable(int num_paths, const struct icc_bulk_data *paths) +{ + while (--num_paths >= 0) + icc_disable(paths[num_paths].path); +} +EXPORT_SYMBOL_GPL(icc_bulk_disable); diff --git a/include/linux/interconnect.h b/include/linux/interconnect.h index 3a63d98613fc..e47028096ba8 100644 --- a/include/linux/interconnect.h +++ b/include/linux/interconnect.h @@ -23,6 +23,28 @@ struct icc_path; struct device; +/** + * struct icc_bulk_data - Data used for bulk icc operations. + * + * @path: reference to the path returned by icc_get() + * @name: the name from the "interconnect-names" DT property + * @avg_bw: average bandwidth in icc units + * @peak_bw: peak bandwidth in icc units + */ +struct icc_bulk_data { + struct icc_path *path; + const char *name; + u32 avg_bw; + u32 peak_bw; +}; + +int __must_check of_icc_bulk_get(struct device *dev, int num_paths, + struct icc_bulk_data *paths); +void icc_bulk_put(int num_paths, struct icc_bulk_data *paths); +int icc_bulk_set_bw(int num_paths, const struct icc_bulk_data *paths); +int icc_bulk_enable(int num_paths, const struct icc_bulk_data *paths); +void icc_bulk_disable(int num_paths, const struct icc_bulk_data *paths); + #if IS_ENABLED(CONFIG_INTERCONNECT) struct icc_path *icc_get(struct device *dev, const int src_id, -- cgit v1.2.3 From 03f8108c0acc9f399088dbb0c6bd762c39707688 Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Mon, 15 Jun 2020 19:03:36 +0300 Subject: PCI: qcom: Disable power management for uPD720201 USB3 controller The uPD720201 USB3 host controller (connected to PCIe) on the Dragonboard 845c is often failing during suspend and resume. The following messages are seen over the console: PM: suspend entry (s2idle) Filesystems sync: 0.000 seconds Freezing user space processes ... (elapsed 0.001 seconds) done. OOM killer disabled. Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done. printk: Suspending console(s) (use no_console_suspend to debug) dwc3-qcom a8f8800.usb: HS-PHY not in L2 dwc3-qcom a6f8800.usb: HS-PHY not in L2 xhci_hcd 0000:01:00.0: can't change power state from D3hot to D0 (config space inaccessible) xhci_hcd 0000:01:00.0: can't change power state from D3hot to D0 (config space inaccessible) xhci_hcd 0000:01:00.0: Controller not ready at resume -19 xhci_hcd 0000:01:00.0: PCI post-resume error -19! xhci_hcd 0000:01:00.0: HC died; cleaning up Then the USB devices are not functional anymore. Let's disable the PM of the controller for now, as this will at least keep USB devices working even after suspend and resume. Signed-off-by: Georgi Djakov --- drivers/pci/controller/dwc/pcie-qcom.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 138e1a2d21cc..c1f502682a19 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1439,6 +1439,13 @@ static void qcom_fixup_class(struct pci_dev *dev) { dev->class = PCI_CLASS_BRIDGE_PCI << 8; } + +static void qcom_fixup_nopm(struct pci_dev *dev) +{ + dev->pm_cap = 0; + dev_info(&dev->dev, "Disabling PCI power management\n"); +} + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0101, qcom_fixup_class); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0104, qcom_fixup_class); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0106, qcom_fixup_class); @@ -1446,6 +1453,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0107, qcom_fixup_class); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0302, qcom_fixup_class); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1000, qcom_fixup_class); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1001, qcom_fixup_class); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_RENESAS, 0x0014, qcom_fixup_nopm); static struct platform_driver qcom_pcie_driver = { .probe = qcom_pcie_probe, -- cgit v1.2.3 From 9d5e571609e52b30dd592db6c2f40eef81e6db65 Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Tue, 9 Jun 2020 23:02:03 +0300 Subject: arm64: defconfig: Enable the PM8xxx RTC driver Enable the driver for the real time clock found in the PMICs on various Qualcomm platforms. Signed-off-by: Georgi Djakov --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 883e8bace3ed..387807e40010 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -760,6 +760,7 @@ CONFIG_RTC_DRV_S3C=y CONFIG_RTC_DRV_PL031=y CONFIG_RTC_DRV_SUN6I=y CONFIG_RTC_DRV_ARMADA38X=y +CONFIG_RTC_DRV_PM8XXX=m CONFIG_RTC_DRV_TEGRA=y CONFIG_RTC_DRV_SNVS=m CONFIG_RTC_DRV_IMX_SC=m -- cgit v1.2.3