xref: /openbmc/linux/drivers/bcma/driver_pci.c (revision 44a8e3772f53a5337e74700fc166a3d4c3ef59a2)
18369ae33SRafał Miłecki /*
28369ae33SRafał Miłecki  * Broadcom specific AMBA
38369ae33SRafał Miłecki  * PCI Core
48369ae33SRafał Miłecki  *
58369ae33SRafał Miłecki  * Copyright 2005, Broadcom Corporation
6eb032b98SMichael Büsch  * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
78369ae33SRafał Miłecki  *
88369ae33SRafał Miłecki  * Licensed under the GNU/GPL. See COPYING for details.
98369ae33SRafał Miłecki  */
108369ae33SRafał Miłecki 
118369ae33SRafał Miłecki #include "bcma_private.h"
12*44a8e377SPaul Gortmaker #include <linux/export.h>
138369ae33SRafał Miłecki #include <linux/bcma/bcma.h>
148369ae33SRafał Miłecki 
158369ae33SRafał Miłecki /**************************************************
168369ae33SRafał Miłecki  * R/W ops.
178369ae33SRafał Miłecki  **************************************************/
188369ae33SRafał Miłecki 
198369ae33SRafał Miłecki static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
208369ae33SRafał Miłecki {
218369ae33SRafał Miłecki 	pcicore_write32(pc, 0x130, address);
228369ae33SRafał Miłecki 	pcicore_read32(pc, 0x130);
238369ae33SRafał Miłecki 	return pcicore_read32(pc, 0x134);
248369ae33SRafał Miłecki }
258369ae33SRafał Miłecki 
268369ae33SRafał Miłecki #if 0
278369ae33SRafał Miłecki static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
288369ae33SRafał Miłecki {
298369ae33SRafał Miłecki 	pcicore_write32(pc, 0x130, address);
308369ae33SRafał Miłecki 	pcicore_read32(pc, 0x130);
318369ae33SRafał Miłecki 	pcicore_write32(pc, 0x134, data);
328369ae33SRafał Miłecki }
338369ae33SRafał Miłecki #endif
348369ae33SRafał Miłecki 
358369ae33SRafał Miłecki static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
368369ae33SRafał Miłecki {
378369ae33SRafał Miłecki 	const u16 mdio_control = 0x128;
388369ae33SRafał Miłecki 	const u16 mdio_data = 0x12C;
398369ae33SRafał Miłecki 	u32 v;
408369ae33SRafał Miłecki 	int i;
418369ae33SRafał Miłecki 
428369ae33SRafał Miłecki 	v = (1 << 30); /* Start of Transaction */
438369ae33SRafał Miłecki 	v |= (1 << 28); /* Write Transaction */
448369ae33SRafał Miłecki 	v |= (1 << 17); /* Turnaround */
458369ae33SRafał Miłecki 	v |= (0x1F << 18);
468369ae33SRafał Miłecki 	v |= (phy << 4);
478369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_data, v);
488369ae33SRafał Miłecki 
498369ae33SRafał Miłecki 	udelay(10);
508369ae33SRafał Miłecki 	for (i = 0; i < 200; i++) {
518369ae33SRafał Miłecki 		v = pcicore_read32(pc, mdio_control);
528369ae33SRafał Miłecki 		if (v & 0x100 /* Trans complete */)
538369ae33SRafał Miłecki 			break;
548369ae33SRafał Miłecki 		msleep(1);
558369ae33SRafał Miłecki 	}
568369ae33SRafał Miłecki }
578369ae33SRafał Miłecki 
588369ae33SRafał Miłecki static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
598369ae33SRafał Miłecki {
608369ae33SRafał Miłecki 	const u16 mdio_control = 0x128;
618369ae33SRafał Miłecki 	const u16 mdio_data = 0x12C;
628369ae33SRafał Miłecki 	int max_retries = 10;
638369ae33SRafał Miłecki 	u16 ret = 0;
648369ae33SRafał Miłecki 	u32 v;
658369ae33SRafał Miłecki 	int i;
668369ae33SRafał Miłecki 
678369ae33SRafał Miłecki 	v = 0x80; /* Enable Preamble Sequence */
688369ae33SRafał Miłecki 	v |= 0x2; /* MDIO Clock Divisor */
698369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_control, v);
708369ae33SRafał Miłecki 
718369ae33SRafał Miłecki 	if (pc->core->id.rev >= 10) {
728369ae33SRafał Miłecki 		max_retries = 200;
738369ae33SRafał Miłecki 		bcma_pcie_mdio_set_phy(pc, device);
748369ae33SRafał Miłecki 	}
758369ae33SRafał Miłecki 
768369ae33SRafał Miłecki 	v = (1 << 30); /* Start of Transaction */
778369ae33SRafał Miłecki 	v |= (1 << 29); /* Read Transaction */
788369ae33SRafał Miłecki 	v |= (1 << 17); /* Turnaround */
798369ae33SRafał Miłecki 	if (pc->core->id.rev < 10)
808369ae33SRafał Miłecki 		v |= (u32)device << 22;
818369ae33SRafał Miłecki 	v |= (u32)address << 18;
828369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_data, v);
838369ae33SRafał Miłecki 	/* Wait for the device to complete the transaction */
848369ae33SRafał Miłecki 	udelay(10);
85f1a9c1e6SRafał Miłecki 	for (i = 0; i < max_retries; i++) {
868369ae33SRafał Miłecki 		v = pcicore_read32(pc, mdio_control);
878369ae33SRafał Miłecki 		if (v & 0x100 /* Trans complete */) {
888369ae33SRafał Miłecki 			udelay(10);
898369ae33SRafał Miłecki 			ret = pcicore_read32(pc, mdio_data);
908369ae33SRafał Miłecki 			break;
918369ae33SRafał Miłecki 		}
928369ae33SRafał Miłecki 		msleep(1);
938369ae33SRafał Miłecki 	}
948369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_control, 0);
958369ae33SRafał Miłecki 	return ret;
968369ae33SRafał Miłecki }
978369ae33SRafał Miłecki 
988369ae33SRafał Miłecki static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
998369ae33SRafał Miłecki 				u8 address, u16 data)
1008369ae33SRafał Miłecki {
1018369ae33SRafał Miłecki 	const u16 mdio_control = 0x128;
1028369ae33SRafał Miłecki 	const u16 mdio_data = 0x12C;
1038369ae33SRafał Miłecki 	int max_retries = 10;
1048369ae33SRafał Miłecki 	u32 v;
1058369ae33SRafał Miłecki 	int i;
1068369ae33SRafał Miłecki 
1078369ae33SRafał Miłecki 	v = 0x80; /* Enable Preamble Sequence */
1088369ae33SRafał Miłecki 	v |= 0x2; /* MDIO Clock Divisor */
1098369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_control, v);
1108369ae33SRafał Miłecki 
1118369ae33SRafał Miłecki 	if (pc->core->id.rev >= 10) {
1128369ae33SRafał Miłecki 		max_retries = 200;
1138369ae33SRafał Miłecki 		bcma_pcie_mdio_set_phy(pc, device);
1148369ae33SRafał Miłecki 	}
1158369ae33SRafał Miłecki 
1168369ae33SRafał Miłecki 	v = (1 << 30); /* Start of Transaction */
1178369ae33SRafał Miłecki 	v |= (1 << 28); /* Write Transaction */
1188369ae33SRafał Miłecki 	v |= (1 << 17); /* Turnaround */
1198369ae33SRafał Miłecki 	if (pc->core->id.rev < 10)
1208369ae33SRafał Miłecki 		v |= (u32)device << 22;
1218369ae33SRafał Miłecki 	v |= (u32)address << 18;
1228369ae33SRafał Miłecki 	v |= data;
1238369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_data, v);
1248369ae33SRafał Miłecki 	/* Wait for the device to complete the transaction */
1258369ae33SRafał Miłecki 	udelay(10);
1268369ae33SRafał Miłecki 	for (i = 0; i < max_retries; i++) {
1278369ae33SRafał Miłecki 		v = pcicore_read32(pc, mdio_control);
1288369ae33SRafał Miłecki 		if (v & 0x100 /* Trans complete */)
1298369ae33SRafał Miłecki 			break;
1308369ae33SRafał Miłecki 		msleep(1);
1318369ae33SRafał Miłecki 	}
1328369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_control, 0);
1338369ae33SRafał Miłecki }
1348369ae33SRafał Miłecki 
1358369ae33SRafał Miłecki /**************************************************
1368369ae33SRafał Miłecki  * Workarounds.
1378369ae33SRafał Miłecki  **************************************************/
1388369ae33SRafał Miłecki 
1398369ae33SRafał Miłecki static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
1408369ae33SRafał Miłecki {
1418369ae33SRafał Miłecki 	return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
1428369ae33SRafał Miłecki }
1438369ae33SRafał Miłecki 
1448369ae33SRafał Miłecki static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
1458369ae33SRafał Miłecki {
1468369ae33SRafał Miłecki 	const u8 serdes_pll_device = 0x1D;
1478369ae33SRafał Miłecki 	const u8 serdes_rx_device = 0x1F;
1488369ae33SRafał Miłecki 	u16 tmp;
1498369ae33SRafał Miłecki 
1508369ae33SRafał Miłecki 	bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */,
1518369ae33SRafał Miłecki 			      bcma_pcicore_polarity_workaround(pc));
1528369ae33SRafał Miłecki 	tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */);
1538369ae33SRafał Miłecki 	if (tmp & 0x4000)
1548369ae33SRafał Miłecki 		bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000);
1558369ae33SRafał Miłecki }
1568369ae33SRafał Miłecki 
1578369ae33SRafał Miłecki /**************************************************
1588369ae33SRafał Miłecki  * Init.
1598369ae33SRafał Miłecki  **************************************************/
1608369ae33SRafał Miłecki 
1619352f69cSRafał Miłecki static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
1628369ae33SRafał Miłecki {
1638369ae33SRafał Miłecki 	bcma_pcicore_serdes_workaround(pc);
1648369ae33SRafał Miłecki }
1651de520f4SRafał Miłecki 
1669352f69cSRafał Miłecki static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
1679352f69cSRafał Miłecki {
1689352f69cSRafał Miłecki 	struct bcma_bus *bus = pc->core->bus;
1699352f69cSRafał Miłecki 	u16 chipid_top;
1709352f69cSRafał Miłecki 
1719352f69cSRafał Miłecki 	chipid_top = (bus->chipinfo.id & 0xFF00);
1729352f69cSRafał Miłecki 	if (chipid_top != 0x4700 &&
1739352f69cSRafał Miłecki 	    chipid_top != 0x5300)
1749352f69cSRafał Miłecki 		return false;
1759352f69cSRafał Miłecki 
1766e6e8c51SJohn W. Linville #ifdef CONFIG_SSB_DRIVER_PCICORE
17726f2622eSRafał Miłecki 	if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
1789352f69cSRafał Miłecki 		return false;
1796e6e8c51SJohn W. Linville #endif /* CONFIG_SSB_DRIVER_PCICORE */
1809352f69cSRafał Miłecki 
1819352f69cSRafał Miłecki #if 0
1829352f69cSRafał Miłecki 	/* TODO: on BCMA we use address from EROM instead of magic formula */
1839352f69cSRafał Miłecki 	u32 tmp;
1849352f69cSRafał Miłecki 	return !mips_busprobe32(tmp, (bus->mmio +
1859352f69cSRafał Miłecki 		(pc->core->core_index * BCMA_CORE_SIZE)));
1869352f69cSRafał Miłecki #endif
1879352f69cSRafał Miłecki 
1889352f69cSRafał Miłecki 	return true;
1899352f69cSRafał Miłecki }
1909352f69cSRafał Miłecki 
1919352f69cSRafał Miłecki void bcma_core_pci_init(struct bcma_drv_pci *pc)
1929352f69cSRafał Miłecki {
193517f43e5SHauke Mehrtens 	if (pc->setup_done)
194517f43e5SHauke Mehrtens 		return;
195517f43e5SHauke Mehrtens 
1969352f69cSRafał Miłecki 	if (bcma_core_pci_is_in_hostmode(pc)) {
1979352f69cSRafał Miłecki #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
1989352f69cSRafał Miłecki 		bcma_core_pci_hostmode_init(pc);
1999352f69cSRafał Miłecki #else
2009352f69cSRafał Miłecki 		pr_err("Driver compiled without support for hostmode PCI\n");
2019352f69cSRafał Miłecki #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
2029352f69cSRafał Miłecki 	} else {
2039352f69cSRafał Miłecki 		bcma_core_pci_clientmode_init(pc);
2049352f69cSRafał Miłecki 	}
205517f43e5SHauke Mehrtens 
206517f43e5SHauke Mehrtens 	pc->setup_done = true;
2079352f69cSRafał Miłecki }
2089352f69cSRafał Miłecki 
2091de520f4SRafał Miłecki int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
2101de520f4SRafał Miłecki 			  bool enable)
2111de520f4SRafał Miłecki {
2121de520f4SRafał Miłecki 	struct pci_dev *pdev = pc->core->bus->host_pci;
2131de520f4SRafał Miłecki 	u32 coremask, tmp;
214ecd177c2SHauke Mehrtens 	int err = 0;
215ecd177c2SHauke Mehrtens 
216ecd177c2SHauke Mehrtens 	if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
217ecd177c2SHauke Mehrtens 		/* This bcma device is not on a PCI host-bus. So the IRQs are
218ecd177c2SHauke Mehrtens 		 * not routed through the PCI core.
219ecd177c2SHauke Mehrtens 		 * So we must not enable routing through the PCI core. */
220ecd177c2SHauke Mehrtens 		goto out;
221ecd177c2SHauke Mehrtens 	}
2221de520f4SRafał Miłecki 
2231de520f4SRafał Miłecki 	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
2241de520f4SRafał Miłecki 	if (err)
2251de520f4SRafał Miłecki 		goto out;
2261de520f4SRafał Miłecki 
2271de520f4SRafał Miłecki 	coremask = BIT(core->core_index) << 8;
2281de520f4SRafał Miłecki 	if (enable)
2291de520f4SRafał Miłecki 		tmp |= coremask;
2301de520f4SRafał Miłecki 	else
2311de520f4SRafał Miłecki 		tmp &= ~coremask;
2321de520f4SRafał Miłecki 
2331de520f4SRafał Miłecki 	err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
2341de520f4SRafał Miłecki 
2351de520f4SRafał Miłecki out:
2361de520f4SRafał Miłecki 	return err;
2371de520f4SRafał Miłecki }
238440ca98fSRafał Miłecki EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
239