root / hw / versatile_pci.c @ 0986ac3b
History | View | Annotate | Download (3.1 kB)
1 | 502a5395 | pbrook | /*
|
---|---|---|---|
2 | 502a5395 | pbrook | * ARM Versatile/PB PCI host controller
|
3 | 502a5395 | pbrook | *
|
4 | 502a5395 | pbrook | * Copyright (c) 2006 CodeSourcery.
|
5 | 502a5395 | pbrook | * Written by Paul Brook
|
6 | 502a5395 | pbrook | *
|
7 | 502a5395 | pbrook | * This code is licenced under the LGPL.
|
8 | 502a5395 | pbrook | */
|
9 | 502a5395 | pbrook | |
10 | 502a5395 | pbrook | #include "vl.h" |
11 | 502a5395 | pbrook | |
12 | 502a5395 | pbrook | static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr) |
13 | 502a5395 | pbrook | { |
14 | 502a5395 | pbrook | return addr & 0xf8ff; |
15 | 502a5395 | pbrook | } |
16 | 502a5395 | pbrook | |
17 | 502a5395 | pbrook | static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr, |
18 | 502a5395 | pbrook | uint32_t val) |
19 | 502a5395 | pbrook | { |
20 | 502a5395 | pbrook | pci_data_write(opaque, vpb_pci_config_addr (addr), val, 1);
|
21 | 502a5395 | pbrook | } |
22 | 502a5395 | pbrook | |
23 | 502a5395 | pbrook | static void pci_vpb_config_writew (void *opaque, target_phys_addr_t addr, |
24 | 502a5395 | pbrook | uint32_t val) |
25 | 502a5395 | pbrook | { |
26 | 502a5395 | pbrook | #ifdef TARGET_WORDS_BIGENDIAN
|
27 | 502a5395 | pbrook | val = bswap16(val); |
28 | 502a5395 | pbrook | #endif
|
29 | 502a5395 | pbrook | pci_data_write(opaque, vpb_pci_config_addr (addr), val, 2);
|
30 | 502a5395 | pbrook | } |
31 | 502a5395 | pbrook | |
32 | 502a5395 | pbrook | static void pci_vpb_config_writel (void *opaque, target_phys_addr_t addr, |
33 | 502a5395 | pbrook | uint32_t val) |
34 | 502a5395 | pbrook | { |
35 | 502a5395 | pbrook | #ifdef TARGET_WORDS_BIGENDIAN
|
36 | 502a5395 | pbrook | val = bswap32(val); |
37 | 502a5395 | pbrook | #endif
|
38 | 502a5395 | pbrook | pci_data_write(opaque, vpb_pci_config_addr (addr), val, 4);
|
39 | 502a5395 | pbrook | } |
40 | 502a5395 | pbrook | |
41 | 502a5395 | pbrook | static uint32_t pci_vpb_config_readb (void *opaque, target_phys_addr_t addr) |
42 | 502a5395 | pbrook | { |
43 | 502a5395 | pbrook | uint32_t val; |
44 | 502a5395 | pbrook | val = pci_data_read(opaque, vpb_pci_config_addr (addr), 1);
|
45 | 502a5395 | pbrook | return val;
|
46 | 502a5395 | pbrook | } |
47 | 502a5395 | pbrook | |
48 | 502a5395 | pbrook | static uint32_t pci_vpb_config_readw (void *opaque, target_phys_addr_t addr) |
49 | 502a5395 | pbrook | { |
50 | 502a5395 | pbrook | uint32_t val; |
51 | 502a5395 | pbrook | val = pci_data_read(opaque, vpb_pci_config_addr (addr), 2);
|
52 | 502a5395 | pbrook | #ifdef TARGET_WORDS_BIGENDIAN
|
53 | 502a5395 | pbrook | val = bswap16(val); |
54 | 502a5395 | pbrook | #endif
|
55 | 502a5395 | pbrook | return val;
|
56 | 502a5395 | pbrook | } |
57 | 502a5395 | pbrook | |
58 | 502a5395 | pbrook | static uint32_t pci_vpb_config_readl (void *opaque, target_phys_addr_t addr) |
59 | 502a5395 | pbrook | { |
60 | 502a5395 | pbrook | uint32_t val; |
61 | 502a5395 | pbrook | val = pci_data_read(opaque, vpb_pci_config_addr (addr), 4);
|
62 | 502a5395 | pbrook | #ifdef TARGET_WORDS_BIGENDIAN
|
63 | 502a5395 | pbrook | val = bswap32(val); |
64 | 502a5395 | pbrook | #endif
|
65 | 502a5395 | pbrook | return val;
|
66 | 502a5395 | pbrook | } |
67 | 502a5395 | pbrook | |
68 | 502a5395 | pbrook | static CPUWriteMemoryFunc *pci_vpb_config_write[] = {
|
69 | 502a5395 | pbrook | &pci_vpb_config_writeb, |
70 | 502a5395 | pbrook | &pci_vpb_config_writew, |
71 | 502a5395 | pbrook | &pci_vpb_config_writel, |
72 | 502a5395 | pbrook | }; |
73 | 502a5395 | pbrook | |
74 | 502a5395 | pbrook | static CPUReadMemoryFunc *pci_vpb_config_read[] = {
|
75 | 502a5395 | pbrook | &pci_vpb_config_readb, |
76 | 502a5395 | pbrook | &pci_vpb_config_readw, |
77 | 502a5395 | pbrook | &pci_vpb_config_readl, |
78 | 502a5395 | pbrook | }; |
79 | 502a5395 | pbrook | |
80 | 502a5395 | pbrook | static void pci_vpb_set_irq(PCIDevice *d, void *pic, int irq_num, int level) |
81 | 502a5395 | pbrook | { |
82 | 502a5395 | pbrook | pic_set_irq_new(pic, 27 + irq_num, level);
|
83 | 502a5395 | pbrook | } |
84 | 502a5395 | pbrook | |
85 | 502a5395 | pbrook | PCIBus *pci_vpb_init(void *pic)
|
86 | 502a5395 | pbrook | { |
87 | 502a5395 | pbrook | PCIBus *s; |
88 | 502a5395 | pbrook | PCIDevice *d; |
89 | 502a5395 | pbrook | int mem_config;
|
90 | 502a5395 | pbrook | |
91 | 502a5395 | pbrook | s = pci_register_bus(pci_vpb_set_irq, pic, 11 << 3); |
92 | 502a5395 | pbrook | /* ??? Register memory space. */
|
93 | 502a5395 | pbrook | |
94 | 502a5395 | pbrook | mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
|
95 | 502a5395 | pbrook | pci_vpb_config_write, s); |
96 | 502a5395 | pbrook | /* Selfconfig area. */
|
97 | 502a5395 | pbrook | cpu_register_physical_memory(0x41000000, 0x10000, mem_config); |
98 | 502a5395 | pbrook | /* Normal config area. */
|
99 | 502a5395 | pbrook | cpu_register_physical_memory(0x42000000, 0x10000, mem_config); |
100 | 502a5395 | pbrook | |
101 | 502a5395 | pbrook | d = pci_register_device(s, "Versatile/PB PCI Controller",
|
102 | 502a5395 | pbrook | sizeof(PCIDevice), -1, NULL, NULL); |
103 | 502a5395 | pbrook | d->config[0x00] = 0xee; // vendor_id |
104 | 502a5395 | pbrook | d->config[0x01] = 0x10; |
105 | 502a5395 | pbrook | d->config[0x02] = 0x00; // device_id |
106 | 502a5395 | pbrook | d->config[0x03] = 0x03; |
107 | 502a5395 | pbrook | d->config[0x04] = 0x00; |
108 | 502a5395 | pbrook | d->config[0x05] = 0x00; |
109 | 502a5395 | pbrook | d->config[0x06] = 0x20; |
110 | 502a5395 | pbrook | d->config[0x07] = 0x02; |
111 | 502a5395 | pbrook | d->config[0x08] = 0x00; // revision |
112 | 502a5395 | pbrook | d->config[0x09] = 0x00; // programming i/f |
113 | 502a5395 | pbrook | d->config[0x0A] = 0x40; // class_sub = pci host |
114 | 502a5395 | pbrook | d->config[0x0B] = 0x0b; // class_base = PCI_bridge |
115 | 502a5395 | pbrook | d->config[0x0D] = 0x10; // latency_timer |
116 | 502a5395 | pbrook | |
117 | 502a5395 | pbrook | return s;
|
118 | 502a5395 | pbrook | } |