pci.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:31k
- /*
- * BRIEF MODULE DESCRIPTION
- * Galileo Evaluation Boards PCI support.
- *
- * The general-purpose functions to read/write and configure the GT64120A's
- * PCI registers (function names start with pci0 or pci1) are either direct
- * copies of functions written by Galileo Technology, or are modifications
- * of their functions to work with Linux 2.4 vs Linux 2.2. These functions
- * are Copyright - Galileo Technology.
- *
- * Other functions are derived from other MIPS PCI implementations, or were
- * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <linux/config.h>
- #include <linux/types.h>
- #include <linux/pci.h>
- #include <linux/kernel.h>
- #include <linux/slab.h>
- #include <linux/version.h>
- #include <asm/pci.h>
- #include <asm/io.h>
- #include <asm/gt64120/gt64120.h>
- #include <linux/init.h>
- #ifdef CONFIG_PCI
- #define SELF 0
- /*
- * These functions and structures provide the BIOS scan and mapping of the PCI
- * devices.
- */
- #define MAX_PCI_DEVS 10
- struct pci_device {
- u32 slot;
- u32 BARtype[6];
- u32 BARsize[6];
- };
- static void __init scan_and_initialize_pci(void);
- static u32 __init scan_pci_bus(struct pci_device *pci_devices);
- static void __init allocate_pci_space(struct pci_device *pci_devices);
- /*
- * The functions that actually read and write to the controller.
- *
- * Copied from or modified from Galileo Technology code.
- */
- static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device);
- static void pci0WriteConfigReg(unsigned int offset,
- struct pci_dev *device, unsigned int data);
- static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device);
- static void pci1WriteConfigReg(unsigned int offset,
- struct pci_dev *device, unsigned int data);
- static void pci0MapIOspace(unsigned int pci0IoBase,
- unsigned int pci0IoLength);
- static void pci1MapIOspace(unsigned int pci1IoBase,
- unsigned int pci1IoLength);
- static void pci0MapMemory0space(unsigned int pci0Mem0Base,
- unsigned int pci0Mem0Length);
- static void pci1MapMemory0space(unsigned int pci1Mem0Base,
- unsigned int pci1Mem0Length);
- static void pci0MapMemory1space(unsigned int pci0Mem1Base,
- unsigned int pci0Mem1Length);
- static void pci1MapMemory1space(unsigned int pci1Mem1Base,
- unsigned int pci1Mem1Length);
- static unsigned int pci0GetIOspaceBase(void);
- static unsigned int pci0GetIOspaceSize(void);
- static unsigned int pci0GetMemory0Base(void);
- static unsigned int pci0GetMemory0Size(void);
- static unsigned int pci0GetMemory1Base(void);
- static unsigned int pci0GetMemory1Size(void);
- static unsigned int pci1GetIOspaceBase(void);
- static unsigned int pci1GetIOspaceSize(void);
- static unsigned int pci1GetMemory0Base(void);
- static unsigned int pci1GetMemory0Size(void);
- static unsigned int pci1GetMemory1Base(void);
- static unsigned int pci1GetMemory1Size(void);
- /* Functions to implement "pci ops" */
- static int galileo_pcibios_read_config_word(struct pci_dev *dev,
- int offset, u16 * val);
- static int galileo_pcibios_read_config_byte(struct pci_dev *dev,
- int offset, u8 * val);
- static int galileo_pcibios_read_config_dword(struct pci_dev *dev,
- int offset, u32 * val);
- static int galileo_pcibios_write_config_byte(struct pci_dev *dev,
- int offset, u8 val);
- static int galileo_pcibios_write_config_word(struct pci_dev *dev,
- int offset, u16 val);
- static int galileo_pcibios_write_config_dword(struct pci_dev *dev,
- int offset, u32 val);
- static void galileo_pcibios_set_master(struct pci_dev *dev);
- /*
- * General-purpose PCI functions.
- */
- /*
- * pci0MapIOspace - Maps PCI0 IO space for the master.
- * Inputs: base and length of pci0Io
- */
- static void pci0MapIOspace(unsigned int pci0IoBase,
- unsigned int pci0IoLength)
- {
- unsigned int pci0IoTop =
- (unsigned int) (pci0IoBase + pci0IoLength);
- if (pci0IoLength == 0)
- pci0IoTop++;
- pci0IoBase = (unsigned int) (pci0IoBase >> 21);
- pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21);
- GT_WRITE(GT_PCI0IOLD_OFS, pci0IoBase);
- GT_WRITE(GT_PCI0IOHD_OFS, pci0IoTop);
- }
- /*
- * pci1MapIOspace - Maps PCI1 IO space for the master.
- * Inputs: base and length of pci1Io
- */
- static void pci1MapIOspace(unsigned int pci1IoBase,
- unsigned int pci1IoLength)
- {
- unsigned int pci1IoTop =
- (unsigned int) (pci1IoBase + pci1IoLength);
- if (pci1IoLength == 0)
- pci1IoTop++;
- pci1IoBase = (unsigned int) (pci1IoBase >> 21);
- pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21);
- GT_WRITE(GT_PCI1IOLD_OFS, pci1IoBase);
- GT_WRITE(GT_PCI1IOHD_OFS, pci1IoTop);
- }
- /*
- * pci0MapMemory0space - Maps PCI0 memory0 space for the master.
- * Inputs: base and length of pci0Mem0
- */
- static void pci0MapMemory0space(unsigned int pci0Mem0Base,
- unsigned int pci0Mem0Length)
- {
- unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length;
- if (pci0Mem0Length == 0)
- pci0Mem0Top++;
- pci0Mem0Base = pci0Mem0Base >> 21;
- pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21;
- GT_WRITE(GT_PCI0M0LD_OFS, pci0Mem0Base);
- GT_WRITE(GT_PCI0M0HD_OFS, pci0Mem0Top);
- }
- /*
- * pci1MapMemory0space - Maps PCI1 memory0 space for the master.
- * Inputs: base and length of pci1Mem0
- */
- static void pci1MapMemory0space(unsigned int pci1Mem0Base,
- unsigned int pci1Mem0Length)
- {
- unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length;
- if (pci1Mem0Length == 0)
- pci1Mem0Top++;
- pci1Mem0Base = pci1Mem0Base >> 21;
- pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21;
- GT_WRITE(GT_PCI1M0LD_OFS, pci1Mem0Base);
- GT_WRITE(GT_PCI1M0HD_OFS, pci1Mem0Top);
- }
- /*
- * pci0MapMemory1space - Maps PCI0 memory1 space for the master.
- * Inputs: base and length of pci0Mem1
- */
- static void pci0MapMemory1space(unsigned int pci0Mem1Base,
- unsigned int pci0Mem1Length)
- {
- unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length;
- if (pci0Mem1Length == 0)
- pci0Mem1Top++;
- pci0Mem1Base = pci0Mem1Base >> 21;
- pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21;
- GT_WRITE(GT_PCI0M1LD_OFS, pci0Mem1Base);
- GT_WRITE(GT_PCI0M1HD_OFS, pci0Mem1Top);
- }
- /*
- * pci1MapMemory1space - Maps PCI1 memory1 space for the master.
- * Inputs: base and length of pci1Mem1
- */
- static void pci1MapMemory1space(unsigned int pci1Mem1Base,
- unsigned int pci1Mem1Length)
- {
- unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length;
- if (pci1Mem1Length == 0)
- pci1Mem1Top++;
- pci1Mem1Base = pci1Mem1Base >> 21;
- pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21;
- GT_WRITE(GT_PCI1M1LD_OFS, pci1Mem1Base);
- GT_WRITE(GT_PCI1M1HD_OFS, pci1Mem1Top);
- }
- /*
- * pci0GetIOspaceBase - Return PCI0 IO Base Address.
- * Inputs: N/A
- * Returns: PCI0 IO Base Address.
- */
- static unsigned int pci0GetIOspaceBase(void)
- {
- unsigned int base;
- GT_READ(GT_PCI0IOLD_OFS, &base);
- base = base << 21;
- return base;
- }
- /*
- * pci0GetIOspaceSize - Return PCI0 IO Bar Size.
- * Inputs: N/A
- * Returns: PCI0 IO Bar Size.
- */
- static unsigned int pci0GetIOspaceSize(void)
- {
- unsigned int top, base, size;
- GT_READ(GT_PCI0IOLD_OFS, &base);
- base = base << 21;
- GT_READ(GT_PCI0IOHD_OFS, &top);
- top = (top << 21);
- size = ((top - base) & 0xfffffff);
- size = size | 0x1fffff;
- return (size + 1);
- }
- /*
- * pci0GetMemory0Base - Return PCI0 Memory 0 Base Address.
- * Inputs: N/A
- * Returns: PCI0 Memory 0 Base Address.
- */
- static unsigned int pci0GetMemory0Base(void)
- {
- unsigned int base;
- GT_READ(GT_PCI0M0LD_OFS, &base);
- base = base << 21;
- return base;
- }
- /*
- * pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size.
- * Inputs: N/A
- * Returns: PCI0 Memory 0 Bar Size.
- */
- static unsigned int pci0GetMemory0Size(void)
- {
- unsigned int top, base, size;
- GT_READ(GT_PCI0M0LD_OFS, &base);
- base = base << 21;
- GT_READ(GT_PCI0M0HD_OFS, &top);
- top = (top << 21);
- size = ((top - base) & 0xfffffff);
- size = size | 0x1fffff;
- return (size + 1);
- }
- /*
- * pci0GetMemory1Base - Return PCI0 Memory 1 Base Address.
- * Inputs: N/A
- * Returns: PCI0 Memory 1 Base Address.
- */
- static unsigned int pci0GetMemory1Base(void)
- {
- unsigned int base;
- GT_READ(GT_PCI0M1LD_OFS, &base);
- base = base << 21;
- return base;
- }
- /*
- * pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size.
- * Inputs: N/A
- * Returns: PCI0 Memory 1 Bar Size.
- */
- static unsigned int pci0GetMemory1Size(void)
- {
- unsigned int top, base, size;
- GT_READ(GT_PCI0M1LD_OFS, &base);
- base = base << 21;
- GT_READ(GT_PCI0M1HD_OFS, &top);
- top = (top << 21);
- size = ((top - base) & 0xfffffff);
- size = size | 0x1fffff;
- return (size + 1);
- }
- /*
- * pci1GetIOspaceBase - Return PCI1 IO Base Address.
- * Inputs: N/A
- * Returns: PCI1 IO Base Address.
- */
- static unsigned int pci1GetIOspaceBase(void)
- {
- unsigned int base;
- GT_READ(GT_PCI1IOLD_OFS, &base);
- base = base << 21;
- return base;
- }
- /*
- * pci1GetIOspaceSize - Return PCI1 IO Bar Size.
- * Inputs: N/A
- * Returns: PCI1 IO Bar Size.
- */
- static unsigned int pci1GetIOspaceSize(void)
- {
- unsigned int top, base, size;
- GT_READ(GT_PCI1IOLD_OFS, &base);
- base = base << 21;
- GT_READ(GT_PCI1IOHD_OFS, &top);
- top = (top << 21);
- size = ((top - base) & 0xfffffff);
- size = size | 0x1fffff;
- return (size + 1);
- }
- /*
- * pci1GetMemory0Base - Return PCI1 Memory 0 Base Address.
- * Inputs: N/A
- * Returns: PCI1 Memory 0 Base Address.
- */
- static unsigned int pci1GetMemory0Base(void)
- {
- unsigned int base;
- GT_READ(GT_PCI1M0LD_OFS, &base);
- base = base << 21;
- return base;
- }
- /*
- * pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size.
- * Inputs: N/A
- * Returns: PCI1 Memory 0 Bar Size.
- */
- static unsigned int pci1GetMemory0Size(void)
- {
- unsigned int top, base, size;
- GT_READ(GT_PCI1M1LD_OFS, &base);
- base = base << 21;
- GT_READ(GT_PCI1M1HD_OFS, &top);
- top = (top << 21);
- size = ((top - base) & 0xfffffff);
- size = size | 0x1fffff;
- return (size + 1);
- }
- /*
- * pci1GetMemory1Base - Return PCI1 Memory 1 Base Address.
- * Inputs: N/A
- * Returns: PCI1 Memory 1 Base Address.
- */
- static unsigned int pci1GetMemory1Base(void)
- {
- unsigned int base;
- GT_READ(GT_PCI1M1LD_OFS, &base);
- base = base << 21;
- return base;
- }
- /*
- * pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size.
- * Inputs: N/A
- * Returns: PCI1 Memory 1 Bar Size.
- */
- static unsigned int pci1GetMemory1Size(void)
- {
- unsigned int top, base, size;
- GT_READ(GT_PCI1M1LD_OFS, &base);
- base = base << 21;
- GT_READ(GT_PCI1M1HD_OFS, &top);
- top = (top << 21);
- size = ((top - base) & 0xfffffff);
- size = size | 0x1fffff;
- return (size + 1);
- }
- /*
- * pci_range_ck -
- *
- * Check if the pci device that are trying to access does really exists
- * on the evaluation board.
- *
- * Inputs :
- * bus - bus number (0 for PCI 0 ; 1 for PCI 1)
- * dev - number of device on the specific pci bus
- *
- * Outpus :
- * 0 - if OK , 1 - if failure
- */
- static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev)
- {
- /*
- * We don't even pretend to handle other busses than bus 0 correctly.
- * Accessing device 31 crashes the CP7000 for some reason.
- */
- if ((bus == 0) && (dev != 31))
- return 0;
- return -1;
- }
- /*
- * pciXReadConfigReg - Read from a PCI configuration register
- * - Make sure the GT is configured as a master before
- * reading from another device on the PCI.
- * - The function takes care of Big/Little endian conversion.
- * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI
- * spec)
- * pciDevNum: The device number needs to be addressed.
- * RETURNS: data , if the data == 0xffffffff check the master abort bit in the
- * cause register to make sure the data is valid
- *
- * Configuration Address 0xCF8:
- *
- * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
- * |congif|Reserved| Bus |Device|Function|Register|00|
- * |Enable| |Number|Number| Number | Number | | <=field Name
- *
- */
- static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device)
- {
- unsigned int DataForRegCf8;
- unsigned int data;
- DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
- (PCI_FUNC(device->devfn) << 8) |
- (offset & ~0x3)) | 0x80000000;
- GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
- /*
- * The casual observer might wonder why the READ is duplicated here,
- * rather than immediately following the WRITE, and just have the swap
- * in the "if". That's because there is a latency problem with trying
- * to read immediately after setting up the address register. The "if"
- * check gives enough time for the address to stabilize, so the READ
- * can work.
- */
- if (PCI_SLOT(device->devfn) == SELF) { /* This board */
- GT_READ(GT_PCI0_CFGDATA_OFS, &data);
- return data;
- } else { /* The PCI is working in LE Mode so swap the Data. */
- GT_READ(GT_PCI0_CFGDATA_OFS, &data);
- return cpu_to_le32(data);
- }
- }
- static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device)
- {
- unsigned int DataForRegCf8;
- unsigned int data;
- DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
- (PCI_FUNC(device->devfn) << 8) |
- (offset & ~0x3)) | 0x80000000;
- /*
- * The casual observer might wonder why the READ is duplicated here,
- * rather than immediately following the WRITE, and just have the
- * swap in the "if". That's because there is a latency problem
- * with trying to read immediately after setting up the address
- * register. The "if" check gives enough time for the address
- * to stabilize, so the READ can work.
- */
- if (PCI_SLOT(device->devfn) == SELF) { /* This board */
- /* when configurating our own PCI 1 L-unit the access is through
- the PCI 0 interface with reg number = reg number + 0x80 */
- DataForRegCf8 |= 0x80;
- GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
- } else { /* The PCI is working in LE Mode so swap the Data. */
- GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8);
- }
- if (PCI_SLOT(device->devfn) == SELF) { /* This board */
- GT_READ(GT_PCI0_CFGDATA_OFS, &data);
- return data;
- } else {
- GT_READ(GT_PCI1_CFGDATA_OFS, &data);
- return cpu_to_le32(data);
- }
- }
- /*
- * pciXWriteConfigReg - Write to a PCI configuration register
- * - Make sure the GT is configured as a master before
- * writingto another device on the PCI.
- * - The function takes care of Big/Little endian conversion.
- * Inputs: unsigned int regOffset: The register offset as it apears in the
- * GT spec
- * (or any other PCI device spec)
- * pciDevNum: The device number needs to be addressed.
- *
- * Configuration Address 0xCF8:
- *
- * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
- * |congif|Reserved| Bus |Device|Function|Register|00|
- * |Enable| |Number|Number| Number | Number | | <=field Name
- *
- */
- static void pci0WriteConfigReg(unsigned int offset,
- struct pci_dev *device, unsigned int data)
- {
- unsigned int DataForRegCf8;
- DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
- (PCI_FUNC(device->devfn) << 8) |
- (offset & ~0x3)) | 0x80000000;
- GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
- if (PCI_SLOT(device->devfn) == SELF) { /* This board */
- GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
- } else { /* configuration Transaction over the pci. */
- /* The PCI is working in LE Mode so swap the Data. */
- GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data));
- }
- }
- static void pci1WriteConfigReg(unsigned int offset,
- struct pci_dev *device, unsigned int data)
- {
- unsigned int DataForRegCf8;
- DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
- (PCI_FUNC(device->devfn) << 8) |
- (offset & ~0x3)) | 0x80000000;
- /*
- * There is a latency problem
- * with trying to read immediately after setting up the address
- * register. The "if" check gives enough time for the address
- * to stabilize, so the WRITE can work.
- */
- if (PCI_SLOT(device->devfn) == SELF) { /* This board */
- /*
- * when configurating our own PCI 1 L-unit the access is through
- * the PCI 0 interface with reg number = reg number + 0x80
- */
- DataForRegCf8 |= 0x80;
- GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
- } else { /* configuration Transaction over the pci. */
- /* The PCI is working in LE Mode so swap the Data. */
- GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8);
- }
- if (PCI_SLOT(device->devfn) == SELF) { /* This board */
- GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
- } else { /* configuration Transaction over the pci. */
- GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data));
- }
- }
- /*
- * galileo_pcibios_(read/write)_config_(dword/word/byte) -
- *
- * reads/write a dword/word/byte register from the configuration space
- * of a device.
- *
- * Inputs :
- * bus - bus number
- * dev - device number
- * offset - register offset in the configuration space
- * val - value to be written / read
- *
- * Outputs :
- * PCIBIOS_SUCCESSFUL when operation was succesfull
- * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous
- * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned
- */
- static int galileo_pcibios_read_config_dword(struct pci_dev *device,
- int offset, u32 * val)
- {
- int dev, bus;
- bus = device->bus->number;
- dev = PCI_SLOT(device->devfn);
- if (pci_range_ck(bus, dev)) {
- *val = 0xffffffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- if (offset & 0x3)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- if (bus == 0)
- *val = pci0ReadConfigReg(offset, device);
- /* This is so that the upper PCI layer will get the correct return value if
- we're not attached to anything. */
- if ((offset == 0) && (*val == 0xffffffff)) {
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- return PCIBIOS_SUCCESSFUL;
- }
- static int galileo_pcibios_read_config_word(struct pci_dev *device,
- int offset, u16 * val)
- {
- int dev, bus;
- bus = device->bus->number;
- dev = PCI_SLOT(device->devfn);
- if (pci_range_ck(bus, dev)) {
- *val = 0xffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- if (offset & 0x1)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- if (bus == 0)
- *val =
- (unsigned short) (pci0ReadConfigReg(offset, device) >>
- ((offset & ~0x3) * 8));
- return PCIBIOS_SUCCESSFUL;
- }
- static int galileo_pcibios_read_config_byte(struct pci_dev *device,
- int offset, u8 * val)
- {
- int dev, bus;
- bus = device->bus->number;
- dev = PCI_SLOT(device->devfn);
- if (pci_range_ck(bus, dev)) {
- *val = 0xff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- if (bus == 0)
- *val =
- (unsigned char) (pci0ReadConfigReg(offset, device) >>
- ((offset & ~0x3) * 8));
- /*
- * This is so that the upper PCI layer will get the correct return
- * value if we're not attached to anything.
- */
- if ((offset == 0xe) && (*val == 0xff)) {
- u32 MasterAbort;
- GT_READ(GT_INTRCAUSE_OFS, &MasterAbort);
- if (MasterAbort & 0x40000) {
- GT_WRITE(GT_INTRCAUSE_OFS,
- (MasterAbort & 0xfffbffff));
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- }
- return PCIBIOS_SUCCESSFUL;
- }
- static int galileo_pcibios_write_config_dword(struct pci_dev *device,
- int offset, u32 val)
- {
- int dev, bus;
- bus = device->bus->number;
- dev = PCI_SLOT(device->devfn);
- if (pci_range_ck(bus, dev))
- return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset & 0x3)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- if (bus == 0)
- pci0WriteConfigReg(offset, device, val);
- // if (bus == 1) pci1WriteConfigReg (offset,device,val);
- return PCIBIOS_SUCCESSFUL;
- }
- static int galileo_pcibios_write_config_word(struct pci_dev *device,
- int offset, u16 val)
- {
- int dev, bus;
- unsigned long tmp;
- bus = device->bus->number;
- dev = PCI_SLOT(device->devfn);
- if (pci_range_ck(bus, dev))
- return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset & 0x1)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- if (bus == 0)
- tmp = pci0ReadConfigReg(offset, device);
- // if (bus == 1) tmp = pci1ReadConfigReg (offset,device);
- if ((offset % 4) == 0)
- tmp = (tmp & 0xffff0000) | (val & 0xffff);
- if ((offset % 4) == 2)
- tmp = (tmp & 0x0000ffff) | ((val & 0xffff) << 16);
- if (bus == 0)
- pci0WriteConfigReg(offset, device, tmp);
- // if (bus == 1) pci1WriteConfigReg (offset,device,tmp);
- return PCIBIOS_SUCCESSFUL;
- }
- static int galileo_pcibios_write_config_byte(struct pci_dev *device,
- int offset, u8 val)
- {
- int dev, bus;
- unsigned long tmp;
- bus = device->bus->number;
- dev = PCI_SLOT(device->devfn);
- if (pci_range_ck(bus, dev))
- return PCIBIOS_DEVICE_NOT_FOUND;
- if (bus == 0)
- tmp = pci0ReadConfigReg(offset, device);
- // if (bus == 1) tmp = pci1ReadConfigReg (offset,device);
- if ((offset % 4) == 0)
- tmp = (tmp & 0xffffff00) | (val & 0xff);
- if ((offset % 4) == 1)
- tmp = (tmp & 0xffff00ff) | ((val & 0xff) << 8);
- if ((offset % 4) == 2)
- tmp = (tmp & 0xff00ffff) | ((val & 0xff) << 16);
- if ((offset % 4) == 3)
- tmp = (tmp & 0x00ffffff) | ((val & 0xff) << 24);
- if (bus == 0)
- pci0WriteConfigReg(offset, device, tmp);
- // if (bus == 1) pci1WriteConfigReg (offset,device,tmp);
- return PCIBIOS_SUCCESSFUL;
- }
- static void galileo_pcibios_set_master(struct pci_dev *dev)
- {
- u16 cmd;
- galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MASTER;
- galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd);
- }
- /* Externally-expected functions. Do not change function names */
- int pcibios_enable_resources(struct pci_dev *dev)
- {
- u16 cmd, old_cmd;
- u8 tmp1;
- int idx;
- struct resource *r;
- galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd);
- old_cmd = cmd;
- for (idx = 0; idx < 6; idx++) {
- r = &dev->resource[idx];
- if (!r->start && r->end) {
- printk(KERN_ERR
- "PCI: Device %s not available because of "
- "resource collisionsn", dev->slot_name);
- return -EINVAL;
- }
- if (r->flags & IORESOURCE_IO)
- cmd |= PCI_COMMAND_IO;
- if (r->flags & IORESOURCE_MEM)
- cmd |= PCI_COMMAND_MEMORY;
- }
- if (cmd != old_cmd) {
- galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd);
- }
- /*
- * Let's fix up the latency timer and cache line size here. Cache
- * line size = 32 bytes / sizeof dword (4) = 8.
- * Latency timer must be > 8. 32 is random but appears to work.
- */
- galileo_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
- if (tmp1 != 8) {
- printk(KERN_WARNING "PCI setting cache line size to 8 from "
- "%dn", tmp1);
- galileo_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
- 8);
- }
- galileo_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1);
- if (tmp1 < 32) {
- printk(KERN_WARNING "PCI setting latency timer to 32 from %dn",
- tmp1);
- galileo_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER,
- 32);
- }
- return 0;
- }
- int pcibios_enable_device(struct pci_dev *dev)
- {
- return pcibios_enable_resources(dev);
- }
- void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
- {
- u32 new, check;
- int reg;
- return;
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4 * resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /*
- * Somebody might have asked allocation of a non-standard
- * resource
- */
- return;
- }
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) &
- ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
- PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)n", dev->slot_name, resource,
- new, check);
- }
- }
- void pcibios_align_resource(void *data, struct resource *res,
- unsigned long size)
- {
- struct pci_dev *dev = data;
- if (res->flags & IORESOURCE_IO) {
- unsigned long start = res->start;
- /* We need to avoid collisions with `mirrored' VGA ports
- and other strange ISA hardware, so we always want the
- addresses kilobyte aligned. */
- if (size > 0x100) {
- printk(KERN_ERR "PCI: I/O Region %s/%d too large"
- " (%ld bytes)n", dev->slot_name,
- dev->resource - res, size);
- }
- start = (start + 1024 - 1) & ~(1024 - 1);
- res->start = start;
- }
- }
- struct pci_ops galileo_pci_ops = {
- galileo_pcibios_read_config_byte,
- galileo_pcibios_read_config_word,
- galileo_pcibios_read_config_dword,
- galileo_pcibios_write_config_byte,
- galileo_pcibios_write_config_word,
- galileo_pcibios_write_config_dword
- };
- struct pci_fixup pcibios_fixups[] = {
- {0}
- };
- void __init pcibios_fixup_bus(struct pci_bus *c)
- {
- gt64120_board_pcibios_fixup_bus(c);
- }
- /*
- * This code was derived from Galileo Technology's example
- * and significantly reworked.
- *
- * This is very simple. It does not scan multiple function devices. It does
- * not scan behind bridges. Those would be simple to implement, but we don't
- * currently need this.
- */
- static void __init scan_and_initialize_pci(void)
- {
- struct pci_device pci_devices[MAX_PCI_DEVS];
- if (scan_pci_bus(pci_devices)) {
- allocate_pci_space(pci_devices);
- }
- }
- /*
- * This is your basic PCI scan. It goes through each slot and checks to
- * see if there's something that responds. If so, then get the size and
- * type of each of the responding BARs. Save them for later.
- */
- static u32 __init scan_pci_bus(struct pci_device *pci_devices)
- {
- u32 arrayCounter = 0;
- u32 memType;
- u32 memSize;
- u32 pci_slot, bar;
- u32 id;
- u32 c18RegValue;
- struct pci_dev device;
- /*
- * According to PCI REV 2.1 MAX agents on the bus are 21.
- * We don't bother scanning ourselves (slot 0).
- */
- for (pci_slot = 1; pci_slot < 22; pci_slot++) {
- device.devfn = PCI_DEVFN(pci_slot, 0);
- id = pci0ReadConfigReg(PCI_VENDOR_ID, &device);
- /*
- * Check for a PCI Master Abort (nothing responds in the
- * slot)
- */
- GT_READ(GT_INTRCAUSE_OFS, &c18RegValue);
- /*
- * Clearing bit 18 of in the Cause Register 0xc18 by
- * writting 0.
- */
- GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff));
- if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) {
- pci_devices[arrayCounter].slot = pci_slot;
- for (bar = 0; bar < 6; bar++) {
- memType =
- pci0ReadConfigReg(PCI_BASE_ADDRESS_0 +
- (bar * 4), &device);
- pci_devices[arrayCounter].BARtype[bar] =
- memType & 1;
- pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +
- (bar * 4), &device,
- 0xffffffff);
- memSize =
- pci0ReadConfigReg(PCI_BASE_ADDRESS_0 +
- (bar * 4), &device);
- if (memType & 1) { /* IO space */
- pci_devices[arrayCounter].
- BARsize[bar] =
- ~(memSize & 0xfffffffc) + 1;
- } else { /* memory space */
- pci_devices[arrayCounter].
- BARsize[bar] =
- ~(memSize & 0xfffffff0) + 1;
- }
- } /* BAR counter */
- arrayCounter++;
- }
- /* found a device */
- } /* slot counter */
- if (arrayCounter < MAX_PCI_DEVS)
- pci_devices[arrayCounter].slot = -1;
- return arrayCounter;
- }
- #define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
- #define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
- /*
- * This function goes through the list of devices and allocates the BARs in
- * either IO or MEM space. It does it in order of size, which will limit the
- * amount of fragmentation we have in the IO and MEM spaces.
- */
- static void __init allocate_pci_space(struct pci_device *pci_devices)
- {
- u32 count, maxcount, bar;
- u32 maxSize, maxDevice, maxBAR;
- u32 alignto;
- u32 base;
- u32 pci0_mem_base = pci0GetMemory0Base();
- u32 pci0_io_base = pci0GetIOspaceBase();
- struct pci_dev device;
- /* How many PCI devices do we have? */
- maxcount = MAX_PCI_DEVS;
- for (count = 0; count < MAX_PCI_DEVS; count++) {
- if (pci_devices[count].slot == -1) {
- maxcount = count;
- break;
- }
- }
- do {
- /* Find the largest size BAR we need to allocate */
- maxSize = 0;
- for (count = 0; count < maxcount; count++) {
- for (bar = 0; bar < 6; bar++) {
- if (pci_devices[count].BARsize[bar] >
- maxSize) {
- maxSize =
- pci_devices[count].
- BARsize[bar];
- maxDevice = count;
- maxBAR = bar;
- }
- }
- }
- /*
- * We've found the largest BAR. Allocate it into IO or
- * mem space. We don't idiot check the bases to make
- * sure they haven't overflowed the current size for that
- * aperture.
- * Don't bother to enable the device's IO or MEM space here.
- * That will be done in pci_enable_resources if the device is
- * activated by a driver.
- */
- if (maxSize) {
- device.devfn =
- PCI_DEVFN(pci_devices[maxDevice].slot, 0);
- if (pci_devices[maxDevice].BARtype[maxBAR] == 1) {
- alignto = MAX(0x1000, maxSize);
- base = ALIGN(pci0_io_base, alignto);
- pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +
- (maxBAR * 4), &device,
- base | 0x1);
- pci0_io_base = base + alignto;
- } else {
- alignto = MAX(0x1000, maxSize);
- base = ALIGN(pci0_mem_base, alignto);
- pci0WriteConfigReg(PCI_BASE_ADDRESS_0 +
- (maxBAR * 4), &device,
- base);
- pci0_mem_base = base + alignto;
- }
- /*
- * This entry is finished. Remove it from the list
- * we'll scan.
- */
- pci_devices[maxDevice].BARsize[maxBAR] = 0;
- }
- } while (maxSize);
- }
- void __init pcibios_init(void)
- {
- u32 tmp;
- struct pci_dev controller;
- controller.devfn = SELF;
- GT_READ(GT_PCI0_CMD_OFS, &tmp);
- GT_READ(GT_PCI0_BARE_OFS, &tmp);
- /*
- * You have to enable bus mastering to configure any other
- * card on the bus.
- */
- tmp = pci0ReadConfigReg(PCI_COMMAND, &controller);
- tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
- pci0WriteConfigReg(PCI_COMMAND, &controller, tmp);
- /* This scans the PCI bus and sets up initial values. */
- scan_and_initialize_pci();
- /*
- * Reset PCI I/O and PCI MEM values to ones supported by EVM.
- */
- ioport_resource.start = GT_PCI_IO_BASE;
- ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
- iomem_resource.start = GT_PCI_MEM_BASE;
- iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
- pci_scan_bus(0, &galileo_pci_ops, NULL);
- }
- /*
- * for parsing "pci=" kernel boot arguments.
- */
- char *pcibios_setup(char *str)
- {
- printk(KERN_INFO "rr: pcibios_setupn");
- /* Nothing to do for now. */
- return str;
- }
- unsigned __init int pcibios_assign_all_busses(void)
- {
- return 1;
- }
- #endif /* CONFIG_PCI */