Root/
1 | /* |
2 | * linux/arch/arm/mach-pxa/cm-x2xx-pci.c |
3 | * |
4 | * PCI bios-type initialisation for PCI machines |
5 | * |
6 | * Bits taken from various places. |
7 | * |
8 | * Copyright (C) 2007, 2008 Compulab, Ltd. |
9 | * Mike Rapoport <mike@compulab.co.il> |
10 | * |
11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as |
13 | * published by the Free Software Foundation. |
14 | */ |
15 | |
16 | #include <linux/kernel.h> |
17 | #include <linux/pci.h> |
18 | #include <linux/init.h> |
19 | #include <linux/device.h> |
20 | #include <linux/platform_device.h> |
21 | #include <linux/irq.h> |
22 | #include <linux/gpio.h> |
23 | |
24 | #include <asm/mach/pci.h> |
25 | #include <asm/mach-types.h> |
26 | |
27 | #include <asm/hardware/it8152.h> |
28 | |
29 | unsigned long it8152_base_address; |
30 | static int cmx2xx_it8152_irq_gpio; |
31 | |
32 | /* |
33 | * Only first 64MB of memory can be accessed via PCI. |
34 | * We use GFP_DMA to allocate safe buffers to do map/unmap. |
35 | * This is really ugly and we need a better way of specifying |
36 | * DMA-capable regions of memory. |
37 | */ |
38 | void __init cmx2xx_pci_adjust_zones(unsigned long *zone_size, |
39 | unsigned long *zhole_size) |
40 | { |
41 | unsigned int sz = SZ_64M >> PAGE_SHIFT; |
42 | |
43 | if (machine_is_armcore()) { |
44 | pr_info("Adjusting zones for CM-X2XX\n"); |
45 | |
46 | /* |
47 | * Only adjust if > 64M on current system |
48 | */ |
49 | if (zone_size[0] <= sz) |
50 | return; |
51 | |
52 | zone_size[1] = zone_size[0] - sz; |
53 | zone_size[0] = sz; |
54 | zhole_size[1] = zhole_size[0]; |
55 | zhole_size[0] = 0; |
56 | } |
57 | } |
58 | |
59 | static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc) |
60 | { |
61 | /* clear our parent irq */ |
62 | desc->chip->ack(irq); |
63 | |
64 | it8152_irq_demux(irq, desc); |
65 | } |
66 | |
67 | void __cmx2xx_pci_init_irq(int irq_gpio) |
68 | { |
69 | it8152_init_irq(); |
70 | |
71 | cmx2xx_it8152_irq_gpio = irq_gpio; |
72 | |
73 | set_irq_type(gpio_to_irq(irq_gpio), IRQ_TYPE_EDGE_RISING); |
74 | |
75 | set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx2xx_it8152_irq_demux); |
76 | } |
77 | |
78 | #ifdef CONFIG_PM |
79 | static unsigned long sleep_save_ite[10]; |
80 | |
81 | void __cmx2xx_pci_suspend(void) |
82 | { |
83 | /* save ITE state */ |
84 | sleep_save_ite[0] = __raw_readl(IT8152_INTC_PDCNIMR); |
85 | sleep_save_ite[1] = __raw_readl(IT8152_INTC_LPCNIMR); |
86 | sleep_save_ite[2] = __raw_readl(IT8152_INTC_LPNIAR); |
87 | |
88 | /* Clear ITE IRQ's */ |
89 | __raw_writel((0), IT8152_INTC_PDCNIRR); |
90 | __raw_writel((0), IT8152_INTC_LPCNIRR); |
91 | } |
92 | |
93 | void __cmx2xx_pci_resume(void) |
94 | { |
95 | /* restore IT8152 state */ |
96 | __raw_writel((sleep_save_ite[0]), IT8152_INTC_PDCNIMR); |
97 | __raw_writel((sleep_save_ite[1]), IT8152_INTC_LPCNIMR); |
98 | __raw_writel((sleep_save_ite[2]), IT8152_INTC_LPNIAR); |
99 | } |
100 | #else |
101 | void cmx2xx_pci_suspend(void) {} |
102 | void cmx2xx_pci_resume(void) {} |
103 | #endif |
104 | |
105 | /* PCI IRQ mapping*/ |
106 | static int __init cmx2xx_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) |
107 | { |
108 | int irq; |
109 | |
110 | dev_dbg(&dev->dev, "%s: slot=%x, pin=%x\n", __func__, slot, pin); |
111 | |
112 | irq = it8152_pci_map_irq(dev, slot, pin); |
113 | if (irq) |
114 | return irq; |
115 | |
116 | /* |
117 | Here comes the ugly part. The routing is baseboard specific, |
118 | but defining a platform for each possible base of CM-X2XX is |
119 | unrealistic. Here we keep mapping for ATXBase and SB-X2XX. |
120 | */ |
121 | /* ATXBASE PCI slot */ |
122 | if (slot == 7) |
123 | return IT8152_PCI_INTA; |
124 | |
125 | /* ATXBase/SB-X2XX CardBus */ |
126 | if (slot == 8 || slot == 0) |
127 | return IT8152_PCI_INTB; |
128 | |
129 | /* ATXBase Ethernet */ |
130 | if (slot == 9) |
131 | return IT8152_PCI_INTA; |
132 | |
133 | /* CM-x255 Onboard Ethernet */ |
134 | if (slot == 15) |
135 | return IT8152_PCI_INTC; |
136 | |
137 | /* SB-x2xx Ethernet */ |
138 | if (slot == 16) |
139 | return IT8152_PCI_INTA; |
140 | |
141 | /* PC104+ interrupt routing */ |
142 | if ((slot == 17) || (slot == 19)) |
143 | return IT8152_PCI_INTA; |
144 | if ((slot == 18) || (slot == 20)) |
145 | return IT8152_PCI_INTB; |
146 | |
147 | return(0); |
148 | } |
149 | |
150 | static void cmx2xx_pci_preinit(void) |
151 | { |
152 | pr_info("Initializing CM-X2XX PCI subsystem\n"); |
153 | |
154 | __raw_writel(0x800, IT8152_PCI_CFG_ADDR); |
155 | if (__raw_readl(IT8152_PCI_CFG_DATA) == 0x81521283) { |
156 | pr_info("PCI Bridge found.\n"); |
157 | |
158 | /* set PCI I/O base at 0 */ |
159 | writel(0x848, IT8152_PCI_CFG_ADDR); |
160 | writel(0, IT8152_PCI_CFG_DATA); |
161 | |
162 | /* set PCI memory base at 0 */ |
163 | writel(0x840, IT8152_PCI_CFG_ADDR); |
164 | writel(0, IT8152_PCI_CFG_DATA); |
165 | |
166 | writel(0x20, IT8152_GPIO_GPDR); |
167 | |
168 | /* CardBus Controller on ATXbase baseboard */ |
169 | writel(0x4000, IT8152_PCI_CFG_ADDR); |
170 | if (readl(IT8152_PCI_CFG_DATA) == 0xAC51104C) { |
171 | pr_info("CardBus Bridge found.\n"); |
172 | |
173 | /* Configure socket 0 */ |
174 | writel(0x408C, IT8152_PCI_CFG_ADDR); |
175 | writel(0x1022, IT8152_PCI_CFG_DATA); |
176 | |
177 | writel(0x4080, IT8152_PCI_CFG_ADDR); |
178 | writel(0x3844d060, IT8152_PCI_CFG_DATA); |
179 | |
180 | writel(0x4090, IT8152_PCI_CFG_ADDR); |
181 | writel(((readl(IT8152_PCI_CFG_DATA) & 0xffff) | |
182 | 0x60440000), |
183 | IT8152_PCI_CFG_DATA); |
184 | |
185 | writel(0x4018, IT8152_PCI_CFG_ADDR); |
186 | writel(0xb0000000, IT8152_PCI_CFG_DATA); |
187 | |
188 | /* Configure socket 1 */ |
189 | writel(0x418C, IT8152_PCI_CFG_ADDR); |
190 | writel(0x1022, IT8152_PCI_CFG_DATA); |
191 | |
192 | writel(0x4180, IT8152_PCI_CFG_ADDR); |
193 | writel(0x3844d060, IT8152_PCI_CFG_DATA); |
194 | |
195 | writel(0x4190, IT8152_PCI_CFG_ADDR); |
196 | writel(((readl(IT8152_PCI_CFG_DATA) & 0xffff) | |
197 | 0x60440000), |
198 | IT8152_PCI_CFG_DATA); |
199 | |
200 | writel(0x4118, IT8152_PCI_CFG_ADDR); |
201 | writel(0xb0000000, IT8152_PCI_CFG_DATA); |
202 | } |
203 | } |
204 | } |
205 | |
206 | static struct hw_pci cmx2xx_pci __initdata = { |
207 | .swizzle = pci_std_swizzle, |
208 | .map_irq = cmx2xx_pci_map_irq, |
209 | .nr_controllers = 1, |
210 | .setup = it8152_pci_setup, |
211 | .scan = it8152_pci_scan_bus, |
212 | .preinit = cmx2xx_pci_preinit, |
213 | }; |
214 | |
215 | static int __init cmx2xx_init_pci(void) |
216 | { |
217 | if (machine_is_armcore()) |
218 | pci_common_init(&cmx2xx_pci); |
219 | |
220 | return 0; |
221 | } |
222 | |
223 | subsys_initcall(cmx2xx_init_pci); |
224 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9