1/* 2 * Support for PCI on Celleb platform. 3 * 4 * (C) Copyright 2006-2007 TOSHIBA CORPORATION 5 * 6 * This code is based on arch/powerpc/kernel/rtas_pci.c: 7 * Copyright (C) 2001 Dave Engebretsen, IBM Corporation 8 * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with this program; if not, write to the Free Software Foundation, Inc., 22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 25#undef DEBUG 26 27#include <linux/kernel.h> 28#include <linux/threads.h> 29#include <linux/pci.h> 30#include <linux/string.h> 31#include <linux/init.h> 32#include <linux/bootmem.h> 33#include <linux/pci_regs.h> 34#include <linux/of.h> 35#include <linux/of_device.h> 36#include <linux/slab.h> 37 38#include <asm/io.h> 39#include <asm/irq.h> 40#include <asm/prom.h> 41#include <asm/pci-bridge.h> 42#include <asm/ppc-pci.h> 43 44#include "io-workarounds.h" 45#include "celleb_pci.h" 46 47#define MAX_PCI_DEVICES 32 48#define MAX_PCI_FUNCTIONS 8 49#define MAX_PCI_BASE_ADDRS 3 /* use 64 bit address */ 50 51/* definition for fake pci configuration area for GbE, .... ,and etc. */ 52 53struct celleb_pci_resource { 54 struct resource r[MAX_PCI_BASE_ADDRS]; 55}; 56 57struct celleb_pci_private { 58 unsigned char *fake_config[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS]; 59 struct celleb_pci_resource *res[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS]; 60}; 61 62static inline u8 celleb_fake_config_readb(void *addr) 63{ 64 u8 *p = addr; 65 return *p; 66} 67 68static inline u16 celleb_fake_config_readw(void *addr) 69{ 70 __le16 *p = addr; 71 return le16_to_cpu(*p); 72} 73 74static inline u32 celleb_fake_config_readl(void *addr) 75{ 76 __le32 *p = addr; 77 return le32_to_cpu(*p); 78} 79 80static inline void celleb_fake_config_writeb(u32 val, void *addr) 81{ 82 u8 *p = addr; 83 *p = val; 84} 85 86static inline void celleb_fake_config_writew(u32 val, void *addr) 87{ 88 __le16 val16; 89 __le16 *p = addr; 90 val16 = cpu_to_le16(val); 91 *p = val16; 92} 93 94static inline void celleb_fake_config_writel(u32 val, void *addr) 95{ 96 __le32 val32; 97 __le32 *p = addr; 98 val32 = cpu_to_le32(val); 99 *p = val32; 100} 101 102static unsigned char *get_fake_config_start(struct pci_controller *hose, 103 int devno, int fn) 104{ 105 struct celleb_pci_private *private = hose->private_data; 106 107 if (private == NULL) 108 return NULL; 109 110 return private->fake_config[devno][fn]; 111} 112 113static struct celleb_pci_resource *get_resource_start( 114 struct pci_controller *hose, 115 int devno, int fn) 116{ 117 struct celleb_pci_private *private = hose->private_data; 118 119 if (private == NULL) 120 return NULL; 121 122 return private->res[devno][fn]; 123} 124 125 126static void celleb_config_read_fake(unsigned char *config, int where, 127 int size, u32 *val) 128{ 129 char *p = config + where; 130 131 switch (size) { 132 case 1: 133 *val = celleb_fake_config_readb(p); 134 break; 135 case 2: 136 *val = celleb_fake_config_readw(p); 137 break; 138 case 4: 139 *val = celleb_fake_config_readl(p); 140 break; 141 } 142} 143 144static void celleb_config_write_fake(unsigned char *config, int where, 145 int size, u32 val) 146{ 147 char *p = config + where; 148 149 switch (size) { 150 case 1: 151 celleb_fake_config_writeb(val, p); 152 break; 153 case 2: 154 celleb_fake_config_writew(val, p); 155 break; 156 case 4: 157 celleb_fake_config_writel(val, p); 158 break; 159 } 160} 161 162static int celleb_fake_pci_read_config(struct pci_bus *bus, 163 unsigned int devfn, int where, int size, u32 *val) 164{ 165 char *config; 166 struct pci_controller *hose = pci_bus_to_host(bus); 167 unsigned int devno = devfn >> 3; 168 unsigned int fn = devfn & 0x7; 169 170 /* allignment check */ 171 BUG_ON(where % size); 172 173 pr_debug(" fake read: bus=0x%x, ", bus->number); 174 config = get_fake_config_start(hose, devno, fn); 175 176 pr_debug("devno=0x%x, where=0x%x, size=0x%x, ", devno, where, size); 177 if (!config) { 178 pr_debug("failed\n"); 179 return PCIBIOS_DEVICE_NOT_FOUND; 180 } 181 182 celleb_config_read_fake(config, where, size, val); 183 pr_debug("val=0x%x\n", *val); 184 185 return PCIBIOS_SUCCESSFUL; 186} 187 188 189static int celleb_fake_pci_write_config(struct pci_bus *bus, 190 unsigned int devfn, int where, int size, u32 val) 191{ 192 char *config; 193 struct pci_controller *hose = pci_bus_to_host(bus); 194 struct celleb_pci_resource *res; 195 unsigned int devno = devfn >> 3; 196 unsigned int fn = devfn & 0x7; 197 198 /* allignment check */ 199 BUG_ON(where % size); 200 201 config = get_fake_config_start(hose, devno, fn); 202 203 if (!config) 204 return PCIBIOS_DEVICE_NOT_FOUND; 205 206 if (val == ~0) { 207 int i = (where - PCI_BASE_ADDRESS_0) >> 3; 208 209 switch (where) { 210 case PCI_BASE_ADDRESS_0: 211 case PCI_BASE_ADDRESS_2: 212 if (size != 4) 213 return PCIBIOS_DEVICE_NOT_FOUND; 214 res = get_resource_start(hose, devno, fn); 215 if (!res) 216 return PCIBIOS_DEVICE_NOT_FOUND; 217 celleb_config_write_fake(config, where, size, 218 (res->r[i].end - res->r[i].start)); 219 return PCIBIOS_SUCCESSFUL; 220 case PCI_BASE_ADDRESS_1: 221 case PCI_BASE_ADDRESS_3: 222 case PCI_BASE_ADDRESS_4: 223 case PCI_BASE_ADDRESS_5: 224 break; 225 default: 226 break; 227 } 228 } 229 230 celleb_config_write_fake(config, where, size, val); 231 pr_debug(" fake write: where=%x, size=%d, val=%x\n", 232 where, size, val); 233 234 return PCIBIOS_SUCCESSFUL; 235} 236 237static struct pci_ops celleb_fake_pci_ops = { 238 .read = celleb_fake_pci_read_config, 239 .write = celleb_fake_pci_write_config, 240}; 241 242static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose, 243 unsigned int devno, unsigned int fn, 244 unsigned int num_base_addr) 245{ 246 u32 val; 247 unsigned char *config; 248 struct celleb_pci_resource *res; 249 250 config = get_fake_config_start(hose, devno, fn); 251 res = get_resource_start(hose, devno, fn); 252 253 if (!config || !res) 254 return; 255 256 switch (num_base_addr) { 257 case 3: 258 val = (res->r[2].start & 0xfffffff0) 259 | PCI_BASE_ADDRESS_MEM_TYPE_64; 260 celleb_config_write_fake(config, PCI_BASE_ADDRESS_4, 4, val); 261 val = res->r[2].start >> 32; 262 celleb_config_write_fake(config, PCI_BASE_ADDRESS_5, 4, val); 263 /* FALLTHROUGH */ 264 case 2: 265 val = (res->r[1].start & 0xfffffff0) 266 | PCI_BASE_ADDRESS_MEM_TYPE_64; 267 celleb_config_write_fake(config, PCI_BASE_ADDRESS_2, 4, val); 268 val = res->r[1].start >> 32; 269 celleb_config_write_fake(config, PCI_BASE_ADDRESS_3, 4, val); 270 /* FALLTHROUGH */ 271 case 1: 272 val = (res->r[0].start & 0xfffffff0) 273 | PCI_BASE_ADDRESS_MEM_TYPE_64; 274 celleb_config_write_fake(config, PCI_BASE_ADDRESS_0, 4, val); 275 val = res->r[0].start >> 32; 276 celleb_config_write_fake(config, PCI_BASE_ADDRESS_1, 4, val); 277 break; 278 } 279 280 val = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; 281 celleb_config_write_fake(config, PCI_COMMAND, 2, val); 282} 283 284static int __init celleb_setup_fake_pci_device(struct device_node *node, 285 struct pci_controller *hose) 286{ 287 unsigned int rlen; 288 int num_base_addr = 0; 289 u32 val; 290 const u32 *wi0, *wi1, *wi2, *wi3, *wi4; 291 unsigned int devno, fn; 292 struct celleb_pci_private *private = hose->private_data; 293 unsigned char **config = NULL; 294 struct celleb_pci_resource **res = NULL; 295 const char *name; 296 const unsigned long *li; 297 int size, result; 298 299 if (private == NULL) { 300 printk(KERN_ERR "PCI: " 301 "memory space for pci controller is not assigned\n"); 302 goto error; 303 } 304 305 name = of_get_property(node, "model", &rlen); 306 if (!name) { 307 printk(KERN_ERR "PCI: model property not found.\n"); 308 goto error; 309 } 310 311 wi4 = of_get_property(node, "reg", &rlen); 312 if (wi4 == NULL) 313 goto error; 314 315 devno = ((wi4[0] >> 8) & 0xff) >> 3; 316 fn = (wi4[0] >> 8) & 0x7; 317 318 pr_debug("PCI: celleb_setup_fake_pci() %s devno=%x fn=%x\n", name, 319 devno, fn); 320 321 size = 256; 322 config = &private->fake_config[devno][fn]; 323 *config = alloc_maybe_bootmem(size, GFP_KERNEL); 324 if (*config == NULL) { 325 printk(KERN_ERR "PCI: " 326 "not enough memory for fake configuration space\n"); 327 goto error; 328 } 329 pr_debug("PCI: fake config area assigned 0x%016lx\n", 330 (unsigned long)*config); 331 332 size = sizeof(struct celleb_pci_resource); 333 res = &private->res[devno][fn]; 334 *res = alloc_maybe_bootmem(size, GFP_KERNEL); 335 if (*res == NULL) { 336 printk(KERN_ERR 337 "PCI: not enough memory for resource data space\n"); 338 goto error; 339 } 340 pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res); 341 342 wi0 = of_get_property(node, "device-id", NULL); 343 wi1 = of_get_property(node, "vendor-id", NULL); 344 wi2 = of_get_property(node, "class-code", NULL); 345 wi3 = of_get_property(node, "revision-id", NULL); 346 if (!wi0 || !wi1 || !wi2 || !wi3) { 347 printk(KERN_ERR "PCI: Missing device tree properties.\n"); 348 goto error; 349 } 350 351 celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff); 352 celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff); 353 pr_debug("class-code = 0x%08x\n", wi2[0]); 354 355 celleb_config_write_fake(*config, PCI_CLASS_PROG, 1, wi2[0] & 0xff); 356 celleb_config_write_fake(*config, PCI_CLASS_DEVICE, 2, 357 (wi2[0] >> 8) & 0xffff); 358 celleb_config_write_fake(*config, PCI_REVISION_ID, 1, wi3[0]); 359 360 while (num_base_addr < MAX_PCI_BASE_ADDRS) { 361 result = of_address_to_resource(node, 362 num_base_addr, &(*res)->r[num_base_addr]); 363 if (result) 364 break; 365 num_base_addr++; 366 } 367 368 celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr); 369 370 li = of_get_property(node, "interrupts", &rlen); 371 if (!li) { 372 printk(KERN_ERR "PCI: interrupts not found.\n"); 373 goto error; 374 } 375 val = li[0]; 376 celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1); 377 celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val); 378 379#ifdef DEBUG 380 pr_debug("PCI: %s irq=%ld\n", name, li[0]); 381 for (i = 0; i < 6; i++) { 382 celleb_config_read_fake(*config, 383 PCI_BASE_ADDRESS_0 + 0x4 * i, 4, 384 &val); 385 pr_debug("PCI: %s fn=%d base_address_%d=0x%x\n", 386 name, fn, i, val); 387 } 388#endif 389 390 celleb_config_write_fake(*config, PCI_HEADER_TYPE, 1, 391 PCI_HEADER_TYPE_NORMAL); 392 393 return 0; 394 395error: 396 if (mem_init_done) { 397 if (config && *config) 398 kfree(*config); 399 if (res && *res) 400 kfree(*res); 401 402 } else { 403 if (config && *config) { 404 size = 256; 405 free_bootmem((unsigned long)(*config), size); 406 } 407 if (res && *res) { 408 size = sizeof(struct celleb_pci_resource); 409 free_bootmem((unsigned long)(*res), size); 410 } 411 } 412 413 return 1; 414} 415 416static int __init phb_set_bus_ranges(struct device_node *dev, 417 struct pci_controller *phb) 418{ 419 const int *bus_range; 420 unsigned int len; 421 422 bus_range = of_get_property(dev, "bus-range", &len); 423 if (bus_range == NULL || len < 2 * sizeof(int)) 424 return 1; 425 426 phb->first_busno = bus_range[0]; 427 phb->last_busno = bus_range[1]; 428 429 return 0; 430} 431 432static void __init celleb_alloc_private_mem(struct pci_controller *hose) 433{ 434 hose->private_data = 435 alloc_maybe_bootmem(sizeof(struct celleb_pci_private), 436 GFP_KERNEL); 437} 438 439static int __init celleb_setup_fake_pci(struct device_node *dev, 440 struct pci_controller *phb) 441{ 442 struct device_node *node; 443 444 phb->ops = &celleb_fake_pci_ops; 445 celleb_alloc_private_mem(phb); 446 447 for (node = of_get_next_child(dev, NULL); 448 node != NULL; node = of_get_next_child(dev, node)) 449 celleb_setup_fake_pci_device(node, phb); 450 451 return 0; 452} 453 454static struct celleb_phb_spec celleb_fake_pci_spec __initdata = { 455 .setup = celleb_setup_fake_pci, 456}; 457 458static struct of_device_id celleb_phb_match[] __initdata = { 459 { 460 .name = "pci-pseudo", 461 .data = &celleb_fake_pci_spec, 462 }, { 463 .name = "epci", 464 .data = &celleb_epci_spec, 465 }, { 466 .name = "pcie", 467 .data = &celleb_pciex_spec, 468 }, { 469 }, 470}; 471 472static int __init celleb_io_workaround_init(struct pci_controller *phb, 473 struct celleb_phb_spec *phb_spec) 474{ 475 if (phb_spec->ops) { 476 iowa_register_bus(phb, phb_spec->ops, phb_spec->iowa_init, 477 phb_spec->iowa_data); 478 io_workaround_init(); 479 } 480 481 return 0; 482} 483 484int __init celleb_setup_phb(struct pci_controller *phb) 485{ 486 struct device_node *dev = phb->dn; 487 const struct of_device_id *match; 488 struct celleb_phb_spec *phb_spec; 489 int rc; 490 491 match = of_match_node(celleb_phb_match, dev); 492 if (!match) 493 return 1; 494 495 phb_set_bus_ranges(dev, phb); 496 phb->buid = 1; 497 498 phb_spec = match->data; 499 rc = (*phb_spec->setup)(dev, phb); 500 if (rc) 501 return 1; 502 503 return celleb_io_workaround_init(phb, phb_spec); 504} 505 506int celleb_pci_probe_mode(struct pci_bus *bus) 507{ 508 return PCI_PROBE_DEVTREE; 509} 510