VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / mips / pci / pci-ocelot-g.c
index 34c3ec8..239b81f 100644 (file)
 /*
- * Copyright 2002 Momentum Computer
- * Author: Matthew Dharm <mdharm@momenco.com>
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  *
- *  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.
+ * Copyright (C) 2004 by Ralf Baechle
  *
- *  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.
+ * This doesn't really fly - but I don't have a GT64240 system for testing.
  */
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <asm/pci.h>
-#include <asm/io.h>
-#include "gt64240.h"
-
-#include <linux/init.h>
-
-#define SELF 0
-#define MASTER_ABORT_BIT 0x100
+#include <asm/gt64240.h>
+#include <asm/pci_channel.h>
 
 /*
- * These functions and structures provide the BIOS scan and mapping of the PCI
- * devices.
- */
-
-void gt64240_board_pcibios_fixup_bus(struct pci_bus *c);
-
-/*  Functions to implement "pci ops"  */
-static int galileo_pcibios_read_config_word(int bus, int devfn,
-                                           int offset, u16 * val);
-static int galileo_pcibios_read_config_byte(int bus, int devfn,
-                                           int offset, u8 * val);
-static int galileo_pcibios_read_config_dword(int bus, int devfn,
-                                            int offset, u32 * val);
-static int galileo_pcibios_write_config_byte(int bus, int devfn,
-                                            int offset, u8 val);
-static int galileo_pcibios_write_config_word(int bus, int devfn,
-                                            int offset, u16 val);
-static int galileo_pcibios_write_config_dword(int bus, int devfn,
-                                             int offset, u32 val);
-
-static int pci_read(struct pci_bus *bus, unsigned int devfs, int where,
-                   int size, u32 * val);
-static int pci_write(struct pci_bus *bus, unsigned int devfs, int where,
-                    int size, u32 val);
-
-/*
- *  General-purpose PCI functions.
- */
-
-
-/*
- * 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)
-{
-       /* Accessing device 31 crashes the GT-64240. */
-       if (dev < 5)
-               return 0;
-       return -1;
-}
-
-/*
- * galileo_pcibios_(read/write)_config_(dword/word/byte) -
- *
- * reads/write a dword/word/byte register from the configuration space
- * of a device.
- *
- * Note that bus 0 and bus 1 are local, and we assume all other busses are
- * bridged from bus 1.  This is a safe assumption, since any other
- * configuration will require major modifications to the CP7000G
- *
- * 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
+ * We assume these address ranges have been programmed into the GT-64240 by
+ * the firmware.  PMON in case of the Ocelot G does that.  Note the size of
+ * the I/O range is completly stupid; I/O mappings are limited to at most
+ * 256 bytes by the PCI spec and deprecated; and just to make things worse
+ * apparently many devices don't decode more than 64k of I/O space.
  */
 
