Only supports DM6467. The driver code is organized in two parts, DM6467 specific part and 'generic' part which could be easily adopted on other platform/SoCs having same PCI core as in DM6467.
Currently PCI interrupt mapping (INTA-D) is not supported as the EVM has no PCI interrupt pins connected to interript controller. Signed-off-by: Hemant Pedanekar <hema...@ti.com> --- arch/arm/mach-davinci/pci-dm6467.c | 136 ++++++++++ arch/arm/mach-davinci/pci-generic.c | 496 +++++++++++++++++++++++++++++++++++ arch/arm/mach-davinci/pci.h | 76 ++++++ 3 files changed, 708 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/pci-dm6467.c b/arch/arm/mach-davinci/pci-dm6467.c new file mode 100755 index 0000000..056fcb1 --- /dev/null +++ b/arch/arm/mach-davinci/pci-dm6467.c @@ -0,0 +1,136 @@ +/* + * pci-dm6467.c + * Description: + * DM6467 (and in some parts, EVM) specific PCI initialization. + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#undef DEBUG + +#include <linux/kernel.h> /* pr_ wrappers */ +#include <linux/pci.h> /* PCI data structures */ +#include <asm/mach/pci.h> /* hw_pci */ +#include <linux/types.h> + +#include "pci.h" /* Platform spec */ + +#include <mach/hardware.h> /* SoC reg defs, __REG, IO info etc */ +#include <linux/clk.h> /* For clk_enable interface */ + +/* NOTE: + * Most of the code in this file assumes that it is runnig as PCI Host and + * configures the system accordingly. The only place where it is checked if we + * are booted through PCI Boot, is the function dm6467_pci_init (below) before + * it registers with the bios. Thus, if we were not hosting the PCI bus the + * other functions wouldn;t get called anyway as the pci bios will not be + * invoked. + */ + +/* Forward declarations */ +static void __init dm6467_pci_preinit(void); +static int __init dm6467_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin); + +/* Specify the physical address and size information for Host windows to be + * configured in BAR0-5 registers. Note that _ALL_ of the 6 entries must be + * filled. For entries with no real window to be mapped, set bar_window_size=0. + */ +struct pcihost_bar_cfg bar_cfg[6] = { + { PHYS_OFFSET /* bar_window_phys */ , 0x8000000 /* bar_window_size */}, + { 0 , 0 }, + { 0 , 0 }, + { 0 , 0 }, + { 0 , 0 }, + { 0 , 0 } +}; + +/* Plug into Linux PCI BIOS Interface */ +static struct hw_pci davinci_pci __initdata = { + .nr_controllers = 1, + .setup = ti_pci_setup, + .scan = ti_pci_scan, + .preinit = dm6467_pci_preinit, + .postinit = NULL, + .swizzle = pci_std_swizzle, /* Using default Linux + ARM-BIOS algorithm */ + .map_irq = dm6467_pci_map_irq +}; + +/* dm6467_pci_preinit + * This function handles initializations to do before accessing PCI bus. This + * function is optional and most of the things done here could be handled in + * board/SoC level init. + */ +void dm6467_pci_preinit(void) +{ + /* + * Use clk_enable interface to do the PSC init as well as take care of + * pin muxing for PCI module domain + */ + struct clk *pci_clk; + + pr_info("PCI: Enabling Clock...\n"); + pci_clk = clk_get(NULL, "pci"); + if (IS_ERR(pci_clk)) + return; + + clk_enable(pci_clk); + + /* At tis point, we assume here that the board level code has taken care + * of driving RST# over PCI Bus (or, if not, then already taken care in + * H/W - this is default behavior of the EVM) + */ +} + +int dm6467_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* + * Standard EVM doesn't have any dedicated lines connected to PCI + * Interrupts. + */ + + return -1; +} + +/* dm6467_pci_init + * PCI system initialization. Fills in required information for PCI BIOS to + * perrform enumeratios and invokes pci_common_init. + */ +static int __init dm6467_pci_init(void) +{ + /* Since DM64xx can act either as PCI host or target, we should check + * here if we are 'target' and skip setting up PCI BIOS for enumeration. + * We check BOOTCFG BOOTMODE[0:3] and PCIEN to determine if we are set + * to boot as a PCI Target (from a PCI Host) or following other boot + * modes. We skip enumeration in former case. + * Note : BOOTCFG values are latched across soft resets and thus the + * check below cannot detect any change in actual boot mode (if at all + * that is possible!). [REVISIT: Porting related] + */ + u32 bootcfg = __raw_readl( + (IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE) + BOOTCFG)); + u32 bootmode = bootcfg & 0xf; + + pr_info("PCI: bootcfg = %#x, bootmode = %#x\n", bootcfg, bootmode); + + if (!((bootcfg & (1 << 16)) && ((bootmode == 2) || (bootmode == 3)))) { + pr_info("PCI: Invoking PCI BIOS...\n"); + pci_common_init(&davinci_pci); + } else { + pr_info("PCI: Skipping PCI Host setup...\n"); + } + + return 0; +} + +subsys_initcall(dm6467_pci_init); + diff --git a/arch/arm/mach-davinci/pci-generic.c b/arch/arm/mach-davinci/pci-generic.c new file mode 100755 index 0000000..3061dd0 --- /dev/null +++ b/arch/arm/mach-davinci/pci-generic.c @@ -0,0 +1,496 @@ +/* + * pci-generic.c + * Description: + * Generic part of PCI Host Driver for TI PCI Module. Note that though code in + * this file is supposed to be 'generic' it might still require some tweaking + * when porting to other boards/platform using same TI PCI Module + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#undef DEBUG + +#include <linux/kernel.h> /* pr_ wrappers */ +#include <linux/pci.h> /* PCI data structures */ +#include <asm/mach/pci.h> /* hw_pci */ +#include <linux/types.h> +#include <linux/interrupt.h> +#include <asm/irq.h> + +#include "pci.h" /* Platform spec */ + +/* + * PCI Register Offsets + */ +#define PCISTATSET 0x010 +#define PCISTATCLR 0x014 +#define PCIHINTSET 0x020 +#define PCIHINTCLR 0x024 +#define PCIBINTSET 0x030 +#define PCIBINTCLR 0x034 +#define PCIVENDEVMIR 0x100 +#define PCICSRMIR 0x104 +#define PCICLREVMIR 0x108 +#define PCICLINEMIR 0x10C +#define PCIBARMSK(n) (0x110 + (4 * n)) /* 6 Registers */ +#define PCISUBIDMIR 0x12C +#define PCICPBPTRMIR 0x134 +#define PCILGINTMIR 0x13C +#define PCISLVCNTL 0x180 +#define PCIBARTRL(n) (0x1C0 + (4 * n)) /* 6 Registers */ +#define PCIBARMIR(n) (0x1E0 + (4 * n)) /* 6 Registers */ +#define PCIMCFGDAT 0x300 +#define PCIMCFGADR 0x304 +#define PCIMCFGCMD 0x308 +#define PCIMSTCFG 0x310 +#define PCIADDSUB(n) (0x314 + (4 * n)) /* 32 Registers */ +#define PCIVENDEVPRG 0x394 +#define PCICLREVPRG 0x39C +#define PCISUBIDPRG 0x3A0 +#define PCIMAXLGPRG 0x3A4 +#define PCICFGDONE 0x3AC + +#define PCI_WAIT_FOR_RDY() pci_wait_for_rdy() + +#define CFG_PCIM_CMD_IO (1 << 2) +#define CFG_PCIM_CMD_CONFIG (0) +#define CFG_PCIM_CMD_READ (1 << 0) +#define CFG_PCIM_CMD_WRITE (0) + +/* Command Register Values */ +#define PCIM_INTA_DIS (1 << 10) /* Don't pass interrupt on INTA */ +#define PCIM_SERR_EN (1 << 8) /* Propagate error on SERR# */ +#define PCIM_PERR_EN (1 << 6) /* Consider parity error */ +#define PCIM_MEMWRINV_EN (1 << 4) /* Invalidate memory writes */ +#define PCIM_BUS_MASTER (1 << 2) /* Set as PCI master */ +#define PCIM_MEMACC_EN (1 << 1) /* Host as memory slave */ +#define PCIM_IOACC_EN (1 << 0) /* Host as IO device */ +#define PCIM_SPLCYC_EN (1 << 3) /* Could be used for sideband + signalling (non-critical) */ +/* Default value used for CSMIR register */ +#define CFG_PCIM_CSR_VAL (PCIM_SERR_EN | PCIM_MEMWRINV_EN \ + | PCIM_BUS_MASTER \ + | PCIM_MEMACC_EN \ + | PCIM_INTA_DIS) + +#define PCIM_MAX_LAT_SHIFT (24) +#define PCIM_MAX_LAT_MASK (0xFF << PCIM_MAX_LAT_SHIFT) +#define PCIM_MAX_LAT_VAL (CFG_PCIM_MAX_LAT << PCIM_MAX_LAT_SHIFT) + +#define PCIM_MIN_GRANT_SHIFT (16) +#define PCIM_MIN_GRANT_MASK (0xFF << PCIM_MIN_GRANT_SHIFT) +#define PCIM_MIN_GRANT_VAL (CFG_PCIM_MIN_GRANT \ + << PCIM_MIN_GRANT_SHIFT) + +/* Error mask for errors to check on CFG/IO */ +#define CFG_PCI_ERR_MASK ((0xf << 28) | (1 < 24)) + +/* Protect PCI accesses (config/io read/writes) */ +static DEFINE_SPINLOCK(ti_pci_lock); + +static inline void dump_pci_status(u32 status) +{ + pr_debug("PCI: Error Status:\nData Parity Error: %d, " + "System Error: %d\nMaster Abort: %d, " + "Target Abort: %d\nParity Report: %d\n", + ((status & (1 << 31)) != 0), ((status & (1 << 30)) != 0), + ((status & (1 << 29)) != 0), ((status & (1 << 28)) != 0), + ((status & (1 << 24)) != 0)); +} + +/* ti_pci_setup + * This function does Host controller configuration before bios starts PCI bus + * enumeration (scan). + */ +int ti_pci_setup(int nr, struct pci_sys_data *sys) +{ + int i, bar_en = 0; + struct resource *res; + + pr_info("PCI: Setting up Host Controller...\n"); + pr_debug("PCI: PCIADDSUB[0] @%#x\n", (u32)PCI_REGV(PCIADDSUB(0))); + + if (nr != 0) + return 0; + + /* Make specified Host windows visible over PCI bus. This will enable + * PCI Masters to perform DMA to Host System RAM (1:1 mapping of + * course!). + */ + for (i = 0; i < 6; i++) { + u32 size = bar_cfg[i].bar_window_size; + u32 addr = bar_cfg[i].bar_window_phys; + + if (size) { + /* Ensure size in 16 B to 2 GB range */ + if (size < 16) + size = 16; + else if (size > 0x80000000) + size = 0x80000000; + + if (size & (size - 1)) + size = 1 << fls(size); + + bar_en |= (1 << i); + + /* 1:1 from PCI -> Host */ + __raw_writel(addr, PCI_REGV(PCIBARTRL(i))); + + /* Setup PCI BAR Mirror register to bus address (= phys) + */ + __raw_writel(addr, PCI_REGV(PCIBARMIR(i))); + } + + /* Set writable bits - masking for size */ + __raw_writel(~(size-1), PCI_REGV(PCIBARMSK(i))); + } + + /* Enable applicable BAR windows in Slave control register and Set + * CFG_DONE to enable PCI access + */ + __raw_writel(((bar_en << 16) | 1), PCI_REGV(PCISLVCNTL)); + + /* IMPORTANT *** Change our class code from + * PCI_BASE_CLASS_SIGNAL_PROCESSING(PCI_CLASS_SP_OTHER = 0x1180) to + * PCI_CLASS_BRIDGE_HOST (0x0600) to prevent resource (BAR) assignment + * to us. The PCI probe will be happy with whatever original BAR + * settings we have! + * If at all we want to restore the default class-subclass values, the + * best place would be to set mirror register after returning from + * pci_common_init () [in dm6467_pci_init()]. + */ + __raw_writel(((__raw_readl(PCI_REGV(PCICLREVMIR)) & 0xffff) + | (PCI_CLASS_BRIDGE_HOST << 16)), + PCI_REGV(PCICLREVMIR)); + + /* + * Set PHYADDR <-> BUSADDR mapping for accessing 256MB PCI space + */ + + /* Using Direct 1:1 mapping of DMSoC <-> PCI memory space */ + for (i = 0; i < CFG_PCIM_WINDOW_CNT; i++) + __raw_writel((CFG_PCIM_MEM_START + (CFG_PCIM_WINDOW_SZ*i)), + PCI_REGV(PCIADDSUB(i))); + + + /* Setup as PCI master */ + pr_debug("PCI: Default PCICSRMIR = %x\n", + __raw_readl(PCI_REGV(PCICSRMIR))); + + __raw_writel((__raw_readl(PCI_REGV(PCICSRMIR)) | CFG_PCIM_CSR_VAL), + PCI_REGV(PCICSRMIR)); + + pr_debug("PCI: New PCICSRMIR = %x\n", + __raw_readl(PCI_REGV(PCICSRMIR))); + + __raw_writel(((__raw_readl(PCI_REGV(PCILGINTMIR)) + & ~PCIM_MAX_LAT_MASK & ~PCIM_MIN_GRANT_MASK) + | PCIM_MAX_LAT_VAL | PCIM_MIN_GRANT_VAL), + PCI_REGV(PCILGINTMIR)); + + /* + * Setup resources which will be used assign BARs to targets during + * scanning + */ + + /* Overwrite the resources which were set up by default by + * pcibios_init_hw + */ + res = kzalloc(sizeof(*res) * 2, GFP_KERNEL); + if (res == NULL) { + panic("PCI: resource structure allocation failed.\n"); + /* Not reached */ + return 0; + } + + res[0].start = PCIBIOS_MIN_IO; + res[0].end = PCIBIOS_MAX_IO; + res[0].name = "PCI I/O"; + res[0].flags = IORESOURCE_IO; + + res[1].start = CFG_PCIM_MEM_START; + res[1].end = CFG_PCIM_MEM_END; + res[1].name = "PCI Memory"; + res[1].flags = IORESOURCE_MEM; + + request_resource(&ioport_resource, &res[0]); + request_resource(&iomem_resource, &res[1]); + + sys->resource[0] = &res[0]; + sys->resource[1] = &res[1]; + sys->resource[2] = NULL; + + return 1; +} + +static inline u32 get_config_addr(u8 bus, u16 devfn, int where) +{ + u32 addr; + + /* Determine configuration cycle type depending upon the bus: + * - TYPE 0 for PCI bus directly connected to host + * - TYPE 1 for across bridge(s) + */ + if (bus == 0) { + /* TYPE 0 */ + addr = (1 << (11 + PCI_SLOT(devfn))) | (PCI_FUNC(devfn) << 8) + | (where & ~3); + } else { + /* TYPE 1 */ + addr = (bus << 16) | (PCI_SLOT(devfn) << 11) + | (PCI_FUNC(devfn) << 8) | (where & ~3) | 1; + } + + return addr; +} + +static inline int get_byte_enables(u32 addr, u32 size) +{ + /* + * Byte Enables (BE#[3:0]) will be generated taking into account AD[1:0] + * and size of transaction (1-4 Byte). Refer following table: + * PCI_ADDR[1:0] Starting Byte BE#[3:0] + * ----------------------------------------------------------------- + * 00 Byte 0 xxx0 (size = 1->4) + * 01 Byte 1 xx01 (size = 1->3) + * 10 Byte 2 x011 (size = 1->2) + * 11 Byte 3 0111 (size = 1) + * + * (Here 'x' can either be '0' (byte enabled) or '1' as required by + * 'size') + * + * As mentioned above, BE values are function of 'size' and AD[1:0] as + * well as size so we start by doing sanity check on combination of + * supplied parameters. We won't return any error as such, but any + * wrong combination will result into either all BE de-asserted or + * only/all possible BEs asserted. E.g., + * size=0 -> All BEs de-asserted + * size>4 -> Only possible BEs de-asserted + */ + + addr &= 3; + + pr_debug("PCI: AD[1:0]:size = %01x:%01x, Byte enables = %#x\n", + addr&3, size, ((((1 << size) - 1) << addr) & 0xf)); + + /* BE values are inverted for BE# */ + return (((1 << size) - 1) << addr) & 0xf; +} + +/* + * Returns: + * 0 - When READY bit is not set within timeout, else non-zero. + */ +static inline int pci_wait_for_rdy(void) +{ + int wait_cnt = CFG_PCI_READY_WAITCNT; + + /* Note : This function doesn't check aborts since the READY bit it set + * when bus aborts happen. Need to verify this is true for all kinds of + * PCI access errors. + */ + while (wait_cnt && !(__raw_readl(PCI_REGV(PCIMCFGCMD)) + & (1 << 31))) + wait_cnt--; + + + return (wait_cnt != 0); +} + +static inline int pci_err(void) +{ + u32 status = __raw_readl(PCI_REGV(PCICSRMIR)); + if (status & CFG_PCI_ERR_MASK) { + dump_pci_status(status); + return status >> 24; + } else { + return 0; + } +} + +static inline int pci_cfgio_read(u32 addr, int size, u32 *value, + int be, int access_type) +{ + unsigned long flags; + int ret_val = 0; + + spin_lock_irqsave(&ti_pci_lock, flags); + + /* Check of READY. Continue even if not READY as we will catch the error + * after operation. Same logic is applied for 'write' operation below... + */ + if (!PCI_WAIT_FOR_RDY()) + pr_warning("PCI: CFG/IO not ready." + "Might need tuning CFG_PCI_READY_WAITCNT value.\n"); + + /* Clear aborts */ + __raw_writel((__raw_readl(PCI_REGV(PCICSRMIR)) | (0xFF << 24)), + PCI_REGV(PCICSRMIR)); + + __raw_writel(addr, PCI_REGV(PCIMCFGADR)); + + __raw_writel(((1 << 31) | ((access_type == PCI_ACCESS_TYPE_CFG) + ? CFG_PCIM_CMD_CONFIG : CFG_PCIM_CMD_IO) + | CFG_PCIM_CMD_READ + | (be << 4)), PCI_REGV(PCIMCFGCMD)); + + /* Check for READY. */ + ret_val = !PCI_WAIT_FOR_RDY(); + + if (pci_err()) { + pr_debug("PCI: CFG/IO Read @%#x Failed.\n", addr); + *value = ~0; + /* Clear aborts */ + __raw_writel((__raw_readl(PCI_REGV(PCICSRMIR)) | (0xFF << 24)), + PCI_REGV(PCICSRMIR)); + ret_val = -1; + } else { + *value = __raw_readl(PCI_REGV(PCIMCFGDAT)); + pr_debug("PCI: Config/IO read done, value = %x\n", *value); + } + + spin_unlock_irqrestore(&ti_pci_lock, flags); + return ret_val; +} + +/* + * This is just a wrapper (exported) to provide BE value for I/O + */ +int ti_pci_io_read(u32 addr, int size, u32 *value) +{ + int ret_val = pci_cfgio_read(addr, size, value, + get_byte_enables(addr, size), + PCI_ACCESS_TYPE_IO); + *value >>= ((addr & 3)*8); + pr_debug("PCI: IO read @%#x = %#x\n", addr, *value); + return ret_val; +} +EXPORT_SYMBOL(ti_pci_io_read); + +static int ti_pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *value) +{ + u8 bus_num = bus->number; + + /* Sanity checks */ + if ((bus_num == 0) && (PCI_SLOT(devfn) >= PCI_MAX_SLOTS)) + return PCIBIOS_DEVICE_NOT_FOUND; + + pr_debug("PCI: Reading config[%x] for device %04x:%02x:%02x ...", + where, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn)); + + if (pci_cfgio_read(get_config_addr(bus_num, devfn, where), size, + value, get_byte_enables(where, size), + PCI_ACCESS_TYPE_CFG)) { + /* Ignoring other error codes (> 0) */ + pr_debug("failed."); + return PCIBIOS_DEVICE_NOT_FOUND; + } else { + *value >>= ((where & 3)*8); + pr_debug("done, value = %x\n", *value); + return PCIBIOS_SUCCESSFUL; + } +} + +static int pci_cfgio_write(u32 addr, int size, u32 value, + int be, int access_type) +{ + unsigned long flags; + int ret_val = 0; + + spin_lock_irqsave(&ti_pci_lock, flags); + + /* Check of READY */ + if (!PCI_WAIT_FOR_RDY()) + pr_warning("PCI: CFG/IO not ready." + "Might need tuning CFG_PCI_READY_WAITCNT value.\n"); + + /* Clear aborts */ + __raw_writel((__raw_readl(PCI_REGV(PCICSRMIR)) | (0xFF << 24)), + PCI_REGV(PCICSRMIR)); + + __raw_writel((value << ((addr & 3)*8)), PCI_REGV(PCIMCFGDAT)); + __raw_writel(addr, PCI_REGV(PCIMCFGADR)); + + __raw_writel((0x80000000 | ((access_type == PCI_ACCESS_TYPE_CFG) + ? CFG_PCIM_CMD_CONFIG : CFG_PCIM_CMD_IO) + | CFG_PCIM_CMD_WRITE | (be << 4)), + PCI_REGV(PCIMCFGCMD)); + + /* Check for READY. */ + ret_val = !PCI_WAIT_FOR_RDY(); + + if (pci_err()) { + pr_debug("PCI: CFG/IO Write @%#x Failed\n", addr); + /* Clear aborts */ + __raw_writel((__raw_readl(PCI_REGV(PCICSRMIR)) | (0xFF << 24)), + PCI_REGV(PCICSRMIR)); + ret_val = -1; + } else { + pr_debug("PCI: Config/IO write done.\n"); + } + + spin_unlock_irqrestore(&ti_pci_lock, flags); + return ret_val; +} + +/* + * This is just a wrapper (exported) to provide BE value for I/O + */ +int ti_pci_io_write(u32 addr, int size, u32 value) +{ + pr_debug("PCI: IO write @%#x = %#x\n", addr, value); + return pci_cfgio_write(addr, size, value, + get_byte_enables(addr, size), + PCI_ACCESS_TYPE_IO); +} +EXPORT_SYMBOL(ti_pci_io_write); + +static int ti_pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + u8 bus_num = bus->number; + + /* Sanity checks */ + if ((bus_num == 0) && (PCI_SLOT(devfn) >= PCI_MAX_SLOTS)) + return PCIBIOS_DEVICE_NOT_FOUND; + + pr_debug("PCI: Writing config[%x] = %x " + "for device %04x:%02x:%02x ...", where, value, + bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn)); + + if (pci_cfgio_write(get_config_addr(bus_num, devfn, where), + size, value, get_byte_enables(where, size), + PCI_ACCESS_TYPE_CFG)) { + /* Ignoring other error codes (> 0) */ + pr_debug("failed.\n"); + return PCIBIOS_DEVICE_NOT_FOUND; + } else { + pr_debug("done.\n"); + return PCIBIOS_SUCCESSFUL; + } +} + +static struct pci_ops ti_pci_ops = { + .read = ti_pci_read_config, + .write = ti_pci_write_config, +}; + +struct pci_bus *ti_pci_scan(int nr, struct pci_sys_data *sys) +{ + pr_info("PCI: Starting PCI scan...\n"); + if (nr == 0) + return pci_scan_bus(0, &ti_pci_ops, sys); + + return NULL; +} + diff --git a/arch/arm/mach-davinci/pci.h b/arch/arm/mach-davinci/pci.h new file mode 100755 index 0000000..c91b6f3 --- /dev/null +++ b/arch/arm/mach-davinci/pci.h @@ -0,0 +1,76 @@ +/* + * pci.h + * Description: + * PCI module specific types and definitions. + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ASM_ARCH_PCI_H +#define __ASM_ARCH_PCI_H + +#include <mach/hardware.h> + +/* + * Configuration options + */ + +/* Could be updated with optimum PCILGINTMIR values */ +#define CFG_PCIM_MAX_LAT 0xF +#define CFG_PCIM_MIN_GRANT 0xF + +#define CFG_PCI_INTSET_MASK ((0x3 << 1) | (0x3 << 5)) +#define CFG_PCI_INTCLR_MASK (CFG_PCI_INTSET_MASK) + +#define PCI_MAX_SLOTS (21) /* Only checked for bus=0 as + IDSEL can be provided + only within AD[31:11] */ + +#define CFG_PCIM_WINDOW_SZ (0x00800000) /* Master window size */ +#define CFG_PCIM_WINDOW_CNT (32) /* Number of windows */ +#define CFG_PCIM_MEM_START (PCIBIOS_MIN_MEM) /* PCI master memory map + base NOTE: We are using + 1:1 mapping, i.e., + 0x30000000 from DMSoC + side is translated as + 0x30000000 on PCI Bus */ +#define CFG_PCIM_MEM_END (CFG_PCIM_MEM_START \ + + (CFG_PCIM_WINDOW_SZ \ + * CFG_PCIM_WINDOW_CNT) \ + - 1) /* PCI master memory map size */ + + +/* The default value below can be substituted with proper timeout value which + * taking into account various PCI system parameters (buses, devices/slots, + * average latency to gain PCI bus access etc) to have sufficiant time till the + * master completes previous transaction. + */ +#define CFG_PCI_READY_WAITCNT 0xffff + +/* + * Provide the virtual address of PCI Backend register at specified offset. Uses + * SoC specific PCI register base for address calculation. + */ +#define PCI_REGV(reg) (IO_ADDRESS(DAVINCI_DM646X_PCI_CTL_BASE) + reg) + +struct pcihost_bar_cfg { + u32 bar_window_phys; + u32 bar_window_size; +}; + +/* Forward declarations */ +extern int __init ti_pci_setup(int nr, struct pci_sys_data *); +extern struct pci_bus * __init ti_pci_scan(int nr, struct pci_sys_data *); +extern struct pcihost_bar_cfg bar_cfg[6]; + +#endif /* __ASM_ARCH_PCI_H */ + -- 1.6.2.4 _______________________________________________ Davinci-linux-open-source mailing list Davinci-linux-open-source@linux.davincidsp.com http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source