diff options
Diffstat (limited to 'arch/mips/pci/ops-pmcmsp.c')
-rw-r--r-- | arch/mips/pci/ops-pmcmsp.c | 944 |
1 files changed, 0 insertions, 944 deletions
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c deleted file mode 100644 index ad5dd711c575..000000000000 --- a/arch/mips/pci/ops-pmcmsp.c +++ /dev/null @@ -1,944 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * PMC-Sierra MSP board specific pci_ops - * - * Copyright 2001 MontaVista Software Inc. - * Copyright 2005-2007 PMC-Sierra, Inc - * - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven <geert@linux-m68k.org> - */ - -#define PCI_COUNTERS 1 - -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/interrupt.h> - -#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS) -#include <linux/proc_fs.h> -#include <linux/seq_file.h> -#endif /* CONFIG_PROC_FS && PCI_COUNTERS */ - -#include <linux/kernel.h> -#include <linux/init.h> - -#include <asm/byteorder.h> -#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) -#include <asm/mipsmtregs.h> -#endif - -#include <msp_prom.h> -#include <msp_cic_int.h> -#include <msp_pci.h> -#include <msp_regs.h> -#include <msp_regops.h> - -#define PCI_ACCESS_READ 0 -#define PCI_ACCESS_WRITE 1 - -#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS) -static char proc_init; -extern struct proc_dir_entry *proc_bus_pci_dir; -unsigned int pci_int_count[32]; - -static void pci_proc_init(void); - -/***************************************************************************** - * - * FUNCTION: show_msp_pci_counts - * _________________________________________________________________________ - * - * DESCRIPTION: Prints the count of how many times each PCI - * interrupt has asserted. Can be invoked by the - * /proc filesystem. - * - * INPUTS: m - synthetic file construction data - * v - iterator - * - * RETURNS: 0 or error - * - ****************************************************************************/ -static int show_msp_pci_counts(struct seq_file *m, void *v) -{ - int i; - unsigned int intcount, total = 0; - - for (i = 0; i < 32; ++i) { - intcount = pci_int_count[i]; - if (intcount != 0) { - seq_printf(m, "[%d] = %u\n", i, intcount); - total += intcount; - } - } - - seq_printf(m, "total = %u\n", total); - return 0; -} - -/***************************************************************************** - * - * FUNCTION: gen_pci_cfg_wr_show - * _________________________________________________________________________ - * - * DESCRIPTION: Generates a configuration write cycle for debug purposes. - * The IDSEL line asserted and location and data written are - * immaterial. Just want to be able to prove that a - * configuration write can be correctly generated on the - * PCI bus. Intent is that this function by invocable from - * the /proc filesystem. - * - * INPUTS: m - synthetic file construction data - * v - iterator - * - * RETURNS: 0 or error - * - ****************************************************************************/ -static int gen_pci_cfg_wr_show(struct seq_file *m, void *v) -{ - unsigned char where = 0; /* Write to static Device/Vendor ID */ - unsigned char bus_num = 0; /* Bus 0 */ - unsigned char dev_fn = 0xF; /* Arbitrary device number */ - u32 wr_data = 0xFF00AA00; /* Arbitrary data */ - struct msp_pci_regs *preg = (void *)PCI_BASE_REG; - unsigned long value; - int intr; - - seq_puts(m, "PMC MSP PCI: Beginning\n"); - - if (proc_init == 0) { - pci_proc_init(); - proc_init = ~0; - } - - seq_puts(m, "PMC MSP PCI: Before Cfg Wr\n"); - - /* - * Generate PCI Configuration Write Cycle - */ - - /* Clear cause register bits */ - preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F); - - /* Setup address that is to appear on PCI bus */ - preg->config_addr = BPCI_CFGADDR_ENABLE | - (bus_num << BPCI_CFGADDR_BUSNUM_SHF) | - (dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) | - (where & 0xFC); - - value = cpu_to_le32(wr_data); - - /* Launch the PCI configuration write cycle */ - *PCI_CONFIG_SPACE_REG = value; - - /* - * Check if the PCI configuration cycle (rd or wr) succeeded, by - * checking the status bits for errors like master or target abort. - */ - intr = preg->if_status; - - seq_puts(m, "PMC MSP PCI: After Cfg Wr\n"); - return 0; -} - -/***************************************************************************** - * - * FUNCTION: pci_proc_init - * _________________________________________________________________________ - * - * DESCRIPTION: Create entries in the /proc filesystem for debug access. - * - * INPUTS: none - * - * OUTPUTS: none - * - * RETURNS: none - * - ****************************************************************************/ -static void pci_proc_init(void) -{ - proc_create_single("pmc_msp_pci_rd_cnt", 0, NULL, show_msp_pci_counts); - proc_create_single("pmc_msp_pci_cfg_wr", 0, NULL, gen_pci_cfg_wr_show); -} -#endif /* CONFIG_PROC_FS && PCI_COUNTERS */ - -/***************************************************************************** - * - * STRUCT: pci_io_resource - * _________________________________________________________________________ - * - * DESCRIPTION: Defines the address range that pciauto() will use to - * assign to the I/O BARs of PCI devices. - * - * Use the start and end addresses of the MSP7120 PCI Host - * Controller I/O space, in the form that they appear on the - * PCI bus AFTER MSP7120 has performed address translation. - * - * For I/O accesses, MSP7120 ignores OATRAN and maps I/O - * accesses into the bottom 0xFFF region of address space, - * so that is the range to put into the pci_io_resource - * struct. - * - * In MSP4200, the start address was 0x04 instead of the - * expected 0x00. Will just assume there was a good reason - * for this! - * - * NOTES: Linux, by default, will assign I/O space to the lowest - * region of address space. Since MSP7120 and Linux, - * by default, have no offset in between how they map, the - * io_offset element of pci_controller struct should be set - * to zero. - * ELEMENTS: - * name - String used for a meaningful name. - * - * start - Start address of MSP7120's I/O space, as MSP7120 presents - * the address on the PCI bus. - * - * end - End address of MSP7120's I/O space, as MSP7120 presents - * the address on the PCI bus. - * - * flags - Attributes indicating the type of resource. In this case, - * indicate I/O space. - * - ****************************************************************************/ -static struct resource pci_io_resource = { - .name = "pci IO space", - .start = 0x04, - .end = 0x0FFF, - .flags = IORESOURCE_IO /* I/O space */ -}; - -/***************************************************************************** - * - * STRUCT: pci_mem_resource - * _________________________________________________________________________ - * - * DESCRIPTION: Defines the address range that pciauto() will use to - * assign to the memory BARs of PCI devices. - * - * The .start and .end values are dependent upon how address - * translation is performed by the OATRAN regiser. - * - * The values to use for .start and .end are the values - * in the form they appear on the PCI bus AFTER MSP7120 has - * performed OATRAN address translation. - * - * ELEMENTS: - * name - String used for a meaningful name. - * - * start - Start address of MSP7120's memory space, as MSP7120 presents - * the address on the PCI bus. - * - * end - End address of MSP7120's memory space, as MSP7120 presents - * the address on the PCI bus. - * - * flags - Attributes indicating the type of resource. In this case, - * indicate memory space. - * - ****************************************************************************/ -static struct resource pci_mem_resource = { - .name = "pci memory space", - .start = MSP_PCI_SPACE_BASE, - .end = MSP_PCI_SPACE_END, - .flags = IORESOURCE_MEM /* memory space */ -}; - -/***************************************************************************** - * - * FUNCTION: bpci_interrupt - * _________________________________________________________________________ - * - * DESCRIPTION: PCI status interrupt handler. Updates the count of how - * many times each status bit has been set, then clears - * the status bits. If the appropriate macros are defined, - * these counts can be viewed via the /proc filesystem. - * - * INPUTS: irq - unused - * dev_id - unused - * pt_regs - unused - * - * OUTPUTS: none - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * - ****************************************************************************/ -static irqreturn_t bpci_interrupt(int irq, void *dev_id) -{ - struct msp_pci_regs *preg = (void *)PCI_BASE_REG; - unsigned int stat = preg->if_status; - -#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS) - int i; - for (i = 0; i < 32; ++i) { - if ((1 << i) & stat) - ++pci_int_count[i]; - } -#endif /* PROC_FS && PCI_COUNTERS */ - - /* printk("PCI ISR: Status=%08X\n", stat); */ - - /* write to clear all asserted interrupts */ - preg->if_status = stat; - - return IRQ_HANDLED; -} - -/***************************************************************************** - * - * FUNCTION: msp_pcibios_config_access - * _________________________________________________________________________ - * - * DESCRIPTION: Performs a PCI configuration access (rd or wr), then - * checks that the access succeeded by querying MSP7120's - * PCI status bits. - * - * INPUTS: - * access_type - kind of PCI configuration cycle to perform - * (read or write). Legal values are - * PCI_ACCESS_WRITE and PCI_ACCESS_READ. - * - * bus - pointer to the bus number of the device to - * be targeted for the configuration cycle. - * The only element of the pci_bus structure - * used is bus->number. This argument determines - * if the configuration access will be Type 0 or - * Type 1. Since MSP7120 assumes itself to be the - * PCI Host, any non-zero bus->number generates - * a Type 1 access. - * - * devfn - this is an 8-bit field. The lower three bits - * specify the function number of the device to - * be targeted for the configuration cycle, with - * all three-bit combinations being legal. The - * upper five bits specify the device number, - * with legal values being 10 to 31. - * - * where - address within the Configuration Header - * space to access. - * - * data - for write accesses, contains the data to - * write. - * - * OUTPUTS: - * data - for read accesses, contains the value read. - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - access failure - * - ****************************************************************************/ -int msp_pcibios_config_access(unsigned char access_type, - struct pci_bus *bus, - unsigned int devfn, - unsigned char where, - u32 *data) -{ - struct msp_pci_regs *preg = (void *)PCI_BASE_REG; - unsigned char bus_num = bus->number; - unsigned char dev_fn = (unsigned char)devfn; - unsigned long intr; - unsigned long value; - static char pciirqflag; - int ret; -#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) - unsigned int vpe_status; -#endif - -#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS) - if (proc_init == 0) { - pci_proc_init(); - proc_init = ~0; - } -#endif /* CONFIG_PROC_FS && PCI_COUNTERS */ - - /* - * Just the first time this function invokes, allocate - * an interrupt line for PCI host status interrupts. The - * allocation assigns an interrupt handler to the interrupt. - */ - if (pciirqflag == 0) { - ret = request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */ - bpci_interrupt, - IRQF_SHARED, - "PMC MSP PCI Host", - preg); - if (ret != 0) - return ret; - pciirqflag = ~0; - } - -#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) - vpe_status = dvpe(); -#endif - - /* - * Clear PCI cause register bits. - * - * In Polo, the PCI Host had a dedicated DMA called the - * Block Copy (not to be confused with the general purpose Block - * Copy Engine block). There appear to have been special interrupts - * for this Block Copy, called Block Copy 0 Fault (BC0F) and - * Block Copy 1 Fault (BC1F). MSP4200 and MSP7120 don't have this - * dedicated Block Copy block, so these two interrupts are now - * marked reserved. In case the Block Copy is resurrected in a - * future design, maintain the code that treats these two interrupts - * specially. - * - * Write to clear all interrupts in the PCI status register, aside - * from BC0F and BC1F. - */ - preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F); - - /* Setup address that is to appear on PCI bus */ - preg->config_addr = BPCI_CFGADDR_ENABLE | - (bus_num << BPCI_CFGADDR_BUSNUM_SHF) | - (dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) | - (where & 0xFC); - - /* IF access is a PCI configuration write */ - if (access_type == PCI_ACCESS_WRITE) { - value = cpu_to_le32(*data); - *PCI_CONFIG_SPACE_REG = value; - } else { - /* ELSE access is a PCI configuration read */ - value = le32_to_cpu(*PCI_CONFIG_SPACE_REG); - *data = value; - } - - /* - * Check if the PCI configuration cycle (rd or wr) succeeded, by - * checking the status bits for errors like master or target abort. - */ - intr = preg->if_status; - - /* Clear config access */ - preg->config_addr = 0; - - /* IF error occurred */ - if (intr & ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F)) { - /* Clear status bits */ - preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F); - -#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) - evpe(vpe_status); -#endif - - return -1; - } - -#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) - evpe(vpe_status); -#endif - - return PCIBIOS_SUCCESSFUL; -} - -/***************************************************************************** - * - * FUNCTION: msp_pcibios_read_config_byte - * _________________________________________________________________________ - * - * DESCRIPTION: Read a byte from PCI configuration address spac - * Since the hardware can't address 8 bit chunks - * directly, read a 32-bit chunk, then mask off extraneous - * bits. - * - * INPUTS bus - structure containing attributes for the PCI bus - * that the read is destined for. - * devfn - device/function combination that the read is - * destined for. - * where - register within the Configuration Header space - * to access. - * - * OUTPUTS val - read data - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - read access failure - * - ****************************************************************************/ -static int -msp_pcibios_read_config_byte(struct pci_bus *bus, - unsigned int devfn, - int where, - u32 *val) -{ - u32 data = 0; - - /* - * If the config access did not complete normally (e.g., underwent - * master abort) do the PCI compliant thing, which is to supply an - * all ones value. - */ - if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) { - *val = 0xFFFFFFFF; - return -1; - } - - *val = (data >> ((where & 3) << 3)) & 0x0ff; - - return PCIBIOS_SUCCESSFUL; -} - -/***************************************************************************** - * - * FUNCTION: msp_pcibios_read_config_word - * _________________________________________________________________________ - * - * DESCRIPTION: Read a word (16 bits) from PCI configuration address space. - * Since the hardware can't address 16 bit chunks - * directly, read a 32-bit chunk, then mask off extraneous - * bits. - * - * INPUTS bus - structure containing attributes for the PCI bus - * that the read is destined for. - * devfn - device/function combination that the read is - * destined for. - * where - register within the Configuration Header space - * to access. - * - * OUTPUTS val - read data - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * PCIBIOS_BAD_REGISTER_NUMBER - bad register address - * -1 - read access failure - * - ****************************************************************************/ -static int -msp_pcibios_read_config_word(struct pci_bus *bus, - unsigned int devfn, - int where, - u32 *val) -{ - u32 data = 0; - - /* if (where & 1) */ /* Commented out non-compliant code. - * Should allow word access to configuration - * registers, with only exception being when - * the word access would wrap around into - * the next dword. - */ - if ((where & 3) == 3) { - *val = 0xFFFFFFFF; - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - /* - * If the config access did not complete normally (e.g., underwent - * master abort) do the PCI compliant thing, which is to supply an - * all ones value. - */ - if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) { - *val = 0xFFFFFFFF; - return -1; - } - - *val = (data >> ((where & 3) << 3)) & 0x0ffff; - - return PCIBIOS_SUCCESSFUL; -} - -/***************************************************************************** - * - * FUNCTION: msp_pcibios_read_config_dword - * _________________________________________________________________________ - * - * DESCRIPTION: Read a double word (32 bits) from PCI configuration - * address space. - * - * INPUTS bus - structure containing attributes for the PCI bus - * that the read is destined for. - * devfn - device/function combination that the read is - * destined for. - * where - register within the Configuration Header space - * to access. - * - * OUTPUTS val - read data - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * PCIBIOS_BAD_REGISTER_NUMBER - bad register address - * -1 - read access failure - * - ****************************************************************************/ -static int -msp_pcibios_read_config_dword(struct pci_bus *bus, - unsigned int devfn, - int where, - u32 *val) -{ - u32 data = 0; - - /* Address must be dword aligned. */ - if (where & 3) { - *val = 0xFFFFFFFF; - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - /* - * If the config access did not complete normally (e.g., underwent - * master abort) do the PCI compliant thing, which is to supply an - * all ones value. - */ - if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) { - *val = 0xFFFFFFFF; - return -1; - } - - *val = data; - - return PCIBIOS_SUCCESSFUL; -} - -/***************************************************************************** - * - * FUNCTION: msp_pcibios_write_config_byte - * _________________________________________________________________________ - * - * DESCRIPTION: Write a byte to PCI configuration address space. - * Since the hardware can't address 8 bit chunks - * directly, a read-modify-write is performed. - * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * val - value to write - * - * OUTPUTS none - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - write access failure - * - ****************************************************************************/ -static int -msp_pcibios_write_config_byte(struct pci_bus *bus, - unsigned int devfn, - int where, - u8 val) -{ - u32 data = 0; - - /* read config space */ - if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) - return -1; - - /* modify the byte within the dword */ - data = (data & ~(0xff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - - /* write back the full dword */ - if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, - where, &data)) - return -1; - - return PCIBIOS_SUCCESSFUL; -} - -/***************************************************************************** - * - * FUNCTION: msp_pcibios_write_config_word - * _________________________________________________________________________ - * - * DESCRIPTION: Write a word (16-bits) to PCI configuration address space. - * Since the hardware can't address 16 bit chunks - * directly, a read-modify-write is performed. - * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * val - value to write - * - * OUTPUTS none - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * PCIBIOS_BAD_REGISTER_NUMBER - bad register address - * -1 - write access failure - * - ****************************************************************************/ -static int -msp_pcibios_write_config_word(struct pci_bus *bus, - unsigned int devfn, - int where, - u16 val) -{ - u32 data = 0; - - /* Fixed non-compliance: if (where & 1) */ - if ((where & 3) == 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - /* read config space */ - if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) - return -1; - - /* modify the word within the dword */ - data = (data & ~(0xffff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - - /* write back the full dword */ - if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, - where, &data)) - return -1; - - return PCIBIOS_SUCCESSFUL; -} - -/***************************************************************************** - * - * FUNCTION: msp_pcibios_write_config_dword - * _________________________________________________________________________ - * - * DESCRIPTION: Write a double word (32-bits) to PCI configuration address - * space. - * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * val - value to write - * - * OUTPUTS none - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * PCIBIOS_BAD_REGISTER_NUMBER - bad register address - * -1 - write access failure - * - ****************************************************************************/ -static int -msp_pcibios_write_config_dword(struct pci_bus *bus, - unsigned int devfn, - int where, - u32 val) -{ - /* check that address is dword aligned */ - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - /* perform write */ - if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, - where, &val)) - return -1; - - return PCIBIOS_SUCCESSFUL; -} - -/***************************************************************************** - * - * FUNCTION: msp_pcibios_read_config - * _________________________________________________________________________ - * - * DESCRIPTION: Interface the PCI configuration read request with - * the appropriate function, based on how many bytes - * the read request is. - * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * size - in units of bytes, should be 1, 2, or 4. - * - * OUTPUTS val - value read, with any extraneous bytes masked - * to zero. - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - failure - * - ****************************************************************************/ -int -msp_pcibios_read_config(struct pci_bus *bus, - unsigned int devfn, - int where, - int size, - u32 *val) -{ - if (size == 1) { - if (msp_pcibios_read_config_byte(bus, devfn, where, val)) { - return -1; - } - } else if (size == 2) { - if (msp_pcibios_read_config_word(bus, devfn, where, val)) { - return -1; - } - } else if (size == 4) { - if (msp_pcibios_read_config_dword(bus, devfn, where, val)) { - return -1; - } - } else { - *val = 0xFFFFFFFF; - return -1; - } - - return PCIBIOS_SUCCESSFUL; -} - -/***************************************************************************** - * - * FUNCTION: msp_pcibios_write_config - * _________________________________________________________________________ - * - * DESCRIPTION: Interface the PCI configuration write request with - * the appropriate function, based on how many bytes - * the read request is. - * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * size - in units of bytes, should be 1, 2, or 4. - * val - value to write - * - * OUTPUTS: none - * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - failure - * - ****************************************************************************/ -int -msp_pcibios_write_config(struct pci_bus *bus, - unsigned int devfn, - int where, - int size, - u32 val) -{ - if (size == 1) { - if (msp_pcibios_write_config_byte(bus, devfn, - where, (u8)(0xFF & val))) { - return -1; - } - } else if (size == 2) { - if (msp_pcibios_write_config_word(bus, devfn, - where, (u16)(0xFFFF & val))) { - return -1; - } - } else if (size == 4) { - if (msp_pcibios_write_config_dword(bus, devfn, where, val)) { - return -1; - } - } else { - return -1; - } - - return PCIBIOS_SUCCESSFUL; -} - -/***************************************************************************** - * - * STRUCTURE: msp_pci_ops - * _________________________________________________________________________ - * - * DESCRIPTION: structure to abstract the hardware specific PCI - * configuration accesses. - * - * ELEMENTS: - * read - function for Linux to generate PCI Configuration reads. - * write - function for Linux to generate PCI Configuration writes. - * - ****************************************************************************/ -struct pci_ops msp_pci_ops = { - .read = msp_pcibios_read_config, - .write = msp_pcibios_write_config -}; - -/***************************************************************************** - * - * STRUCTURE: msp_pci_controller - * _________________________________________________________________________ - * - * Describes the attributes of the MSP7120 PCI Host Controller - * - * ELEMENTS: - * pci_ops - abstracts the hardware specific PCI configuration - * accesses. - * - * mem_resource - address range pciauto() uses to assign to PCI device - * memory BARs. - * - * mem_offset - offset between how MSP7120 outbound PCI memory - * transaction addresses appear on the PCI bus and how Linux - * wants to configure memory BARs of the PCI devices. - * MSP7120 does nothing funky, so just set to zero. - * - * io_resource - address range pciauto() uses to assign to PCI device - * I/O BARs. - * - * io_offset - offset between how MSP7120 outbound PCI I/O - * transaction addresses appear on the PCI bus and how - * Linux defaults to configure I/O BARs of the PCI devices. - * MSP7120 maps outbound I/O accesses into the bottom - * bottom 4K of PCI address space (and ignores OATRAN). - * Since the Linux default is to configure I/O BARs to the - * bottom 4K, no special offset is needed. Just set to zero. - * - ****************************************************************************/ -static struct pci_controller msp_pci_controller = { - .pci_ops = &msp_pci_ops, - .mem_resource = &pci_mem_resource, - .mem_offset = 0, - .io_map_base = MSP_PCI_IOSPACE_BASE, - .io_resource = &pci_io_resource, - .io_offset = 0 -}; - -/***************************************************************************** - * - * FUNCTION: msp_pci_init - * _________________________________________________________________________ - * - * DESCRIPTION: Initialize the PCI Host Controller and register it with - * Linux so Linux can seize control of the PCI bus. - * - ****************************************************************************/ -void __init msp_pci_init(void) -{ - struct msp_pci_regs *preg = (void *)PCI_BASE_REG; - u32 id; - - /* Extract Device ID */ - id = read_reg32(PCI_JTAG_DEVID_REG, 0xFFFF) >> 12; - - /* Check if JTAG ID identifies MSP7120 */ - if (!MSP_HAS_PCI(id)) { - printk(KERN_WARNING "PCI: No PCI; id reads as %x\n", id); - goto no_pci; - } - - /* - * Enable flushing of the PCI-SDRAM queue upon a read - * of the SDRAM's Memory Configuration Register. - */ - *(unsigned long *)QFLUSH_REG_1 = 3; - - /* Configure PCI Host Controller. */ - preg->if_status = ~0; /* Clear cause register bits */ - preg->config_addr = 0; /* Clear config access */ - preg->oatran = MSP_PCI_OATRAN; /* PCI outbound addr translation */ - preg->if_mask = 0xF8BF87C0; /* Enable all PCI status interrupts */ - - /* configure so inb(), outb(), and family are functional */ - set_io_port_base(MSP_PCI_IOSPACE_BASE); - - /* Tell Linux the details of the MSP7120 PCI Host Controller */ - register_pci_controller(&msp_pci_controller); - - return; - -no_pci: - /* Disable PCI channel */ - printk(KERN_WARNING "PCI: no host PCI bus detected\n"); -} |