1/* 2 * BRIEF MODULE DESCRIPTION 3 * Pb1500 specific pci support. 4 * 5 * Copyright 2001,2002 MontaVista Software Inc. 6 * Author: MontaVista Software, Inc. 7 * ppopov@mvista.com or source@mvista.com 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 * 14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * You should have received a copy of the GNU General Public License along 26 * with this program; if not, write to the Free Software Foundation, Inc., 27 * 675 Mass Ave, Cambridge, MA 02139, USA. 28 */ 29#include <linux/config.h> 30 31#ifdef CONFIG_PCI 32 33#include <linux/types.h> 34#include <linux/pci.h> 35#include <linux/kernel.h> 36#include <linux/init.h> 37 38#include <asm/au1000.h> 39#include <asm/pb1500.h> 40#include <asm/pci_channel.h> 41 42#define PCI_ACCESS_READ 0 43#define PCI_ACCESS_WRITE 1 44 45#undef DEBUG 46#ifdef DEBUG 47#define DBG(x...) printk(x) 48#else 49#define DBG(x...) 50#endif 51 52#ifndef CONFIG_CPU_AU1500 53struct pci_channel mips_pci_channels[] = { 54 {(struct pci_ops *) NULL, (struct resource *) NULL, 55 (struct resource *) NULL, (int) NULL, (int) NULL} 56}; 57#else 58 59/* TBD */ 60static struct resource pci_io_resource = { 61 "pci IO space", 62 Au1500_PCI_IO_START, 63 Au1500_PCI_IO_END, 64 IORESOURCE_IO 65}; 66 67static struct resource pci_mem_resource = { 68 "pci memory space", 69 Au1500_PCI_MEM_START, 70 Au1500_PCI_MEM_END, 71 IORESOURCE_MEM 72}; 73 74extern struct pci_ops pb1500_pci_ops; 75 76struct pci_channel mips_pci_channels[] = { 77 {&pb1500_pci_ops, &pci_io_resource, &pci_mem_resource, (10<<3),(16<<3)}, 78 {(struct pci_ops *) NULL, (struct resource *) NULL, 79 (struct resource *) NULL, (int) NULL, (int) NULL} 80}; 81 82static unsigned long cfg_addr; 83static int config_access(unsigned char access_type, struct pci_dev *dev, 84 unsigned char where, u32 * data) 85{ 86 unsigned char bus = dev->bus->number; 87 unsigned int dev_fn = dev->devfn; 88 unsigned int device, function; 89 unsigned long config, status; 90 static int first = 1; 91 92 /* 93 * 7:3 = slot 94 * 2:0 = function 95 */ 96 97 if (bus != 0) { 98 *data = 0xffffffff; 99 return -1; 100 } 101 102 if (first) { 103 first = 0; 104 cfg_addr = ioremap(Au1500_EXT_CFG, 0x10000000); 105 if (!cfg_addr) 106 printk (KERN_ERR "PCI unable to ioremap cfg space\n"); 107 } 108 109 device = (dev_fn >> 3) & 0x1f; 110 function = dev_fn & 0x7; 111 112 //if (!cfg_addr || (device < 10) || (device > 16)) { 113 if (!cfg_addr || (device > 16)) { 114 *data = 0xffffffff; 115 return -1; 116 } 117 118 au_writel(((0x2000 << 16) | (au_readl(Au1500_PCI_STATCMD) & 0xffff)), 119 Au1500_PCI_STATCMD); 120 //au_writel(au_readl(Au1500_PCI_CFG) & ~PCI_ERROR, Au1500_PCI_CFG); 121 au_sync_udelay(1); 122 123 /* setup the lower 31 bits of the 36 bit address */ 124 config = cfg_addr | 125 ((1<<device)<<11) | (function << 8) | (where & ~0x3); 126 127 128 if (access_type == PCI_ACCESS_WRITE) { 129 au_writel(*data, config); 130 } else { 131 *data = au_readl(config); 132 } 133 au_sync_udelay(1); 134 135 DBG("config_access: %d bus %d device %d at %x *data %x, conf %x\n", 136 access_type, bus, device, where, *data, config); 137 138 /* check master abort */ 139 status = au_readl(Au1500_PCI_STATCMD); 140 if (status & (1<<29)) { 141 *data = 0xffffffff; 142 return -1; 143 } else if ((status >> 28) & 0xf) { 144 DBG("PCI ERR detected: status %x\n", status); 145 *data = 0xffffffff; 146 return -1; 147 } 148 else { 149 return PCIBIOS_SUCCESSFUL; 150 } 151} 152 153 154static int read_config_byte(struct pci_dev *dev, int where, u8 * val) 155{ 156 u32 data; 157 int ret; 158 159 ret = config_access(PCI_ACCESS_READ, dev, where, &data); 160 if (where & 1) data >>= 8; 161 if (where & 2) data >>= 16; 162 *val = data & 0xff; 163 return ret; 164} 165 166 167static int read_config_word(struct pci_dev *dev, int where, u16 * val) 168{ 169 u32 data; 170 int ret; 171 172 ret = config_access(PCI_ACCESS_READ, dev, where, &data); 173 if (where & 2) data >>= 16; 174 *val = data & 0xffff; 175 return ret; 176} 177 178static int read_config_dword(struct pci_dev *dev, int where, u32 * val) 179{ 180 int ret; 181 182 ret = config_access(PCI_ACCESS_READ, dev, where, val); 183 return ret; 184} 185 186 187static int write_config_byte(struct pci_dev *dev, int where, u8 val) 188{ 189 u32 data = 0; 190 191 if (config_access(PCI_ACCESS_READ, dev, where, &data)) 192 return -1; 193 194 data = (data & ~(0xff << ((where & 3) << 3))) | 195 (val << ((where & 3) << 3)); 196 197 if (config_access(PCI_ACCESS_WRITE, dev, where, &data)) 198 return -1; 199 200 return PCIBIOS_SUCCESSFUL; 201} 202 203static int write_config_word(struct pci_dev *dev, int where, u16 val) 204{ 205 u32 data = 0; 206 207 if (where & 1) 208 return PCIBIOS_BAD_REGISTER_NUMBER; 209 210 if (config_access(PCI_ACCESS_READ, dev, where, &data)) 211 return -1; 212 213 data = (data & ~(0xffff << ((where & 3) << 3))) | 214 (val << ((where & 3) << 3)); 215 216 if (config_access(PCI_ACCESS_WRITE, dev, where, &data)) 217 return -1; 218 219 220 return PCIBIOS_SUCCESSFUL; 221} 222 223static int write_config_dword(struct pci_dev *dev, int where, u32 val) 224{ 225 if (where & 3) 226 return PCIBIOS_BAD_REGISTER_NUMBER; 227 228 if (config_access(PCI_ACCESS_WRITE, dev, where, &val)) 229 return -1; 230 231 return PCIBIOS_SUCCESSFUL; 232} 233 234struct pci_ops pb1500_pci_ops = { 235 read_config_byte, 236 read_config_word, 237 read_config_dword, 238 write_config_byte, 239 write_config_word, 240 write_config_dword 241}; 242 243#endif // CONFIG_CPU_AU1500 244#endif /* CONFIG_PCI */ 245 246