1/* 2 * Copyright (C) 2001,2002,2005 Broadcom Corporation 3 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 */ 19 20#include <linux/types.h> 21#include <linux/pci.h> 22#include <linux/kernel.h> 23#include <linux/init.h> 24#include <linux/mm.h> 25#include <linux/console.h> 26#include <linux/tty.h> 27 28#include <asm/sibyte/bcm1480_regs.h> 29#include <asm/sibyte/bcm1480_scd.h> 30#include <asm/sibyte/board.h> 31#include <asm/io.h> 32 33/* 34 * Macros for calculating offsets into config space given a device 35 * structure or dev/fun/reg 36 */ 37#define CFGOFFSET(bus, devfn, where) (((bus)<<16)+((devfn)<<8)+(where)) 38#define CFGADDR(bus, devfn, where) CFGOFFSET((bus)->number, (devfn), where) 39 40static void *cfg_space; 41 42#define PCI_BUS_ENABLED 1 43#define PCI_DEVICE_MODE 2 44 45static int bcm1480_bus_status; 46 47#define PCI_BRIDGE_DEVICE 0 48 49/* 50 * Read/write 32-bit values in config space. 51 */ 52static inline u32 READCFG32(u32 addr) 53{ 54 return *(u32 *)(cfg_space + (addr&~3)); 55} 56 57static inline void WRITECFG32(u32 addr, u32 data) 58{ 59 *(u32 *)(cfg_space + (addr & ~3)) = data; 60} 61 62int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 63{ 64 if (pin == 0) 65 return -1; 66 67 return K_BCM1480_INT_PCI_INTA - 1 + pin; 68} 69 70/* Do platform specific device initialization at pci_enable_device() time */ 71int pcibios_plat_dev_init(struct pci_dev *dev) 72{ 73 return 0; 74} 75 76/* 77 * Some checks before doing config cycles: 78 * In PCI Device Mode, hide everything on bus 0 except the LDT host 79 * bridge. Otherwise, access is controlled by bridge MasterEn bits. 80 */ 81static int bcm1480_pci_can_access(struct pci_bus *bus, int devfn) 82{ 83 u32 devno; 84 85 if (!(bcm1480_bus_status & (PCI_BUS_ENABLED | PCI_DEVICE_MODE))) 86 return 0; 87 88 if (bus->number == 0) { 89 devno = PCI_SLOT(devfn); 90 if (bcm1480_bus_status & PCI_DEVICE_MODE) 91 return 0; 92 else 93 return 1; 94 } else 95 return 1; 96} 97 98/* 99 * Read/write access functions for various sizes of values 100 * in config space. Return all 1's for disallowed accesses 101 * for a kludgy but adequate simulation of master aborts. 102 */ 103 104static int bcm1480_pcibios_read(struct pci_bus *bus, unsigned int devfn, 105 int where, int size, u32 * val) 106{ 107 u32 data = 0; 108 109 if ((size == 2) && (where & 1)) 110 return PCIBIOS_BAD_REGISTER_NUMBER; 111 else if ((size == 4) && (where & 3)) 112 return PCIBIOS_BAD_REGISTER_NUMBER; 113 114 if (bcm1480_pci_can_access(bus, devfn)) 115 data = READCFG32(CFGADDR(bus, devfn, where)); 116 else 117 data = 0xFFFFFFFF; 118 119 if (size == 1) 120 *val = (data >> ((where & 3) << 3)) & 0xff; 121 else if (size == 2) 122 *val = (data >> ((where & 3) << 3)) & 0xffff; 123 else 124 *val = data; 125 126 return PCIBIOS_SUCCESSFUL; 127} 128 129static int bcm1480_pcibios_write(struct pci_bus *bus, unsigned int devfn, 130 int where, int size, u32 val) 131{ 132 u32 cfgaddr = CFGADDR(bus, devfn, where); 133 u32 data = 0; 134 135 if ((size == 2) && (where & 1)) 136 return PCIBIOS_BAD_REGISTER_NUMBER; 137 else if ((size == 4) && (where & 3)) 138 return PCIBIOS_BAD_REGISTER_NUMBER; 139 140 if (!bcm1480_pci_can_access(bus, devfn)) 141 return PCIBIOS_BAD_REGISTER_NUMBER; 142 143 data = READCFG32(cfgaddr); 144 145 if (size == 1) 146 data = (data & ~(0xff << ((where & 3) << 3))) | 147 (val << ((where & 3) << 3)); 148 else if (size == 2) 149 data = (data & ~(0xffff << ((where & 3) << 3))) | 150 (val << ((where & 3) << 3)); 151 else 152 data = val; 153 154 WRITECFG32(cfgaddr, data); 155 156 return PCIBIOS_SUCCESSFUL; 157} 158 159struct pci_ops bcm1480_pci_ops = { 160 bcm1480_pcibios_read, 161 bcm1480_pcibios_write, 162}; 163 164static struct resource bcm1480_mem_resource = { 165 .name = "BCM1480 PCI MEM", 166 .start = A_BCM1480_PHYS_PCI_MEM_MATCH_BYTES, 167 .end = A_BCM1480_PHYS_PCI_MEM_MATCH_BYTES + 0xfffffffUL, 168 .flags = IORESOURCE_MEM, 169}; 170 171static struct resource bcm1480_io_resource = { 172 .name = "BCM1480 PCI I/O", 173 .start = A_BCM1480_PHYS_PCI_IO_MATCH_BYTES, 174 .end = A_BCM1480_PHYS_PCI_IO_MATCH_BYTES + 0x1ffffffUL, 175 .flags = IORESOURCE_IO, 176}; 177 178struct pci_controller bcm1480_controller = { 179 .pci_ops = &bcm1480_pci_ops, 180 .mem_resource = &bcm1480_mem_resource, 181 .io_resource = &bcm1480_io_resource, 182 .io_offset = A_BCM1480_PHYS_PCI_IO_MATCH_BYTES, 183}; 184 185 186static int __init bcm1480_pcibios_init(void) 187{ 188 uint32_t cmdreg; 189 uint64_t reg; 190 191 /* CFE will assign PCI resources */ 192 pci_probe_only = 1; 193 194 /* Avoid ISA compat ranges. */ 195 PCIBIOS_MIN_IO = 0x00008000UL; 196 PCIBIOS_MIN_MEM = 0x01000000UL; 197 198 /* Set I/O resource limits. - unlimited for now to accomodate HT */ 199 ioport_resource.end = 0xffffffffUL; 200 iomem_resource.end = 0xffffffffUL; 201 202 cfg_space = ioremap(A_BCM1480_PHYS_PCI_CFG_MATCH_BITS, 16*1024*1024); 203 204 /* 205 * See if the PCI bus has been configured by the firmware. 206 */ 207 reg = __raw_readq(IOADDR(A_SCD_SYSTEM_CFG)); 208 if (!(reg & M_BCM1480_SYS_PCI_HOST)) { 209 bcm1480_bus_status |= PCI_DEVICE_MODE; 210 } else { 211 cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 212 PCI_COMMAND)); 213 if (!(cmdreg & PCI_COMMAND_MASTER)) { 214 printk 215 ("PCI: Skipping PCI probe. Bus is not initialized.\n"); 216 iounmap(cfg_space); 217 return 1; 218 } 219 bcm1480_bus_status |= PCI_BUS_ENABLED; 220 } 221 222 /* turn on ExpMemEn */ 223 cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40)); 224 WRITECFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40), 225 cmdreg | 0x10); 226 cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), 0x40)); 227 228 229 bcm1480_controller.io_map_base = (unsigned long) 230 ioremap(A_BCM1480_PHYS_PCI_IO_MATCH_BYTES, 65536); 231 bcm1480_controller.io_map_base -= bcm1480_controller.io_offset; 232 set_io_port_base(bcm1480_controller.io_map_base); 233 234 register_pci_controller(&bcm1480_controller); 235 236#ifdef CONFIG_VGA_CONSOLE 237 take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1); 238#endif 239 return 0; 240} 241 242arch_initcall(bcm1480_pcibios_init); 243