diff options
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/pcie.c | 223 |
1 files changed, 99 insertions, 124 deletions
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index ad14bb2d8092..13383af20ed4 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -50,51 +50,6 @@ #define MSELECT_CONFIG_0_ENABLE_PCIE_APERTURE 5 -#define PINMUX_AUX_PEX_L0_RST_N_0 0x33bc -#define PINMUX_AUX_PEX_L0_RST_N_0_E_INPUT 5 -#define PINMUX_AUX_PEX_L0_RST_N_0_E_INPUT_ENABLE 1 - -#define PINMUX_AUX_PEX_L1_RST_N_0 0x33cc -#define PINMUX_AUX_PEX_L1_RST_N_0_E_INPUT 5 -#define PINMUX_AUX_PEX_L1_RST_N_0_E_INPUT_ENABLE 1 - -#define PINMUX_AUX_PEX_L2_RST_N_0 0x33d8 -#define PINMUX_AUX_PEX_L2_RST_N_0_E_INPUT 5 -#define PINMUX_AUX_PEX_L2_RST_N_0_E_INPUT_ENABLE 1 -#define AFI_PEX0_CTRL_0_PEX0_CLKREQ_EN 1 -#define NV_PCIE2_PADS_REFCLK_CFG1 0x000000cc -#define APBDEV_PMC_SCRATCH42_0_PCX_CLAMP_MASK 0x1 - - -#define AFI_MSI_VEC0_0 0x6c -#define AFI_MSI_VEC1_0 0x70 -#define AFI_MSI_VEC2_0 0x74 -#define AFI_MSI_VEC3_0 0x78 -#define AFI_MSI_VEC4_0 0x7c -#define AFI_MSI_VEC5_0 0x80 -#define AFI_MSI_VEC6_0 0x84 -#define AFI_MSI_VEC7_0 0x88 - -#define AFI_MSI_EN_VEC0_0 0x8c -#define AFI_MSI_EN_VEC1_0 0x90 -#define AFI_MSI_EN_VEC2_0 0x94 -#define AFI_MSI_EN_VEC3_0 0x98 -#define AFI_MSI_EN_VEC4_0 0x9c -#define AFI_MSI_EN_VEC5_0 0xa0 -#define AFI_MSI_EN_VEC6_0 0xa4 -#define AFI_MSI_EN_VEC7_0 0xa8 - -#define AFI_MSI_FPCI_BAR_ST_0 0x64 -#define AFI_MSI_BAR_SZ_0 0x60 -#define AFI_MSI_AXI_BAR_ST_0 0x68 -#define AFI_INTR_MASK_0 0xb4 -#define AFI_INTR_MASK_0_INT_MASK 0 -#define AFI_INTR_MASK_0_MSI_MASK 8 - - -#define AFI_PEXBIAS_CTRL_0 0x168 - - /* register definitions */ #define AFI_OFFSET 0x3800 #define PADS_OFFSET 0x3000 @@ -130,6 +85,24 @@ #define AFI_MSI_FPCI_BAR_ST 0x64 #define AFI_MSI_AXI_BAR_ST 0x68 +#define AFI_MSI_VEC0_0 0x6c +#define AFI_MSI_VEC1_0 0x70 +#define AFI_MSI_VEC2_0 0x74 +#define AFI_MSI_VEC3_0 0x78 +#define AFI_MSI_VEC4_0 0x7c +#define AFI_MSI_VEC5_0 0x80 +#define AFI_MSI_VEC6_0 0x84 +#define AFI_MSI_VEC7_0 0x88 + +#define AFI_MSI_EN_VEC0_0 0x8c +#define AFI_MSI_EN_VEC1_0 0x90 +#define AFI_MSI_EN_VEC2_0 0x94 +#define AFI_MSI_EN_VEC3_0 0x98 +#define AFI_MSI_EN_VEC4_0 0x9c +#define AFI_MSI_EN_VEC5_0 0xa0 +#define AFI_MSI_EN_VEC6_0 0xa4 +#define AFI_MSI_EN_VEC7_0 0xa8 + #define AFI_CONFIGURATION 0xac #define AFI_CONFIGURATION_EN_FPCI (1 << 0) @@ -140,19 +113,19 @@ #define AFI_INTR_MASK_MSI_MASK (1 << 8) #define AFI_INTR_CODE 0xb8 -#define AFI_INTR_CODE_MASK 0xf -#define AFI_INTR_MASTER_ABORT 4 -#define AFI_INTR_LEGACY 6 +#define AFI_INTR_CODE_MASK 0xf +#define AFI_INTR_MASTER_ABORT 4 +#define AFI_INTR_LEGACY 6 #define AFI_INTR_SIGNATURE 0xbc #define AFI_SM_INTR_ENABLE 0xc4 #define AFI_AFI_INTR_ENABLE 0xc8 -#define AFI_INTR_EN_INI_SLVERR (1 << 0) -#define AFI_INTR_EN_INI_DECERR (1 << 1) -#define AFI_INTR_EN_TGT_SLVERR (1 << 2) -#define AFI_INTR_EN_TGT_DECERR (1 << 3) -#define AFI_INTR_EN_TGT_WRERR (1 << 4) +#define AFI_INTR_EN_INI_SLVERR (1 << 0) +#define AFI_INTR_EN_INI_DECERR (1 << 1) +#define AFI_INTR_EN_TGT_SLVERR (1 << 2) +#define AFI_INTR_EN_TGT_DECERR (1 << 3) +#define AFI_INTR_EN_TGT_WRERR (1 << 4) #define AFI_INTR_EN_DFPCI_DECERR (1 << 5) #define AFI_INTR_EN_AXI_DECERR (1 << 6) #define AFI_INTR_EN_FPCI_TIMEOUT (1 << 7) @@ -174,8 +147,11 @@ #define AFI_PEX1_CTRL 0x118 #define AFI_PEX2_CTRL 0x128 #define AFI_PEX_CTRL_RST (1 << 0) +#define AFI_PEX_CTRL_CLKREQ_EN (1 << 1) #define AFI_PEX_CTRL_REFCLK_EN (1 << 3) +#define AFI_PEXBIAS_CTRL_0 0x168 + #define RP_VEND_XP 0x00000F00 #define RP_VEND_XP_DL_UP (1 << 30) @@ -205,6 +181,8 @@ #define PADS_PLL_CTL_TXCLKREF_DIV10 (0 << 20) #define PADS_PLL_CTL_TXCLKREF_DIV5 (1 << 20) +#define PADS_REFCLK_CFG1 0x000000CC + /* PMC access is required for PCIE xclk (un)clamping */ #define PMC_SCRATCH42 0x144 #define PMC_SCRATCH42_PCX_CLAMP (1 << 0) @@ -285,7 +263,7 @@ */ #define PCIE_IOMAP_SZ (PCIE_REGS_SZ + PCIE_CFG_SZ + PCIE_EXT_CFG_SZ) -#define MMIO_BASE (TEGRA_PCIE_BASE + SZ_48M) +#define MMIO_BASE (TEGRA_PCIE_BASE + PCIE_IOMAP_SZ) #define MMIO_SIZE SZ_1M #define MEM_BASE_0 (TEGRA_PCIE_BASE + SZ_256M) #define MEM_SIZE SZ_256M @@ -623,8 +601,8 @@ static struct hw_pci tegra_pcie_hw = { }; #ifdef CONFIG_PM -static int tegra_pci_suspend(struct device *dev); -static int tegra_pci_resume(struct device *dev); +static int tegra_pcie_suspend(struct device *dev); +static int tegra_pcie_resume(struct device *dev); /* It enumerates the devices when dock is connected after system boot */ /* this is similar to pcibios_init_hw in bios32.c */ @@ -665,14 +643,14 @@ static void tegra_pcie_attach(void) if (!is_dock_conn_at_boot) tegra_pcie.num_ports = 1; #ifdef CONFIG_PM - tegra_pci_resume(NULL); + tegra_pcie_resume(NULL); #endif } static void tegra_pcie_detach(void) { #ifdef CONFIG_PM - tegra_pci_suspend(NULL); + tegra_pcie_suspend(NULL); #endif } @@ -814,11 +792,9 @@ static void tegra_pcie_enable_controller(void) { u32 val, reg; int i; - void __iomem *reg_apb_misc_base; void __iomem *reg_mselect_base; - reg_apb_misc_base = IO_ADDRESS(TEGRA_APB_MISC_BASE); - reg_mselect_base = IO_ADDRESS(TEGRA_MSELECT_BASE); + reg_mselect_base = IO_ADDRESS(TEGRA_MSELECT_BASE); /* select the PCIE APERTURE in MSELECT config */ reg = readl(reg_mselect_base); reg |= 1 << MSELECT_CONFIG_0_ENABLE_PCIE_APERTURE; @@ -827,8 +803,7 @@ static void tegra_pcie_enable_controller(void) /* Enable slot clock and pulse the reset signals */ for (i = 0, reg = AFI_PEX0_CTRL; i < MAX_PCIE_SUPPORTED_PORTS; i++, reg += (i*8)) { - val = afi_readl(reg) | AFI_PEX_CTRL_REFCLK_EN | - (1 << AFI_PEX0_CTRL_0_PEX0_CLKREQ_EN); + val = afi_readl(reg) | AFI_PEX_CTRL_CLKREQ_EN | AFI_PEX_CTRL_REFCLK_EN; afi_writel(val, reg); val &= ~AFI_PEX_CTRL_RST; afi_writel(val, reg); @@ -838,7 +813,8 @@ static void tegra_pcie_enable_controller(void) } afi_writel(0, AFI_PEXBIAS_CTRL_0); - /* Enable dual controller and both ports */ + /* Enable all PCIE controller and */ + /* system management configuration of PCIE crossbar */ val = afi_readl(AFI_PCIE_CONFIG); val &= ~(AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE | AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE | @@ -851,6 +827,7 @@ static void tegra_pcie_enable_controller(void) #endif afi_writel(val, AFI_PCIE_CONFIG); + /* Disable Gen 2 capability of PCIE */ val = afi_readl(AFI_FUSE) & ~AFI_FUSE_PCIE_T0_GEN2_DIS; afi_writel(val, AFI_FUSE); @@ -863,15 +840,15 @@ static void tegra_pcie_enable_controller(void) /* * set up PHY PLL inputs select PLLE output as refclock, - * set TX ref sel to div10 (not div5) + * set pll TX clock ref to div10 (not div5) + * set pll ref clock buf to enable. */ val = pads_readl(PADS_PLL_CTL); val &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK); #ifdef CONFIG_ARCH_TEGRA_2x_SOC val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_DIV10); #else - val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | - PADS_PLL_CTL_TXCLKREF_BUF_EN); + val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_BUF_EN); #endif pads_writel(val, PADS_PLL_CTL); @@ -884,7 +861,7 @@ static void tegra_pcie_enable_controller(void) * This doesn't exist in the documentation */ pads_writel(0xfa5cfa5c, 0xc8); - pads_writel(0x0000FA5C, NV_PCIE2_PADS_REFCLK_CFG1); + pads_writel(0x0000FA5C, PADS_REFCLK_CFG1); /* Wait for the PLL to lock */ do { @@ -923,7 +900,7 @@ static void tegra_pcie_enable_controller(void) return; } -static int tegra_pci_enable_regulators(void) +static int tegra_pcie_enable_regulators(void) { if (tegra_pcie.power_rails_enabled) return 0; @@ -976,7 +953,7 @@ static int tegra_pci_enable_regulators(void) return 0; } -static int tegra_pci_disable_regulators(void) +static int tegra_pcie_disable_regulators(void) { int err = 0; if (tegra_pcie.power_rails_enabled == 0) @@ -996,23 +973,31 @@ err_exit: return err; } +static int tegra_pcie_power_regate(void) +{ + int err; + err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_PCIE); + if (err) { + pr_err("PCIE: powerup sequence failed: %d\n", err); + return err; + } + tegra_periph_reset_assert(tegra_pcie.pcie_xclk); + return clk_enable(tegra_pcie.pll_e); +} + #ifdef CONFIG_PM static int tegra_pcie_power_on(void) { int err = 0; if (tegra_pcie.pcie_power_enabled) return 0; - err = tegra_pci_enable_regulators(); + err = tegra_pcie_enable_regulators(); if (err) goto err_exit; - err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_PCIE); + err = tegra_pcie_power_regate(); if (err) goto err_exit; - tegra_periph_reset_assert(tegra_pcie.pcie_xclk); - if (tegra_pcie.pll_e) - clk_enable(tegra_pcie.pll_e); - tegra_pcie.pcie_power_enabled = 1; err_exit: return err; @@ -1031,25 +1016,13 @@ static int tegra_pcie_power_off(void) if (err) goto err_exit; - err = tegra_pci_disable_regulators(); + err = tegra_pcie_disable_regulators(); tegra_pcie.pcie_power_enabled = 0; err_exit: return err; } -static int tegra_pcie_power_regate(void) -{ - int err; - err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_PCIE); - if (err) { - pr_err("PCIE: powerup sequence failed: %d\n", err); - return err; - } - tegra_periph_reset_assert(tegra_pcie.pcie_xclk); - return clk_enable(tegra_pcie.pll_e); -} - static int tegra_pcie_clocks_get(void) { /* reset the PCIEXCLK */ @@ -1082,8 +1055,9 @@ static int tegra_pcie_get_resources(void) { struct resource *res_mmio = 0; int err; + tegra_pcie.power_rails_enabled = 0; - err = tegra_pci_enable_regulators(); + err = tegra_pcie_enable_regulators(); if (err) { pr_err("PCIE: failed to enable power rails %d\n", err); goto err_pwr_on_rail; @@ -1102,6 +1076,7 @@ static int tegra_pcie_get_resources(void) goto err_pwr_on; } + /* Allocate config space virtual memory */ tegra_pcie.regs = ioremap_nocache(TEGRA_PCIE_BASE, PCIE_IOMAP_SZ); if (tegra_pcie.regs == NULL) { pr_err("PCIE: Failed to map PCI/AFI registers\n"); @@ -1116,6 +1091,7 @@ static int tegra_pcie_get_resources(void) goto err_req_io; } + /* Allocate downstream IO virtual memory */ tegra_pcie_io_base = ioremap_nocache(res_mmio->start, resource_size(res_mmio)); if (tegra_pcie_io_base == NULL) { @@ -1145,7 +1121,7 @@ err_map_reg: err_pwr_on: tegra_pcie_clocks_put(); err_pwr_on_rail: - tegra_pci_disable_regulators(); + tegra_pcie_disable_regulators(); return err; } @@ -1273,7 +1249,7 @@ static int tegra_pcie_init(void) tegra_pcie_setup_translations(); for (port = 0; port < MAX_PCIE_SUPPORTED_PORTS; port++) { ctrl_offset += (port * 8); - rp_offset = (rp_offset + 0x1000) * port; + rp_offset = (rp_offset + RP_OFFSET) * port; if (tegra_pcie.plat_data->port_status[port]) tegra_pcie_add_port(port, rp_offset, ctrl_offset); } @@ -1315,7 +1291,7 @@ err_irq: return err; } -static int tegra_pci_probe(struct platform_device *pdev) +static int tegra_pcie_probe(struct platform_device *pdev) { int ret; struct pci_dev *dev = NULL; @@ -1338,7 +1314,7 @@ static int tegra_pci_probe(struct platform_device *pdev) } #ifdef CONFIG_PM -static int tegra_pci_suspend(struct device *dev) +static int tegra_pcie_suspend(struct device *dev) { int ret = 0; struct pci_dev *pdev = NULL; @@ -1357,7 +1333,7 @@ static int tegra_pci_suspend(struct device *dev) return tegra_pcie_power_off(); } -static int tegra_pci_resume(struct device *dev) +static int tegra_pcie_resume(struct device *dev) { int ret = 0; struct pci_bus *b = NULL; @@ -1406,41 +1382,42 @@ static int tegra_pci_resume(struct device *dev) } #endif -static int tegra_pci_remove(struct platform_device *pdev) +static int tegra_pcie_remove(struct platform_device *pdev) { return 0; } + #ifdef CONFIG_PM -static const struct dev_pm_ops tegra_pci_pm_ops = { - .suspend = tegra_pci_suspend, - .resume = tegra_pci_resume, +static const struct dev_pm_ops tegra_pcie_pm_ops = { + .suspend = tegra_pcie_suspend, + .resume = tegra_pcie_resume, }; #endif -static struct platform_driver tegra_pci_driver = { - .probe = tegra_pci_probe, - .remove = tegra_pci_remove, +static struct platform_driver tegra_pcie_driver = { + .probe = tegra_pcie_probe, + .remove = tegra_pcie_remove, .driver = { .name = "tegra-pcie", .owner = THIS_MODULE, #ifdef CONFIG_PM - .pm = &tegra_pci_pm_ops, + .pm = &tegra_pcie_pm_ops, #endif }, }; -static int __init tegra_pci_init_driver(void) +static int __init tegra_pcie_init_driver(void) { - return platform_driver_register(&tegra_pci_driver); + return platform_driver_register(&tegra_pcie_driver); } -static void __exit tegra_pci_exit_driver(void) +static void __exit tegra_pcie_exit_driver(void) { - platform_driver_unregister(&tegra_pci_driver); + platform_driver_unregister(&tegra_pcie_driver); } -module_init(tegra_pci_init_driver); -module_exit(tegra_pci_exit_driver); +module_init(tegra_pcie_init_driver); +module_exit(tegra_pcie_exit_driver); static struct irq_chip tegra_irq_chip_msi_pcie = { .name = "PCIe-MSI", @@ -1504,7 +1481,7 @@ void msi_map_release(struct msi_map_entry *entry) } } -static irqreturn_t pci_tegra_msi_isr(int irq, void *arg) +static irqreturn_t tegra_pcie_msi_isr(int irq, void *arg) { int i; int offset; @@ -1536,14 +1513,13 @@ static irqreturn_t pci_tegra_msi_isr(int irq, void *arg) return IRQ_HANDLED; } -static bool pci_tegra_enable_msi(void) +static bool tegra_pcie_enable_msi(void) { bool retval = false; u32 reg; u32 msi_base = 0; u32 msi_aligned = 0; - /* enables MSI interrupts. */ /* this only happens once. */ if (msi_enable) { retval = true; @@ -1551,14 +1527,14 @@ static bool pci_tegra_enable_msi(void) } msi_map_init(); - if (request_irq(INT_PCIE_MSI, pci_tegra_msi_isr, + /* enables MSI interrupts. */ + if (request_irq(INT_PCIE_MSI, tegra_pcie_msi_isr, IRQF_SHARED, "PCIe-MSI", - pci_tegra_msi_isr)) { + tegra_pcie_msi_isr)) { pr_err("%s: Cannot register IRQ %u\n", __func__, INT_PCIE_MSI); goto exit; } - /* setup AFI/FPCI range */ /* FIXME do this better! should be based on PAGE_SIZE */ msi_base = __get_free_pages(GFP_KERNEL, 3); @@ -1566,14 +1542,14 @@ static bool pci_tegra_enable_msi(void) msi_aligned = virt_to_phys((void *)msi_aligned); #ifdef CONFIG_ARCH_TEGRA_2x_SOC - afi_writel(msi_aligned, AFI_MSI_FPCI_BAR_ST_0); + afi_writel(msi_aligned, AFI_MSI_FPCI_BAR_ST); #else /* different from T20!*/ - afi_writel(msi_aligned>>8, AFI_MSI_FPCI_BAR_ST_0); + afi_writel(msi_aligned>>8, AFI_MSI_FPCI_BAR_ST); #endif - afi_writel(msi_aligned, AFI_MSI_AXI_BAR_ST_0); + afi_writel(msi_aligned, AFI_MSI_AXI_BAR_ST); /* this register is in 4K increments */ - afi_writel(1, AFI_MSI_BAR_SZ_0); + afi_writel(1, AFI_MSI_BAR_SZ); /* enable all MSI vectors */ afi_writel(0xffffffff, AFI_MSI_EN_VEC0_0); @@ -1587,9 +1563,8 @@ static bool pci_tegra_enable_msi(void) /* and unmask the MSI interrupt */ reg = 0; - reg |= ((1 << AFI_INTR_MASK_0_INT_MASK) | - (1 << AFI_INTR_MASK_0_MSI_MASK)); - afi_writel(reg, AFI_INTR_MASK_0); + reg |= (AFI_INTR_MASK_INT_MASK | AFI_INTR_MASK_MSI_MASK); + afi_writel(reg, AFI_INTR_MASK); set_irq_flags(INT_PCIE_MSI, IRQF_VALID); @@ -1611,7 +1586,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) struct msi_msg msg; struct msi_map_entry *map_entry = NULL; - if (!pci_tegra_enable_msi()) + if (!tegra_pcie_enable_msi()) goto exit; map_entry = msi_map_get(); @@ -1626,7 +1601,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) irq_set_msi_desc(map_entry->irq, desc); set_irq_flags(map_entry->irq, IRQF_VALID); - msg.address_lo = afi_readl(AFI_MSI_AXI_BAR_ST_0); + msg.address_lo = afi_readl(AFI_MSI_AXI_BAR_ST); /* 32 bit address only */ msg.address_hi = 0; msg.data = map_entry->index; |