powerpc/fsl-pci: Keep PCI SoC controller registers in pci_controller

Move to keeping the SoC registers that control and config the PCI
controllers on FSL SoCs in the pci_controller struct.  This allows us to
not need to ioremap() the registers in multiple different places that
use them.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
This commit is contained in:
Kumar Gala 2013-03-13 14:07:15 -05:00
parent 9f4c350d52
commit 34642bbb3d
2 changed files with 34 additions and 40 deletions

View File

@ -70,6 +70,8 @@ struct pci_controller {
* BIG_ENDIAN - cfg_addr is a big endian register * BIG_ENDIAN - cfg_addr is a big endian register
* BROKEN_MRM - the 440EPx/GRx chips have an errata that causes hangs on * BROKEN_MRM - the 440EPx/GRx chips have an errata that causes hangs on
* the PLB4. Effectively disable MRM commands by setting this. * the PLB4. Effectively disable MRM commands by setting this.
* FSL_CFG_REG_LINK - Freescale controller version in which the PCIe
* link status is in a RC PCIe cfg register (vs being a SoC register)
*/ */
#define PPC_INDIRECT_TYPE_SET_CFG_TYPE 0x00000001 #define PPC_INDIRECT_TYPE_SET_CFG_TYPE 0x00000001
#define PPC_INDIRECT_TYPE_EXT_REG 0x00000002 #define PPC_INDIRECT_TYPE_EXT_REG 0x00000002
@ -77,6 +79,7 @@ struct pci_controller {
#define PPC_INDIRECT_TYPE_NO_PCIE_LINK 0x00000008 #define PPC_INDIRECT_TYPE_NO_PCIE_LINK 0x00000008
#define PPC_INDIRECT_TYPE_BIG_ENDIAN 0x00000010 #define PPC_INDIRECT_TYPE_BIG_ENDIAN 0x00000010
#define PPC_INDIRECT_TYPE_BROKEN_MRM 0x00000020 #define PPC_INDIRECT_TYPE_BROKEN_MRM 0x00000020
#define PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK 0x00000040
u32 indirect_type; u32 indirect_type;
/* Currently, we limit ourselves to 1 IO range and 3 mem /* Currently, we limit ourselves to 1 IO range and 3 mem
* ranges since the common pci_bus structure can't handle more * ranges since the common pci_bus structure can't handle more
@ -90,9 +93,9 @@ struct pci_controller {
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
unsigned long buid; unsigned long buid;
#endif /* CONFIG_PPC64 */
void *private_data; void *private_data;
#endif /* CONFIG_PPC64 */
}; };
/* These are used for config access before all the PCI probing /* These are used for config access before all the PCI probing

View File

@ -54,34 +54,22 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
return; return;
} }
static int __init fsl_pcie_check_link(struct pci_controller *hose, static int __init fsl_pcie_check_link(struct pci_controller *hose)
struct resource *rsrc)
{ {
struct ccsr_pci __iomem *pci = NULL;
u32 val; u32 val;
/* for PCIe IP rev 3.0 or greater use CSR0 for link state */ if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) {
if (rsrc) { early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n", if (val < PCIE_LTSSM_L0)
(u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1); return 1;
pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1); } else {
if (!pci) { struct ccsr_pci __iomem *pci = hose->private_data;
dev_err(hose->parent, "Unable to map PCIe registers\n"); /* for PCIe IP rev 3.0 or greater use CSR0 for link state */
return -ENOMEM; val = (in_be32(&pci->pex_csr0) & PEX_CSR0_LTSSM_MASK)
} >> PEX_CSR0_LTSSM_SHIFT;
if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_3_0) { if (val != PEX_CSR0_LTSSM_L0)
val = (in_be32(&pci->pex_csr0) & PEX_CSR0_LTSSM_MASK) return 1;
>> PEX_CSR0_LTSSM_SHIFT;
if (val != PEX_CSR0_LTSSM_L0)
return 1;
iounmap(pci);
return 0;
}
iounmap(pci);
} }
early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
if (val < PCIE_LTSSM_L0)
return 1;
return 0; return 0;
} }
@ -148,10 +136,9 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci,
} }
/* atmu setup for fsl pci/pcie controller */ /* atmu setup for fsl pci/pcie controller */
static void setup_pci_atmu(struct pci_controller *hose, static void setup_pci_atmu(struct pci_controller *hose)
struct resource *rsrc)
{ {
struct ccsr_pci __iomem *pci; struct ccsr_pci __iomem *pci = hose->private_data;
int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4; int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4;
u64 mem, sz, paddr_hi = 0; u64 mem, sz, paddr_hi = 0;
u64 paddr_lo = ULLONG_MAX; u64 paddr_lo = ULLONG_MAX;
@ -162,15 +149,6 @@ static void setup_pci_atmu(struct pci_controller *hose,
const u64 *reg; const u64 *reg;
int len; int len;
pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
(u64)rsrc->start, (u64)resource_size(rsrc));
pci = ioremap(rsrc->start, resource_size(rsrc));
if (!pci) {
dev_err(hose->parent, "Unable to map ATMU registers\n");
return;
}
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) { if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) {
win_idx = 2; win_idx = 2;
@ -451,6 +429,7 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
const int *bus_range; const int *bus_range;
u8 hdr_type, progif; u8 hdr_type, progif;
struct device_node *dev; struct device_node *dev;
struct ccsr_pci __iomem *pci;
dev = pdev->dev.of_node; dev = pdev->dev.of_node;
@ -483,9 +462,19 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
hose->first_busno = bus_range ? bus_range[0] : 0x0; hose->first_busno = bus_range ? bus_range[0] : 0x0;
hose->last_busno = bus_range ? bus_range[1] : 0xff; hose->last_busno = bus_range ? bus_range[1] : 0xff;
pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
(u64)rsrc.start, (u64)resource_size(&rsrc));
pci = hose->private_data = ioremap(rsrc.start, resource_size(&rsrc));
if (!hose->private_data)
goto no_bridge;
setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4, setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
PPC_INDIRECT_TYPE_BIG_ENDIAN); PPC_INDIRECT_TYPE_BIG_ENDIAN);
if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0)
hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
/* For PCIE read HEADER_TYPE to identify controler mode */ /* For PCIE read HEADER_TYPE to identify controler mode */
early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type); early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type);
@ -505,7 +494,7 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) { if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
hose->indirect_type |= PPC_INDIRECT_TYPE_EXT_REG | hose->indirect_type |= PPC_INDIRECT_TYPE_EXT_REG |
PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
if (fsl_pcie_check_link(hose, &rsrc)) if (fsl_pcie_check_link(hose))
hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
} }
@ -522,11 +511,12 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
pci_process_bridge_OF_ranges(hose, dev, is_primary); pci_process_bridge_OF_ranges(hose, dev, is_primary);
/* Setup PEX window registers */ /* Setup PEX window registers */
setup_pci_atmu(hose, &rsrc); setup_pci_atmu(hose);
return 0; return 0;
no_bridge: no_bridge:
iounmap(hose->private_data);
/* unmap cfg_data & cfg_addr separately if not on same page */ /* unmap cfg_data & cfg_addr separately if not on same page */
if (((unsigned long)hose->cfg_data & PAGE_MASK) != if (((unsigned long)hose->cfg_data & PAGE_MASK) !=
((unsigned long)hose->cfg_addr & PAGE_MASK)) ((unsigned long)hose->cfg_addr & PAGE_MASK))
@ -703,11 +693,12 @@ static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
WARN_ON(hose->dn->data); WARN_ON(hose->dn->data);
hose->dn->data = pcie; hose->dn->data = pcie;
hose->ops = &mpc83xx_pcie_ops; hose->ops = &mpc83xx_pcie_ops;
hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0); out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0);
out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0); out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0);
if (fsl_pcie_check_link(hose, NULL)) if (fsl_pcie_check_link(hose))
hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK; hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
return 0; return 0;