From f7b7868ced6dd5c8e9362c813b1fbb554f7a5812 Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Wed, 28 Aug 2013 20:53:30 +0900 Subject: [PATCH 1/3] PCI: designware: Drop "addr" arg from dw_pcie_readl_rc()/dw_pcie_writel_rc() The "dbi_addr" argument to dw_pcie_readl_rc() and dw_pcie_writel_rc() is redundant and misleading because we always have the "struct pcie_port" and we always want to use the address from there. This patch removes the argument and changes the callers to match. No functional change. [bhelgaas: changelog] Signed-off-by: Seungwon Jeon Signed-off-by: Bjorn Helgaas Acked-by: Jingoo Han --- drivers/pci/host/pcie-designware.c | 135 ++++++++++++----------------- 1 file changed, 55 insertions(+), 80 deletions(-) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 77b0c257f215..c10e9ac9bbbc 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -99,22 +99,20 @@ int cfg_write(void __iomem *addr, int where, int size, u32 val) return PCIBIOS_SUCCESSFUL; } -static inline void dw_pcie_readl_rc(struct pcie_port *pp, - void __iomem *dbi_addr, u32 *val) +static inline void dw_pcie_readl_rc(struct pcie_port *pp, u32 reg, u32 *val) { if (pp->ops->readl_rc) - pp->ops->readl_rc(pp, dbi_addr, val); + pp->ops->readl_rc(pp, pp->dbi_base + reg, val); else - *val = readl(dbi_addr); + *val = readl(pp->dbi_base + reg); } -static inline void dw_pcie_writel_rc(struct pcie_port *pp, - u32 val, void __iomem *dbi_addr) +static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg) { if (pp->ops->writel_rc) - pp->ops->writel_rc(pp, val, dbi_addr); + pp->ops->writel_rc(pp, val, pp->dbi_base + reg); else - writel(val, dbi_addr); + writel(val, pp->dbi_base + reg); } int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, @@ -251,86 +249,64 @@ int __init dw_pcie_host_init(struct pcie_port *pp) static void dw_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev) { - u32 val; - void __iomem *dbi_base = pp->dbi_base; - /* Program viewport 0 : OUTBOUND : CFG0 */ - val = PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT); - dw_pcie_writel_rc(pp, pp->cfg0_base, dbi_base + PCIE_ATU_LOWER_BASE); - dw_pcie_writel_rc(pp, (pp->cfg0_base >> 32), - dbi_base + PCIE_ATU_UPPER_BASE); + dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, + PCIE_ATU_VIEWPORT); + dw_pcie_writel_rc(pp, pp->cfg0_base, PCIE_ATU_LOWER_BASE); + dw_pcie_writel_rc(pp, (pp->cfg0_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->cfg0_base + pp->config.cfg0_size - 1, - dbi_base + PCIE_ATU_LIMIT); - dw_pcie_writel_rc(pp, busdev, dbi_base + PCIE_ATU_LOWER_TARGET); - dw_pcie_writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_TARGET); - dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG0, dbi_base + PCIE_ATU_CR1); - val = PCIE_ATU_ENABLE; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_CR2); + PCIE_ATU_LIMIT); + dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); + dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); + dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG0, PCIE_ATU_CR1); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); } static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev) { - u32 val; - void __iomem *dbi_base = pp->dbi_base; - /* Program viewport 1 : OUTBOUND : CFG1 */ - val = PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT); - dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, dbi_base + PCIE_ATU_CR1); - val = PCIE_ATU_ENABLE; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_CR2); - dw_pcie_writel_rc(pp, pp->cfg1_base, dbi_base + PCIE_ATU_LOWER_BASE); - dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), - dbi_base + PCIE_ATU_UPPER_BASE); + dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, + PCIE_ATU_VIEWPORT); + dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); + dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE); + dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1, - dbi_base + PCIE_ATU_LIMIT); - dw_pcie_writel_rc(pp, busdev, dbi_base + PCIE_ATU_LOWER_TARGET); - dw_pcie_writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_TARGET); + PCIE_ATU_LIMIT); + dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); + dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); } static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) { - u32 val; - void __iomem *dbi_base = pp->dbi_base; - /* Program viewport 0 : OUTBOUND : MEM */ - val = PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT); - dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, dbi_base + PCIE_ATU_CR1); - val = PCIE_ATU_ENABLE; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_CR2); - dw_pcie_writel_rc(pp, pp->mem_base, dbi_base + PCIE_ATU_LOWER_BASE); - dw_pcie_writel_rc(pp, (pp->mem_base >> 32), - dbi_base + PCIE_ATU_UPPER_BASE); + dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, + PCIE_ATU_VIEWPORT); + dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); + dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE); + dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1, - dbi_base + PCIE_ATU_LIMIT); - dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, - dbi_base + PCIE_ATU_LOWER_TARGET); + PCIE_ATU_LIMIT); + dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET); dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr), - dbi_base + PCIE_ATU_UPPER_TARGET); + PCIE_ATU_UPPER_TARGET); } static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) { - u32 val; - void __iomem *dbi_base = pp->dbi_base; - /* Program viewport 1 : OUTBOUND : IO */ - val = PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT); - dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, dbi_base + PCIE_ATU_CR1); - val = PCIE_ATU_ENABLE; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_CR2); - dw_pcie_writel_rc(pp, pp->io_base, dbi_base + PCIE_ATU_LOWER_BASE); - dw_pcie_writel_rc(pp, (pp->io_base >> 32), - dbi_base + PCIE_ATU_UPPER_BASE); + dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, + PCIE_ATU_VIEWPORT); + dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); + dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE); + dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1, - dbi_base + PCIE_ATU_LIMIT); - dw_pcie_writel_rc(pp, pp->config.io_bus_addr, - dbi_base + PCIE_ATU_LOWER_TARGET); + PCIE_ATU_LIMIT); + dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET); dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr), - dbi_base + PCIE_ATU_UPPER_TARGET); + PCIE_ATU_UPPER_TARGET); } static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, @@ -518,13 +494,12 @@ static struct hw_pci dw_pci = { void dw_pcie_setup_rc(struct pcie_port *pp) { struct pcie_port_info *config = &pp->config; - void __iomem *dbi_base = pp->dbi_base; u32 val; u32 membase; u32 memlimit; /* set the number of lines as 4 */ - dw_pcie_readl_rc(pp, dbi_base + PCIE_PORT_LINK_CONTROL, &val); + dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val); val &= ~PORT_LINK_MODE_MASK; switch (pp->lanes) { case 1: @@ -537,10 +512,10 @@ void dw_pcie_setup_rc(struct pcie_port *pp) val |= PORT_LINK_MODE_4_LANES; break; } - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_PORT_LINK_CONTROL); + dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL); /* set link width speed control register */ - dw_pcie_readl_rc(pp, dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL, &val); + dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, &val); val &= ~PORT_LOGIC_LINK_WIDTH_MASK; switch (pp->lanes) { case 1: @@ -553,36 +528,36 @@ void dw_pcie_setup_rc(struct pcie_port *pp) val |= PORT_LOGIC_LINK_WIDTH_4_LANES; break; } - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); + dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL); /* setup RC BARs */ - dw_pcie_writel_rc(pp, 0x00000004, dbi_base + PCI_BASE_ADDRESS_0); - dw_pcie_writel_rc(pp, 0x00000004, dbi_base + PCI_BASE_ADDRESS_1); + dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_0); + dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_1); /* setup interrupt pins */ - dw_pcie_readl_rc(pp, dbi_base + PCI_INTERRUPT_LINE, &val); + dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE, &val); val &= 0xffff00ff; val |= 0x00000100; - dw_pcie_writel_rc(pp, val, dbi_base + PCI_INTERRUPT_LINE); + dw_pcie_writel_rc(pp, val, PCI_INTERRUPT_LINE); /* setup bus numbers */ - dw_pcie_readl_rc(pp, dbi_base + PCI_PRIMARY_BUS, &val); + dw_pcie_readl_rc(pp, PCI_PRIMARY_BUS, &val); val &= 0xff000000; val |= 0x00010100; - dw_pcie_writel_rc(pp, val, dbi_base + PCI_PRIMARY_BUS); + dw_pcie_writel_rc(pp, val, PCI_PRIMARY_BUS); /* setup memory base, memory limit */ membase = ((u32)pp->mem_base & 0xfff00000) >> 16; memlimit = (config->mem_size + (u32)pp->mem_base) & 0xfff00000; val = memlimit | membase; - dw_pcie_writel_rc(pp, val, dbi_base + PCI_MEMORY_BASE); + dw_pcie_writel_rc(pp, val, PCI_MEMORY_BASE); /* setup command register */ - dw_pcie_readl_rc(pp, dbi_base + PCI_COMMAND, &val); + dw_pcie_readl_rc(pp, PCI_COMMAND, &val); val &= 0xffff0000; val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; - dw_pcie_writel_rc(pp, val, dbi_base + PCI_COMMAND); + dw_pcie_writel_rc(pp, val, PCI_COMMAND); } MODULE_AUTHOR("Jingoo Han "); From 058dd016a1ed43d0d8e0c6c10a472d560a3299b4 Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Thu, 29 Aug 2013 21:35:56 +0900 Subject: [PATCH 2/3] PCI: exynos: Add I/O access wrappers This patch adds wrappers for MMIO access to ELBI, PHY, and other registers. No functional change. [bhelgaas: changelog] Signed-off-by: Seungwon Jeon Signed-off-by: Bjorn Helgaas Acked-by: Jingoo Han --- drivers/pci/host/pci-exynos.c | 158 +++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 68 deletions(-) diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index 012ca8aec71a..94e096bb2d0a 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c @@ -91,19 +91,49 @@ struct exynos_pcie { #define PCIE_PHY_TRSV3_RXCDR 0x2ec #define PCIE_PHY_TRSV3_LVCC 0x31c +static inline void exynos_elb_writel(struct exynos_pcie *pcie, u32 val, u32 reg) +{ + writel(val, pcie->elbi_base + reg); +} + +static inline u32 exynos_elb_readl(struct exynos_pcie *pcie, u32 reg) +{ + return readl(pcie->elbi_base + reg); +} + +static inline void exynos_phy_writel(struct exynos_pcie *pcie, u32 val, u32 reg) +{ + writel(val, pcie->phy_base + reg); +} + +static inline u32 exynos_phy_readl(struct exynos_pcie *pcie, u32 reg) +{ + return readl(pcie->phy_base + reg); +} + +static inline void exynos_blk_writel(struct exynos_pcie *pcie, u32 val, u32 reg) +{ + writel(val, pcie->block_base + reg); +} + +static inline u32 exynos_blk_readl(struct exynos_pcie *pcie, u32 reg) +{ + return readl(pcie->block_base + reg); +} + static void exynos_pcie_sideband_dbi_w_mode(struct pcie_port *pp, bool on) { u32 val; struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); if (on) { - val = readl(exynos_pcie->elbi_base + PCIE_ELBI_SLV_AWMISC); + val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_AWMISC); val |= PCIE_ELBI_SLV_DBI_ENABLE; - writel(val, exynos_pcie->elbi_base + PCIE_ELBI_SLV_AWMISC); + exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_AWMISC); } else { - val = readl(exynos_pcie->elbi_base + PCIE_ELBI_SLV_AWMISC); + val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_AWMISC); val &= ~PCIE_ELBI_SLV_DBI_ENABLE; - writel(val, exynos_pcie->elbi_base + PCIE_ELBI_SLV_AWMISC); + exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_AWMISC); } } @@ -113,13 +143,13 @@ static void exynos_pcie_sideband_dbi_r_mode(struct pcie_port *pp, bool on) struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); if (on) { - val = readl(exynos_pcie->elbi_base + PCIE_ELBI_SLV_ARMISC); + val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_ARMISC); val |= PCIE_ELBI_SLV_DBI_ENABLE; - writel(val, exynos_pcie->elbi_base + PCIE_ELBI_SLV_ARMISC); + exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_ARMISC); } else { - val = readl(exynos_pcie->elbi_base + PCIE_ELBI_SLV_ARMISC); + val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_ARMISC); val &= ~PCIE_ELBI_SLV_DBI_ENABLE; - writel(val, exynos_pcie->elbi_base + PCIE_ELBI_SLV_ARMISC); + exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_ARMISC); } } @@ -127,95 +157,89 @@ static void exynos_pcie_assert_core_reset(struct pcie_port *pp) { u32 val; struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - void __iomem *elbi_base = exynos_pcie->elbi_base; - val = readl(elbi_base + PCIE_CORE_RESET); + val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET); val &= ~PCIE_CORE_RESET_ENABLE; - writel(val, elbi_base + PCIE_CORE_RESET); - writel(0, elbi_base + PCIE_PWR_RESET); - writel(0, elbi_base + PCIE_STICKY_RESET); - writel(0, elbi_base + PCIE_NONSTICKY_RESET); + exynos_elb_writel(exynos_pcie, val, PCIE_CORE_RESET); + exynos_elb_writel(exynos_pcie, 0, PCIE_PWR_RESET); + exynos_elb_writel(exynos_pcie, 0, PCIE_STICKY_RESET); + exynos_elb_writel(exynos_pcie, 0, PCIE_NONSTICKY_RESET); } static void exynos_pcie_deassert_core_reset(struct pcie_port *pp) { u32 val; struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - void __iomem *elbi_base = exynos_pcie->elbi_base; - void __iomem *block_base = exynos_pcie->block_base; - val = readl(elbi_base + PCIE_CORE_RESET); + val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET); val |= PCIE_CORE_RESET_ENABLE; - writel(val, elbi_base + PCIE_CORE_RESET); - writel(1, elbi_base + PCIE_STICKY_RESET); - writel(1, elbi_base + PCIE_NONSTICKY_RESET); - writel(1, elbi_base + PCIE_APP_INIT_RESET); - writel(0, elbi_base + PCIE_APP_INIT_RESET); - writel(1, block_base + PCIE_PHY_MAC_RESET); + + exynos_elb_writel(exynos_pcie, val, PCIE_CORE_RESET); + exynos_elb_writel(exynos_pcie, 1, PCIE_STICKY_RESET); + exynos_elb_writel(exynos_pcie, 1, PCIE_NONSTICKY_RESET); + exynos_elb_writel(exynos_pcie, 1, PCIE_APP_INIT_RESET); + exynos_elb_writel(exynos_pcie, 0, PCIE_APP_INIT_RESET); + exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_MAC_RESET); } static void exynos_pcie_assert_phy_reset(struct pcie_port *pp) { struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - void __iomem *block_base = exynos_pcie->block_base; - writel(0, block_base + PCIE_PHY_MAC_RESET); - writel(1, block_base + PCIE_PHY_GLOBAL_RESET); + exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_MAC_RESET); + exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_GLOBAL_RESET); } static void exynos_pcie_deassert_phy_reset(struct pcie_port *pp) { struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - void __iomem *elbi_base = exynos_pcie->elbi_base; - void __iomem *block_base = exynos_pcie->block_base; - writel(0, block_base + PCIE_PHY_GLOBAL_RESET); - writel(1, elbi_base + PCIE_PWR_RESET); - writel(0, block_base + PCIE_PHY_COMMON_RESET); - writel(0, block_base + PCIE_PHY_CMN_REG); - writel(0, block_base + PCIE_PHY_TRSVREG_RESET); - writel(0, block_base + PCIE_PHY_TRSV_RESET); + exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_GLOBAL_RESET); + exynos_elb_writel(exynos_pcie, 1, PCIE_PWR_RESET); + exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET); + exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_CMN_REG); + exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSVREG_RESET); + exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET); } static void exynos_pcie_init_phy(struct pcie_port *pp) { struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - void __iomem *phy_base = exynos_pcie->phy_base; /* DCC feedback control off */ - writel(0x29, phy_base + PCIE_PHY_DCC_FEEDBACK); + exynos_phy_writel(exynos_pcie, 0x29, PCIE_PHY_DCC_FEEDBACK); /* set TX/RX impedance */ - writel(0xd5, phy_base + PCIE_PHY_IMPEDANCE); + exynos_phy_writel(exynos_pcie, 0xd5, PCIE_PHY_IMPEDANCE); /* set 50Mhz PHY clock */ - writel(0x14, phy_base + PCIE_PHY_PLL_DIV_0); - writel(0x12, phy_base + PCIE_PHY_PLL_DIV_1); + exynos_phy_writel(exynos_pcie, 0x14, PCIE_PHY_PLL_DIV_0); + exynos_phy_writel(exynos_pcie, 0x12, PCIE_PHY_PLL_DIV_1); /* set TX Differential output for lane 0 */ - writel(0x7f, phy_base + PCIE_PHY_TRSV0_DRV_LVL); + exynos_phy_writel(exynos_pcie, 0x7f, PCIE_PHY_TRSV0_DRV_LVL); /* set TX Pre-emphasis Level Control for lane 0 to minimum */ - writel(0x0, phy_base + PCIE_PHY_TRSV0_EMP_LVL); + exynos_phy_writel(exynos_pcie, 0x0, PCIE_PHY_TRSV0_EMP_LVL); /* set RX clock and data recovery bandwidth */ - writel(0xe7, phy_base + PCIE_PHY_PLL_BIAS); - writel(0x82, phy_base + PCIE_PHY_TRSV0_RXCDR); - writel(0x82, phy_base + PCIE_PHY_TRSV1_RXCDR); - writel(0x82, phy_base + PCIE_PHY_TRSV2_RXCDR); - writel(0x82, phy_base + PCIE_PHY_TRSV3_RXCDR); + exynos_phy_writel(exynos_pcie, 0xe7, PCIE_PHY_PLL_BIAS); + exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV0_RXCDR); + exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV1_RXCDR); + exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV2_RXCDR); + exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV3_RXCDR); /* change TX Pre-emphasis Level Control for lanes */ - writel(0x39, phy_base + PCIE_PHY_TRSV0_EMP_LVL); - writel(0x39, phy_base + PCIE_PHY_TRSV1_EMP_LVL); - writel(0x39, phy_base + PCIE_PHY_TRSV2_EMP_LVL); - writel(0x39, phy_base + PCIE_PHY_TRSV3_EMP_LVL); + exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV0_EMP_LVL); + exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV1_EMP_LVL); + exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV2_EMP_LVL); + exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV3_EMP_LVL); /* set LVCC */ - writel(0x20, phy_base + PCIE_PHY_TRSV0_LVCC); - writel(0xa0, phy_base + PCIE_PHY_TRSV1_LVCC); - writel(0xa0, phy_base + PCIE_PHY_TRSV2_LVCC); - writel(0xa0, phy_base + PCIE_PHY_TRSV3_LVCC); + exynos_phy_writel(exynos_pcie, 0x20, PCIE_PHY_TRSV0_LVCC); + exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV1_LVCC); + exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV2_LVCC); + exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV3_LVCC); } static void exynos_pcie_assert_reset(struct pcie_port *pp) @@ -233,9 +257,6 @@ static int exynos_pcie_establish_link(struct pcie_port *pp) u32 val; int count = 0; struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - void __iomem *elbi_base = exynos_pcie->elbi_base; - void __iomem *block_base = exynos_pcie->block_base; - void __iomem *phy_base = exynos_pcie->phy_base; if (dw_pcie_link_up(pp)) { dev_err(pp->dev, "Link already up\n"); @@ -253,9 +274,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp) exynos_pcie_init_phy(pp); /* pulse for common reset */ - writel(1, block_base + PCIE_PHY_COMMON_RESET); + exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_COMMON_RESET); udelay(500); - writel(0, block_base + PCIE_PHY_COMMON_RESET); + exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET); /* de-assert core reset */ exynos_pcie_deassert_core_reset(pp); @@ -267,15 +288,18 @@ static int exynos_pcie_establish_link(struct pcie_port *pp) exynos_pcie_assert_reset(pp); /* assert LTSSM enable */ - writel(PCIE_ELBI_LTSSM_ENABLE, elbi_base + PCIE_APP_LTSSM_ENABLE); + exynos_elb_writel(exynos_pcie, PCIE_ELBI_LTSSM_ENABLE, + PCIE_APP_LTSSM_ENABLE); /* check if the link is up or not */ while (!dw_pcie_link_up(pp)) { mdelay(100); count++; if (count == 10) { - while (readl(phy_base + PCIE_PHY_PLL_LOCKED) == 0) { - val = readl(block_base + PCIE_PHY_PLL_LOCKED); + while (exynos_phy_readl(exynos_pcie, + PCIE_PHY_PLL_LOCKED) == 0) { + val = exynos_blk_readl(exynos_pcie, + PCIE_PHY_PLL_LOCKED); dev_info(pp->dev, "PLL Locked: 0x%x\n", val); } dev_err(pp->dev, "PCIe Link Fail\n"); @@ -292,10 +316,9 @@ static void exynos_pcie_clear_irq_pulse(struct pcie_port *pp) { u32 val; struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - void __iomem *elbi_base = exynos_pcie->elbi_base; - val = readl(elbi_base + PCIE_IRQ_PULSE); - writel(val, elbi_base + PCIE_IRQ_PULSE); + val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE); + exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE); return; } @@ -303,12 +326,11 @@ static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp) { u32 val; struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - void __iomem *elbi_base = exynos_pcie->elbi_base; /* enable INTX interrupt */ val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | IRQ_INTC_ASSERT | IRQ_INTD_ASSERT, - writel(val, elbi_base + PCIE_IRQ_EN_PULSE); + exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE); return; } @@ -369,7 +391,7 @@ static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, static int exynos_pcie_link_up(struct pcie_port *pp) { struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); - u32 val = readl(exynos_pcie->elbi_base + PCIE_ELBI_RDLH_LINKUP); + u32 val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_RDLH_LINKUP); if (val == PCIE_ELBI_LTSSM_ENABLE) return 1; From 3dc48af310709b85d07c8b0d3aa8f1ead02829d3 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 29 Aug 2013 16:17:05 -0400 Subject: [PATCH 3/3] PCI/ACPI: Fix _OSC ordering to allow PCIe hotplug use when available This fixes the problem of acpiphp claiming slots that should be managed by pciehp, which may keep ExpressCard slots from working. The acpiphp driver claims PCIe slots unless the BIOS has granted us control of PCIe native hotplug via _OSC. Prior to v3.10, the acpiphp .add method (add_bridge()) was always called *after* we had requested native hotplug control with _OSC. But after 3b63aaa70e ("PCI: acpiphp: Do not use ACPI PCI subdriver mechanism"), which appeared in v3.10, acpiphp initialization is done during the bus scan via the pcibios_add_bus() hook, and this happens *before* we request native hotplug control. Therefore, acpiphp doesn't know yet whether the BIOS will grant control, and it claims slots that we should be handling with native hotplug. This patch requests native hotplug control earlier, so we know whether the BIOS granted it to us before we initialize acpiphp. To avoid reintroducing the ASPM issue fixed by b8178f130e ('Revert "PCI/ACPI: Request _OSC control before scanning PCI root bus"'), we run _OSC earlier but defer the actual ASPM calls until after the bus scan is complete. Tested successfully by myself. [bhelgaas: changelog, mark for stable] Reference: https://bugzilla.kernel.org/show_bug.cgi?id=60736 Signed-off-by: Neil Horman Signed-off-by: Bjorn Helgaas Acked-by: Yinghai Lu CC: stable@vger.kernel.org # v3.10+ CC: Len Brown CC: "Rafael J. Wysocki" --- drivers/acpi/pci_root.c | 62 +++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 5917839321b8..a67853e3c419 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -378,6 +378,7 @@ static int acpi_pci_root_add(struct acpi_device *device, struct acpi_pci_root *root; u32 flags, base_flags; acpi_handle handle = device->handle; + bool no_aspm = false, clear_aspm = false; root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); if (!root) @@ -437,27 +438,6 @@ static int acpi_pci_root_add(struct acpi_device *device, flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; acpi_pci_osc_support(root, flags); - /* - * TBD: Need PCI interface for enumeration/configuration of roots. - */ - - /* - * Scan the Root Bridge - * -------------------- - * Must do this prior to any attempt to bind the root device, as the - * PCI namespace does not get created until this call is made (and - * thus the root bridge's pci_dev does not exist). - */ - root->bus = pci_acpi_scan_root(root); - if (!root->bus) { - dev_err(&device->dev, - "Bus %04x:%02x not present in PCI namespace\n", - root->segment, (unsigned int)root->secondary.start); - result = -ENODEV; - goto end; - } - - /* Indicate support for various _OSC capabilities. */ if (pci_ext_cfg_avail()) flags |= OSC_EXT_PCI_CONFIG_SUPPORT; if (pcie_aspm_support_enabled()) { @@ -471,7 +451,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (ACPI_FAILURE(status)) { dev_info(&device->dev, "ACPI _OSC support " "notification failed, disabling PCIe ASPM\n"); - pcie_no_aspm(); + no_aspm = true; flags = base_flags; } } @@ -503,7 +483,7 @@ static int acpi_pci_root_add(struct acpi_device *device, * We have ASPM control, but the FADT indicates * that it's unsupported. Clear it. */ - pcie_clear_aspm(root->bus); + clear_aspm = true; } } else { dev_info(&device->dev, @@ -512,7 +492,14 @@ static int acpi_pci_root_add(struct acpi_device *device, acpi_format_exception(status), flags); dev_info(&device->dev, "ACPI _OSC control for PCIe not granted, disabling ASPM\n"); - pcie_no_aspm(); + /* + * We want to disable ASPM here, but aspm_disabled + * needs to remain in its state from boot so that we + * properly handle PCIe 1.1 devices. So we set this + * flag here, to defer the action until after the ACPI + * root scan. + */ + no_aspm = true; } } else { dev_info(&device->dev, @@ -520,6 +507,33 @@ static int acpi_pci_root_add(struct acpi_device *device, "(_OSC support mask: 0x%02x)\n", flags); } + /* + * TBD: Need PCI interface for enumeration/configuration of roots. + */ + + /* + * Scan the Root Bridge + * -------------------- + * Must do this prior to any attempt to bind the root device, as the + * PCI namespace does not get created until this call is made (and + * thus the root bridge's pci_dev does not exist). + */ + root->bus = pci_acpi_scan_root(root); + if (!root->bus) { + dev_err(&device->dev, + "Bus %04x:%02x not present in PCI namespace\n", + root->segment, (unsigned int)root->secondary.start); + result = -ENODEV; + goto end; + } + + if (clear_aspm) { + dev_info(&device->dev, "Disabling ASPM (FADT indicates it is unsupported)\n"); + pcie_clear_aspm(root->bus); + } + if (no_aspm) + pcie_no_aspm(); + pci_acpi_add_bus_pm_notifier(device, root->bus); if (device->wakeup.flags.run_wake) device_set_run_wake(root->bus->bridge, true);