aboutsummaryrefslogtreecommitdiff
path: root/pkgs/patches-linux-5.15/0006-PCI-mvebu-Add-support-for-compiling-driver-as-module.patch
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/patches-linux-5.15/0006-PCI-mvebu-Add-support-for-compiling-driver-as-module.patch')
-rw-r--r--pkgs/patches-linux-5.15/0006-PCI-mvebu-Add-support-for-compiling-driver-as-module.patch175
1 files changed, 175 insertions, 0 deletions
diff --git a/pkgs/patches-linux-5.15/0006-PCI-mvebu-Add-support-for-compiling-driver-as-module.patch b/pkgs/patches-linux-5.15/0006-PCI-mvebu-Add-support-for-compiling-driver-as-module.patch
new file mode 100644
index 0000000..2ff5eef
--- /dev/null
+++ b/pkgs/patches-linux-5.15/0006-PCI-mvebu-Add-support-for-compiling-driver-as-module.patch
@@ -0,0 +1,175 @@
+From 2d12fdead984145ea791cac44c0b0ce25504f4c5 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Sun, 31 Oct 2021 22:55:20 +0100
+Subject: [PATCH 06/90] PCI: mvebu: Add support for compiling driver as module
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Now when driver uses devm_pci_remap_iospace() function, it is possible
+implement ->remove() callback for unbinding device from driver.
+
+Implement mvebu_pcie_remove() callback with proper cleanup phase, drop
+driver's suppress_bind_attrs flag and switch type of CONFIG_PCI_MVEBU
+option from bool to tristate.
+
+This allows to compile pci-mvebu.c driver as loadable module pci-mvebu.ko
+with ability to unload it.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+---
+ drivers/pci/controller/Kconfig | 2 +-
+ drivers/pci/controller/pci-mvebu.c | 91 +++++++++++++++++++++++++-----
+ 2 files changed, 77 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
+index 326f7d13024f..a4c99ebff85e 100644
+--- a/drivers/pci/controller/Kconfig
++++ b/drivers/pci/controller/Kconfig
+@@ -4,7 +4,7 @@ menu "PCI controller drivers"
+ depends on PCI
+
+ config PCI_MVEBU
+- bool "Marvell EBU PCIe controller"
++ tristate "Marvell EBU PCIe controller"
+ depends on ARCH_MVEBU || ARCH_DOVE || COMPILE_TEST
+ depends on MVEBU_MBUS
+ depends on ARM
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index 9cbf10d6fc30..504eb9b94c0f 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -6,6 +6,7 @@
+ */
+
+ #include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/pci.h>
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+@@ -154,22 +155,13 @@ static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)
+ mvebu_writel(port, stat, PCIE_STAT_OFF);
+ }
+
+-/*
+- * Setup PCIE BARs and Address Decode Wins:
+- * BAR[0] -> internal registers (needed for MSI)
+- * BAR[1] -> covers all DRAM banks
+- * BAR[2] -> Disabled
+- * WIN[0-3] -> DRAM bank[0-3]
+- */
+-static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
++static void mvebu_pcie_disable_wins(struct mvebu_pcie_port *port)
+ {
+- const struct mbus_dram_target_info *dram;
+- u32 size;
+ int i;
+
+- dram = mv_mbus_dram_info();
++ mvebu_writel(port, 0, PCIE_BAR_LO_OFF(0));
++ mvebu_writel(port, 0, PCIE_BAR_HI_OFF(0));
+
+- /* First, disable and clear BARs and windows. */
+ for (i = 1; i < 3; i++) {
+ mvebu_writel(port, 0, PCIE_BAR_CTRL_OFF(i));
+ mvebu_writel(port, 0, PCIE_BAR_LO_OFF(i));
+@@ -185,6 +177,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
+ mvebu_writel(port, 0, PCIE_WIN5_CTRL_OFF);
+ mvebu_writel(port, 0, PCIE_WIN5_BASE_OFF);
+ mvebu_writel(port, 0, PCIE_WIN5_REMAP_OFF);
++}
++
++/*
++ * Setup PCIE BARs and Address Decode Wins:
++ * BAR[0] -> internal registers (needed for MSI)
++ * BAR[1] -> covers all DRAM banks
++ * BAR[2] -> Disabled
++ * WIN[0-3] -> DRAM bank[0-3]
++ */
++static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
++{
++ const struct mbus_dram_target_info *dram;
++ u32 size;
++ int i;
++
++ dram = mv_mbus_dram_info();
++
++ /* First, disable and clear BARs and windows. */
++ mvebu_pcie_disable_wins(port);
+
+ /* Setup windows for DDR banks. Count total DDR size on the fly. */
+ size = 0;
+@@ -1257,6 +1268,52 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
+ return pci_host_probe(bridge);
+ }
+
++static int mvebu_pcie_remove(struct platform_device *pdev)
++{
++ struct mvebu_pcie *pcie = platform_get_drvdata(pdev);
++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
++ u32 cmd;
++ int i;
++
++ /* Remove PCI bus with all devices. */
++ pci_lock_rescan_remove();
++ pci_stop_root_bus(bridge->bus);
++ pci_remove_root_bus(bridge->bus);
++ pci_unlock_rescan_remove();
++
++ for (i = 0; i < pcie->nports; i++) {
++ struct mvebu_pcie_port *port = &pcie->ports[i];
++
++ if (!port->base)
++ continue;
++
++ /* Disable Root Bridge I/O space, memory space and bus mastering. */
++ cmd = mvebu_readl(port, PCIE_CMD_OFF);
++ cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
++ mvebu_writel(port, cmd, PCIE_CMD_OFF);
++
++ /* Mask all interrupt sources. */
++ mvebu_writel(port, 0, PCIE_MASK_OFF);
++
++ /* Free config space for emulated root bridge. */
++ pci_bridge_emul_cleanup(&port->bridge);
++
++ /* Disable and clear BARs and windows. */
++ mvebu_pcie_disable_wins(port);
++
++ /* Delete PCIe IO and MEM windows. */
++ if (port->iowin.size)
++ mvebu_pcie_del_windows(port, port->iowin.base, port->iowin.size);
++ if (port->memwin.size)
++ mvebu_pcie_del_windows(port, port->memwin.base, port->memwin.size);
++
++ /* Power down card and disable clocks. Must be the last step. */
++ mvebu_pcie_powerdown(port);
++ }
++
++ return 0;
++}
++
+ static const struct of_device_id mvebu_pcie_of_match_table[] = {
+ { .compatible = "marvell,armada-xp-pcie", },
+ { .compatible = "marvell,armada-370-pcie", },
+@@ -1273,10 +1330,14 @@ static struct platform_driver mvebu_pcie_driver = {
+ .driver = {
+ .name = "mvebu-pcie",
+ .of_match_table = mvebu_pcie_of_match_table,
+- /* driver unloading/unbinding currently not supported */
+- .suppress_bind_attrs = true,
+ .pm = &mvebu_pcie_pm_ops,
+ },
+ .probe = mvebu_pcie_probe,
++ .remove = mvebu_pcie_remove,
+ };
+-builtin_platform_driver(mvebu_pcie_driver);
++module_platform_driver(mvebu_pcie_driver);
++
++MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@bootlin.com>");
++MODULE_AUTHOR("Pali Rohár <pali@kernel.org>");
++MODULE_DESCRIPTION("Marvell EBU PCIe controller");
++MODULE_LICENSE("GPL v2");
+--
+2.34.1
+