| 1 | #include <linux/types.h> |
| 2 | #include <linux/pci.h> |
| 3 | #include <linux/kernel.h> |
| 4 | #include <linux/init.h> |
| 5 | #include <linux/delay.h> |
| 6 | #include <linux/mm.h> |
| 7 | #include <asm/addrspace.h> |
| 8 | #include <linux/vmalloc.h> |
| 9 | #include <ifxmips.h> |
| 10 | #include <ifxmips_irq.h> |
| 11 | #include <ifxmips_cgu.h> |
| 12 | |
| 13 | #define IFXMIPS_PCI_MEM_BASE 0x18000000 |
| 14 | #define IFXMIPS_PCI_MEM_SIZE 0x02000000 |
| 15 | #define IFXMIPS_PCI_IO_BASE 0x1AE00000 |
| 16 | #define IFXMIPS_PCI_IO_SIZE 0x00200000 |
| 17 | |
| 18 | extern int ifxmips_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val); |
| 19 | extern int ifxmips_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val); |
| 20 | |
| 21 | struct pci_ops ifxmips_pci_ops = |
| 22 | { |
| 23 | .read = ifxmips_pci_read_config_dword, |
| 24 | .write = ifxmips_pci_write_config_dword |
| 25 | }; |
| 26 | |
| 27 | static struct resource pci_io_resource = |
| 28 | { |
| 29 | .name = "io pci IO space", |
| 30 | .start = IFXMIPS_PCI_IO_BASE, |
| 31 | .end = IFXMIPS_PCI_IO_BASE + IFXMIPS_PCI_IO_SIZE - 1, |
| 32 | .flags = IORESOURCE_IO |
| 33 | }; |
| 34 | |
| 35 | static struct resource pci_mem_resource = |
| 36 | { |
| 37 | .name = "ext pci memory space", |
| 38 | .start = IFXMIPS_PCI_MEM_BASE, |
| 39 | .end = IFXMIPS_PCI_MEM_BASE + IFXMIPS_PCI_MEM_SIZE - 1, |
| 40 | .flags = IORESOURCE_MEM |
| 41 | }; |
| 42 | |
| 43 | static struct pci_controller ifxmips_pci_controller = |
| 44 | { |
| 45 | .pci_ops = &ifxmips_pci_ops, |
| 46 | .mem_resource = &pci_mem_resource, |
| 47 | .mem_offset = 0x00000000UL, |
| 48 | .io_resource = &pci_io_resource, |
| 49 | .io_offset = 0x00000000UL, |
| 50 | }; |
| 51 | |
| 52 | /* the cpu can can generate the 33Mhz or rely on an external clock the cgu needs the |
| 53 | proper setting, otherwise the cpu hangs. we have no way of runtime detecting this */ |
| 54 | u32 ifxmips_pci_mapped_cfg; |
| 55 | int ifxmips_pci_external_clock = 0; |
| 56 | |
| 57 | /* Since the PCI REQ pins can be reused for other functionality, make it possible |
| 58 | to exclude those from interpretation by the PCI controller */ |
| 59 | int ifxmips_pci_req_mask = 0xf; |
| 60 | |
| 61 | static int __init |
| 62 | ifxmips_pci_set_external_clk(char *str) |
| 63 | { |
| 64 | printk("cgu: setting up external pci clock\n"); |
| 65 | ifxmips_pci_external_clock = 1; |
| 66 | return 1; |
| 67 | } |
| 68 | __setup("pci_external_clk", ifxmips_pci_set_external_clk); |
| 69 | |
| 70 | int |
| 71 | pcibios_plat_dev_init(struct pci_dev *dev) |
| 72 | { |
| 73 | u8 pin; |
| 74 | |
| 75 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); |
| 76 | switch(pin) |
| 77 | { |
| 78 | case 0: |
| 79 | break; |
| 80 | case 1: |
| 81 | //falling edge level triggered:0x4, low level:0xc, rising edge:0x2 |
| 82 | ifxmips_w32(ifxmips_r32(IFXMIPS_EBU_PCC_CON) | 0xc, IFXMIPS_EBU_PCC_CON); |
| 83 | ifxmips_w32(ifxmips_r32(IFXMIPS_EBU_PCC_IEN) | 0x10, IFXMIPS_EBU_PCC_IEN); |
| 84 | break; |
| 85 | case 2: |
| 86 | case 3: |
| 87 | case 4: |
| 88 | printk ("WARNING: interrupt pin %d not supported yet!\n", pin); |
| 89 | default: |
| 90 | printk ("WARNING: invalid interrupt pin %d\n", pin); |
| 91 | return 1; |
| 92 | } |
| 93 | return 0; |
| 94 | } |
| 95 | |
| 96 | static u32 calc_bar11mask(void) |
| 97 | { |
| 98 | u32 mem, bar11mask; |
| 99 | |
| 100 | /* BAR11MASK value depends on available memory on system. */ |
| 101 | mem = num_physpages * PAGE_SIZE; |
| 102 | bar11mask = (0x0ffffff0 & ~((1 << (fls(mem) -1)) -1)) | 8; |
| 103 | |
| 104 | return bar11mask; |
| 105 | } |
| 106 | |
| 107 | static void __init |
| 108 | ifxmips_pci_startup(void) |
| 109 | { |
| 110 | u32 temp_buffer; |
| 111 | |
| 112 | cgu_setup_pci_clk(ifxmips_pci_external_clock); |
| 113 | |
| 114 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OUT) | (1 << 5), IFXMIPS_GPIO_P1_OUT); |
| 115 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OD) | (1 << 5), IFXMIPS_GPIO_P1_OD); |
| 116 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_DIR) | (1 << 5), IFXMIPS_GPIO_P1_DIR); |
| 117 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL1) & ~(1 << 5), IFXMIPS_GPIO_P1_ALTSEL1); |
| 118 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL0) & ~(1 << 5), IFXMIPS_GPIO_P1_ALTSEL0); |
| 119 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_DIR) & ~0x2000, IFXMIPS_GPIO_P1_DIR); |
| 120 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_DIR) | 0x4000, IFXMIPS_GPIO_P1_DIR); |
| 121 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL1) & ~0x6000, IFXMIPS_GPIO_P1_ALTSEL1); |
| 122 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL0) | 0x6000, IFXMIPS_GPIO_P1_ALTSEL0); |
| 123 | /* enable auto-switching between PCI and EBU */ |
| 124 | ifxmips_w32(0xa, PCI_CR_CLK_CTRL); |
| 125 | /* busy, i.e. configuration is not done, PCI access has to be retried */ |
| 126 | ifxmips_w32(ifxmips_r32(PCI_CR_PCI_MOD) & ~(1 << 24), PCI_CR_PCI_MOD); |
| 127 | wmb (); |
| 128 | /* BUS Master/IO/MEM access */ |
| 129 | ifxmips_w32(ifxmips_r32(PCI_CS_STS_CMD) | 7, PCI_CS_STS_CMD); |
| 130 | |
| 131 | /* enable external 2 PCI masters */ |
| 132 | temp_buffer = ifxmips_r32(PCI_CR_PC_ARB); |
| 133 | temp_buffer &= (~(ifxmips_pci_req_mask << 16)); |
| 134 | /* enable internal arbiter */ |
| 135 | temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT); |
| 136 | /* enable internal PCI master reqest */ |
| 137 | temp_buffer &= (~(3 << PCI_MASTER0_REQ_MASK_2BITS)); |
| 138 | |
| 139 | /* enable EBU reqest */ |
| 140 | temp_buffer &= (~(3 << PCI_MASTER1_REQ_MASK_2BITS)); |
| 141 | |
| 142 | /* enable all external masters request */ |
| 143 | temp_buffer &= (~(3 << PCI_MASTER2_REQ_MASK_2BITS)); |
| 144 | ifxmips_w32(temp_buffer, PCI_CR_PC_ARB); |
| 145 | wmb (); |
| 146 | |
| 147 | ifxmips_w32(0x18000000, PCI_CR_FCI_ADDR_MAP0); |
| 148 | ifxmips_w32(0x18400000, PCI_CR_FCI_ADDR_MAP1); |
| 149 | ifxmips_w32(0x18800000, PCI_CR_FCI_ADDR_MAP2); |
| 150 | ifxmips_w32(0x18c00000, PCI_CR_FCI_ADDR_MAP3); |
| 151 | ifxmips_w32(0x19000000, PCI_CR_FCI_ADDR_MAP4); |
| 152 | ifxmips_w32(0x19400000, PCI_CR_FCI_ADDR_MAP5); |
| 153 | ifxmips_w32(0x19800000, PCI_CR_FCI_ADDR_MAP6); |
| 154 | ifxmips_w32(0x19c00000, PCI_CR_FCI_ADDR_MAP7); |
| 155 | ifxmips_w32(0x1ae00000, PCI_CR_FCI_ADDR_MAP11hg); |
| 156 | ifxmips_w32(calc_bar11mask(), PCI_CR_BAR11MASK); |
| 157 | ifxmips_w32(0, PCI_CR_PCI_ADDR_MAP11); |
| 158 | ifxmips_w32(0, PCI_CS_BASE_ADDR1); |
| 159 | #ifdef CONFIG_SWAP_IO_SPACE |
| 160 | /* both TX and RX endian swap are enabled */ |
| 161 | ifxmips_w32(ifxmips_r32(PCI_CR_PCI_EOI) | 3, PCI_CR_PCI_EOI); |
| 162 | wmb (); |
| 163 | #endif |
| 164 | /*TODO: disable BAR2 & BAR3 - why was this in the origianl infineon code */ |
| 165 | ifxmips_w32(ifxmips_r32(PCI_CR_BAR12MASK) | 0x80000000, PCI_CR_BAR12MASK); |
| 166 | ifxmips_w32(ifxmips_r32(PCI_CR_BAR13MASK) | 0x80000000, PCI_CR_BAR13MASK); |
| 167 | /*use 8 dw burst length */ |
| 168 | ifxmips_w32(0x303, PCI_CR_FCI_BURST_LENGTH); |
| 169 | ifxmips_w32(ifxmips_r32(PCI_CR_PCI_MOD) | (1 << 24), PCI_CR_PCI_MOD); |
| 170 | wmb(); |
| 171 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OUT) & ~(1 << 5), IFXMIPS_GPIO_P1_OUT); |
| 172 | wmb(); |
| 173 | mdelay(1); |
| 174 | ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OUT) | (1 << 5), IFXMIPS_GPIO_P1_OUT); |
| 175 | } |
| 176 | |
| 177 | int __init |
| 178 | pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin){ |
| 179 | switch(slot) |
| 180 | { |
| 181 | case 13: |
| 182 | /* IDSEL = AD29 --> USB Host Controller */ |
| 183 | return (INT_NUM_IM1_IRL0 + 17); |
| 184 | case 14: |
| 185 | /* IDSEL = AD30 --> mini PCI connector */ |
| 186 | return (INT_NUM_IM0_IRL0 + 22); |
| 187 | default: |
| 188 | printk("Warning: no IRQ found for PCI device in slot %d, pin %d\n", slot, pin); |
| 189 | return 0; |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | int __init |
| 194 | pcibios_init(void) |
| 195 | { |
| 196 | extern int pci_probe_only; |
| 197 | |
| 198 | pci_probe_only = 0; |
| 199 | printk("PCI: Probing PCI hardware on host bus 0.\n"); |
| 200 | ifxmips_pci_startup (); |
| 201 | ifxmips_pci_mapped_cfg = (u32)ioremap_nocache(0x17000000, 0x800 * 16); |
| 202 | printk("IFXMips PCI mapped to 0x%08lX\n", (unsigned long)ifxmips_pci_mapped_cfg); |
| 203 | ifxmips_pci_controller.io_map_base = (unsigned long)ioremap(IFXMIPS_PCI_IO_BASE, IFXMIPS_PCI_IO_SIZE - 1); |
| 204 | printk("IFXMips PCI I/O mapped to 0x%08lX\n", (unsigned long)ifxmips_pci_controller.io_map_base); |
| 205 | register_pci_controller(&ifxmips_pci_controller); |
| 206 | return 0; |
| 207 | } |
| 208 | |
| 209 | arch_initcall(pcibios_init); |
| 210 | |