Root/target/linux/gemini/patches-3.3/140-arm-gemini-add-pci-support.patch

1--- a/arch/arm/Kconfig
2+++ b/arch/arm/Kconfig
3@@ -379,6 +379,7 @@ config ARCH_GEMINI
4     select CPU_FA526
5     select ARCH_REQUIRE_GPIOLIB
6     select ARCH_USES_GETTIMEOFFSET
7+ select MIGHT_HAVE_PCI
8     help
9       Support for the Cortina Systems Gemini family SoCs
10 
11--- a/arch/arm/mach-gemini/include/mach/hardware.h
12+++ b/arch/arm/mach-gemini/include/mach/hardware.h
13@@ -71,4 +71,9 @@
14  */
15 #define IO_ADDRESS(x) ((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000)
16 
17+/*
18+ * PCI subsystem macros
19+ */
20+#define pcibios_assign_all_busses() 1
21+
22 #endif
23--- a/arch/arm/mach-gemini/include/mach/irqs.h
24+++ b/arch/arm/mach-gemini/include/mach/irqs.h
25@@ -43,11 +43,14 @@
26 
27 #define NORMAL_IRQ_NUM 32
28 
29-#define GPIO_IRQ_BASE NORMAL_IRQ_NUM
30+#define PCI_IRQ_BASE NORMAL_IRQ_NUM
31+#define PCI_IRQ_NUM 4
32+
33+#define GPIO_IRQ_BASE (NORMAL_IRQ_NUM + PCI_IRQ_NUM)
34 #define GPIO_IRQ_NUM (3 * 32)
35 
36 #define ARCH_TIMER_IRQ IRQ_TIMER2
37 
38-#define NR_IRQS (NORMAL_IRQ_NUM + GPIO_IRQ_NUM)
39+#define NR_IRQS (NORMAL_IRQ_NUM + PCI_IRQ_NUM + GPIO_IRQ_NUM)
40 
41 #endif /* __MACH_IRQS_H__ */
42--- a/arch/arm/mach-gemini/Makefile
43+++ b/arch/arm/mach-gemini/Makefile
44@@ -6,6 +6,8 @@
45 
46 obj-y := irq.o mm.o time.o devices.o gpio.o
47 
48+obj-$(CONFIG_PCI) += pci.o
49+
50 # Board-specific support
51 obj-$(CONFIG_MACH_NAS4220B) += board-nas4220b.o
52 obj-$(CONFIG_MACH_RUT100) += board-rut1xx.o
53--- a/arch/arm/mach-gemini/mm.c
54+++ b/arch/arm/mach-gemini/mm.c
55@@ -59,6 +59,11 @@ static struct map_desc gemini_io_desc[]
56         .length = SZ_512K,
57         .type = MT_DEVICE,
58     }, {
59+ .virtual = IO_ADDRESS(GEMINI_PCI_IO_BASE),
60+ .pfn = __phys_to_pfn(GEMINI_PCI_IO_BASE),
61+ .length = SZ_512K,
62+ .type = MT_DEVICE,
63+ }, {
64         .virtual = IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
65         .pfn = __phys_to_pfn(GEMINI_FLASH_CTRL_BASE),
66         .length = SZ_512K,
67--- /dev/null
68+++ b/arch/arm/mach-gemini/pci.c
69@@ -0,0 +1,321 @@
70+/*
71+ * Support for Gemini PCI Controller
72+ *
73+ * Copyright (C) 2009 Janos Laube <janos.dev@gmail.com>
74+ * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
75+ *
76+ * based on SL2312 PCI controller code
77+ * Storlink (C) 2003
78+ *
79+ * This program is free software; you can redistribute it and/or modify
80+ * it under the terms of the GNU General Public License as published by
81+ * the Free Software Foundation; either version 2 of the License, or
82+ * (at your option) any later version.
83+ */
84+
85+#include <linux/kernel.h>
86+#include <linux/pci.h>
87+#include <linux/irq.h>
88+#include <linux/gpio.h>
89+
90+#include <asm/mach/pci.h>
91+
92+#include <mach/irqs.h>
93+#include <mach/hardware.h>
94+
95+#define GEMINI_PCI_IOSIZE_1M 0x0000
96+
97+#define GEMINI_PCI_PMC 0x40
98+#define GEMINI_PCI_PMCSR 0x44
99+#define GEMINI_PCI_CTRL1 0x48
100+#define GEMINI_PCI_CTRL2 0x4C
101+#define GEMINI_PCI_MEM1_BASE_SIZE 0x50
102+#define GEMINI_PCI_MEM2_BASE_SIZE 0x54
103+#define GEMINI_PCI_MEM3_BASE_SIZE 0x58
104+
105+#define PCI_CTRL2_INTSTS_OFFSET 28
106+#define PCI_CTRL2_INTMASK_OFFSET 22
107+
108+#define GEMINI_PCI_DMA_MASK 0xFFF00000
109+#define GEMINI_PCI_DMA_MEM1_BASE 0x00000000
110+#define GEMINI_PCI_DMA_MEM2_BASE 0x00000000
111+#define GEMINI_PCI_DMA_MEM3_BASE 0x00000000
112+#define GEMINI_PCI_DMA_MEM1_SIZE 7
113+#define GEMINI_PCI_DMA_MEM2_SIZE 6
114+#define GEMINI_PCI_DMA_MEM3_SIZE 6
115+
116+#define PCI_CONF_ENABLE (1 << 31)
117+#define PCI_CONF_WHERE(r) ((r) & 0xFC)
118+#define PCI_CONF_BUS(b) (((b) & 0xFF) << 16)
119+#define PCI_CONF_DEVICE(d) (((d) & 0x1F) << 11)
120+#define PCI_CONF_FUNCTION(f) (((f) & 0x07) << 8)
121+
122+#define PCI_IOSIZE_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE))
123+#define PCI_PROT_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x04)
124+#define PCI_CTRL_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x08)
125+#define PCI_SOFTRST_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x10)
126+#define PCI_CONFIG_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x28)
127+#define PCI_DATA_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x2C)
128+
129+
130+static DEFINE_SPINLOCK(gemini_pci_lock);
131+
132+static int gemini_pci_read_config(struct pci_bus* bus, unsigned int fn,
133+ int config, int size, u32* value)
134+{
135+ unsigned long irq_flags;
136+
137+ spin_lock_irqsave(&gemini_pci_lock, irq_flags);
138+
139+ __raw_writel(PCI_CONF_BUS(bus->number) |
140+ PCI_CONF_DEVICE(PCI_SLOT(fn)) |
141+ PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
142+ PCI_CONF_WHERE(config) |
143+ PCI_CONF_ENABLE,
144+ PCI_CONFIG_REG);
145+
146+ *value = __raw_readl(PCI_DATA_REG);
147+
148+ if (size == 1)
149+ *value = (*value >> (8 * (config & 3))) & 0xFF;
150+ else if (size == 2)
151+ *value = (*value >> (8 * (config & 3))) & 0xFFFF;
152+
153+ spin_unlock_irqrestore(&gemini_pci_lock, irq_flags);
154+
155+ dev_dbg(&bus->dev,
156+ "[read] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
157+ PCI_SLOT(fn), PCI_FUNC(fn), config, size, *value);
158+
159+ return PCIBIOS_SUCCESSFUL;
160+}
161+
162+static int gemini_pci_write_config(struct pci_bus* bus, unsigned int fn,
163+ int config, int size, u32 value)
164+{
165+ unsigned long irq_flags = 0;
166+ int ret = PCIBIOS_SUCCESSFUL;
167+
168+ dev_dbg(&bus->dev,
169+ "[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
170+ PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
171+
172+ spin_lock_irqsave(&gemini_pci_lock, irq_flags);
173+
174+ __raw_writel(PCI_CONF_BUS(bus->number) |
175+ PCI_CONF_DEVICE(PCI_SLOT(fn)) |
176+ PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
177+ PCI_CONF_WHERE(config) |
178+ PCI_CONF_ENABLE,
179+ PCI_CONFIG_REG);
180+
181+ switch(size) {
182+ case 4:
183+ __raw_writel(value, PCI_DATA_REG);
184+ break;
185+ case 2:
186+ __raw_writew(value, PCI_DATA_REG + (config & 3));
187+ break;
188+ case 1:
189+ __raw_writeb(value, PCI_DATA_REG + (config & 3));
190+ break;
191+ default:
192+ ret = PCIBIOS_BAD_REGISTER_NUMBER;
193+ }
194+
195+ spin_unlock_irqrestore(&gemini_pci_lock, irq_flags);
196+
197+ return ret;
198+}
199+
200+static struct pci_ops gemini_pci_ops = {
201+ .read = gemini_pci_read_config,
202+ .write = gemini_pci_write_config,
203+};
204+
205+static struct resource gemini_pci_resource_io = {
206+ .name = "PCI I/O Space",
207+ .start = IO_ADDRESS(GEMINI_PCI_IO_BASE),
208+ .end = IO_ADDRESS(GEMINI_PCI_IO_BASE) + SZ_1M - 1,
209+ .flags = IORESOURCE_IO,
210+};
211+
212+static struct resource gemini_pci_resource_mem = {
213+ .name = "PCI Memory Space",
214+ .start = GEMINI_PCI_MEM_BASE,
215+ .end = GEMINI_PCI_MEM_BASE + SZ_128M - 1,
216+ .flags = IORESOURCE_MEM,
217+};
218+
219+static int __init gemini_pci_request_resources(struct pci_sys_data *sys)
220+{
221+ if (request_resource(&ioport_resource, &gemini_pci_resource_io))
222+ goto bad_resources;
223+ if (request_resource(&iomem_resource, &gemini_pci_resource_mem))
224+ goto bad_resources;
225+
226+ pci_add_resource(&sys->resources, &gemini_pci_resource_io);
227+ pci_add_resource(&sys->resources, &gemini_pci_resource_mem);
228+
229+ return 0;
230+
231+bad_resources:
232+ pr_err("Gemini PCI: request_resource() failed. "
233+ "Abort PCI bus enumeration.\n");
234+ return -1;
235+}
236+
237+static int __init gemini_pci_setup(int nr, struct pci_sys_data *sys)
238+{
239+ unsigned int cmd;
240+
241+ pcibios_min_io = 0x100;
242+ pcibios_min_mem = 0;
243+
244+ if ((nr > 0) || gemini_pci_request_resources(sys))
245+ return 0;
246+
247+ /* setup I/O space to 1MB size */
248+ __raw_writel(GEMINI_PCI_IOSIZE_1M, PCI_IOSIZE_REG);
249+
250+ /* setup hostbridge */
251+ cmd = __raw_readl(PCI_CTRL_REG);
252+ cmd |= PCI_COMMAND_IO;
253+ cmd |= PCI_COMMAND_MEMORY;
254+ cmd |= PCI_COMMAND_MASTER;
255+ __raw_writel(cmd, PCI_CTRL_REG);
256+
257+ return 1;
258+}
259+
260+static struct pci_bus* __init gemini_pci_scan_bus(int nr, struct pci_sys_data* sys)
261+{
262+ unsigned int reg = 0;
263+ struct pci_bus* bus = 0;
264+
265+ bus = pci_scan_bus(nr, &gemini_pci_ops, sys);
266+ if (bus) {
267+ dev_dbg(&bus->dev, "setting up PCI DMA\n");
268+ reg = (GEMINI_PCI_DMA_MEM1_BASE & GEMINI_PCI_DMA_MASK)
269+ | (GEMINI_PCI_DMA_MEM1_SIZE << 16);
270+ gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM1_BASE_SIZE, 4, reg);
271+ reg = (GEMINI_PCI_DMA_MEM2_BASE & GEMINI_PCI_DMA_MASK)
272+ | (GEMINI_PCI_DMA_MEM2_SIZE << 16);
273+ gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM2_BASE_SIZE, 4, reg);
274+ reg = (GEMINI_PCI_DMA_MEM3_BASE & GEMINI_PCI_DMA_MASK)
275+ | (GEMINI_PCI_DMA_MEM3_SIZE << 16);
276+ gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM3_BASE_SIZE, 4, reg);
277+ }
278+
279+ return bus;
280+}
281+
282+/* Should work with all boards based on original Storlink EVB */
283+static int __init gemini_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
284+{
285+ if (slot < 9 || slot > 12)
286+ return -1;
287+
288+ return PCI_IRQ_BASE + (((slot - 9) + (pin - 1)) & 0x3);
289+}
290+
291+static struct hw_pci gemini_hw_pci __initdata = {
292+ .nr_controllers = 1,
293+ .setup = gemini_pci_setup,
294+ .scan = gemini_pci_scan_bus,
295+ .swizzle = pci_std_swizzle,
296+ .map_irq = gemini_pci_map_irq,
297+};
298+
299+/* we need this for muxed PCI interrupts handling */
300+static struct pci_bus bogus_pci_bus;
301+
302+static void gemini_pci_ack_irq(struct irq_data *d)
303+{
304+ unsigned int irq = d->irq;
305+ unsigned int reg;
306+
307+ gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
308+ reg &= ~(0xF << PCI_CTRL2_INTSTS_OFFSET);
309+ reg |= 1 << (irq - PCI_IRQ_BASE + PCI_CTRL2_INTSTS_OFFSET);
310+ gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
311+}
312+
313+static void gemini_pci_mask_irq(struct irq_data *d)
314+{
315+ unsigned int irq = d->irq;
316+ unsigned int reg;
317+
318+ gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
319+ reg &= ~((0xF << PCI_CTRL2_INTSTS_OFFSET)
320+ | (1 << (irq - PCI_IRQ_BASE + PCI_CTRL2_INTMASK_OFFSET)));
321+ gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
322+}
323+
324+static void gemini_pci_unmask_irq(struct irq_data *d)
325+{
326+ unsigned int irq = d->irq;
327+ unsigned int reg;
328+
329+ gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
330+ reg &= ~(0xF << PCI_CTRL2_INTSTS_OFFSET);
331+ reg |= 1 << (irq - PCI_IRQ_BASE + PCI_CTRL2_INTMASK_OFFSET);
332+ gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
333+}
334+
335+static void gemini_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
336+{
337+ unsigned int pci_irq_no, irq_stat, reg, i;
338+
339+ gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
340+ irq_stat = reg >> PCI_CTRL2_INTSTS_OFFSET;
341+
342+ for (i = 0; i < 4; i++) {
343+
344+ if ((irq_stat & (1 << i)) == 0)
345+ continue;
346+
347+ pci_irq_no = PCI_IRQ_BASE + i;
348+
349+ BUG_ON(!(irq_desc[pci_irq_no].handle_irq));
350+ irq_desc[pci_irq_no].handle_irq(pci_irq_no,
351+ &irq_desc[pci_irq_no]);
352+ }
353+}
354+
355+static struct irq_chip gemini_pci_irq_chip = {
356+ .name = "PCI",
357+ .irq_ack = gemini_pci_ack_irq,
358+ .irq_mask = gemini_pci_mask_irq,
359+ .irq_unmask = gemini_pci_unmask_irq,
360+};
361+
362+static int __init gemini_pci_init(void)
363+{
364+ int i;
365+
366+ for (i = 72; i <= 95; i++)
367+ gpio_request(i, "PCI");
368+
369+ /* initialize our bogus bus */
370+ dev_set_name(&bogus_pci_bus.dev, "PCI IRQ handler");
371+ bogus_pci_bus.number = 0;
372+
373+ /* mask and clear all interrupts */
374+ gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2 + 2, 2,
375+ 0xF000);
376+
377+ for (i = PCI_IRQ_BASE; i < PCI_IRQ_BASE + 4; i++) {
378+ irq_set_chip_and_handler(i, &gemini_pci_irq_chip,
379+ handle_level_irq);
380+ set_irq_flags(i, IRQF_VALID);
381+ }
382+
383+ irq_set_chained_handler(IRQ_PCI, gemini_pci_irq_handler);
384+
385+ pci_common_init(&gemini_hw_pci);
386+
387+ return 0;
388+}
389+
390+subsys_initcall(gemini_pci_init);
391

Archive Download this file



interactive