aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAaron Sierra <asierra@xes-inc.com>2012-03-28 10:43:10 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-01 06:00:21 -0400
commit4630b130b30be6420394ba31121e111c8771ca08 (patch)
treefce77d11a96017ff4cea9fe1e7ecb5d082354677 /drivers
parentf4bf7cf4cab90c98fe68a7afa12fb72790fd04bf (diff)
mfd: Add LPC driver for Intel ICH chipsets
This driver currently creates resources for use by a forthcoming ICH chipset GPIO driver. It could be expanded to create the resources for converting the esb2rom (mtd) and iTCO_wdt (wdt), and potentially more, drivers to use the mfd model. Signed-off-by: Aaron Sierra <asierra@xes-inc.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/Kconfig9
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/lpc_ich.c719
3 files changed, 729 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 11e44386fa9b..c6edba69678a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -748,6 +748,15 @@ config LPC_SCH
748 LPC bridge function of the Intel SCH provides support for 748 LPC bridge function of the Intel SCH provides support for
749 System Management Bus and General Purpose I/O. 749 System Management Bus and General Purpose I/O.
750 750
751config LPC_ICH
752 tristate "Intel ICH LPC"
753 depends on PCI
754 select MFD_CORE
755 help
756 The LPC bridge function of the Intel ICH provides support for
757 many functional units. This driver provides needed support for
758 other drivers to control these functions, currently GPIO.
759
751config MFD_RDC321X 760config MFD_RDC321X
752 tristate "Support for RDC-R321x southbridge" 761 tristate "Support for RDC-R321x southbridge"
753 select MFD_CORE 762 select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 05fa538c5efe..c4500c35d5ba 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -99,6 +99,7 @@ obj-$(CONFIG_MFD_DB5500_PRCMU) += db5500-prcmu.o
99obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o 99obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
100obj-$(CONFIG_PMIC_ADP5520) += adp5520.o 100obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
101obj-$(CONFIG_LPC_SCH) += lpc_sch.o 101obj-$(CONFIG_LPC_SCH) += lpc_sch.o
102obj-$(CONFIG_LPC_ICH) += lpc_ich.o
102obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o 103obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o
103obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o 104obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o
104obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o 105obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
new file mode 100644
index 000000000000..7e3a7b6ab022
--- /dev/null
+++ b/drivers/mfd/lpc_ich.c
@@ -0,0 +1,719 @@
1/*
2 * lpc_ich.c - LPC interface for Intel ICH
3 *
4 * LPC bridge function of the Intel ICH contains many other
5 * functional units, such as Interrupt controllers, Timers,
6 * Power Management, System Management, GPIO, RTC, and LPC
7 * Configuration Registers.
8 *
9 * This driver is derived from lpc_sch.
10
11 * Copyright (c) 2011 Extreme Engineering Solution, Inc.
12 * Author: Aaron Sierra <asierra@xes-inc.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License 2 as published
16 * by the Free Software Foundation.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; see the file COPYING. If not, write to
25 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 * This driver supports the following I/O Controller hubs:
28 * (See the intel documentation on http://developer.intel.com.)
29 * document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO)
30 * document number 290687-002, 298242-027: 82801BA (ICH2)
31 * document number 290733-003, 290739-013: 82801CA (ICH3-S)
32 * document number 290716-001, 290718-007: 82801CAM (ICH3-M)
33 * document number 290744-001, 290745-025: 82801DB (ICH4)
34 * document number 252337-001, 252663-008: 82801DBM (ICH4-M)
35 * document number 273599-001, 273645-002: 82801E (C-ICH)
36 * document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R)
37 * document number 300641-004, 300884-013: 6300ESB
38 * document number 301473-002, 301474-026: 82801F (ICH6)
39 * document number 313082-001, 313075-006: 631xESB, 632xESB
40 * document number 307013-003, 307014-024: 82801G (ICH7)
41 * document number 322896-001, 322897-001: NM10
42 * document number 313056-003, 313057-017: 82801H (ICH8)
43 * document number 316972-004, 316973-012: 82801I (ICH9)
44 * document number 319973-002, 319974-002: 82801J (ICH10)
45 * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
46 * document number 320066-003, 320257-008: EP80597 (IICH)
47 * document number 324645-001, 324646-001: Cougar Point (CPT)
48 * document number TBD : Patsburg (PBG)
49 * document number TBD : DH89xxCC
50 * document number TBD : Panther Point
51 * document number TBD : Lynx Point
52 */
53
54#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
55
56#include <linux/init.h>
57#include <linux/kernel.h>
58#include <linux/module.h>
59#include <linux/errno.h>
60#include <linux/acpi.h>
61#include <linux/pci.h>
62#include <linux/mfd/core.h>
63#include <linux/mfd/lpc_ich.h>
64
65#define ACPIBASE 0x40
66#define ACPIBASE_GPE_OFF 0x28
67#define ACPIBASE_GPE_END 0x2f
68#define ACPICTRL 0x44
69
70#define GPIOBASE 0x48
71#define GPIOCTRL 0x4C
72
73static int lpc_ich_acpi_save = -1;
74static int lpc_ich_gpio_save = -1;
75
76static struct resource gpio_ich_res[] = {
77 /* GPIO */
78 {
79 .flags = IORESOURCE_IO,
80 },
81 /* ACPI - GPE0 */
82 {
83 .flags = IORESOURCE_IO,
84 },
85};
86
87enum lpc_cells {
88 LPC_GPIO = 0,
89};
90
91static struct mfd_cell lpc_ich_cells[] = {
92 [LPC_GPIO] = {
93 .name = "gpio_ich",
94 .num_resources = ARRAY_SIZE(gpio_ich_res),
95 .resources = gpio_ich_res,
96 .ignore_resource_conflicts = true,
97 },
98};
99
100/* chipset related info */
101enum lpc_chipsets {
102 LPC_ICH = 0, /* ICH */
103 LPC_ICH0, /* ICH0 */
104 LPC_ICH2, /* ICH2 */
105 LPC_ICH2M, /* ICH2-M */
106 LPC_ICH3, /* ICH3-S */
107 LPC_ICH3M, /* ICH3-M */
108 LPC_ICH4, /* ICH4 */
109 LPC_ICH4M, /* ICH4-M */
110 LPC_CICH, /* C-ICH */
111 LPC_ICH5, /* ICH5 & ICH5R */
112 LPC_6300ESB, /* 6300ESB */
113 LPC_ICH6, /* ICH6 & ICH6R */
114 LPC_ICH6M, /* ICH6-M */
115 LPC_ICH6W, /* ICH6W & ICH6RW */
116 LPC_631XESB, /* 631xESB/632xESB */
117 LPC_ICH7, /* ICH7 & ICH7R */
118 LPC_ICH7DH, /* ICH7DH */
119 LPC_ICH7M, /* ICH7-M & ICH7-U */
120 LPC_ICH7MDH, /* ICH7-M DH */
121 LPC_NM10, /* NM10 */
122 LPC_ICH8, /* ICH8 & ICH8R */
123 LPC_ICH8DH, /* ICH8DH */
124 LPC_ICH8DO, /* ICH8DO */
125 LPC_ICH8M, /* ICH8M */
126 LPC_ICH8ME, /* ICH8M-E */
127 LPC_ICH9, /* ICH9 */
128 LPC_ICH9R, /* ICH9R */
129 LPC_ICH9DH, /* ICH9DH */
130 LPC_ICH9DO, /* ICH9DO */
131 LPC_ICH9M, /* ICH9M */
132 LPC_ICH9ME, /* ICH9M-E */
133 LPC_ICH10, /* ICH10 */
134 LPC_ICH10R, /* ICH10R */
135 LPC_ICH10D, /* ICH10D */
136 LPC_ICH10DO, /* ICH10DO */
137 LPC_PCH, /* PCH Desktop Full Featured */
138 LPC_PCHM, /* PCH Mobile Full Featured */
139 LPC_P55, /* P55 */
140 LPC_PM55, /* PM55 */
141 LPC_H55, /* H55 */
142 LPC_QM57, /* QM57 */
143 LPC_H57, /* H57 */
144 LPC_HM55, /* HM55 */
145 LPC_Q57, /* Q57 */
146 LPC_HM57, /* HM57 */
147 LPC_PCHMSFF, /* PCH Mobile SFF Full Featured */
148 LPC_QS57, /* QS57 */
149 LPC_3400, /* 3400 */
150 LPC_3420, /* 3420 */
151 LPC_3450, /* 3450 */
152 LPC_EP80579, /* EP80579 */
153 LPC_CPT, /* Cougar Point */
154 LPC_CPTD, /* Cougar Point Desktop */
155 LPC_CPTM, /* Cougar Point Mobile */
156 LPC_PBG, /* Patsburg */
157 LPC_DH89XXCC, /* DH89xxCC */
158 LPC_PPT, /* Panther Point */
159 LPC_LPT, /* Lynx Point */
160};
161
162struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
163 [LPC_ICH] = {
164 .name = "ICH",
165 },
166 [LPC_ICH0] = {
167 .name = "ICH0",
168 },
169 [LPC_ICH2] = {
170 .name = "ICH2",
171 },
172 [LPC_ICH2M] = {
173 .name = "ICH2-M",
174 },
175 [LPC_ICH3] = {
176 .name = "ICH3-S",
177 },
178 [LPC_ICH3M] = {
179 .name = "ICH3-M",
180 },
181 [LPC_ICH4] = {
182 .name = "ICH4",
183 },
184 [LPC_ICH4M] = {
185 .name = "ICH4-M",
186 },
187 [LPC_CICH] = {
188 .name = "C-ICH",
189 },
190 [LPC_ICH5] = {
191 .name = "ICH5 or ICH5R",
192 },
193 [LPC_6300ESB] = {
194 .name = "6300ESB",
195 },
196 [LPC_ICH6] = {
197 .name = "ICH6 or ICH6R",
198 .gpio_version = ICH_V6_GPIO,
199 },
200 [LPC_ICH6M] = {
201 .name = "ICH6-M",
202 .gpio_version = ICH_V6_GPIO,
203 },
204 [LPC_ICH6W] = {
205 .name = "ICH6W or ICH6RW",
206 .gpio_version = ICH_V6_GPIO,
207 },
208 [LPC_631XESB] = {
209 .name = "631xESB/632xESB",
210 .gpio_version = ICH_V6_GPIO,
211 },
212 [LPC_ICH7] = {
213 .name = "ICH7 or ICH7R",
214 .gpio_version = ICH_V7_GPIO,
215 },
216 [LPC_ICH7DH] = {
217 .name = "ICH7DH",
218 .gpio_version = ICH_V7_GPIO,
219 },
220 [LPC_ICH7M] = {
221 .name = "ICH7-M or ICH7-U",
222 .gpio_version = ICH_V7_GPIO,
223 },
224 [LPC_ICH7MDH] = {
225 .name = "ICH7-M DH",
226 .gpio_version = ICH_V7_GPIO,
227 },
228 [LPC_NM10] = {
229 .name = "NM10",
230 },
231 [LPC_ICH8] = {
232 .name = "ICH8 or ICH8R",
233 .gpio_version = ICH_V7_GPIO,
234 },
235 [LPC_ICH8DH] = {
236 .name = "ICH8DH",
237 .gpio_version = ICH_V7_GPIO,
238 },
239 [LPC_ICH8DO] = {
240 .name = "ICH8DO",
241 .gpio_version = ICH_V7_GPIO,
242 },
243 [LPC_ICH8M] = {
244 .name = "ICH8M",
245 .gpio_version = ICH_V7_GPIO,
246 },
247 [LPC_ICH8ME] = {
248 .name = "ICH8M-E",
249 .gpio_version = ICH_V7_GPIO,
250 },
251 [LPC_ICH9] = {
252 .name = "ICH9",
253 .gpio_version = ICH_V9_GPIO,
254 },
255 [LPC_ICH9R] = {
256 .name = "ICH9R",
257 .gpio_version = ICH_V9_GPIO,
258 },
259 [LPC_ICH9DH] = {
260 .name = "ICH9DH",
261 .gpio_version = ICH_V9_GPIO,
262 },
263 [LPC_ICH9DO] = {
264 .name = "ICH9DO",
265 .gpio_version = ICH_V9_GPIO,
266 },
267 [LPC_ICH9M] = {
268 .name = "ICH9M",
269 .gpio_version = ICH_V9_GPIO,
270 },
271 [LPC_ICH9ME] = {
272 .name = "ICH9M-E",
273 .gpio_version = ICH_V9_GPIO,
274 },
275 [LPC_ICH10] = {
276 .name = "ICH10",
277 .gpio_version = ICH_V10CONS_GPIO,
278 },
279 [LPC_ICH10R] = {
280 .name = "ICH10R",
281 .gpio_version = ICH_V10CONS_GPIO,
282 },
283 [LPC_ICH10D] = {
284 .name = "ICH10D",
285 .gpio_version = ICH_V10CORP_GPIO,
286 },
287 [LPC_ICH10DO] = {
288 .name = "ICH10DO",
289 .gpio_version = ICH_V10CORP_GPIO,
290 },
291 [LPC_PCH] = {
292 .name = "PCH Desktop Full Featured",
293 .gpio_version = ICH_V5_GPIO,
294 },
295 [LPC_PCHM] = {
296 .name = "PCH Mobile Full Featured",
297 .gpio_version = ICH_V5_GPIO,
298 },
299 [LPC_P55] = {
300 .name = "P55",
301 .gpio_version = ICH_V5_GPIO,
302 },
303 [LPC_PM55] = {
304 .name = "PM55",
305 .gpio_version = ICH_V5_GPIO,
306 },
307 [LPC_H55] = {
308 .name = "H55",
309 .gpio_version = ICH_V5_GPIO,
310 },
311 [LPC_QM57] = {
312 .name = "QM57",
313 .gpio_version = ICH_V5_GPIO,
314 },
315 [LPC_H57] = {
316 .name = "H57",
317 .gpio_version = ICH_V5_GPIO,
318 },
319 [LPC_HM55] = {
320 .name = "HM55",
321 .gpio_version = ICH_V5_GPIO,
322 },
323 [LPC_Q57] = {
324 .name = "Q57",
325 .gpio_version = ICH_V5_GPIO,
326 },
327 [LPC_HM57] = {
328 .name = "HM57",
329 .gpio_version = ICH_V5_GPIO,
330 },
331 [LPC_PCHMSFF] = {
332 .name = "PCH Mobile SFF Full Featured",
333 .gpio_version = ICH_V5_GPIO,
334 },
335 [LPC_QS57] = {
336 .name = "QS57",
337 .gpio_version = ICH_V5_GPIO,
338 },
339 [LPC_3400] = {
340 .name = "3400",
341 .gpio_version = ICH_V5_GPIO,
342 },
343 [LPC_3420] = {
344 .name = "3420",
345 .gpio_version = ICH_V5_GPIO,
346 },
347 [LPC_3450] = {
348 .name = "3450",
349 .gpio_version = ICH_V5_GPIO,
350 },
351 [LPC_EP80579] = {
352 .name = "EP80579",
353 },
354 [LPC_CPT] = {
355 .name = "Cougar Point",
356 .gpio_version = ICH_V5_GPIO,
357 },
358 [LPC_CPTD] = {
359 .name = "Cougar Point Desktop",
360 .gpio_version = ICH_V5_GPIO,
361 },
362 [LPC_CPTM] = {
363 .name = "Cougar Point Mobile",
364 .gpio_version = ICH_V5_GPIO,
365 },
366 [LPC_PBG] = {
367 .name = "Patsburg",
368 },
369 [LPC_DH89XXCC] = {
370 .name = "DH89xxCC",
371 },
372 [LPC_PPT] = {
373 .name = "Panther Point",
374 },
375 [LPC_LPT] = {
376 .name = "Lynx Point",
377 },
378};
379
380/*
381 * This data only exists for exporting the supported PCI ids
382 * via MODULE_DEVICE_TABLE. We do not actually register a
383 * pci_driver, because the I/O Controller Hub has also other
384 * functions that probably will be registered by other drivers.
385 */
386static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = {
387 { PCI_VDEVICE(INTEL, 0x2410), LPC_ICH},
388 { PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0},
389 { PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2},
390 { PCI_VDEVICE(INTEL, 0x244c), LPC_ICH2M},
391 { PCI_VDEVICE(INTEL, 0x2480), LPC_ICH3},
392 { PCI_VDEVICE(INTEL, 0x248c), LPC_ICH3M},
393 { PCI_VDEVICE(INTEL, 0x24c0), LPC_ICH4},
394 { PCI_VDEVICE(INTEL, 0x24cc), LPC_ICH4M},
395 { PCI_VDEVICE(INTEL, 0x2450), LPC_CICH},
396 { PCI_VDEVICE(INTEL, 0x24d0), LPC_ICH5},
397 { PCI_VDEVICE(INTEL, 0x25a1), LPC_6300ESB},
398 { PCI_VDEVICE(INTEL, 0x2640), LPC_ICH6},
399 { PCI_VDEVICE(INTEL, 0x2641), LPC_ICH6M},
400 { PCI_VDEVICE(INTEL, 0x2642), LPC_ICH6W},
401 { PCI_VDEVICE(INTEL, 0x2670), LPC_631XESB},
402 { PCI_VDEVICE(INTEL, 0x2671), LPC_631XESB},
403 { PCI_VDEVICE(INTEL, 0x2672), LPC_631XESB},
404 { PCI_VDEVICE(INTEL, 0x2673), LPC_631XESB},
405 { PCI_VDEVICE(INTEL, 0x2674), LPC_631XESB},
406 { PCI_VDEVICE(INTEL, 0x2675), LPC_631XESB},
407 { PCI_VDEVICE(INTEL, 0x2676), LPC_631XESB},
408 { PCI_VDEVICE(INTEL, 0x2677), LPC_631XESB},
409 { PCI_VDEVICE(INTEL, 0x2678), LPC_631XESB},
410 { PCI_VDEVICE(INTEL, 0x2679), LPC_631XESB},
411 { PCI_VDEVICE(INTEL, 0x267a), LPC_631XESB},
412 { PCI_VDEVICE(INTEL, 0x267b), LPC_631XESB},
413 { PCI_VDEVICE(INTEL, 0x267c), LPC_631XESB},
414 { PCI_VDEVICE(INTEL, 0x267d), LPC_631XESB},
415 { PCI_VDEVICE(INTEL, 0x267e), LPC_631XESB},
416 { PCI_VDEVICE(INTEL, 0x267f), LPC_631XESB},
417 { PCI_VDEVICE(INTEL, 0x27b8), LPC_ICH7},
418 { PCI_VDEVICE(INTEL, 0x27b0), LPC_ICH7DH},
419 { PCI_VDEVICE(INTEL, 0x27b9), LPC_ICH7M},
420 { PCI_VDEVICE(INTEL, 0x27bd), LPC_ICH7MDH},
421 { PCI_VDEVICE(INTEL, 0x27bc), LPC_NM10},
422 { PCI_VDEVICE(INTEL, 0x2810), LPC_ICH8},
423 { PCI_VDEVICE(INTEL, 0x2812), LPC_ICH8DH},
424 { PCI_VDEVICE(INTEL, 0x2814), LPC_ICH8DO},
425 { PCI_VDEVICE(INTEL, 0x2815), LPC_ICH8M},
426 { PCI_VDEVICE(INTEL, 0x2811), LPC_ICH8ME},
427 { PCI_VDEVICE(INTEL, 0x2918), LPC_ICH9},
428 { PCI_VDEVICE(INTEL, 0x2916), LPC_ICH9R},
429 { PCI_VDEVICE(INTEL, 0x2912), LPC_ICH9DH},
430 { PCI_VDEVICE(INTEL, 0x2914), LPC_ICH9DO},
431 { PCI_VDEVICE(INTEL, 0x2919), LPC_ICH9M},
432 { PCI_VDEVICE(INTEL, 0x2917), LPC_ICH9ME},
433 { PCI_VDEVICE(INTEL, 0x3a18), LPC_ICH10},
434 { PCI_VDEVICE(INTEL, 0x3a16), LPC_ICH10R},
435 { PCI_VDEVICE(INTEL, 0x3a1a), LPC_ICH10D},
436 { PCI_VDEVICE(INTEL, 0x3a14), LPC_ICH10DO},
437 { PCI_VDEVICE(INTEL, 0x3b00), LPC_PCH},
438 { PCI_VDEVICE(INTEL, 0x3b01), LPC_PCHM},
439 { PCI_VDEVICE(INTEL, 0x3b02), LPC_P55},
440 { PCI_VDEVICE(INTEL, 0x3b03), LPC_PM55},
441 { PCI_VDEVICE(INTEL, 0x3b06), LPC_H55},
442 { PCI_VDEVICE(INTEL, 0x3b07), LPC_QM57},
443 { PCI_VDEVICE(INTEL, 0x3b08), LPC_H57},
444 { PCI_VDEVICE(INTEL, 0x3b09), LPC_HM55},
445 { PCI_VDEVICE(INTEL, 0x3b0a), LPC_Q57},
446 { PCI_VDEVICE(INTEL, 0x3b0b), LPC_HM57},
447 { PCI_VDEVICE(INTEL, 0x3b0d), LPC_PCHMSFF},
448 { PCI_VDEVICE(INTEL, 0x3b0f), LPC_QS57},
449 { PCI_VDEVICE(INTEL, 0x3b12), LPC_3400},
450 { PCI_VDEVICE(INTEL, 0x3b14), LPC_3420},
451 { PCI_VDEVICE(INTEL, 0x3b16), LPC_3450},
452 { PCI_VDEVICE(INTEL, 0x5031), LPC_EP80579},
453 { PCI_VDEVICE(INTEL, 0x1c41), LPC_CPT},
454 { PCI_VDEVICE(INTEL, 0x1c42), LPC_CPTD},
455 { PCI_VDEVICE(INTEL, 0x1c43), LPC_CPTM},
456 { PCI_VDEVICE(INTEL, 0x1c44), LPC_CPT},
457 { PCI_VDEVICE(INTEL, 0x1c45), LPC_CPT},
458 { PCI_VDEVICE(INTEL, 0x1c46), LPC_CPT},
459 { PCI_VDEVICE(INTEL, 0x1c47), LPC_CPT},
460 { PCI_VDEVICE(INTEL, 0x1c48), LPC_CPT},
461 { PCI_VDEVICE(INTEL, 0x1c49), LPC_CPT},
462 { PCI_VDEVICE(INTEL, 0x1c4a), LPC_CPT},
463 { PCI_VDEVICE(INTEL, 0x1c4b), LPC_CPT},
464 { PCI_VDEVICE(INTEL, 0x1c4c), LPC_CPT},
465 { PCI_VDEVICE(INTEL, 0x1c4d), LPC_CPT},
466 { PCI_VDEVICE(INTEL, 0x1c4e), LPC_CPT},
467 { PCI_VDEVICE(INTEL, 0x1c4f), LPC_CPT},
468 { PCI_VDEVICE(INTEL, 0x1c50), LPC_CPT},
469 { PCI_VDEVICE(INTEL, 0x1c51), LPC_CPT},
470 { PCI_VDEVICE(INTEL, 0x1c52), LPC_CPT},
471 { PCI_VDEVICE(INTEL, 0x1c53), LPC_CPT},
472 { PCI_VDEVICE(INTEL, 0x1c54), LPC_CPT},
473 { PCI_VDEVICE(INTEL, 0x1c55), LPC_CPT},
474 { PCI_VDEVICE(INTEL, 0x1c56), LPC_CPT},
475 { PCI_VDEVICE(INTEL, 0x1c57), LPC_CPT},
476 { PCI_VDEVICE(INTEL, 0x1c58), LPC_CPT},
477 { PCI_VDEVICE(INTEL, 0x1c59), LPC_CPT},
478 { PCI_VDEVICE(INTEL, 0x1c5a), LPC_CPT},
479 { PCI_VDEVICE(INTEL, 0x1c5b), LPC_CPT},
480 { PCI_VDEVICE(INTEL, 0x1c5c), LPC_CPT},
481 { PCI_VDEVICE(INTEL, 0x1c5d), LPC_CPT},
482 { PCI_VDEVICE(INTEL, 0x1c5e), LPC_CPT},
483 { PCI_VDEVICE(INTEL, 0x1c5f), LPC_CPT},
484 { PCI_VDEVICE(INTEL, 0x1d40), LPC_PBG},
485 { PCI_VDEVICE(INTEL, 0x1d41), LPC_PBG},
486 { PCI_VDEVICE(INTEL, 0x2310), LPC_DH89XXCC},
487 { PCI_VDEVICE(INTEL, 0x1e40), LPC_PPT},
488 { PCI_VDEVICE(INTEL, 0x1e41), LPC_PPT},
489 { PCI_VDEVICE(INTEL, 0x1e42), LPC_PPT},
490 { PCI_VDEVICE(INTEL, 0x1e43), LPC_PPT},
491 { PCI_VDEVICE(INTEL, 0x1e44), LPC_PPT},
492 { PCI_VDEVICE(INTEL, 0x1e45), LPC_PPT},
493 { PCI_VDEVICE(INTEL, 0x1e46), LPC_PPT},
494 { PCI_VDEVICE(INTEL, 0x1e47), LPC_PPT},
495 { PCI_VDEVICE(INTEL, 0x1e48), LPC_PPT},
496 { PCI_VDEVICE(INTEL, 0x1e49), LPC_PPT},
497 { PCI_VDEVICE(INTEL, 0x1e4a), LPC_PPT},
498 { PCI_VDEVICE(INTEL, 0x1e4b), LPC_PPT},
499 { PCI_VDEVICE(INTEL, 0x1e4c), LPC_PPT},
500 { PCI_VDEVICE(INTEL, 0x1e4d), LPC_PPT},
501 { PCI_VDEVICE(INTEL, 0x1e4e), LPC_PPT},
502 { PCI_VDEVICE(INTEL, 0x1e4f), LPC_PPT},
503 { PCI_VDEVICE(INTEL, 0x1e50), LPC_PPT},
504 { PCI_VDEVICE(INTEL, 0x1e51), LPC_PPT},
505 { PCI_VDEVICE(INTEL, 0x1e52), LPC_PPT},
506 { PCI_VDEVICE(INTEL, 0x1e53), LPC_PPT},
507 { PCI_VDEVICE(INTEL, 0x1e54), LPC_PPT},
508 { PCI_VDEVICE(INTEL, 0x1e55), LPC_PPT},
509 { PCI_VDEVICE(INTEL, 0x1e56), LPC_PPT},
510 { PCI_VDEVICE(INTEL, 0x1e57), LPC_PPT},
511 { PCI_VDEVICE(INTEL, 0x1e58), LPC_PPT},
512 { PCI_VDEVICE(INTEL, 0x1e59), LPC_PPT},
513 { PCI_VDEVICE(INTEL, 0x1e5a), LPC_PPT},
514 { PCI_VDEVICE(INTEL, 0x1e5b), LPC_PPT},
515 { PCI_VDEVICE(INTEL, 0x1e5c), LPC_PPT},
516 { PCI_VDEVICE(INTEL, 0x1e5d), LPC_PPT},
517 { PCI_VDEVICE(INTEL, 0x1e5e), LPC_PPT},
518 { PCI_VDEVICE(INTEL, 0x1e5f), LPC_PPT},
519 { PCI_VDEVICE(INTEL, 0x8c40), LPC_LPT},
520 { PCI_VDEVICE(INTEL, 0x8c41), LPC_LPT},
521 { PCI_VDEVICE(INTEL, 0x8c42), LPC_LPT},
522 { PCI_VDEVICE(INTEL, 0x8c43), LPC_LPT},
523 { PCI_VDEVICE(INTEL, 0x8c44), LPC_LPT},
524 { PCI_VDEVICE(INTEL, 0x8c45), LPC_LPT},
525 { PCI_VDEVICE(INTEL, 0x8c46), LPC_LPT},
526 { PCI_VDEVICE(INTEL, 0x8c47), LPC_LPT},
527 { PCI_VDEVICE(INTEL, 0x8c48), LPC_LPT},
528 { PCI_VDEVICE(INTEL, 0x8c49), LPC_LPT},
529 { PCI_VDEVICE(INTEL, 0x8c4a), LPC_LPT},
530 { PCI_VDEVICE(INTEL, 0x8c4b), LPC_LPT},
531 { PCI_VDEVICE(INTEL, 0x8c4c), LPC_LPT},
532 { PCI_VDEVICE(INTEL, 0x8c4d), LPC_LPT},
533 { PCI_VDEVICE(INTEL, 0x8c4e), LPC_LPT},
534 { PCI_VDEVICE(INTEL, 0x8c4f), LPC_LPT},
535 { PCI_VDEVICE(INTEL, 0x8c50), LPC_LPT},
536 { PCI_VDEVICE(INTEL, 0x8c51), LPC_LPT},
537 { PCI_VDEVICE(INTEL, 0x8c52), LPC_LPT},
538 { PCI_VDEVICE(INTEL, 0x8c53), LPC_LPT},
539 { PCI_VDEVICE(INTEL, 0x8c54), LPC_LPT},
540 { PCI_VDEVICE(INTEL, 0x8c55), LPC_LPT},
541 { PCI_VDEVICE(INTEL, 0x8c56), LPC_LPT},
542 { PCI_VDEVICE(INTEL, 0x8c57), LPC_LPT},
543 { PCI_VDEVICE(INTEL, 0x8c58), LPC_LPT},
544 { PCI_VDEVICE(INTEL, 0x8c59), LPC_LPT},
545 { PCI_VDEVICE(INTEL, 0x8c5a), LPC_LPT},
546 { PCI_VDEVICE(INTEL, 0x8c5b), LPC_LPT},
547 { PCI_VDEVICE(INTEL, 0x8c5c), LPC_LPT},
548 { PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT},
549 { PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT},
550 { PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT},
551 { 0, }, /* End of list */
552};
553MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
554
555static void lpc_ich_restore_config_space(struct pci_dev *dev)
556{
557 if (lpc_ich_acpi_save >= 0) {
558 pci_write_config_byte(dev, ACPICTRL, lpc_ich_acpi_save);
559 lpc_ich_acpi_save = -1;
560 }
561
562 if (lpc_ich_gpio_save >= 0) {
563 pci_write_config_byte(dev, GPIOCTRL, lpc_ich_gpio_save);
564 lpc_ich_gpio_save = -1;
565 }
566}
567
568static void __devinit lpc_ich_enable_acpi_space(struct pci_dev *dev)
569{
570 u8 reg_save;
571
572 pci_read_config_byte(dev, ACPICTRL, &reg_save);
573 pci_write_config_byte(dev, ACPICTRL, reg_save | 0x10);
574 lpc_ich_acpi_save = reg_save;
575}
576
577static void __devinit lpc_ich_enable_gpio_space(struct pci_dev *dev)
578{
579 u8 reg_save;
580
581 pci_read_config_byte(dev, GPIOCTRL, &reg_save);
582 pci_write_config_byte(dev, GPIOCTRL, reg_save | 0x10);
583 lpc_ich_gpio_save = reg_save;
584}
585
586static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
587 const struct pci_device_id *id)
588{
589 cell->platform_data = &lpc_chipset_info[id->driver_data];
590 cell->pdata_size = sizeof(struct lpc_ich_info);
591}
592
593static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
594 const struct pci_device_id *id)
595{
596 u32 base_addr_cfg;
597 u32 base_addr;
598 int ret;
599 bool acpi_conflict = false;
600 struct resource *res;
601
602 /* Setup power management base register */
603 pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg);
604 base_addr = base_addr_cfg & 0x0000ff80;
605 if (!base_addr) {
606 dev_err(&dev->dev, "I/O space for ACPI uninitialized\n");
607 lpc_ich_cells[LPC_GPIO].num_resources--;
608 goto gpe0_done;
609 }
610
611 res = &gpio_ich_res[ICH_RES_GPE0];
612 res->start = base_addr + ACPIBASE_GPE_OFF;
613 res->end = base_addr + ACPIBASE_GPE_END;
614 ret = acpi_check_resource_conflict(res);
615 if (ret) {
616 /*
617 * This isn't fatal for the GPIO, but we have to make sure that
618 * the platform_device subsystem doesn't see this resource
619 * or it will register an invalid region.
620 */
621 lpc_ich_cells[LPC_GPIO].num_resources--;
622 acpi_conflict = true;
623 } else {
624 lpc_ich_enable_acpi_space(dev);
625 }
626
627gpe0_done:
628 /* Setup GPIO base register */
629 pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
630 base_addr = base_addr_cfg & 0x0000ff80;
631 if (!base_addr) {
632 dev_err(&dev->dev, "I/O space for GPIO uninitialized\n");
633 ret = -ENODEV;
634 goto gpio_done;
635 }
636
637 /* Older devices provide fewer GPIO and have a smaller resource size. */
638 res = &gpio_ich_res[ICH_RES_GPIO];
639 res->start = base_addr;
640 switch (lpc_chipset_info[id->driver_data].gpio_version) {
641 case ICH_V5_GPIO:
642 case ICH_V10CORP_GPIO:
643 res->end = res->start + 128 - 1;
644 break;
645 default:
646 res->end = res->start + 64 - 1;
647 break;
648 }
649
650 ret = acpi_check_resource_conflict(res);
651 if (ret) {
652 /* this isn't necessarily fatal for the GPIO */
653 acpi_conflict = true;
654 goto gpio_done;
655 }
656 lpc_ich_enable_gpio_space(dev);
657
658 lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);
659 ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO],
660 1, NULL, 0);
661
662gpio_done:
663 if (acpi_conflict)
664 pr_warn("Resource conflict(s) found affecting %s\n",
665 lpc_ich_cells[LPC_GPIO].name);
666 return ret;
667}
668
669static int __devinit lpc_ich_probe(struct pci_dev *dev,
670 const struct pci_device_id *id)
671{
672 int ret;
673 bool cell_added = false;
674
675 ret = lpc_ich_init_gpio(dev, id);
676 if (!ret)
677 cell_added = true;
678
679 /*
680 * We only care if at least one or none of the cells registered
681 * successfully.
682 */
683 if (!cell_added) {
684 lpc_ich_restore_config_space(dev);
685 return -ENODEV;
686 }
687
688 return 0;
689}
690
691static void __devexit lpc_ich_remove(struct pci_dev *dev)
692{
693 mfd_remove_devices(&dev->dev);
694 lpc_ich_restore_config_space(dev);
695}
696
697static struct pci_driver lpc_ich_driver = {
698 .name = "lpc_ich",
699 .id_table = lpc_ich_ids,
700 .probe = lpc_ich_probe,
701 .remove = __devexit_p(lpc_ich_remove),
702};
703
704static int __init lpc_ich_init(void)
705{
706 return pci_register_driver(&lpc_ich_driver);
707}
708
709static void __exit lpc_ich_exit(void)
710{
711 pci_unregister_driver(&lpc_ich_driver);
712}
713
714module_init(lpc_ich_init);
715module_exit(lpc_ich_exit);
716
717MODULE_AUTHOR("Aaron Sierra <asierra@xes-inc.com>");
718MODULE_DESCRIPTION("LPC interface for Intel ICH");
719MODULE_LICENSE("GPL");