PageRenderTime 11ms CodeModel.GetById 5ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/mips/gt64120/common/pci.c

https://bitbucket.org/evzijst/gittest
C | 147 lines | 49 code | 14 blank | 84 comment | 5 complexity | b039be8de254c20e415ef7920f1a762a MD5 | raw file
  1/*
  2 * BRIEF MODULE DESCRIPTION
  3 * Galileo Evaluation Boards PCI support.
  4 *
  5 * The general-purpose functions to read/write and configure the GT64120A's
  6 * PCI registers (function names start with pci0 or pci1) are either direct
  7 * copies of functions written by Galileo Technology, or are modifications
  8 * of their functions to work with Linux 2.4 vs Linux 2.2.  These functions
  9 * are Copyright - Galileo Technology.
 10 *
 11 * Other functions are derived from other MIPS PCI implementations, or were
 12 * written by RidgeRun, Inc,  Copyright (C) 2000 RidgeRun, Inc.
 13 *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
 14 *
 15 *  This program is free software; you can redistribute  it and/or modify it
 16 *  under  the terms of  the GNU General  Public License as published by the
 17 *  Free Software Foundation;  either version 2 of the  License, or (at your
 18 *  option) any later version.
 19 *
 20 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
 21 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
 22 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 23 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
 24 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 25 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
 26 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 27 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
 28 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 29 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 30 *
 31 *  You should have received a copy of the  GNU General Public License along
 32 *  with this program; if not, write  to the Free Software Foundation, Inc.,
 33 *  675 Mass Ave, Cambridge, MA 02139, USA.
 34 */
 35#include <linux/init.h>
 36#include <linux/types.h>
 37#include <linux/pci.h>
 38#include <linux/kernel.h>
 39#include <asm/gt64120.h>
 40
 41#define SELF 0
 42
 43/*
 44 * pciXReadConfigReg  - Read from a PCI configuration register
 45 *                    - Make sure the GT is configured as a master before
 46 *                      reading from another device on the PCI.
 47 *                   - The function takes care of Big/Little endian conversion.
 48 * INPUTS:   regOffset: The register offset as it apears in the GT spec (or PCI
 49 *                        spec)
 50 *           pciDevNum: The device number needs to be addressed.
 51 * RETURNS: data , if the data == 0xffffffff check the master abort bit in the
 52 *                 cause register to make sure the data is valid
 53 *
 54 *  Configuration Address 0xCF8:
 55 *
 56 *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
 57 *  |congif|Reserved|  Bus |Device|Function|Register|00|
 58 *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
 59 *
 60 */
 61static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device)
 62{
 63	unsigned int DataForRegCf8;
 64	unsigned int data;
 65
 66	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
 67			 (PCI_FUNC(device->devfn) << 8) |
 68			 (offset & ~0x3)) | 0x80000000;
 69	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
 70
 71	/*
 72	 * The casual observer might wonder why the READ is duplicated here,
 73	 * rather than immediately following the WRITE, and just have the swap
 74	 * in the "if".  That's because there is a latency problem with trying
 75	 * to read immediately after setting up the address register.  The "if"
 76	 * check gives enough time for the address to stabilize, so the READ
 77	 * can work.
 78	 */
 79	if (PCI_SLOT(device->devfn) == SELF)	/* This board */
 80		return GT_READ(GT_PCI0_CFGDATA_OFS);
 81	else		/* PCI is little endian so swap the Data. */
 82		return __GT_READ(GT_PCI0_CFGDATA_OFS);
 83}
 84
 85/*
 86 * pciXWriteConfigReg - Write to a PCI configuration register
 87 *                    - Make sure the GT is configured as a master before
 88 *                      writingto another device on the PCI.
 89 *                    - The function takes care of Big/Little endian conversion.
 90 * Inputs:   unsigned int regOffset: The register offset as it apears in the
 91 *           GT spec
 92 *                   (or any other PCI device spec)
 93 *           pciDevNum: The device number needs to be addressed.
 94 *
 95 *  Configuration Address 0xCF8:
 96 *
 97 *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
 98 *  |congif|Reserved|  Bus |Device|Function|Register|00|
 99 *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
100 *
101 */
102static void pci0WriteConfigReg(unsigned int offset,
103			       struct pci_dev *device, unsigned int data)
104{
105	unsigned int DataForRegCf8;
106
107	DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
108			 (PCI_FUNC(device->devfn) << 8) |
109			 (offset & ~0x3)) | 0x80000000;
110	GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
111
112	if (PCI_SLOT(device->devfn) == SELF) 	/* This board */
113		GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
114	else 			/* configuration Transaction over the pci. */
115		__GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
116}
117
118extern struct pci_ops gt64120_pci_ops;
119
120void __init pcibios_init(void)
121{
122	u32 tmp;
123	struct pci_dev controller;
124
125	controller.devfn = SELF;
126
127	tmp = GT_READ(GT_PCI0_CMD_OFS);		/* Huh??? -- Ralf  */
128	tmp = GT_READ(GT_PCI0_BARE_OFS);
129
130	/*
131	 * You have to enable bus mastering to configure any other
132	 * card on the bus.
133	 */
134	tmp = pci0ReadConfigReg(PCI_COMMAND, &controller);
135	tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
136	pci0WriteConfigReg(PCI_COMMAND, &controller, tmp);
137
138	/*
139	 *  Reset PCI I/O and PCI MEM values to ones supported by EVM.
140	 */
141	ioport_resource.start	= GT_PCI_IO_BASE;
142	ioport_resource.end	= GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
143	iomem_resource.start	= GT_PCI_MEM_BASE;
144	iomem_resource.end	= GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1;
145
146	pci_scan_bus(0, &gt64120_pci_ops, NULL);
147}