xref: /openbmc/linux/drivers/bcma/driver_pci.c (revision 440ca98fe8407808a9ad8e934f6e28408f546313)
18369ae33SRafał Miłecki /*
28369ae33SRafał Miłecki  * Broadcom specific AMBA
38369ae33SRafał Miłecki  * PCI Core
48369ae33SRafał Miłecki  *
58369ae33SRafał Miłecki  * Copyright 2005, Broadcom Corporation
68369ae33SRafał Miłecki  * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
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"
128369ae33SRafał Miłecki #include <linux/bcma/bcma.h>
138369ae33SRafał Miłecki 
148369ae33SRafał Miłecki /**************************************************
158369ae33SRafał Miłecki  * R/W ops.
168369ae33SRafał Miłecki  **************************************************/
178369ae33SRafał Miłecki 
188369ae33SRafał Miłecki static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
198369ae33SRafał Miłecki {
208369ae33SRafał Miłecki 	pcicore_write32(pc, 0x130, address);
218369ae33SRafał Miłecki 	pcicore_read32(pc, 0x130);
228369ae33SRafał Miłecki 	return pcicore_read32(pc, 0x134);
238369ae33SRafał Miłecki }
248369ae33SRafał Miłecki 
258369ae33SRafał Miłecki #if 0
268369ae33SRafał Miłecki static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
278369ae33SRafał Miłecki {
288369ae33SRafał Miłecki 	pcicore_write32(pc, 0x130, address);
298369ae33SRafał Miłecki 	pcicore_read32(pc, 0x130);
308369ae33SRafał Miłecki 	pcicore_write32(pc, 0x134, data);
318369ae33SRafał Miłecki }
328369ae33SRafał Miłecki #endif
338369ae33SRafał Miłecki 
348369ae33SRafał Miłecki static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
358369ae33SRafał Miłecki {
368369ae33SRafał Miłecki 	const u16 mdio_control = 0x128;
378369ae33SRafał Miłecki 	const u16 mdio_data = 0x12C;
388369ae33SRafał Miłecki 	u32 v;
398369ae33SRafał Miłecki 	int i;
408369ae33SRafał Miłecki 
418369ae33SRafał Miłecki 	v = (1 << 30); /* Start of Transaction */
428369ae33SRafał Miłecki 	v |= (1 << 28); /* Write Transaction */
438369ae33SRafał Miłecki 	v |= (1 << 17); /* Turnaround */
448369ae33SRafał Miłecki 	v |= (0x1F << 18);
458369ae33SRafał Miłecki 	v |= (phy << 4);
468369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_data, v);
478369ae33SRafał Miłecki 
488369ae33SRafał Miłecki 	udelay(10);
498369ae33SRafał Miłecki 	for (i = 0; i < 200; i++) {
508369ae33SRafał Miłecki 		v = pcicore_read32(pc, mdio_control);
518369ae33SRafał Miłecki 		if (v & 0x100 /* Trans complete */)
528369ae33SRafał Miłecki 			break;
538369ae33SRafał Miłecki 		msleep(1);
548369ae33SRafał Miłecki 	}
558369ae33SRafał Miłecki }
568369ae33SRafał Miłecki 
578369ae33SRafał Miłecki static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
588369ae33SRafał Miłecki {
598369ae33SRafał Miłecki 	const u16 mdio_control = 0x128;
608369ae33SRafał Miłecki 	const u16 mdio_data = 0x12C;
618369ae33SRafał Miłecki 	int max_retries = 10;
628369ae33SRafał Miłecki 	u16 ret = 0;
638369ae33SRafał Miłecki 	u32 v;
648369ae33SRafał Miłecki 	int i;
658369ae33SRafał Miłecki 
668369ae33SRafał Miłecki 	v = 0x80; /* Enable Preamble Sequence */
678369ae33SRafał Miłecki 	v |= 0x2; /* MDIO Clock Divisor */
688369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_control, v);
698369ae33SRafał Miłecki 
708369ae33SRafał Miłecki 	if (pc->core->id.rev >= 10) {
718369ae33SRafał Miłecki 		max_retries = 200;
728369ae33SRafał Miłecki 		bcma_pcie_mdio_set_phy(pc, device);
738369ae33SRafał Miłecki 	}
748369ae33SRafał Miłecki 
758369ae33SRafał Miłecki 	v = (1 << 30); /* Start of Transaction */
768369ae33SRafał Miłecki 	v |= (1 << 29); /* Read Transaction */
778369ae33SRafał Miłecki 	v |= (1 << 17); /* Turnaround */
788369ae33SRafał Miłecki 	if (pc->core->id.rev < 10)
798369ae33SRafał Miłecki 		v |= (u32)device << 22;
808369ae33SRafał Miłecki 	v |= (u32)address << 18;
818369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_data, v);
828369ae33SRafał Miłecki 	/* Wait for the device to complete the transaction */
838369ae33SRafał Miłecki 	udelay(10);
84f1a9c1e6SRafał Miłecki 	for (i = 0; i < max_retries; i++) {
858369ae33SRafał Miłecki 		v = pcicore_read32(pc, mdio_control);
868369ae33SRafał Miłecki 		if (v & 0x100 /* Trans complete */) {
878369ae33SRafał Miłecki 			udelay(10);
888369ae33SRafał Miłecki 			ret = pcicore_read32(pc, mdio_data);
898369ae33SRafał Miłecki 			break;
908369ae33SRafał Miłecki 		}
918369ae33SRafał Miłecki 		msleep(1);
928369ae33SRafał Miłecki 	}
938369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_control, 0);
948369ae33SRafał Miłecki 	return ret;
958369ae33SRafał Miłecki }
968369ae33SRafał Miłecki 
978369ae33SRafał Miłecki static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
988369ae33SRafał Miłecki 				u8 address, u16 data)
998369ae33SRafał Miłecki {
1008369ae33SRafał Miłecki 	const u16 mdio_control = 0x128;
1018369ae33SRafał Miłecki 	const u16 mdio_data = 0x12C;
1028369ae33SRafał Miłecki 	int max_retries = 10;
1038369ae33SRafał Miłecki 	u32 v;
1048369ae33SRafał Miłecki 	int i;
1058369ae33SRafał Miłecki 
1068369ae33SRafał Miłecki 	v = 0x80; /* Enable Preamble Sequence */
1078369ae33SRafał Miłecki 	v |= 0x2; /* MDIO Clock Divisor */
1088369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_control, v);
1098369ae33SRafał Miłecki 
1108369ae33SRafał Miłecki 	if (pc->core->id.rev >= 10) {
1118369ae33SRafał Miłecki 		max_retries = 200;
1128369ae33SRafał Miłecki 		bcma_pcie_mdio_set_phy(pc, device);
1138369ae33SRafał Miłecki 	}
1148369ae33SRafał Miłecki 
1158369ae33SRafał Miłecki 	v = (1 << 30); /* Start of Transaction */
1168369ae33SRafał Miłecki 	v |= (1 << 28); /* Write Transaction */
1178369ae33SRafał Miłecki 	v |= (1 << 17); /* Turnaround */
1188369ae33SRafał Miłecki 	if (pc->core->id.rev < 10)
1198369ae33SRafał Miłecki 		v |= (u32)device << 22;
1208369ae33SRafał Miłecki 	v |= (u32)address << 18;
1218369ae33SRafał Miłecki 	v |= data;
1228369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_data, v);
1238369ae33SRafał Miłecki 	/* Wait for the device to complete the transaction */
1248369ae33SRafał Miłecki 	udelay(10);
1258369ae33SRafał Miłecki 	for (i = 0; i < max_retries; i++) {
1268369ae33SRafał Miłecki 		v = pcicore_read32(pc, mdio_control);
1278369ae33SRafał Miłecki 		if (v & 0x100 /* Trans complete */)
1288369ae33SRafał Miłecki 			break;
1298369ae33SRafał Miłecki 		msleep(1);
1308369ae33SRafał Miłecki 	}
1318369ae33SRafał Miłecki 	pcicore_write32(pc, mdio_control, 0);
1328369ae33SRafał Miłecki }
1338369ae33SRafał Miłecki 
1348369ae33SRafał Miłecki /**************************************************
1358369ae33SRafał Miłecki  * Workarounds.
1368369ae33SRafał Miłecki  **************************************************/
1378369ae33SRafał Miłecki 
1388369ae33SRafał Miłecki static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
1398369ae33SRafał Miłecki {
1408369ae33SRafał Miłecki 	return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
1418369ae33SRafał Miłecki }
1428369ae33SRafał Miłecki 
1438369ae33SRafał Miłecki static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
1448369ae33SRafał Miłecki {
1458369ae33SRafał Miłecki 	const u8 serdes_pll_device = 0x1D;
1468369ae33SRafał Miłecki 	const u8 serdes_rx_device = 0x1F;
1478369ae33SRafał Miłecki 	u16 tmp;
1488369ae33SRafał Miłecki 
1498369ae33SRafał Miłecki 	bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */,
1508369ae33SRafał Miłecki 			      bcma_pcicore_polarity_workaround(pc));
1518369ae33SRafał Miłecki 	tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */);
1528369ae33SRafał Miłecki 	if (tmp & 0x4000)
1538369ae33SRafał Miłecki 		bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000);
1548369ae33SRafał Miłecki }
1558369ae33SRafał Miłecki 
1568369ae33SRafał Miłecki /**************************************************
1578369ae33SRafał Miłecki  * Init.
1588369ae33SRafał Miłecki  **************************************************/
1598369ae33SRafał Miłecki 
1608369ae33SRafał Miłecki void bcma_core_pci_init(struct bcma_drv_pci *pc)
1618369ae33SRafał Miłecki {
1628369ae33SRafał Miłecki 	bcma_pcicore_serdes_workaround(pc);
1638369ae33SRafał Miłecki }
1641de520f4SRafał Miłecki 
1651de520f4SRafał Miłecki int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
1661de520f4SRafał Miłecki 			  bool enable)
1671de520f4SRafał Miłecki {
1681de520f4SRafał Miłecki 	struct pci_dev *pdev = pc->core->bus->host_pci;
1691de520f4SRafał Miłecki 	u32 coremask, tmp;
1701de520f4SRafał Miłecki 	int err;
1711de520f4SRafał Miłecki 
1721de520f4SRafał Miłecki 	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
1731de520f4SRafał Miłecki 	if (err)
1741de520f4SRafał Miłecki 		goto out;
1751de520f4SRafał Miłecki 
1761de520f4SRafał Miłecki 	coremask = BIT(core->core_index) << 8;
1771de520f4SRafał Miłecki 	if (enable)
1781de520f4SRafał Miłecki 		tmp |= coremask;
1791de520f4SRafał Miłecki 	else
1801de520f4SRafał Miłecki 		tmp &= ~coremask;
1811de520f4SRafał Miłecki 
1821de520f4SRafał Miłecki 	err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
1831de520f4SRafał Miłecki 
1841de520f4SRafał Miłecki out:
1851de520f4SRafał Miłecki 	return err;
1861de520f4SRafał Miłecki }
187*440ca98fSRafał Miłecki EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
188