diff options
Diffstat (limited to 'arch/powerpc/platforms/fsl_uli1575.c')
-rw-r--r-- | arch/powerpc/platforms/fsl_uli1575.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c new file mode 100644 index 00000000000..afc9141be63 --- /dev/null +++ b/arch/powerpc/platforms/fsl_uli1575.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * ULI M1575 setup code - specific to Freescale boards | ||
3 | * | ||
4 | * Copyright 2007 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/mc146818rtc.h> | ||
17 | |||
18 | #include <asm/system.h> | ||
19 | #include <asm/pci-bridge.h> | ||
20 | |||
21 | #define ULI_PIRQA 0x08 | ||
22 | #define ULI_PIRQB 0x09 | ||
23 | #define ULI_PIRQC 0x0a | ||
24 | #define ULI_PIRQD 0x0b | ||
25 | #define ULI_PIRQE 0x0c | ||
26 | #define ULI_PIRQF 0x0d | ||
27 | #define ULI_PIRQG 0x0e | ||
28 | |||
29 | #define ULI_8259_NONE 0x00 | ||
30 | #define ULI_8259_IRQ1 0x08 | ||
31 | #define ULI_8259_IRQ3 0x02 | ||
32 | #define ULI_8259_IRQ4 0x04 | ||
33 | #define ULI_8259_IRQ5 0x05 | ||
34 | #define ULI_8259_IRQ6 0x07 | ||
35 | #define ULI_8259_IRQ7 0x06 | ||
36 | #define ULI_8259_IRQ9 0x01 | ||
37 | #define ULI_8259_IRQ10 0x03 | ||
38 | #define ULI_8259_IRQ11 0x09 | ||
39 | #define ULI_8259_IRQ12 0x0b | ||
40 | #define ULI_8259_IRQ14 0x0d | ||
41 | #define ULI_8259_IRQ15 0x0f | ||
42 | |||
43 | u8 uli_pirq_to_irq[8] = { | ||
44 | ULI_8259_IRQ9, /* PIRQA */ | ||
45 | ULI_8259_IRQ10, /* PIRQB */ | ||
46 | ULI_8259_IRQ11, /* PIRQC */ | ||
47 | ULI_8259_IRQ12, /* PIRQD */ | ||
48 | ULI_8259_IRQ5, /* PIRQE */ | ||
49 | ULI_8259_IRQ6, /* PIRQF */ | ||
50 | ULI_8259_IRQ7, /* PIRQG */ | ||
51 | ULI_8259_NONE, /* PIRQH */ | ||
52 | }; | ||
53 | |||
54 | /* set in board code if you want this quirks to do something */ | ||
55 | int uses_fsl_uli_m1575; | ||
56 | |||
57 | /* Bridge */ | ||
58 | static void __devinit early_uli5249(struct pci_dev *dev) | ||
59 | { | ||
60 | unsigned char temp; | ||
61 | |||
62 | if (!uses_fsl_uli_m1575) | ||
63 | return; | ||
64 | |||
65 | pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO | | ||
66 | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | ||
67 | |||
68 | /* read/write lock */ | ||
69 | pci_read_config_byte(dev, 0x7c, &temp); | ||
70 | pci_write_config_byte(dev, 0x7c, 0x80); | ||
71 | |||
72 | /* set as P2P bridge */ | ||
73 | pci_write_config_byte(dev, PCI_CLASS_PROG, 0x01); | ||
74 | dev->class |= 0x1; | ||
75 | |||
76 | /* restore lock */ | ||
77 | pci_write_config_byte(dev, 0x7c, temp); | ||
78 | } | ||
79 | |||
80 | |||
81 | static void __devinit quirk_uli1575(struct pci_dev *dev) | ||
82 | { | ||
83 | int i; | ||
84 | |||
85 | if (!uses_fsl_uli_m1575) | ||
86 | return; | ||
87 | |||
88 | /* | ||
89 | * ULI1575 interrupts route setup | ||
90 | */ | ||
91 | |||
92 | /* ULI1575 IRQ mapping conf register maps PIRQx to IRQn */ | ||
93 | for (i = 0; i < 4; i++) { | ||
94 | u8 val = uli_pirq_to_irq[i*2] | (uli_pirq_to_irq[i*2+1] << 4); | ||
95 | pci_write_config_byte(dev, 0x48 + i, val); | ||
96 | } | ||
97 | |||
98 | /* USB 1.1 OHCI controller 1: dev 28, func 0 - IRQ12 */ | ||
99 | pci_write_config_byte(dev, 0x86, ULI_PIRQD); | ||
100 | |||
101 | /* USB 1.1 OHCI controller 2: dev 28, func 1 - IRQ9 */ | ||
102 | pci_write_config_byte(dev, 0x87, ULI_PIRQA); | ||
103 | |||
104 | /* USB 1.1 OHCI controller 3: dev 28, func 2 - IRQ10 */ | ||
105 | pci_write_config_byte(dev, 0x88, ULI_PIRQB); | ||
106 | |||
107 | /* Lan controller: dev 27, func 0 - IRQ6 */ | ||
108 | pci_write_config_byte(dev, 0x89, ULI_PIRQF); | ||
109 | |||
110 | /* AC97 Audio controller: dev 29, func 0 - IRQ6 */ | ||
111 | pci_write_config_byte(dev, 0x8a, ULI_PIRQF); | ||
112 | |||
113 | /* Modem controller: dev 29, func 1 - IRQ6 */ | ||
114 | pci_write_config_byte(dev, 0x8b, ULI_PIRQF); | ||
115 | |||
116 | /* HD Audio controller: dev 29, func 2 - IRQ6 */ | ||
117 | pci_write_config_byte(dev, 0x8c, ULI_PIRQF); | ||
118 | |||
119 | /* SATA controller: dev 31, func 1 - IRQ5 */ | ||
120 | pci_write_config_byte(dev, 0x8d, ULI_PIRQE); | ||
121 | |||
122 | /* SMB interrupt: dev 30, func 1 - IRQ7 */ | ||
123 | pci_write_config_byte(dev, 0x8e, ULI_PIRQG); | ||
124 | |||
125 | /* PMU ACPI SCI interrupt: dev 30, func 2 - IRQ7 */ | ||
126 | pci_write_config_byte(dev, 0x8f, ULI_PIRQG); | ||
127 | |||
128 | /* USB 2.0 controller: dev 28, func 3 */ | ||
129 | pci_write_config_byte(dev, 0x74, ULI_8259_IRQ11); | ||
130 | |||
131 | /* Primary PATA IDE IRQ: 14 | ||
132 | * Secondary PATA IDE IRQ: 15 | ||
133 | */ | ||
134 | pci_write_config_byte(dev, 0x44, 0x30 | ULI_8259_IRQ14); | ||
135 | pci_write_config_byte(dev, 0x75, ULI_8259_IRQ15); | ||
136 | } | ||
137 | |||
138 | static void __devinit quirk_final_uli1575(struct pci_dev *dev) | ||
139 | { | ||
140 | /* Set i8259 interrupt trigger | ||
141 | * IRQ 3: Level | ||
142 | * IRQ 4: Level | ||
143 | * IRQ 5: Level | ||
144 | * IRQ 6: Level | ||
145 | * IRQ 7: Level | ||
146 | * IRQ 9: Level | ||
147 | * IRQ 10: Level | ||
148 | * IRQ 11: Level | ||
149 | * IRQ 12: Level | ||
150 | * IRQ 14: Edge | ||
151 | * IRQ 15: Edge | ||
152 | */ | ||
153 | if (!uses_fsl_uli_m1575) | ||
154 | return; | ||
155 | |||
156 | outb(0xfa, 0x4d0); | ||
157 | outb(0x1e, 0x4d1); | ||
158 | |||
159 | /* setup RTC */ | ||
160 | CMOS_WRITE(RTC_SET, RTC_CONTROL); | ||
161 | CMOS_WRITE(RTC_24H, RTC_CONTROL); | ||
162 | |||
163 | /* ensure month, date, and week alarm fields are ignored */ | ||
164 | CMOS_WRITE(0, RTC_VALID); | ||
165 | |||
166 | outb_p(0x7c, 0x72); | ||
167 | outb_p(RTC_ALARM_DONT_CARE, 0x73); | ||
168 | |||
169 | outb_p(0x7d, 0x72); | ||
170 | outb_p(RTC_ALARM_DONT_CARE, 0x73); | ||
171 | } | ||
172 | |||
173 | /* SATA */ | ||
174 | static void __devinit quirk_uli5288(struct pci_dev *dev) | ||
175 | { | ||
176 | unsigned char c; | ||
177 | unsigned int d; | ||
178 | |||
179 | if (!uses_fsl_uli_m1575) | ||
180 | return; | ||
181 | |||
182 | /* read/write lock */ | ||
183 | pci_read_config_byte(dev, 0x83, &c); | ||
184 | pci_write_config_byte(dev, 0x83, c|0x80); | ||
185 | |||
186 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &d); | ||
187 | d = (d & 0xff) | (PCI_CLASS_STORAGE_SATA_AHCI << 8); | ||
188 | pci_write_config_dword(dev, PCI_CLASS_REVISION, d); | ||
189 | |||
190 | /* restore lock */ | ||
191 | pci_write_config_byte(dev, 0x83, c); | ||
192 | |||
193 | /* disable emulated PATA mode enabled */ | ||
194 | pci_read_config_byte(dev, 0x84, &c); | ||
195 | pci_write_config_byte(dev, 0x84, c & ~0x01); | ||
196 | } | ||
197 | |||
198 | /* PATA */ | ||
199 | static void __devinit quirk_uli5229(struct pci_dev *dev) | ||
200 | { | ||
201 | unsigned short temp; | ||
202 | |||
203 | if (!uses_fsl_uli_m1575) | ||
204 | return; | ||
205 | |||
206 | pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE | | ||
207 | PCI_COMMAND_MASTER | PCI_COMMAND_IO); | ||
208 | |||
209 | /* Enable Native IRQ 14/15 */ | ||
210 | pci_read_config_word(dev, 0x4a, &temp); | ||
211 | pci_write_config_word(dev, 0x4a, temp | 0x1000); | ||
212 | } | ||
213 | |||
214 | /* We have to do a dummy read on the P2P for the RTC to work, WTF */ | ||
215 | static void __devinit quirk_final_uli5249(struct pci_dev *dev) | ||
216 | { | ||
217 | int i; | ||
218 | u8 *dummy; | ||
219 | struct pci_bus *bus = dev->bus; | ||
220 | |||
221 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | ||
222 | if ((bus->resource[i]) && | ||
223 | (bus->resource[i]->flags & IORESOURCE_MEM)) { | ||
224 | dummy = ioremap(bus->resource[i]->start, 0x4); | ||
225 | if (dummy) { | ||
226 | in_8(dummy); | ||
227 | iounmap(dummy); | ||
228 | } | ||
229 | break; | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | |||
234 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249); | ||
235 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575); | ||
236 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288); | ||
237 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); | ||
238 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5249, quirk_final_uli5249); | ||
239 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x1575, quirk_final_uli1575); | ||
240 | |||
241 | int uli_exclude_device(struct pci_controller *hose, | ||
242 | u_char bus, u_char devfn) | ||
243 | { | ||
244 | if (bus == (hose->first_busno + 2)) { | ||
245 | /* exclude Modem controller */ | ||
246 | if ((PCI_SLOT(devfn) == 29) && (PCI_FUNC(devfn) == 1)) | ||
247 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
248 | |||
249 | /* exclude HD Audio controller */ | ||
250 | if ((PCI_SLOT(devfn) == 29) && (PCI_FUNC(devfn) == 2)) | ||
251 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
252 | } | ||
253 | |||
254 | return PCIBIOS_SUCCESSFUL; | ||
255 | } | ||