66 */
77
88#include <linux/kernel.h>
9+ #include <linux/module.h>
910#include <linux/pci.h>
1011#include <linux/clk.h>
1112#include <linux/delay.h>
@@ -154,22 +155,13 @@ static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)
154155 mvebu_writel (port , stat , PCIE_STAT_OFF );
155156}
156157
157- /*
158- * Setup PCIE BARs and Address Decode Wins:
159- * BAR[0] -> internal registers (needed for MSI)
160- * BAR[1] -> covers all DRAM banks
161- * BAR[2] -> Disabled
162- * WIN[0-3] -> DRAM bank[0-3]
163- */
164- static void mvebu_pcie_setup_wins (struct mvebu_pcie_port * port )
158+ static void mvebu_pcie_disable_wins (struct mvebu_pcie_port * port )
165159{
166- const struct mbus_dram_target_info * dram ;
167- u32 size ;
168160 int i ;
169161
170- dram = mv_mbus_dram_info ();
162+ mvebu_writel (port , 0 , PCIE_BAR_LO_OFF (0 ));
163+ mvebu_writel (port , 0 , PCIE_BAR_HI_OFF (0 ));
171164
172- /* First, disable and clear BARs and windows. */
173165 for (i = 1 ; i < 3 ; i ++ ) {
174166 mvebu_writel (port , 0 , PCIE_BAR_CTRL_OFF (i ));
175167 mvebu_writel (port , 0 , PCIE_BAR_LO_OFF (i ));
@@ -185,6 +177,25 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
185177 mvebu_writel (port , 0 , PCIE_WIN5_CTRL_OFF );
186178 mvebu_writel (port , 0 , PCIE_WIN5_BASE_OFF );
187179 mvebu_writel (port , 0 , PCIE_WIN5_REMAP_OFF );
180+ }
181+
182+ /*
183+ * Setup PCIE BARs and Address Decode Wins:
184+ * BAR[0] -> internal registers (needed for MSI)
185+ * BAR[1] -> covers all DRAM banks
186+ * BAR[2] -> Disabled
187+ * WIN[0-3] -> DRAM bank[0-3]
188+ */
189+ static void mvebu_pcie_setup_wins (struct mvebu_pcie_port * port )
190+ {
191+ const struct mbus_dram_target_info * dram ;
192+ u32 size ;
193+ int i ;
194+
195+ dram = mv_mbus_dram_info ();
196+
197+ /* First, disable and clear BARs and windows. */
198+ mvebu_pcie_disable_wins (port );
188199
189200 /* Setup windows for DDR banks. Count total DDR size on the fly. */
190201 size = 0 ;
@@ -1327,6 +1338,52 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
13271338 return pci_host_probe (bridge );
13281339}
13291340
1341+ static int mvebu_pcie_remove (struct platform_device * pdev )
1342+ {
1343+ struct mvebu_pcie * pcie = platform_get_drvdata (pdev );
1344+ struct pci_host_bridge * bridge = pci_host_bridge_from_priv (pcie );
1345+ u32 cmd ;
1346+ int i ;
1347+
1348+ /* Remove PCI bus with all devices. */
1349+ pci_lock_rescan_remove ();
1350+ pci_stop_root_bus (bridge -> bus );
1351+ pci_remove_root_bus (bridge -> bus );
1352+ pci_unlock_rescan_remove ();
1353+
1354+ for (i = 0 ; i < pcie -> nports ; i ++ ) {
1355+ struct mvebu_pcie_port * port = & pcie -> ports [i ];
1356+
1357+ if (!port -> base )
1358+ continue ;
1359+
1360+ /* Disable Root Bridge I/O space, memory space and bus mastering. */
1361+ cmd = mvebu_readl (port , PCIE_CMD_OFF );
1362+ cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER );
1363+ mvebu_writel (port , cmd , PCIE_CMD_OFF );
1364+
1365+ /* Mask all interrupt sources. */
1366+ mvebu_writel (port , 0 , PCIE_MASK_OFF );
1367+
1368+ /* Free config space for emulated root bridge. */
1369+ pci_bridge_emul_cleanup (& port -> bridge );
1370+
1371+ /* Disable and clear BARs and windows. */
1372+ mvebu_pcie_disable_wins (port );
1373+
1374+ /* Delete PCIe IO and MEM windows. */
1375+ if (port -> iowin .size )
1376+ mvebu_pcie_del_windows (port , port -> iowin .base , port -> iowin .size );
1377+ if (port -> memwin .size )
1378+ mvebu_pcie_del_windows (port , port -> memwin .base , port -> memwin .size );
1379+
1380+ /* Power down card and disable clocks. Must be the last step. */
1381+ mvebu_pcie_powerdown (port );
1382+ }
1383+
1384+ return 0 ;
1385+ }
1386+
13301387static const struct of_device_id mvebu_pcie_of_match_table [] = {
13311388 { .compatible = "marvell,armada-xp-pcie" , },
13321389 { .compatible = "marvell,armada-370-pcie" , },
@@ -1343,10 +1400,14 @@ static struct platform_driver mvebu_pcie_driver = {
13431400 .driver = {
13441401 .name = "mvebu-pcie" ,
13451402 .of_match_table = mvebu_pcie_of_match_table ,
1346- /* driver unloading/unbinding currently not supported */
1347- .suppress_bind_attrs = true,
13481403 .pm = & mvebu_pcie_pm_ops ,
13491404 },
13501405 .probe = mvebu_pcie_probe ,
1406+ .remove = mvebu_pcie_remove ,
13511407};
1352- builtin_platform_driver (mvebu_pcie_driver );
1408+ module_platform_driver (mvebu_pcie_driver );
1409+
1410+ MODULE_AUTHOR ("Thomas Petazzoni <thomas.petazzoni@bootlin.com>" );
1411+ MODULE_AUTHOR ("Pali Rohár <pali@kernel.org>" );
1412+ MODULE_DESCRIPTION ("Marvell EBU PCIe controller" );
1413+ MODULE_LICENSE ("GPL v2" );
0 commit comments