/*1* PMC-Sierra MSP board specific pci_ops2*3* Copyright 2001 MontaVista Software Inc.4* Copyright 2005-2007 PMC-Sierra, Inc5*6* Author: Jun Sun, [email protected] or [email protected]7*8* Much of the code is derived from the original DDB5074 port by9* Geert Uytterhoeven <[email protected]>10*11* This program is free software; you can redistribute it and/or modify it12* under the terms of the GNU General Public License as published by the13* Free Software Foundation; either version 2 of the License, or (at your14* option) any later version.15*16*/1718#define PCI_COUNTERS 11920#include <linux/types.h>21#include <linux/pci.h>22#include <linux/interrupt.h>2324#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)25#include <linux/proc_fs.h>26#include <linux/seq_file.h>27#endif /* CONFIG_PROC_FS && PCI_COUNTERS */2829#include <linux/kernel.h>30#include <linux/init.h>3132#include <asm/byteorder.h>33#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)34#include <asm/mipsmtregs.h>35#endif3637#include <msp_prom.h>38#include <msp_cic_int.h>39#include <msp_pci.h>40#include <msp_regs.h>41#include <msp_regops.h>4243#define PCI_ACCESS_READ 044#define PCI_ACCESS_WRITE 14546#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)47static char proc_init;48extern struct proc_dir_entry *proc_bus_pci_dir;49unsigned int pci_int_count[32];5051static void pci_proc_init(void);5253/*****************************************************************************54*55* FUNCTION: read_msp_pci_counts56* _________________________________________________________________________57*58* DESCRIPTION: Prints the count of how many times each PCI59* interrupt has asserted. Can be invoked by the60* /proc filesystem.61*62* INPUTS: page - part of STDOUT calculation63* off - part of STDOUT calculation64* count - part of STDOUT calculation65* data - unused66*67* OUTPUTS: start - new start location68* eof - end of file pointer69*70* RETURNS: len - STDOUT length71*72****************************************************************************/73static int read_msp_pci_counts(char *page, char **start, off_t off,74int count, int *eof, void *data)75{76int i;77int len = 0;78unsigned int intcount, total = 0;7980for (i = 0; i < 32; ++i) {81intcount = pci_int_count[i];82if (intcount != 0) {83len += sprintf(page + len, "[%d] = %u\n", i, intcount);84total += intcount;85}86}8788len += sprintf(page + len, "total = %u\n", total);89if (len <= off+count)90*eof = 1;9192*start = page + off;93len -= off;94if (len > count)95len = count;96if (len < 0)97len = 0;9899return len;100}101102/*****************************************************************************103*104* FUNCTION: gen_pci_cfg_wr105* _________________________________________________________________________106*107* DESCRIPTION: Generates a configuration write cycle for debug purposes.108* The IDSEL line asserted and location and data written are109* immaterial. Just want to be able to prove that a110* configuration write can be correctly generated on the111* PCI bus. Intent is that this function by invocable from112* the /proc filesystem.113*114* INPUTS: page - part of STDOUT calculation115* off - part of STDOUT calculation116* count - part of STDOUT calculation117* data - unused118*119* OUTPUTS: start - new start location120* eof - end of file pointer121*122* RETURNS: len - STDOUT length123*124****************************************************************************/125static int gen_pci_cfg_wr(char *page, char **start, off_t off,126int count, int *eof, void *data)127{128unsigned char where = 0; /* Write to static Device/Vendor ID */129unsigned char bus_num = 0; /* Bus 0 */130unsigned char dev_fn = 0xF; /* Arbitrary device number */131u32 wr_data = 0xFF00AA00; /* Arbitrary data */132struct msp_pci_regs *preg = (void *)PCI_BASE_REG;133int len = 0;134unsigned long value;135int intr;136137len += sprintf(page + len, "PMC MSP PCI: Beginning\n");138139if (proc_init == 0) {140pci_proc_init();141proc_init = ~0;142}143144len += sprintf(page + len, "PMC MSP PCI: Before Cfg Wr\n");145146/*147* Generate PCI Configuration Write Cycle148*/149150/* Clear cause register bits */151preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);152153/* Setup address that is to appear on PCI bus */154preg->config_addr = BPCI_CFGADDR_ENABLE |155(bus_num << BPCI_CFGADDR_BUSNUM_SHF) |156(dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |157(where & 0xFC);158159value = cpu_to_le32(wr_data);160161/* Launch the PCI configuration write cycle */162*PCI_CONFIG_SPACE_REG = value;163164/*165* Check if the PCI configuration cycle (rd or wr) succeeded, by166* checking the status bits for errors like master or target abort.167*/168intr = preg->if_status;169170len += sprintf(page + len, "PMC MSP PCI: After Cfg Wr\n");171172/* Handle STDOUT calculations */173if (len <= off+count)174*eof = 1;175*start = page + off;176len -= off;177if (len > count)178len = count;179if (len < 0)180len = 0;181182return len;183}184185/*****************************************************************************186*187* FUNCTION: pci_proc_init188* _________________________________________________________________________189*190* DESCRIPTION: Create entries in the /proc filesystem for debug access.191*192* INPUTS: none193*194* OUTPUTS: none195*196* RETURNS: none197*198****************************************************************************/199static void pci_proc_init(void)200{201create_proc_read_entry("pmc_msp_pci_rd_cnt", 0, NULL,202read_msp_pci_counts, NULL);203create_proc_read_entry("pmc_msp_pci_cfg_wr", 0, NULL,204gen_pci_cfg_wr, NULL);205}206#endif /* CONFIG_PROC_FS && PCI_COUNTERS */207208static DEFINE_SPINLOCK(bpci_lock);209210/*****************************************************************************211*212* STRUCT: pci_io_resource213* _________________________________________________________________________214*215* DESCRIPTION: Defines the address range that pciauto() will use to216* assign to the I/O BARs of PCI devices.217*218* Use the start and end addresses of the MSP7120 PCI Host219* Controller I/O space, in the form that they appear on the220* PCI bus AFTER MSP7120 has performed address translation.221*222* For I/O accesses, MSP7120 ignores OATRAN and maps I/O223* accesses into the bottom 0xFFF region of address space,224* so that is the range to put into the pci_io_resource225* struct.226*227* In MSP4200, the start address was 0x04 instead of the228* expected 0x00. Will just assume there was a good reason229* for this!230*231* NOTES: Linux, by default, will assign I/O space to the lowest232* region of address space. Since MSP7120 and Linux,233* by default, have no offset in between how they map, the234* io_offset element of pci_controller struct should be set235* to zero.236* ELEMENTS:237* name - String used for a meaningful name.238*239* start - Start address of MSP7120's I/O space, as MSP7120 presents240* the address on the PCI bus.241*242* end - End address of MSP7120's I/O space, as MSP7120 presents243* the address on the PCI bus.244*245* flags - Attributes indicating the type of resource. In this case,246* indicate I/O space.247*248****************************************************************************/249static struct resource pci_io_resource = {250.name = "pci IO space",251.start = 0x04,252.end = 0x0FFF,253.flags = IORESOURCE_IO /* I/O space */254};255256/*****************************************************************************257*258* STRUCT: pci_mem_resource259* _________________________________________________________________________260*261* DESCRIPTION: Defines the address range that pciauto() will use to262* assign to the memory BARs of PCI devices.263*264* The .start and .end values are dependent upon how address265* translation is performed by the OATRAN regiser.266*267* The values to use for .start and .end are the values268* in the form they appear on the PCI bus AFTER MSP7120 has269* performed OATRAN address translation.270*271* ELEMENTS:272* name - String used for a meaningful name.273*274* start - Start address of MSP7120's memory space, as MSP7120 presents275* the address on the PCI bus.276*277* end - End address of MSP7120's memory space, as MSP7120 presents278* the address on the PCI bus.279*280* flags - Attributes indicating the type of resource. In this case,281* indicate memory space.282*283****************************************************************************/284static struct resource pci_mem_resource = {285.name = "pci memory space",286.start = MSP_PCI_SPACE_BASE,287.end = MSP_PCI_SPACE_END,288.flags = IORESOURCE_MEM /* memory space */289};290291/*****************************************************************************292*293* FUNCTION: bpci_interrupt294* _________________________________________________________________________295*296* DESCRIPTION: PCI status interrupt handler. Updates the count of how297* many times each status bit has been set, then clears298* the status bits. If the appropriate macros are defined,299* these counts can be viewed via the /proc filesystem.300*301* INPUTS: irq - unused302* dev_id - unused303* pt_regs - unused304*305* OUTPUTS: none306*307* RETURNS: PCIBIOS_SUCCESSFUL - success308*309****************************************************************************/310static irqreturn_t bpci_interrupt(int irq, void *dev_id)311{312struct msp_pci_regs *preg = (void *)PCI_BASE_REG;313unsigned int stat = preg->if_status;314315#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)316int i;317for (i = 0; i < 32; ++i) {318if ((1 << i) & stat)319++pci_int_count[i];320}321#endif /* PROC_FS && PCI_COUNTERS */322323/* printk("PCI ISR: Status=%08X\n", stat); */324325/* write to clear all asserted interrupts */326preg->if_status = stat;327328return IRQ_HANDLED;329}330331/*****************************************************************************332*333* FUNCTION: msp_pcibios_config_access334* _________________________________________________________________________335*336* DESCRIPTION: Performs a PCI configuration access (rd or wr), then337* checks that the access succeeded by querying MSP7120's338* PCI status bits.339*340* INPUTS:341* access_type - kind of PCI configuration cycle to perform342* (read or write). Legal values are343* PCI_ACCESS_WRITE and PCI_ACCESS_READ.344*345* bus - pointer to the bus number of the device to346* be targeted for the configuration cycle.347* The only element of the pci_bus structure348* used is bus->number. This argument determines349* if the configuration access will be Type 0 or350* Type 1. Since MSP7120 assumes itself to be the351* PCI Host, any non-zero bus->number generates352* a Type 1 access.353*354* devfn - this is an 8-bit field. The lower three bits355* specify the function number of the device to356* be targeted for the configuration cycle, with357* all three-bit combinations being legal. The358* upper five bits specify the device number,359* with legal values being 10 to 31.360*361* where - address within the Configuration Header362* space to access.363*364* data - for write accesses, contains the data to365* write.366*367* OUTPUTS:368* data - for read accesses, contains the value read.369*370* RETURNS: PCIBIOS_SUCCESSFUL - success371* -1 - access failure372*373****************************************************************************/374int msp_pcibios_config_access(unsigned char access_type,375struct pci_bus *bus,376unsigned int devfn,377unsigned char where,378u32 *data)379{380struct msp_pci_regs *preg = (void *)PCI_BASE_REG;381unsigned char bus_num = bus->number;382unsigned char dev_fn = (unsigned char)devfn;383unsigned long flags;384unsigned long intr;385unsigned long value;386static char pciirqflag;387int ret;388#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)389unsigned int vpe_status;390#endif391392#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)393if (proc_init == 0) {394pci_proc_init();395proc_init = ~0;396}397#endif /* CONFIG_PROC_FS && PCI_COUNTERS */398399/*400* Just the first time this function invokes, allocate401* an interrupt line for PCI host status interrupts. The402* allocation assigns an interrupt handler to the interrupt.403*/404if (pciirqflag == 0) {405ret = request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */406bpci_interrupt,407IRQF_SHARED | IRQF_DISABLED,408"PMC MSP PCI Host",409preg);410if (ret != 0)411return ret;412pciirqflag = ~0;413}414415#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)416local_irq_save(flags);417vpe_status = dvpe();418#else419spin_lock_irqsave(&bpci_lock, flags);420#endif421422/*423* Clear PCI cause register bits.424*425* In Polo, the PCI Host had a dedicated DMA called the426* Block Copy (not to be confused with the general purpose Block427* Copy Engine block). There appear to have been special interrupts428* for this Block Copy, called Block Copy 0 Fault (BC0F) and429* Block Copy 1 Fault (BC1F). MSP4200 and MSP7120 don't have this430* dedicated Block Copy block, so these two interrupts are now431* marked reserved. In case the Block Copy is resurrected in a432* future design, maintain the code that treats these two interrupts433* specially.434*435* Write to clear all interrupts in the PCI status register, aside436* from BC0F and BC1F.437*/438preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);439440/* Setup address that is to appear on PCI bus */441preg->config_addr = BPCI_CFGADDR_ENABLE |442(bus_num << BPCI_CFGADDR_BUSNUM_SHF) |443(dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |444(where & 0xFC);445446/* IF access is a PCI configuration write */447if (access_type == PCI_ACCESS_WRITE) {448value = cpu_to_le32(*data);449*PCI_CONFIG_SPACE_REG = value;450} else {451/* ELSE access is a PCI configuration read */452value = le32_to_cpu(*PCI_CONFIG_SPACE_REG);453*data = value;454}455456/*457* Check if the PCI configuration cycle (rd or wr) succeeded, by458* checking the status bits for errors like master or target abort.459*/460intr = preg->if_status;461462/* Clear config access */463preg->config_addr = 0;464465/* IF error occurred */466if (intr & ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F)) {467/* Clear status bits */468preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);469470#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)471evpe(vpe_status);472local_irq_restore(flags);473#else474spin_unlock_irqrestore(&bpci_lock, flags);475#endif476477return -1;478}479480#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)481evpe(vpe_status);482local_irq_restore(flags);483#else484spin_unlock_irqrestore(&bpci_lock, flags);485#endif486487return PCIBIOS_SUCCESSFUL;488}489490/*****************************************************************************491*492* FUNCTION: msp_pcibios_read_config_byte493* _________________________________________________________________________494*495* DESCRIPTION: Read a byte from PCI configuration address spac496* Since the hardware can't address 8 bit chunks497* directly, read a 32-bit chunk, then mask off extraneous498* bits.499*500* INPUTS bus - structure containing attributes for the PCI bus501* that the read is destined for.502* devfn - device/function combination that the read is503* destined for.504* where - register within the Configuration Header space505* to access.506*507* OUTPUTS val - read data508*509* RETURNS: PCIBIOS_SUCCESSFUL - success510* -1 - read access failure511*512****************************************************************************/513static int514msp_pcibios_read_config_byte(struct pci_bus *bus,515unsigned int devfn,516int where,517u32 *val)518{519u32 data = 0;520521/*522* If the config access did not complete normally (e.g., underwent523* master abort) do the PCI compliant thing, which is to supply an524* all ones value.525*/526if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,527where, &data)) {528*val = 0xFFFFFFFF;529return -1;530}531532*val = (data >> ((where & 3) << 3)) & 0x0ff;533534return PCIBIOS_SUCCESSFUL;535}536537/*****************************************************************************538*539* FUNCTION: msp_pcibios_read_config_word540* _________________________________________________________________________541*542* DESCRIPTION: Read a word (16 bits) from PCI configuration address space.543* Since the hardware can't address 16 bit chunks544* directly, read a 32-bit chunk, then mask off extraneous545* bits.546*547* INPUTS bus - structure containing attributes for the PCI bus548* that the read is destined for.549* devfn - device/function combination that the read is550* destined for.551* where - register within the Configuration Header space552* to access.553*554* OUTPUTS val - read data555*556* RETURNS: PCIBIOS_SUCCESSFUL - success557* PCIBIOS_BAD_REGISTER_NUMBER - bad register address558* -1 - read access failure559*560****************************************************************************/561static int562msp_pcibios_read_config_word(struct pci_bus *bus,563unsigned int devfn,564int where,565u32 *val)566{567u32 data = 0;568569/* if (where & 1) */ /* Commented out non-compliant code.570* Should allow word access to configuration571* registers, with only exception being when572* the word access would wrap around into573* the next dword.574*/575if ((where & 3) == 3) {576*val = 0xFFFFFFFF;577return PCIBIOS_BAD_REGISTER_NUMBER;578}579580/*581* If the config access did not complete normally (e.g., underwent582* master abort) do the PCI compliant thing, which is to supply an583* all ones value.584*/585if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,586where, &data)) {587*val = 0xFFFFFFFF;588return -1;589}590591*val = (data >> ((where & 3) << 3)) & 0x0ffff;592593return PCIBIOS_SUCCESSFUL;594}595596/*****************************************************************************597*598* FUNCTION: msp_pcibios_read_config_dword599* _________________________________________________________________________600*601* DESCRIPTION: Read a double word (32 bits) from PCI configuration602* address space.603*604* INPUTS bus - structure containing attributes for the PCI bus605* that the read is destined for.606* devfn - device/function combination that the read is607* destined for.608* where - register within the Configuration Header space609* to access.610*611* OUTPUTS val - read data612*613* RETURNS: PCIBIOS_SUCCESSFUL - success614* PCIBIOS_BAD_REGISTER_NUMBER - bad register address615* -1 - read access failure616*617****************************************************************************/618static int619msp_pcibios_read_config_dword(struct pci_bus *bus,620unsigned int devfn,621int where,622u32 *val)623{624u32 data = 0;625626/* Address must be dword aligned. */627if (where & 3) {628*val = 0xFFFFFFFF;629return PCIBIOS_BAD_REGISTER_NUMBER;630}631632/*633* If the config access did not complete normally (e.g., underwent634* master abort) do the PCI compliant thing, which is to supply an635* all ones value.636*/637if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,638where, &data)) {639*val = 0xFFFFFFFF;640return -1;641}642643*val = data;644645return PCIBIOS_SUCCESSFUL;646}647648/*****************************************************************************649*650* FUNCTION: msp_pcibios_write_config_byte651* _________________________________________________________________________652*653* DESCRIPTION: Write a byte to PCI configuration address space.654* Since the hardware can't address 8 bit chunks655* directly, a read-modify-write is performed.656*657* INPUTS bus - structure containing attributes for the PCI bus658* that the write is destined for.659* devfn - device/function combination that the write is660* destined for.661* where - register within the Configuration Header space662* to access.663* val - value to write664*665* OUTPUTS none666*667* RETURNS: PCIBIOS_SUCCESSFUL - success668* -1 - write access failure669*670****************************************************************************/671static int672msp_pcibios_write_config_byte(struct pci_bus *bus,673unsigned int devfn,674int where,675u8 val)676{677u32 data = 0;678679/* read config space */680if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,681where, &data))682return -1;683684/* modify the byte within the dword */685data = (data & ~(0xff << ((where & 3) << 3))) |686(val << ((where & 3) << 3));687688/* write back the full dword */689if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,690where, &data))691return -1;692693return PCIBIOS_SUCCESSFUL;694}695696/*****************************************************************************697*698* FUNCTION: msp_pcibios_write_config_word699* _________________________________________________________________________700*701* DESCRIPTION: Write a word (16-bits) to PCI configuration address space.702* Since the hardware can't address 16 bit chunks703* directly, a read-modify-write is performed.704*705* INPUTS bus - structure containing attributes for the PCI bus706* that the write is destined for.707* devfn - device/function combination that the write is708* destined for.709* where - register within the Configuration Header space710* to access.711* val - value to write712*713* OUTPUTS none714*715* RETURNS: PCIBIOS_SUCCESSFUL - success716* PCIBIOS_BAD_REGISTER_NUMBER - bad register address717* -1 - write access failure718*719****************************************************************************/720static int721msp_pcibios_write_config_word(struct pci_bus *bus,722unsigned int devfn,723int where,724u16 val)725{726u32 data = 0;727728/* Fixed non-compliance: if (where & 1) */729if ((where & 3) == 3)730return PCIBIOS_BAD_REGISTER_NUMBER;731732/* read config space */733if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,734where, &data))735return -1;736737/* modify the word within the dword */738data = (data & ~(0xffff << ((where & 3) << 3))) |739(val << ((where & 3) << 3));740741/* write back the full dword */742if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,743where, &data))744return -1;745746return PCIBIOS_SUCCESSFUL;747}748749/*****************************************************************************750*751* FUNCTION: msp_pcibios_write_config_dword752* _________________________________________________________________________753*754* DESCRIPTION: Write a double word (32-bits) to PCI configuration address755* space.756*757* INPUTS bus - structure containing attributes for the PCI bus758* that the write is destined for.759* devfn - device/function combination that the write is760* destined for.761* where - register within the Configuration Header space762* to access.763* val - value to write764*765* OUTPUTS none766*767* RETURNS: PCIBIOS_SUCCESSFUL - success768* PCIBIOS_BAD_REGISTER_NUMBER - bad register address769* -1 - write access failure770*771****************************************************************************/772static int773msp_pcibios_write_config_dword(struct pci_bus *bus,774unsigned int devfn,775int where,776u32 val)777{778/* check that address is dword aligned */779if (where & 3)780return PCIBIOS_BAD_REGISTER_NUMBER;781782/* perform write */783if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,784where, &val))785return -1;786787return PCIBIOS_SUCCESSFUL;788}789790/*****************************************************************************791*792* FUNCTION: msp_pcibios_read_config793* _________________________________________________________________________794*795* DESCRIPTION: Interface the PCI configuration read request with796* the appropriate function, based on how many bytes797* the read request is.798*799* INPUTS bus - structure containing attributes for the PCI bus800* that the write is destined for.801* devfn - device/function combination that the write is802* destined for.803* where - register within the Configuration Header space804* to access.805* size - in units of bytes, should be 1, 2, or 4.806*807* OUTPUTS val - value read, with any extraneous bytes masked808* to zero.809*810* RETURNS: PCIBIOS_SUCCESSFUL - success811* -1 - failure812*813****************************************************************************/814int815msp_pcibios_read_config(struct pci_bus *bus,816unsigned int devfn,817int where,818int size,819u32 *val)820{821if (size == 1) {822if (msp_pcibios_read_config_byte(bus, devfn, where, val)) {823return -1;824}825} else if (size == 2) {826if (msp_pcibios_read_config_word(bus, devfn, where, val)) {827return -1;828}829} else if (size == 4) {830if (msp_pcibios_read_config_dword(bus, devfn, where, val)) {831return -1;832}833} else {834*val = 0xFFFFFFFF;835return -1;836}837838return PCIBIOS_SUCCESSFUL;839}840841/*****************************************************************************842*843* FUNCTION: msp_pcibios_write_config844* _________________________________________________________________________845*846* DESCRIPTION: Interface the PCI configuration write request with847* the appropriate function, based on how many bytes848* the read request is.849*850* INPUTS bus - structure containing attributes for the PCI bus851* that the write is destined for.852* devfn - device/function combination that the write is853* destined for.854* where - register within the Configuration Header space855* to access.856* size - in units of bytes, should be 1, 2, or 4.857* val - value to write858*859* OUTPUTS: none860*861* RETURNS: PCIBIOS_SUCCESSFUL - success862* -1 - failure863*864****************************************************************************/865int866msp_pcibios_write_config(struct pci_bus *bus,867unsigned int devfn,868int where,869int size,870u32 val)871{872if (size == 1) {873if (msp_pcibios_write_config_byte(bus, devfn,874where, (u8)(0xFF & val))) {875return -1;876}877} else if (size == 2) {878if (msp_pcibios_write_config_word(bus, devfn,879where, (u16)(0xFFFF & val))) {880return -1;881}882} else if (size == 4) {883if (msp_pcibios_write_config_dword(bus, devfn, where, val)) {884return -1;885}886} else {887return -1;888}889890return PCIBIOS_SUCCESSFUL;891}892893/*****************************************************************************894*895* STRUCTURE: msp_pci_ops896* _________________________________________________________________________897*898* DESCRIPTION: structure to abstract the hardware specific PCI899* configuration accesses.900*901* ELEMENTS:902* read - function for Linux to generate PCI Configuration reads.903* write - function for Linux to generate PCI Configuration writes.904*905****************************************************************************/906struct pci_ops msp_pci_ops = {907.read = msp_pcibios_read_config,908.write = msp_pcibios_write_config909};910911/*****************************************************************************912*913* STRUCTURE: msp_pci_controller914* _________________________________________________________________________915*916* Describes the attributes of the MSP7120 PCI Host Controller917*918* ELEMENTS:919* pci_ops - abstracts the hardware specific PCI configuration920* accesses.921*922* mem_resource - address range pciauto() uses to assign to PCI device923* memory BARs.924*925* mem_offset - offset between how MSP7120 outbound PCI memory926* transaction addresses appear on the PCI bus and how Linux927* wants to configure memory BARs of the PCI devices.928* MSP7120 does nothing funky, so just set to zero.929*930* io_resource - address range pciauto() uses to assign to PCI device931* I/O BARs.932*933* io_offset - offset between how MSP7120 outbound PCI I/O934* transaction addresses appear on the PCI bus and how935* Linux defaults to configure I/O BARs of the PCI devices.936* MSP7120 maps outbound I/O accesses into the bottom937* bottom 4K of PCI address space (and ignores OATRAN).938* Since the Linux default is to configure I/O BARs to the939* bottom 4K, no special offset is needed. Just set to zero.940*941****************************************************************************/942static struct pci_controller msp_pci_controller = {943.pci_ops = &msp_pci_ops,944.mem_resource = &pci_mem_resource,945.mem_offset = 0,946.io_map_base = MSP_PCI_IOSPACE_BASE,947.io_resource = &pci_io_resource,948.io_offset = 0949};950951/*****************************************************************************952*953* FUNCTION: msp_pci_init954* _________________________________________________________________________955*956* DESCRIPTION: Initialize the PCI Host Controller and register it with957* Linux so Linux can seize control of the PCI bus.958*959****************************************************************************/960void __init msp_pci_init(void)961{962struct msp_pci_regs *preg = (void *)PCI_BASE_REG;963u32 id;964965/* Extract Device ID */966id = read_reg32(PCI_JTAG_DEVID_REG, 0xFFFF) >> 12;967968/* Check if JTAG ID identifies MSP7120 */969if (!MSP_HAS_PCI(id)) {970printk(KERN_WARNING "PCI: No PCI; id reads as %x\n", id);971goto no_pci;972}973974/*975* Enable flushing of the PCI-SDRAM queue upon a read976* of the SDRAM's Memory Configuration Register.977*/978*(unsigned long *)QFLUSH_REG_1 = 3;979980/* Configure PCI Host Controller. */981preg->if_status = ~0; /* Clear cause register bits */982preg->config_addr = 0; /* Clear config access */983preg->oatran = MSP_PCI_OATRAN; /* PCI outbound addr translation */984preg->if_mask = 0xF8BF87C0; /* Enable all PCI status interrupts */985986/* configure so inb(), outb(), and family are functional */987set_io_port_base(MSP_PCI_IOSPACE_BASE);988989/* Tell Linux the details of the MSP7120 PCI Host Controller */990register_pci_controller(&msp_pci_controller);991992return;993994no_pci:995/* Disable PCI channel */996printk(KERN_WARNING "PCI: no host PCI bus detected\n");997}9989991000