27 #include <linux/kernel.h>
29 #include <linux/pci.h>
30 #include <linux/string.h>
36 #include <linux/slab.h>
41 #include <asm/pci-bridge.h>
46 #define MAX_PCI_DEVICES 32
47 #define MAX_PCI_FUNCTIONS 8
48 #define MAX_PCI_BASE_ADDRS 3
61 static inline u8 celleb_fake_config_readb(
void *
addr)
67 static inline u16 celleb_fake_config_readw(
void *
addr)
73 static inline u32 celleb_fake_config_readl(
void *
addr)
79 static inline void celleb_fake_config_writeb(
u32 val,
void *
addr)
85 static inline void celleb_fake_config_writew(
u32 val,
void *
addr)
93 static inline void celleb_fake_config_writel(
u32 val,
void *
addr)
101 static unsigned char *get_fake_config_start(
struct pci_controller *hose,
109 return private->fake_config[
devno][
fn];
121 return private->res[
devno][
fn];
125 static void celleb_config_read_fake(
unsigned char *
config,
int where,
128 char *
p = config + where;
132 *val = celleb_fake_config_readb(p);
135 *val = celleb_fake_config_readw(p);
138 *val = celleb_fake_config_readl(p);
143 static void celleb_config_write_fake(
unsigned char *config,
int where,
146 char *p = config + where;
150 celleb_fake_config_writeb(val, p);
153 celleb_fake_config_writew(val, p);
156 celleb_fake_config_writel(val, p);
161 static int celleb_fake_pci_read_config(
struct pci_bus *
bus,
162 unsigned int devfn,
int where,
int size,
u32 *val)
166 unsigned int devno = devfn >> 3;
167 unsigned int fn = devfn & 0x7;
173 config = get_fake_config_start(hose, devno, fn);
175 pr_debug(
"devno=0x%x, where=0x%x, size=0x%x, ", devno, where, size);
181 celleb_config_read_fake(config, where, size, val);
188 static int celleb_fake_pci_write_config(
struct pci_bus *bus,
189 unsigned int devfn,
int where,
int size,
u32 val)
194 unsigned int devno = devfn >> 3;
195 unsigned int fn = devfn & 0x7;
200 config = get_fake_config_start(hose, devno, fn);
213 res = get_resource_start(hose, devno, fn);
216 celleb_config_write_fake(config, where, size,
217 (res->
r[i].end - res->
r[i].start));
229 celleb_config_write_fake(config, where, size, val);
230 pr_debug(
" fake write: where=%x, size=%d, val=%x\n",
236 static struct pci_ops celleb_fake_pci_ops = {
237 .read = celleb_fake_pci_read_config,
238 .write = celleb_fake_pci_write_config,
241 static inline void celleb_setup_pci_base_addrs(
struct pci_controller *hose,
242 unsigned int devno,
unsigned int fn,
243 unsigned int num_base_addr)
249 config = get_fake_config_start(hose, devno, fn);
250 res = get_resource_start(hose, devno, fn);
255 switch (num_base_addr) {
257 val = (res->
r[2].start & 0xfffffff0)
260 val = res->
r[2].start >> 32;
264 val = (res->
r[1].start & 0xfffffff0)
267 val = res->
r[1].start >> 32;
271 val = (res->
r[0].start & 0xfffffff0)
274 val = res->
r[0].start >> 32;
280 celleb_config_write_fake(config,
PCI_COMMAND, 2, val);
287 int num_base_addr = 0;
289 const u32 *wi0, *wi1, *wi2, *wi3, *wi4;
292 unsigned char **config =
NULL;
295 const unsigned long *
li;
298 if (
private ==
NULL) {
300 "memory space for pci controller is not assigned\n");
314 devno = ((wi4[0] >> 8) & 0xff) >> 3;
315 fn = (wi4[0] >> 8) & 0x7;
317 pr_debug(
"PCI: celleb_setup_fake_pci() %s devno=%x fn=%x\n", name,
321 config = &
private->fake_config[
devno][
fn];
323 if (*config ==
NULL) {
325 "not enough memory for fake configuration space\n");
328 pr_debug(
"PCI: fake config area assigned 0x%016lx\n",
329 (
unsigned long)*config);
332 res = &
private->res[
devno][
fn];
336 "PCI: not enough memory for resource data space\n");
339 pr_debug(
"PCI: res assigned 0x%016lx\n", (
unsigned long)*res);
345 if (!wi0 || !wi1 || !wi2 || !wi3) {
350 celleb_config_write_fake(*config,
PCI_DEVICE_ID, 2, wi0[0] & 0xffff);
351 celleb_config_write_fake(*config,
PCI_VENDOR_ID, 2, wi1[0] & 0xffff);
352 pr_debug(
"class-code = 0x%08x\n", wi2[0]);
354 celleb_config_write_fake(*config,
PCI_CLASS_PROG, 1, wi2[0] & 0xff);
356 (wi2[0] >> 8) & 0xffff);
361 num_base_addr, &(*res)->r[num_base_addr]);
367 celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr);
379 pr_debug(
"PCI: %s irq=%ld\n", name, li[0]);
380 for (i = 0; i < 6; i++) {
381 celleb_config_read_fake(*config,
384 pr_debug(
"PCI: %s fn=%d base_address_%d=0x%x\n",
396 if (config && *config)
402 if (config && *config) {
418 const int *bus_range;
422 if (bus_range ==
NULL || len < 2 *
sizeof(
int))
443 phb->
ops = &celleb_fake_pci_ops;
444 celleb_alloc_private_mem(phb);
448 celleb_setup_fake_pci_device(node, phb);
454 .setup = celleb_setup_fake_pci,
457 static struct of_device_id celleb_phb_match[] __initdata = {
459 .name =
"pci-pseudo",
460 .data = &celleb_fake_pci_spec,
482 phb_set_bus_ranges(dev, phb);
485 phb_spec = match->
data;
486 rc = (*phb_spec->
setup)(dev, phb);
499 return PCI_PROBE_DEVTREE;