summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mvf/pcie.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mvf/pcie.c')
-rw-r--r--arch/arm/mach-mvf/pcie.c484
1 files changed, 0 insertions, 484 deletions
diff --git a/arch/arm/mach-mvf/pcie.c b/arch/arm/mach-mvf/pcie.c
deleted file mode 100644
index 9959bbceaa4d..000000000000
--- a/arch/arm/mach-mvf/pcie.c
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * arch/arm/mach-mx6/pcie.c
- *
- * PCIe host controller driver for IMX6 SOCs
- *
- * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Bits taken from arch/arm/mach-dove/pcie.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-
-#include <asm/sizes.h>
-
-#include "crm_regs.h"
-
-/* Register Definitions */
-#define PRT_LOG_R_BaseAddress 0x700
-
-/* Register DB_R0 */
-/* Debug Register 0 */
-#define DB_R0 (PRT_LOG_R_BaseAddress + 0x28)
-#define DB_R0_RegisterSize 32
-#define DB_R0_RegisterResetValue 0x0
-#define DB_R0_RegisterResetMask 0xFFFFFFFF
-/* End of Register Definition for DB_R0 */
-
-/* Register DB_R1 */
-/* Debug Register 1 */
-#define DB_R1 (PRT_LOG_R_BaseAddress + 0x2c)
-#define DB_R1_RegisterSize 32
-#define DB_R1_RegisterResetValue 0x0
-#define DB_R1_RegisterResetMask 0xFFFFFFFF
-/* End of Register Definition for DB_R1 */
-
-#define ATU_R_BaseAddress 0x900
-#define ATU_VIEWPORT_R (ATU_R_BaseAddress + 0x0)
-#define ATU_REGION_CTRL1_R (ATU_R_BaseAddress + 0x4)
-#define ATU_REGION_CTRL2_R (ATU_R_BaseAddress + 0x8)
-#define ATU_REGION_LOWBASE_R (ATU_R_BaseAddress + 0xC)
-#define ATU_REGION_UPBASE_R (ATU_R_BaseAddress + 0x10)
-#define ATU_REGION_LIMIT_ADDR_R (ATU_R_BaseAddress + 0x14)
-#define ATU_REGION_LOW_TRGT_ADDR_R (ATU_R_BaseAddress + 0x18)
-#define ATU_REGION_UP_TRGT_ADDR_R (ATU_R_BaseAddress + 0x1C)
-
-/* GPR1: iomuxc_gpr1_pcie_ref_clk_en(iomuxc_gpr1[16]) */
-#define iomuxc_gpr1_pcie_ref_clk_en (1 << 16)
-/* GPR1: iomuxc_gpr1_test_powerdown(iomuxc_gpr1_18) */
-#define iomuxc_gpr1_test_powerdown (1 << 18)
-
-/* GPR12: iomuxc_gpr12_los_level(iomuxc_gpr12[8:4]) */
-#define iomuxc_gpr12_los_level (0x1F << 4)
-/* GPR12: iomuxc_gpr12_app_ltssm_enable(iomuxc_gpr12[10]) */
-#define iomuxc_gpr12_app_ltssm_enable (1 << 10)
-/* GPR12: iomuxc_gpr12_device_type(iomuxc_gpr12[15:12]) */
-#define iomuxc_gpr12_device_type (0xF << 12)
-
-/* GPR8: iomuxc_gpr8_tx_deemph_gen1(iomuxc_gpr8[5:0]) */
-#define iomuxc_gpr8_tx_deemph_gen1 (0x3F << 0)
-/* GPR8: iomuxc_gpr8_tx_deemph_gen2_3p5db(iomuxc_gpr8[11:6]) */
-#define iomuxc_gpr8_tx_deemph_gen2_3p5db (0x3F << 6)
-/* GPR8: iomuxc_gpr8_tx_deemph_gen2_6db(iomuxc_gpr8[17:12]) */
-#define iomuxc_gpr8_tx_deemph_gen2_6db (0x3F << 12)
-/* GPR8: iomuxc_gpr8_tx_swing_full(iomuxc_gpr8[24:18]) */
-#define iomuxc_gpr8_tx_swing_full (0x7F << 18)
-/* GPR8: iomuxc_gpr8_tx_swing_low(iomuxc_gpr8[31:25]) */
-#define iomuxc_gpr8_tx_swing_low (0x7F << 25)
-
-/* End of Register Definitions */
-
-#define PCIE_DBI_BASE_ADDR (PCIE_ARB_END_ADDR - SZ_16K + 1)
-
-#define PCIE_CONF_BUS(b) (((b) & 0xFF) << 16)
-#define PCIE_CONF_DEV(d) (((d) & 0x1F) << 11)
-#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 8)
-
-enum {
- MemRdWr = 0,
- MemRdLk = 1,
- IORdWr = 2,
- CfgRdWr0 = 4,
- CfgRdWr1 = 5
-};
-
-struct imx_pcie_port {
- u8 index;
- u8 root_bus_nr;
- void __iomem *base;
- void __iomem *dbi_base;
- spinlock_t conf_lock;
-
- char io_space_name[16];
- char mem_space_name[16];
-
- struct resource res[2];
-};
-
-static struct imx_pcie_port imx_pcie_port[1];
-static int num_pcie_ports;
-
-/* IMX PCIE GPR configure routines */
-static inline void imx_pcie_clrset(u32 mask, u32 val, void __iomem *addr)
-{
- writel(((readl(addr) & ~mask) | (val & mask)), addr);
-}
-
-static struct imx_pcie_port *bus_to_port(int bus)
-{
- int i;
-
- for (i = num_pcie_ports - 1; i >= 0; i--) {
- int rbus = imx_pcie_port[i].root_bus_nr;
- if (rbus != -1 && rbus <= bus)
- break;
- }
-
- return i >= 0 ? imx_pcie_port + i : NULL;
-}
-
-static int __init imx_pcie_setup(int nr, struct pci_sys_data *sys)
-{
- struct imx_pcie_port *pp;
-
- if (nr >= num_pcie_ports)
- return 0;
-
- pp = &imx_pcie_port[nr];
- pp->root_bus_nr = sys->busnr;
-
- /*
- * IORESOURCE_IO
- */
- snprintf(pp->io_space_name, sizeof(pp->io_space_name),
- "PCIe %d I/O", pp->index);
- pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
- pp->res[0].name = pp->io_space_name;
- if (pp->index == 0) {
- pp->res[0].start = PCIE_ARB_BASE_ADDR;
- pp->res[0].end = pp->res[0].start + SZ_64K - 1;
- }
- pp->res[0].flags = IORESOURCE_IO;
- if (request_resource(&ioport_resource, &pp->res[0]))
- panic("Request PCIe IO resource failed\n");
- sys->resource[0] = &pp->res[0];
-
- /*
- * IORESOURCE_MEM
- */
- snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
- "PCIe %d MEM", pp->index);
- pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
- pp->res[1].name = pp->mem_space_name;
- if (pp->index == 0) {
- pp->res[1].start = PCIE_ARB_BASE_ADDR + SZ_64K;
- pp->res[1].end = pp->res[1].start + SZ_16M - SZ_128K - 1;
- }
- pp->res[1].flags = IORESOURCE_MEM;
- if (request_resource(&iomem_resource, &pp->res[1]))
- panic("Request PCIe Memory resource failed\n");
- sys->resource[1] = &pp->res[1];
-
- sys->resource[2] = NULL;
-
- return 1;
-}
-
-static void __init imx_pcie_preinit(void)
-{
- pcibios_setup("debug");
-}
-
-static int imx_pcie_link_up(void __iomem *dbi_base)
-{
- /* Check the pcie link up or link down */
- u32 rc, iterations = 0x100000;
-
- do {
- /* link is debug bit 36 debug 1 start in bit 32 */
- rc = readl(dbi_base + DB_R1) & (0x1 << (36-32)) ;
- iterations--;
- if ((iterations % 0x100000) == 0)
- pr_info("link up failed!\n");
- } while (!rc && iterations);
-
- if (!rc)
- return 0;
- return 1;
-}
-
-static int pcie_valid_config(struct imx_pcie_port *pp, int bus_num, int dev)
-{
- /*If there is no link, then there is no device*/
- if (bus_num != pp->root_bus_nr) {
- if (!imx_pcie_link_up(pp->dbi_base))
- return 0;
- }
-
- /*
- * Don't go out when trying to access nonexisting devices
- * on the local bus.
- * We have only one slot on the root port.
- */
- if (bus_num == pp->root_bus_nr && dev > 0)
- return 0;
-
- return 1;
-}
-
-static void imx_pcie_regions_setup(void __iomem *dbi_base)
-{
- /*
- * i.MX6 defines 16MB in the AXI address map for PCIe.
- *
- * That address space excepted the pcie registers is
- * split and defined into different regions by iATU,
- * with sizes and offsets as follows:
- *
- * 0x0100_0000 --- 0x0100_FFFF 64KB IORESOURCE_IO
- * 0x0101_0000 --- 0x01FE_FFFF 16MB - 128KB IORESOURCE_MEM
- * 0x01FF_0000 --- 0x01FF_FFFF 64KB Cfg + Registers
- */
-
- /* CMD reg:I/O space, MEM space, and Bus Master Enable */
- writel(readl(dbi_base + PCI_COMMAND)
- | PCI_COMMAND_IO
- | PCI_COMMAND_MEMORY
- | PCI_COMMAND_MASTER,
- dbi_base + PCI_COMMAND);
- /*
- * region0 outbound used to access target cfg
- */
- writel(0, dbi_base + ATU_VIEWPORT_R);
- writel(PCIE_ARB_END_ADDR - SZ_64K + 1, dbi_base + ATU_REGION_LOWBASE_R);
- writel(0, dbi_base + ATU_REGION_UPBASE_R);
- writel(PCIE_ARB_END_ADDR, dbi_base + ATU_REGION_LIMIT_ADDR_R);
- writel(0, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R);
- writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R);
- writel(CfgRdWr0, dbi_base + ATU_REGION_CTRL1_R);
- writel((1<<31), dbi_base + ATU_REGION_CTRL2_R);
-
- /*
- * region1 outbound used to as IORESOURCE_IO
- */
- writel(1, dbi_base + ATU_VIEWPORT_R);
- writel(0, dbi_base + ATU_REGION_LOWBASE_R);
- writel(0, dbi_base + ATU_REGION_UPBASE_R);
- writel(SZ_64K - 1, dbi_base + ATU_REGION_LIMIT_ADDR_R);
- writel(0, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R);
- writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R);
- writel(IORdWr, dbi_base + ATU_REGION_CTRL1_R);
- writel((1<<31), dbi_base + ATU_REGION_CTRL2_R);
-
- /*
- * region2 outbound used to as IORESOURCE_MEM
- */
- writel(2, dbi_base + ATU_VIEWPORT_R);
- writel(0, dbi_base + ATU_REGION_LOWBASE_R);
- writel(0, dbi_base + ATU_REGION_UPBASE_R);
- writel(SZ_16M - SZ_128K - 1, dbi_base + ATU_REGION_LIMIT_ADDR_R);
- writel(0, dbi_base + ATU_REGION_LOW_TRGT_ADDR_R);
- writel(0, dbi_base + ATU_REGION_UP_TRGT_ADDR_R);
- writel(MemRdWr, dbi_base + ATU_REGION_CTRL1_R);
- writel((1<<31), dbi_base + ATU_REGION_CTRL2_R);
-}
-
-static int imx_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
- int size, u32 *val)
-{
- struct imx_pcie_port *pp = bus_to_port(bus->number);
- unsigned long flags;
- u32 va_address;
-
- if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
- *val = 0xFFFFFFFF;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
-
- spin_lock_irqsave(&pp->conf_lock, flags);
-
- va_address = (u32)pp->base +
- PCIE_CONF_BUS(bus->number) +
- PCIE_CONF_DEV(PCI_SLOT(devfn)) +
- PCIE_CONF_FUNC(PCI_FUNC(devfn)) +
- (where & ~0x3);
-
- *val = readl(va_address);
-
- if (size == 1)
- *val = (*val >> (8 * (where & 3))) & 0xFF;
- else if (size == 2)
- *val = (*val >> (8 * (where & 3))) & 0xFFFF;
-
- spin_unlock_irqrestore(&pp->conf_lock, flags);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int imx_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
- int where, int size, u32 val)
-{
- struct imx_pcie_port *pp = bus_to_port(bus->number);
- unsigned long flags;
- u32 va_address = 0, mask = 0, tmp = 0;
- int ret = PCIBIOS_SUCCESSFUL;
-
- if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- spin_lock_irqsave(&pp->conf_lock, flags);
-
- va_address = (u32)pp->base +
- PCIE_CONF_BUS(bus->number) +
- PCIE_CONF_DEV(PCI_SLOT(devfn)) +
- PCIE_CONF_FUNC(PCI_FUNC(devfn)) +
- (where & ~0x3);
-
- if (size == 4) {
- writel(val, va_address);
- goto exit;
- }
-
- if (size == 2)
- mask = ~(0xFFFF << ((where & 0x3) * 8));
- else if (size == 1)
- mask = ~(0xFF << ((where & 0x3) * 8));
- else
- ret = PCIBIOS_BAD_REGISTER_NUMBER;
-
- tmp = readl(va_address) & mask;
- tmp |= val << ((where & 0x3) * 8);
- writel(tmp, va_address);
-exit:
- spin_unlock_irqrestore(&pp->conf_lock, flags);
-
- return ret;
-}
-
-static struct pci_ops imx_pcie_ops = {
- .read = imx_pcie_rd_conf,
- .write = imx_pcie_wr_conf,
-};
-
-static struct pci_bus __init *
-imx_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
- struct pci_bus *bus;
-
- if (nr < num_pcie_ports) {
- bus = pci_scan_bus(sys->busnr, &imx_pcie_ops, sys);
- } else {
- bus = NULL;
- BUG();
- }
-
- return bus;
-}
-
-static int __init imx_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- return MXC_INT_PCIE_0;
-}
-
-static struct hw_pci imx_pci __initdata = {
- .nr_controllers = 1,
- .swizzle = pci_std_swizzle,
- .setup = imx_pcie_setup,
- .preinit = imx_pcie_preinit,
- .scan = imx_pcie_scan_bus,
- .map_irq = imx_pcie_map_irq,
-};
-
-static void imx_pcie_enable_controller(void)
-{
- struct clk *pcie_clk;
-
- imx_pcie_clrset(iomuxc_gpr1_test_powerdown, 0 << 18, IOMUXC_GPR1);
-
- /* enable the clks */
- pcie_clk = clk_get(NULL, "pcie_clk");
- if (IS_ERR(pcie_clk))
- pr_err("no pcie clock.\n");
-
- if (clk_enable(pcie_clk)) {
- pr_err("can't enable pcie clock.\n");
- clk_put(pcie_clk);
- }
-}
-
-static void card_reset(void)
-{
- /* Add one reset to the pcie external device */
-}
-
-static void __init add_pcie_port(void __iomem *base, void __iomem *dbi_base)
-{
- if (imx_pcie_link_up(dbi_base)) {
- struct imx_pcie_port *pp = &imx_pcie_port[num_pcie_ports++];
-
- pr_info("IMX PCIe port: link up.\n");
-
- pp->index = 0;
- pp->root_bus_nr = -1;
- pp->base = base;
- pp->dbi_base = dbi_base;
- spin_lock_init(&pp->conf_lock);
- memset(pp->res, 0, sizeof(pp->res));
- } else
- pr_info("IMX PCIe port: link down!\n");
-}
-
-static int __init imx_pcie_init(void)
-{
- void __iomem *base, *dbi_base;
-
- base = ioremap_nocache(PCIE_ARB_END_ADDR - SZ_64K + 1, SZ_32K);
- if (!base) {
- pr_err("error with ioremap in function %s\n", __func__);
- return -EIO;
- }
-
- dbi_base = ioremap_nocache(PCIE_DBI_BASE_ADDR, SZ_16K);
- if (!dbi_base) {
- pr_err("error with ioremap in function %s\n", __func__);
- iounmap(base);
- return -EIO;
- }
-
- /* FIXME the field name should be aligned to RM */
- imx_pcie_clrset(iomuxc_gpr12_app_ltssm_enable, 0 << 10, IOMUXC_GPR12);
-
- /* configure constant input signal to the pcie ctrl and phy */
- imx_pcie_clrset(iomuxc_gpr12_device_type, PCI_EXP_TYPE_ROOT_PORT << 12,
- IOMUXC_GPR12);
- imx_pcie_clrset(iomuxc_gpr12_los_level, 9 << 4, IOMUXC_GPR12);
- imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen1, 21 << 0, IOMUXC_GPR8);
- imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen2_3p5db, 21 << 6, IOMUXC_GPR8);
- imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen2_6db, 32 << 12, IOMUXC_GPR8);
- imx_pcie_clrset(iomuxc_gpr8_tx_swing_full, 115 << 18, IOMUXC_GPR8);
- imx_pcie_clrset(iomuxc_gpr8_tx_swing_low, 115 << 25, IOMUXC_GPR8);
-
- /* Enable the pwr, clks and so on */
- imx_pcie_enable_controller();
-
- imx_pcie_clrset(iomuxc_gpr1_pcie_ref_clk_en, 1 << 16, IOMUXC_GPR1);
-
- /* togle the external card's reset */
- card_reset() ;
-
- usleep_range(3000, 4000);
- imx_pcie_regions_setup(dbi_base);
- usleep_range(3000, 4000);
-
- /* start link up */
- imx_pcie_clrset(iomuxc_gpr12_app_ltssm_enable, 1 << 10, IOMUXC_GPR12);
-
- /* add the pcie port */
- add_pcie_port(base, dbi_base);
-
- pci_common_init(&imx_pci);
- pr_info("pcie init successful\n");
- return 0;
-}
-subsys_initcall(imx_pcie_init);