Commit | Line | Data |
---|---|---|
e47d4889 JC |
1 | /* |
2 | * This program is free software; you can redistribute it and/or modify it | |
3 | * under the terms of the GNU General Public License version 2 as published | |
4 | * by the Free Software Foundation. | |
5 | * | |
6 | * Copyright (C) 2010 John Crispin <blogic@openwrt.org> | |
7 | */ | |
8 | ||
9 | #include <linux/types.h> | |
10 | #include <linux/pci.h> | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/delay.h> | |
14 | #include <linux/mm.h> | |
15 | #include <linux/vmalloc.h> | |
4af92e7a | 16 | #include <linux/export.h> |
e47d4889 JC |
17 | #include <linux/platform_device.h> |
18 | ||
19 | #include <asm/pci.h> | |
20 | #include <asm/gpio.h> | |
21 | #include <asm/addrspace.h> | |
22 | ||
23 | #include <lantiq_soc.h> | |
24 | #include <lantiq_irq.h> | |
25 | #include <lantiq_platform.h> | |
26 | ||
27 | #include "pci-lantiq.h" | |
28 | ||
29 | #define LTQ_PCI_CFG_BASE 0x17000000 | |
30 | #define LTQ_PCI_CFG_SIZE 0x00008000 | |
31 | #define LTQ_PCI_MEM_BASE 0x18000000 | |
32 | #define LTQ_PCI_MEM_SIZE 0x02000000 | |
33 | #define LTQ_PCI_IO_BASE 0x1AE00000 | |
34 | #define LTQ_PCI_IO_SIZE 0x00200000 | |
35 | ||
36 | #define PCI_CR_FCI_ADDR_MAP0 0x00C0 | |
37 | #define PCI_CR_FCI_ADDR_MAP1 0x00C4 | |
38 | #define PCI_CR_FCI_ADDR_MAP2 0x00C8 | |
39 | #define PCI_CR_FCI_ADDR_MAP3 0x00CC | |
40 | #define PCI_CR_FCI_ADDR_MAP4 0x00D0 | |
41 | #define PCI_CR_FCI_ADDR_MAP5 0x00D4 | |
42 | #define PCI_CR_FCI_ADDR_MAP6 0x00D8 | |
43 | #define PCI_CR_FCI_ADDR_MAP7 0x00DC | |
44 | #define PCI_CR_CLK_CTRL 0x0000 | |
45 | #define PCI_CR_PCI_MOD 0x0030 | |
46 | #define PCI_CR_PC_ARB 0x0080 | |
47 | #define PCI_CR_FCI_ADDR_MAP11hg 0x00E4 | |
48 | #define PCI_CR_BAR11MASK 0x0044 | |
49 | #define PCI_CR_BAR12MASK 0x0048 | |
50 | #define PCI_CR_BAR13MASK 0x004C | |
51 | #define PCI_CS_BASE_ADDR1 0x0010 | |
52 | #define PCI_CR_PCI_ADDR_MAP11 0x0064 | |
53 | #define PCI_CR_FCI_BURST_LENGTH 0x00E8 | |
54 | #define PCI_CR_PCI_EOI 0x002C | |
55 | #define PCI_CS_STS_CMD 0x0004 | |
56 | ||
57 | #define PCI_MASTER0_REQ_MASK_2BITS 8 | |
58 | #define PCI_MASTER1_REQ_MASK_2BITS 10 | |
59 | #define PCI_MASTER2_REQ_MASK_2BITS 12 | |
60 | #define INTERNAL_ARB_ENABLE_BIT 0 | |
61 | ||
62 | #define LTQ_CGU_IFCCR 0x0018 | |
63 | #define LTQ_CGU_PCICR 0x0034 | |
64 | ||
65 | #define ltq_pci_w32(x, y) ltq_w32((x), ltq_pci_membase + (y)) | |
66 | #define ltq_pci_r32(x) ltq_r32(ltq_pci_membase + (x)) | |
67 | ||
68 | #define ltq_pci_cfg_w32(x, y) ltq_w32((x), ltq_pci_mapped_cfg + (y)) | |
69 | #define ltq_pci_cfg_r32(x) ltq_r32(ltq_pci_mapped_cfg + (x)) | |
70 | ||
e47d4889 JC |
71 | __iomem void *ltq_pci_mapped_cfg; |
72 | static __iomem void *ltq_pci_membase; | |
73 | ||
74 | int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL; | |
75 | ||
76 | /* Since the PCI REQ pins can be reused for other functionality, make it | |
77 | possible to exclude those from interpretation by the PCI controller */ | |
78 | static int ltq_pci_req_mask = 0xf; | |
79 | ||
80 | static int *ltq_pci_irq_map; | |
81 | ||
82 | struct pci_ops ltq_pci_ops = { | |
83 | .read = ltq_pci_read_config_dword, | |
84 | .write = ltq_pci_write_config_dword | |
85 | }; | |
86 | ||
87 | static struct resource pci_io_resource = { | |
88 | .name = "pci io space", | |
89 | .start = LTQ_PCI_IO_BASE, | |
90 | .end = LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1, | |
91 | .flags = IORESOURCE_IO | |
92 | }; | |
93 | ||
94 | static struct resource pci_mem_resource = { | |
95 | .name = "pci memory space", | |
96 | .start = LTQ_PCI_MEM_BASE, | |
97 | .end = LTQ_PCI_MEM_BASE + LTQ_PCI_MEM_SIZE - 1, | |
98 | .flags = IORESOURCE_MEM | |
99 | }; | |
100 | ||
101 | static struct pci_controller ltq_pci_controller = { | |
102 | .pci_ops = <q_pci_ops, | |
103 | .mem_resource = &pci_mem_resource, | |
104 | .mem_offset = 0x00000000UL, | |
105 | .io_resource = &pci_io_resource, | |
106 | .io_offset = 0x00000000UL, | |
107 | }; | |
108 | ||
109 | int pcibios_plat_dev_init(struct pci_dev *dev) | |
110 | { | |
111 | if (ltqpci_plat_dev_init) | |
112 | return ltqpci_plat_dev_init(dev); | |
113 | ||
114 | return 0; | |
115 | } | |
116 | ||
117 | static u32 ltq_calc_bar11mask(void) | |
118 | { | |
119 | u32 mem, bar11mask; | |
120 | ||
121 | /* BAR11MASK value depends on available memory on system. */ | |
122 | mem = num_physpages * PAGE_SIZE; | |
123 | bar11mask = (0x0ffffff0 & ~((1 << (fls(mem) - 1)) - 1)) | 8; | |
124 | ||
125 | return bar11mask; | |
126 | } | |
127 | ||
e47d4889 JC |
128 | static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) |
129 | { | |
130 | u32 temp_buffer; | |
131 | ||
132 | /* set clock to 33Mhz */ | |
05969546 JC |
133 | if (ltq_is_ar9()) { |
134 | ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR); | |
135 | ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR); | |
136 | } else { | |
137 | ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR); | |
138 | ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR); | |
139 | } | |
e47d4889 JC |
140 | |
141 | /* external or internal clock ? */ | |
142 | if (conf->clock) { | |
143 | ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16), | |
144 | LTQ_CGU_IFCCR); | |
145 | ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR); | |
146 | } else { | |
147 | ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (1 << 16), | |
148 | LTQ_CGU_IFCCR); | |
149 | ltq_cgu_w32((1 << 31) | (1 << 30), LTQ_CGU_PCICR); | |
150 | } | |
151 | ||
152 | /* setup pci clock and gpis used by pci */ | |
bd51db7f | 153 | gpio_request(21, "pci-reset"); |
e47d4889 JC |
154 | |
155 | /* enable auto-switching between PCI and EBU */ | |
156 | ltq_pci_w32(0xa, PCI_CR_CLK_CTRL); | |
157 | ||
158 | /* busy, i.e. configuration is not done, PCI access has to be retried */ | |
159 | ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) & ~(1 << 24), PCI_CR_PCI_MOD); | |
160 | wmb(); | |
161 | /* BUS Master/IO/MEM access */ | |
162 | ltq_pci_cfg_w32(ltq_pci_cfg_r32(PCI_CS_STS_CMD) | 7, PCI_CS_STS_CMD); | |
163 | ||
164 | /* enable external 2 PCI masters */ | |
165 | temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB); | |
166 | temp_buffer &= (~(ltq_pci_req_mask << 16)); | |
167 | /* enable internal arbiter */ | |
168 | temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT); | |
169 | /* enable internal PCI master reqest */ | |
170 | temp_buffer &= (~(3 << PCI_MASTER0_REQ_MASK_2BITS)); | |
171 | ||
172 | /* enable EBU request */ | |
173 | temp_buffer &= (~(3 << PCI_MASTER1_REQ_MASK_2BITS)); | |
174 | ||
175 | /* enable all external masters request */ | |
176 | temp_buffer &= (~(3 << PCI_MASTER2_REQ_MASK_2BITS)); | |
177 | ltq_pci_w32(temp_buffer, PCI_CR_PC_ARB); | |
178 | wmb(); | |
179 | ||
180 | /* setup BAR memory regions */ | |
181 | ltq_pci_w32(0x18000000, PCI_CR_FCI_ADDR_MAP0); | |
182 | ltq_pci_w32(0x18400000, PCI_CR_FCI_ADDR_MAP1); | |
183 | ltq_pci_w32(0x18800000, PCI_CR_FCI_ADDR_MAP2); | |
184 | ltq_pci_w32(0x18c00000, PCI_CR_FCI_ADDR_MAP3); | |
185 | ltq_pci_w32(0x19000000, PCI_CR_FCI_ADDR_MAP4); | |
186 | ltq_pci_w32(0x19400000, PCI_CR_FCI_ADDR_MAP5); | |
187 | ltq_pci_w32(0x19800000, PCI_CR_FCI_ADDR_MAP6); | |
188 | ltq_pci_w32(0x19c00000, PCI_CR_FCI_ADDR_MAP7); | |
189 | ltq_pci_w32(0x1ae00000, PCI_CR_FCI_ADDR_MAP11hg); | |
190 | ltq_pci_w32(ltq_calc_bar11mask(), PCI_CR_BAR11MASK); | |
191 | ltq_pci_w32(0, PCI_CR_PCI_ADDR_MAP11); | |
192 | ltq_pci_w32(0, PCI_CS_BASE_ADDR1); | |
193 | /* both TX and RX endian swap are enabled */ | |
194 | ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_EOI) | 3, PCI_CR_PCI_EOI); | |
195 | wmb(); | |
196 | ltq_pci_w32(ltq_pci_r32(PCI_CR_BAR12MASK) | 0x80000000, | |
197 | PCI_CR_BAR12MASK); | |
198 | ltq_pci_w32(ltq_pci_r32(PCI_CR_BAR13MASK) | 0x80000000, | |
199 | PCI_CR_BAR13MASK); | |
200 | /*use 8 dw burst length */ | |
201 | ltq_pci_w32(0x303, PCI_CR_FCI_BURST_LENGTH); | |
202 | ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) | (1 << 24), PCI_CR_PCI_MOD); | |
203 | wmb(); | |
204 | ||
205 | /* setup irq line */ | |
206 | ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_CON) | 0xc, LTQ_EBU_PCC_CON); | |
207 | ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN); | |
208 | ||
209 | /* toggle reset pin */ | |
210 | __gpio_set_value(21, 0); | |
211 | wmb(); | |
212 | mdelay(1); | |
213 | __gpio_set_value(21, 1); | |
214 | return 0; | |
215 | } | |
216 | ||
217 | int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | |
218 | { | |
219 | if (ltq_pci_irq_map[slot]) | |
220 | return ltq_pci_irq_map[slot]; | |
221 | printk(KERN_ERR "lq_pci: trying to map irq for unknown slot %d\n", | |
222 | slot); | |
223 | ||
224 | return 0; | |
225 | } | |
226 | ||
227 | static int __devinit ltq_pci_probe(struct platform_device *pdev) | |
228 | { | |
229 | struct ltq_pci_data *ltq_pci_data = | |
230 | (struct ltq_pci_data *) pdev->dev.platform_data; | |
29090606 BH |
231 | |
232 | pci_clear_flags(PCI_PROBE_ONLY); | |
e47d4889 JC |
233 | ltq_pci_irq_map = ltq_pci_data->irq; |
234 | ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE); | |
235 | ltq_pci_mapped_cfg = | |
236 | ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE); | |
237 | ltq_pci_controller.io_map_base = | |
238 | (unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1); | |
239 | ltq_pci_startup(ltq_pci_data); | |
240 | register_pci_controller(<q_pci_controller); | |
241 | ||
242 | return 0; | |
243 | } | |
244 | ||
245 | static struct platform_driver | |
246 | ltq_pci_driver = { | |
247 | .probe = ltq_pci_probe, | |
248 | .driver = { | |
249 | .name = "ltq_pci", | |
250 | .owner = THIS_MODULE, | |
251 | }, | |
252 | }; | |
253 | ||
254 | int __init pcibios_init(void) | |
255 | { | |
256 | int ret = platform_driver_register(<q_pci_driver); | |
257 | if (ret) | |
258 | printk(KERN_INFO "ltq_pci: Error registering platfom driver!"); | |
259 | return ret; | |
260 | } | |
261 | ||
262 | arch_initcall(pcibios_init); |