-static int galileo_pcibios_read_config_dword(int bus, int devfn,
-                                            int offset, u32 * val)
-{
-       int dev, func;
-       uint32_t address_reg, data_reg;
-       uint32_t address;
-
-       dev = PCI_SLOT(devfn);
-       func = PCI_FUNC(devfn);
-
-       /* verify the range */
-       if (pci_range_ck(bus, dev))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* select the GT-64240 registers to communicate with the PCI bus */
-       if (bus == 0) {
-               address_reg = PCI_0CONFIGURATION_ADDRESS;
-               data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
-               GT_WRITE(PCI_0ERROR_CAUSE, ~MASTER_ABORT_BIT);
-       } else {
-               address_reg = PCI_1CONFIGURATION_ADDRESS;
-               data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
-               GT_WRITE(PCI_1ERROR_CAUSE, ~MASTER_ABORT_BIT);
-               if (bus == 1)
-                       bus = 0;
-       }
-
-       address = (bus << 16) | (dev << 11) | (func << 8) |
-           (offset & 0xfc) | 0x80000000;
-
-       /* start the configuration cycle */
-       GT_WRITE(address_reg, address);
-
-       /* read the data */
-       GT_READ(data_reg, val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_pcibios_read_config_word(int bus, int devfn,
-                                           int offset, u16 * val)
-{
-       int dev, func;
-       uint32_t address_reg, data_reg;
-       uint32_t address;
-
-       dev = PCI_SLOT(devfn);
-       func = PCI_FUNC(devfn);
-
-       /* verify the range */
-       if (pci_range_ck(bus, dev))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* select the GT-64240 registers to communicate with the PCI bus */
-       if (bus == 0) {
-               address_reg = PCI_0CONFIGURATION_ADDRESS;
-               data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
-               GT_WRITE(PCI_0ERROR_CAUSE, ~MASTER_ABORT_BIT);
-       } else {
-               address_reg = PCI_1CONFIGURATION_ADDRESS;
-               data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
-               GT_WRITE(PCI_1ERROR_CAUSE, ~MASTER_ABORT_BIT);
-               if (bus == 1)
-                       bus = 0;
-       }
-
-       address = (bus << 16) | (dev << 11) | (func << 8) |
-           (offset & 0xfc) | 0x80000000;
-
-       /* start the configuration cycle */
-       GT_WRITE(address_reg, address);
-
-       /* read the data */
-       GT_READ_16(data_reg + (offset & 0x3), val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_pcibios_read_config_byte(int bus, int devfn,
-                                           int offset, u8 * val)
-{
-       int dev, func;
-       uint32_t address_reg, data_reg;
-       uint32_t address;
-
-       dev = PCI_SLOT(devfn);
-       func = PCI_FUNC(devfn);
-
-       /* verify the range */
-       if (pci_range_ck(bus, dev))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* select the GT-64240 registers to communicate with the PCI bus */
-       if (bus == 0) {
-               address_reg = PCI_0CONFIGURATION_ADDRESS;
-               data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
-       } else {
-               address_reg = PCI_1CONFIGURATION_ADDRESS;
-               data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
-               if (bus == 1)
-                       bus = 0;
-       }
-
-       address = (bus << 16) | (dev << 11) | (func << 8) |
-           (offset & 0xfc) | 0x80000000;
+#define gt_io_size     0x20000000UL
+#define gt_io_base     0xe0000000UL
 
-       /* start the configuration cycle */
-       GT_WRITE(address_reg, address);
-
-       /* write the data */
-       GT_READ_8(data_reg + (offset & 0x3), val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_pcibios_write_config_dword(int bus, int devfn,
-                                             int offset, u32 val)
-{
-       int dev, func;
-       uint32_t address_reg, data_reg;
-       uint32_t address;
-
-       dev = PCI_SLOT(devfn);
-       func = PCI_FUNC(devfn);
-
-       /* verify the range */
-       if (pci_range_ck(bus, dev))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* select the GT-64240 registers to communicate with the PCI bus */
-       if (bus == 0) {
-               address_reg = PCI_0CONFIGURATION_ADDRESS;
-               data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
-       } else {
-               address_reg = PCI_1CONFIGURATION_ADDRESS;
-               data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
-               if (bus == 1)
-                       bus = 0;
-       }
-
-       address = (bus << 16) | (dev << 11) | (func << 8) |
-           (offset & 0xfc) | 0x80000000;
-
-       /* start the configuration cycle */
-       GT_WRITE(address_reg, address);
-
-       /* write the data */
-       GT_WRITE(data_reg, val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_pcibios_write_config_word(int bus, int devfn,
-                                            int offset, u16 val)
-{
-       int dev, func;
-       uint32_t address_reg, data_reg;
-       uint32_t address;
-
-       dev = PCI_SLOT(devfn);
-       func = PCI_FUNC(devfn);
-
-       /* verify the range */
-       if (pci_range_ck(bus, dev))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* select the GT-64240 registers to communicate with the PCI bus */
-       if (bus == 0) {
-               address_reg = PCI_0CONFIGURATION_ADDRESS;
-               data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
-       } else {
-               address_reg = PCI_1CONFIGURATION_ADDRESS;
-               data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
-               if (bus == 1)
-                       bus = 0;
-       }
-
-       address = (bus << 16) | (dev << 11) | (func << 8) |
-           (offset & 0xfc) | 0x80000000;
-
-       /* start the configuration cycle */
-       GT_WRITE(address_reg, address);
-
-       /* write the data */
-       GT_WRITE_16(data_reg + (offset & 0x3), val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_pcibios_write_config_byte(int bus, int devfn,
-                                            int offset, u8 val)
-{
-       int dev, func;
-       uint32_t address_reg, data_reg;
-       uint32_t address;
-
-       dev = PCI_SLOT(devfn);
-       func = PCI_FUNC(devfn);
-
-       /* verify the range */
-       if (pci_range_ck(bus, dev))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* select the GT-64240 registers to communicate with the PCI bus */
-       if (bus == 0) {
-               address_reg = PCI_0CONFIGURATION_ADDRESS;
-               data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER;
-       } else {
-               address_reg = PCI_1CONFIGURATION_ADDRESS;
-               data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER;
-               if (bus == 1)
-                       bus = 0;
-       }
-
-       address = (bus << 16) | (dev << 11) | (func << 8) |
-           (offset & 0xfc) | 0x80000000;
-
-       /* start the configuration cycle */
-       GT_WRITE(address_reg, address);
-
-       /* write the data */
-       GT_WRITE_8(data_reg + (offset & 0x3), val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops galileo_pci_ops = {
-       .read = pci_read,
-       .write = pci_write
+static struct resource gt_pci_mem0_resource = {
+       .name   = "MV64240 PCI0 MEM",
+       .start  = 0xc0000000UL,
+       .end    = 0xcfffffffUL,
+       .flags  = IORESOURCE_MEM
 };
 
-static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
-                   int size, u32 * val)
-{
-       switch (size) {
-       case 1:
-               return galileo_pcibios_read_config_byte(bus->number,
-                                                       devfn, where,
-                                                       (u8 *) val);
-       case 2:
-               return galileo_pcibios_read_config_word(bus->number,
-                                                       devfn, where,
-                                                       (u16 *) val);
-       case 4:
-               return galileo_pcibios_read_config_dword(bus->number,
-                                                        devfn, where,
-                                                        (u32 *) val);
-       }
-       return PCIBIOS_FUNC_NOT_SUPPORTED;
-}
-
-static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
-                    int size, u32 val)
-{
-       switch (size) {
-       case 1:
-               return galileo_pcibios_write_config_byte(bus->number,
-                                                        devfn, where,
-                                                        val);
-       case 2:
-               return galileo_pcibios_write_config_word(bus->number,
-                                                        devfn, where,
-                                                        val);
-       case 4:
-               return galileo_pcibios_write_config_dword(bus->number,
-                                                         devfn, where,
-                                                         val);
-       }
-       return PCIBIOS_FUNC_NOT_SUPPORTED;
-}
-
-struct pci_fixup pcibios_fixups[] = {
-       {0}
+static struct resource gt_pci_io_mem0_resource = {
+       .name   = "MV64240 PCI0 IO MEM",
+       .start  = 0xe0000000UL,
+       .end    = 0xefffffffUL,
+       .flags  = IORESOURCE_IO
 };
 
-void __devinit pcibios_fixup_bus(struct pci_bus *c)
-{
-       gt64240_board_pcibios_fixup_bus(c);
-}
+static struct mv_pci_controller gt_bus0_controller = {
+       .pcic = {
+               .pci_ops        = &mv_pci_ops,
+               .mem_resource   = &gt_pci_mem0_resource,
+               .mem_offset     = 0xc0000000UL,
+               .io_resource    = &gt_pci_io_mem0_resource,
+               .io_offset      = 0x00000000UL
+       },
+       .config_addr    = PCI_0CONFIGURATION_ADDRESS,
+       .config_vreg    = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER,
+};
 
+static struct resource gt_pci_mem1_resource = {
+       .name   = "MV64240 PCI1 MEM",
+       .start  = 0xd0000000UL,
+       .end    = 0xdfffffffUL,
+       .flags  = IORESOURCE_MEM
+};
 
-/********************************************************************
-* pci0P2PConfig - This function set the PCI_0 P2P configurate.
-*                 For more information on the P2P read PCI spec.
-*
-* Inputs:  unsigned int SecondBusLow - Secondery PCI interface Bus Range Lower
-*                                      Boundry.
-*          unsigned int SecondBusHigh - Secondry PCI interface Bus Range upper
-*                                      Boundry.
-*          unsigned int busNum - The CPI bus number to which the PCI interface
-*                                      is connected.
-*          unsigned int devNum - The PCI interface's device number.
-*
-* Returns:  true.
-*/
-void pci0P2PConfig(unsigned int SecondBusLow, unsigned int SecondBusHigh,
-                  unsigned int busNum, unsigned int devNum)
-{
-       uint32_t regData;
+static struct resource gt_pci_io_mem1_resource = {
+       .name   = "MV64240 PCI1 IO MEM",
+       .start  = 0xf0000000UL,
+       .end    = 0xffffffffUL,
+       .flags  = IORESOURCE_IO
+};
 
-       regData = (SecondBusLow & 0xff) | ((SecondBusHigh & 0xff) << 8) |
-           ((busNum & 0xff) << 16) | ((devNum & 0x1f) << 24);
-       GT_WRITE(PCI_0P2P_CONFIGURATION, regData);
-}
+static struct mv_pci_controller gt_bus1_controller = {
+       .pcic = {
+               .pci_ops        = &mv_pci_ops,
+               .mem_resource   = &gt_pci_mem1_resource,
+               .mem_offset     = 0xd0000000UL,
+               .io_resource    = &gt_pci_io_mem1_resource,
+               .io_offset      = 0x10000000UL
+       },
+       .config_addr    = PCI_1CONFIGURATION_ADDRESS,
+       .config_vreg    = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER,
+};
 
-/********************************************************************
-* pci1P2PConfig - This function set the PCI_1 P2P configurate.
-*                 For more information on the P2P read PCI spec.
-*
-* Inputs:  unsigned int SecondBusLow - Secondery PCI interface Bus Range Lower
-*               Boundry.
-*          unsigned int SecondBusHigh - Secondry PCI interface Bus Range upper
-*               Boundry.
-*          unsigned int busNum - The CPI bus number to which the PCI interface
-*               is connected.
-*          unsigned int devNum - The PCI interface's device number.
-*
-* Returns:  true.
-*/
-void pci1P2PConfig(unsigned int SecondBusLow, unsigned int SecondBusHigh,
-                  unsigned int busNum, unsigned int devNum)
+static __init int __init ocelot_g_pci_init(void)
 {
-       uint32_t regData;
+       unsigned long io_v_base;
 
-       regData = (SecondBusLow & 0xff) | ((SecondBusHigh & 0xff) << 8) |
-           ((busNum & 0xff) << 16) | ((devNum & 0x1f) << 24);
-       GT_WRITE(PCI_1P2P_CONFIGURATION, regData);
-}
+       if (gt_io_size) {
+               io_v_base = (unsigned long) ioremap(gt_io_base, gt_io_size);
+               if (!io_v_base)
+                       panic("Could not ioremap I/O port range");
 
-#define PCI0_STATUS_COMMAND_REG                 0x4
-#define PCI1_STATUS_COMMAND_REG                 0x84
-
-static int __init pcibios_init(void)
-{
-       /* Reset PCI I/O and PCI MEM values */
-       ioport_resource.start = 0xe0000000;
-       ioport_resource.end = 0xe0000000 + 0x20000000 - 1;
-       iomem_resource.start = 0xc0000000;
-       iomem_resource.end = 0xc0000000 + 0x20000000 - 1;
+               set_io_port_base(io_v_base);
+       }
 
-       pci_scan_bus(0, &galileo_pci_ops, NULL);
-       pci_scan_bus(1, &galileo_pci_ops, NULL);
+       register_pci_controller(&gt_bus0_controller.pcic);
+       register_pci_controller(&gt_bus1_controller.pcic);
 
        return 0;
 }
 
-subsys_initcall(pcibios_init);
+arch_initcall(ocelot_g_pci_init);