aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/lpc_ich.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/lpc_ich.c')
-rw-r--r--drivers/mfd/lpc_ich.c171
1 files changed, 170 insertions, 1 deletions
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 7e3a7b6ab022..027cc8f86132 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -65,14 +65,42 @@
65#define ACPIBASE 0x40 65#define ACPIBASE 0x40
66#define ACPIBASE_GPE_OFF 0x28 66#define ACPIBASE_GPE_OFF 0x28
67#define ACPIBASE_GPE_END 0x2f 67#define ACPIBASE_GPE_END 0x2f
68#define ACPIBASE_SMI_OFF 0x30
69#define ACPIBASE_SMI_END 0x33
70#define ACPIBASE_TCO_OFF 0x60
71#define ACPIBASE_TCO_END 0x7f
68#define ACPICTRL 0x44 72#define ACPICTRL 0x44
69 73
74#define ACPIBASE_GCS_OFF 0x3410
75#define ACPIBASE_GCS_END 0x3414
76
70#define GPIOBASE 0x48 77#define GPIOBASE 0x48
71#define GPIOCTRL 0x4C 78#define GPIOCTRL 0x4C
72 79
80#define RCBABASE 0xf0
81
82#define wdt_io_res(i) wdt_res(0, i)
83#define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i)
84#define wdt_res(b, i) (&wdt_ich_res[(b) + (i)])
85
73static int lpc_ich_acpi_save = -1; 86static int lpc_ich_acpi_save = -1;
74static int lpc_ich_gpio_save = -1; 87static int lpc_ich_gpio_save = -1;
75 88
89static struct resource wdt_ich_res[] = {
90 /* ACPI - TCO */
91 {
92 .flags = IORESOURCE_IO,
93 },
94 /* ACPI - SMI */
95 {
96 .flags = IORESOURCE_IO,
97 },
98 /* GCS */
99 {
100 .flags = IORESOURCE_MEM,
101 },
102};
103
76static struct resource gpio_ich_res[] = { 104static struct resource gpio_ich_res[] = {
77 /* GPIO */ 105 /* GPIO */
78 { 106 {
@@ -85,10 +113,17 @@ static struct resource gpio_ich_res[] = {
85}; 113};
86 114
87enum lpc_cells { 115enum lpc_cells {
88 LPC_GPIO = 0, 116 LPC_WDT = 0,
117 LPC_GPIO,
89}; 118};
90 119
91static struct mfd_cell lpc_ich_cells[] = { 120static struct mfd_cell lpc_ich_cells[] = {
121 [LPC_WDT] = {
122 .name = "iTCO_wdt",
123 .num_resources = ARRAY_SIZE(wdt_ich_res),
124 .resources = wdt_ich_res,
125 .ignore_resource_conflicts = true,
126 },
92 [LPC_GPIO] = { 127 [LPC_GPIO] = {
93 .name = "gpio_ich", 128 .name = "gpio_ich",
94 .num_resources = ARRAY_SIZE(gpio_ich_res), 129 .num_resources = ARRAY_SIZE(gpio_ich_res),
@@ -162,218 +197,276 @@ enum lpc_chipsets {
162struct lpc_ich_info lpc_chipset_info[] __devinitdata = { 197struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
163 [LPC_ICH] = { 198 [LPC_ICH] = {
164 .name = "ICH", 199 .name = "ICH",
200 .iTCO_version = 1,
165 }, 201 },
166 [LPC_ICH0] = { 202 [LPC_ICH0] = {
167 .name = "ICH0", 203 .name = "ICH0",
204 .iTCO_version = 1,
168 }, 205 },
169 [LPC_ICH2] = { 206 [LPC_ICH2] = {
170 .name = "ICH2", 207 .name = "ICH2",
208 .iTCO_version = 1,
171 }, 209 },
172 [LPC_ICH2M] = { 210 [LPC_ICH2M] = {
173 .name = "ICH2-M", 211 .name = "ICH2-M",
212 .iTCO_version = 1,
174 }, 213 },
175 [LPC_ICH3] = { 214 [LPC_ICH3] = {
176 .name = "ICH3-S", 215 .name = "ICH3-S",
216 .iTCO_version = 1,
177 }, 217 },
178 [LPC_ICH3M] = { 218 [LPC_ICH3M] = {
179 .name = "ICH3-M", 219 .name = "ICH3-M",
220 .iTCO_version = 1,
180 }, 221 },
181 [LPC_ICH4] = { 222 [LPC_ICH4] = {
182 .name = "ICH4", 223 .name = "ICH4",
224 .iTCO_version = 1,
183 }, 225 },
184 [LPC_ICH4M] = { 226 [LPC_ICH4M] = {
185 .name = "ICH4-M", 227 .name = "ICH4-M",
228 .iTCO_version = 1,
186 }, 229 },
187 [LPC_CICH] = { 230 [LPC_CICH] = {
188 .name = "C-ICH", 231 .name = "C-ICH",
232 .iTCO_version = 1,
189 }, 233 },
190 [LPC_ICH5] = { 234 [LPC_ICH5] = {
191 .name = "ICH5 or ICH5R", 235 .name = "ICH5 or ICH5R",
236 .iTCO_version = 1,
192 }, 237 },
193 [LPC_6300ESB] = { 238 [LPC_6300ESB] = {
194 .name = "6300ESB", 239 .name = "6300ESB",
240 .iTCO_version = 1,
195 }, 241 },
196 [LPC_ICH6] = { 242 [LPC_ICH6] = {
197 .name = "ICH6 or ICH6R", 243 .name = "ICH6 or ICH6R",
244 .iTCO_version = 2,
198 .gpio_version = ICH_V6_GPIO, 245 .gpio_version = ICH_V6_GPIO,
199 }, 246 },
200 [LPC_ICH6M] = { 247 [LPC_ICH6M] = {
201 .name = "ICH6-M", 248 .name = "ICH6-M",
249 .iTCO_version = 2,
202 .gpio_version = ICH_V6_GPIO, 250 .gpio_version = ICH_V6_GPIO,
203 }, 251 },
204 [LPC_ICH6W] = { 252 [LPC_ICH6W] = {
205 .name = "ICH6W or ICH6RW", 253 .name = "ICH6W or ICH6RW",
254 .iTCO_version = 2,
206 .gpio_version = ICH_V6_GPIO, 255 .gpio_version = ICH_V6_GPIO,
207 }, 256 },
208 [LPC_631XESB] = { 257 [LPC_631XESB] = {
209 .name = "631xESB/632xESB", 258 .name = "631xESB/632xESB",
259 .iTCO_version = 2,
210 .gpio_version = ICH_V6_GPIO, 260 .gpio_version = ICH_V6_GPIO,
211 }, 261 },
212 [LPC_ICH7] = { 262 [LPC_ICH7] = {
213 .name = "ICH7 or ICH7R", 263 .name = "ICH7 or ICH7R",
264 .iTCO_version = 2,
214 .gpio_version = ICH_V7_GPIO, 265 .gpio_version = ICH_V7_GPIO,
215 }, 266 },
216 [LPC_ICH7DH] = { 267 [LPC_ICH7DH] = {
217 .name = "ICH7DH", 268 .name = "ICH7DH",
269 .iTCO_version = 2,
218 .gpio_version = ICH_V7_GPIO, 270 .gpio_version = ICH_V7_GPIO,
219 }, 271 },
220 [LPC_ICH7M] = { 272 [LPC_ICH7M] = {
221 .name = "ICH7-M or ICH7-U", 273 .name = "ICH7-M or ICH7-U",
274 .iTCO_version = 2,
222 .gpio_version = ICH_V7_GPIO, 275 .gpio_version = ICH_V7_GPIO,
223 }, 276 },
224 [LPC_ICH7MDH] = { 277 [LPC_ICH7MDH] = {
225 .name = "ICH7-M DH", 278 .name = "ICH7-M DH",
279 .iTCO_version = 2,
226 .gpio_version = ICH_V7_GPIO, 280 .gpio_version = ICH_V7_GPIO,
227 }, 281 },
228 [LPC_NM10] = { 282 [LPC_NM10] = {
229 .name = "NM10", 283 .name = "NM10",
284 .iTCO_version = 2,
230 }, 285 },
231 [LPC_ICH8] = { 286 [LPC_ICH8] = {
232 .name = "ICH8 or ICH8R", 287 .name = "ICH8 or ICH8R",
288 .iTCO_version = 2,
233 .gpio_version = ICH_V7_GPIO, 289 .gpio_version = ICH_V7_GPIO,
234 }, 290 },
235 [LPC_ICH8DH] = { 291 [LPC_ICH8DH] = {
236 .name = "ICH8DH", 292 .name = "ICH8DH",
293 .iTCO_version = 2,
237 .gpio_version = ICH_V7_GPIO, 294 .gpio_version = ICH_V7_GPIO,
238 }, 295 },
239 [LPC_ICH8DO] = { 296 [LPC_ICH8DO] = {
240 .name = "ICH8DO", 297 .name = "ICH8DO",
298 .iTCO_version = 2,
241 .gpio_version = ICH_V7_GPIO, 299 .gpio_version = ICH_V7_GPIO,
242 }, 300 },
243 [LPC_ICH8M] = { 301 [LPC_ICH8M] = {
244 .name = "ICH8M", 302 .name = "ICH8M",
303 .iTCO_version = 2,
245 .gpio_version = ICH_V7_GPIO, 304 .gpio_version = ICH_V7_GPIO,
246 }, 305 },
247 [LPC_ICH8ME] = { 306 [LPC_ICH8ME] = {
248 .name = "ICH8M-E", 307 .name = "ICH8M-E",
308 .iTCO_version = 2,
249 .gpio_version = ICH_V7_GPIO, 309 .gpio_version = ICH_V7_GPIO,
250 }, 310 },
251 [LPC_ICH9] = { 311 [LPC_ICH9] = {
252 .name = "ICH9", 312 .name = "ICH9",
313 .iTCO_version = 2,
253 .gpio_version = ICH_V9_GPIO, 314 .gpio_version = ICH_V9_GPIO,
254 }, 315 },
255 [LPC_ICH9R] = { 316 [LPC_ICH9R] = {
256 .name = "ICH9R", 317 .name = "ICH9R",
318 .iTCO_version = 2,
257 .gpio_version = ICH_V9_GPIO, 319 .gpio_version = ICH_V9_GPIO,
258 }, 320 },
259 [LPC_ICH9DH] = { 321 [LPC_ICH9DH] = {
260 .name = "ICH9DH", 322 .name = "ICH9DH",
323 .iTCO_version = 2,
261 .gpio_version = ICH_V9_GPIO, 324 .gpio_version = ICH_V9_GPIO,
262 }, 325 },
263 [LPC_ICH9DO] = { 326 [LPC_ICH9DO] = {
264 .name = "ICH9DO", 327 .name = "ICH9DO",
328 .iTCO_version = 2,
265 .gpio_version = ICH_V9_GPIO, 329 .gpio_version = ICH_V9_GPIO,
266 }, 330 },
267 [LPC_ICH9M] = { 331 [LPC_ICH9M] = {
268 .name = "ICH9M", 332 .name = "ICH9M",
333 .iTCO_version = 2,
269 .gpio_version = ICH_V9_GPIO, 334 .gpio_version = ICH_V9_GPIO,
270 }, 335 },
271 [LPC_ICH9ME] = { 336 [LPC_ICH9ME] = {
272 .name = "ICH9M-E", 337 .name = "ICH9M-E",
338 .iTCO_version = 2,
273 .gpio_version = ICH_V9_GPIO, 339 .gpio_version = ICH_V9_GPIO,
274 }, 340 },
275 [LPC_ICH10] = { 341 [LPC_ICH10] = {
276 .name = "ICH10", 342 .name = "ICH10",
343 .iTCO_version = 2,
277 .gpio_version = ICH_V10CONS_GPIO, 344 .gpio_version = ICH_V10CONS_GPIO,
278 }, 345 },
279 [LPC_ICH10R] = { 346 [LPC_ICH10R] = {
280 .name = "ICH10R", 347 .name = "ICH10R",
348 .iTCO_version = 2,
281 .gpio_version = ICH_V10CONS_GPIO, 349 .gpio_version = ICH_V10CONS_GPIO,
282 }, 350 },
283 [LPC_ICH10D] = { 351 [LPC_ICH10D] = {
284 .name = "ICH10D", 352 .name = "ICH10D",
353 .iTCO_version = 2,
285 .gpio_version = ICH_V10CORP_GPIO, 354 .gpio_version = ICH_V10CORP_GPIO,
286 }, 355 },
287 [LPC_ICH10DO] = { 356 [LPC_ICH10DO] = {
288 .name = "ICH10DO", 357 .name = "ICH10DO",
358 .iTCO_version = 2,
289 .gpio_version = ICH_V10CORP_GPIO, 359 .gpio_version = ICH_V10CORP_GPIO,
290 }, 360 },
291 [LPC_PCH] = { 361 [LPC_PCH] = {
292 .name = "PCH Desktop Full Featured", 362 .name = "PCH Desktop Full Featured",
363 .iTCO_version = 2,
293 .gpio_version = ICH_V5_GPIO, 364 .gpio_version = ICH_V5_GPIO,
294 }, 365 },
295 [LPC_PCHM] = { 366 [LPC_PCHM] = {
296 .name = "PCH Mobile Full Featured", 367 .name = "PCH Mobile Full Featured",
368 .iTCO_version = 2,
297 .gpio_version = ICH_V5_GPIO, 369 .gpio_version = ICH_V5_GPIO,
298 }, 370 },
299 [LPC_P55] = { 371 [LPC_P55] = {
300 .name = "P55", 372 .name = "P55",
373 .iTCO_version = 2,
301 .gpio_version = ICH_V5_GPIO, 374 .gpio_version = ICH_V5_GPIO,
302 }, 375 },
303 [LPC_PM55] = { 376 [LPC_PM55] = {
304 .name = "PM55", 377 .name = "PM55",
378 .iTCO_version = 2,
305 .gpio_version = ICH_V5_GPIO, 379 .gpio_version = ICH_V5_GPIO,
306 }, 380 },
307 [LPC_H55] = { 381 [LPC_H55] = {
308 .name = "H55", 382 .name = "H55",
383 .iTCO_version = 2,
309 .gpio_version = ICH_V5_GPIO, 384 .gpio_version = ICH_V5_GPIO,
310 }, 385 },
311 [LPC_QM57] = { 386 [LPC_QM57] = {
312 .name = "QM57", 387 .name = "QM57",
388 .iTCO_version = 2,
313 .gpio_version = ICH_V5_GPIO, 389 .gpio_version = ICH_V5_GPIO,
314 }, 390 },
315 [LPC_H57] = { 391 [LPC_H57] = {
316 .name = "H57", 392 .name = "H57",
393 .iTCO_version = 2,
317 .gpio_version = ICH_V5_GPIO, 394 .gpio_version = ICH_V5_GPIO,
318 }, 395 },
319 [LPC_HM55] = { 396 [LPC_HM55] = {
320 .name = "HM55", 397 .name = "HM55",
398 .iTCO_version = 2,
321 .gpio_version = ICH_V5_GPIO, 399 .gpio_version = ICH_V5_GPIO,
322 }, 400 },
323 [LPC_Q57] = { 401 [LPC_Q57] = {
324 .name = "Q57", 402 .name = "Q57",
403 .iTCO_version = 2,
325 .gpio_version = ICH_V5_GPIO, 404 .gpio_version = ICH_V5_GPIO,
326 }, 405 },
327 [LPC_HM57] = { 406 [LPC_HM57] = {
328 .name = "HM57", 407 .name = "HM57",
408 .iTCO_version = 2,
329 .gpio_version = ICH_V5_GPIO, 409 .gpio_version = ICH_V5_GPIO,
330 }, 410 },
331 [LPC_PCHMSFF] = { 411 [LPC_PCHMSFF] = {
332 .name = "PCH Mobile SFF Full Featured", 412 .name = "PCH Mobile SFF Full Featured",
413 .iTCO_version = 2,
333 .gpio_version = ICH_V5_GPIO, 414 .gpio_version = ICH_V5_GPIO,
334 }, 415 },
335 [LPC_QS57] = { 416 [LPC_QS57] = {
336 .name = "QS57", 417 .name = "QS57",
418 .iTCO_version = 2,
337 .gpio_version = ICH_V5_GPIO, 419 .gpio_version = ICH_V5_GPIO,
338 }, 420 },
339 [LPC_3400] = { 421 [LPC_3400] = {
340 .name = "3400", 422 .name = "3400",
423 .iTCO_version = 2,
341 .gpio_version = ICH_V5_GPIO, 424 .gpio_version = ICH_V5_GPIO,
342 }, 425 },
343 [LPC_3420] = { 426 [LPC_3420] = {
344 .name = "3420", 427 .name = "3420",
428 .iTCO_version = 2,
345 .gpio_version = ICH_V5_GPIO, 429 .gpio_version = ICH_V5_GPIO,
346 }, 430 },
347 [LPC_3450] = { 431 [LPC_3450] = {
348 .name = "3450", 432 .name = "3450",
433 .iTCO_version = 2,
349 .gpio_version = ICH_V5_GPIO, 434 .gpio_version = ICH_V5_GPIO,
350 }, 435 },
351 [LPC_EP80579] = { 436 [LPC_EP80579] = {
352 .name = "EP80579", 437 .name = "EP80579",
438 .iTCO_version = 2,
353 }, 439 },
354 [LPC_CPT] = { 440 [LPC_CPT] = {
355 .name = "Cougar Point", 441 .name = "Cougar Point",
442 .iTCO_version = 2,
356 .gpio_version = ICH_V5_GPIO, 443 .gpio_version = ICH_V5_GPIO,
357 }, 444 },
358 [LPC_CPTD] = { 445 [LPC_CPTD] = {
359 .name = "Cougar Point Desktop", 446 .name = "Cougar Point Desktop",
447 .iTCO_version = 2,
360 .gpio_version = ICH_V5_GPIO, 448 .gpio_version = ICH_V5_GPIO,
361 }, 449 },
362 [LPC_CPTM] = { 450 [LPC_CPTM] = {
363 .name = "Cougar Point Mobile", 451 .name = "Cougar Point Mobile",
452 .iTCO_version = 2,
364 .gpio_version = ICH_V5_GPIO, 453 .gpio_version = ICH_V5_GPIO,
365 }, 454 },
366 [LPC_PBG] = { 455 [LPC_PBG] = {
367 .name = "Patsburg", 456 .name = "Patsburg",
457 .iTCO_version = 2,
368 }, 458 },
369 [LPC_DH89XXCC] = { 459 [LPC_DH89XXCC] = {
370 .name = "DH89xxCC", 460 .name = "DH89xxCC",
461 .iTCO_version = 2,
371 }, 462 },
372 [LPC_PPT] = { 463 [LPC_PPT] = {
373 .name = "Panther Point", 464 .name = "Panther Point",
465 .iTCO_version = 2,
374 }, 466 },
375 [LPC_LPT] = { 467 [LPC_LPT] = {
376 .name = "Lynx Point", 468 .name = "Lynx Point",
469 .iTCO_version = 2,
377 }, 470 },
378}; 471};
379 472
@@ -666,12 +759,88 @@ gpio_done:
666 return ret; 759 return ret;
667} 760}
668 761
762static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
763 const struct pci_device_id *id)
764{
765 u32 base_addr_cfg;
766 u32 base_addr;
767 int ret;
768 bool acpi_conflict = false;
769 struct resource *res;
770
771 /* Setup power management base register */
772 pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg);
773 base_addr = base_addr_cfg & 0x0000ff80;
774 if (!base_addr) {
775 dev_err(&dev->dev, "I/O space for ACPI uninitialized\n");
776 ret = -ENODEV;
777 goto wdt_done;
778 }
779
780 res = wdt_io_res(ICH_RES_IO_TCO);
781 res->start = base_addr + ACPIBASE_TCO_OFF;
782 res->end = base_addr + ACPIBASE_TCO_END;
783 ret = acpi_check_resource_conflict(res);
784 if (ret) {
785 acpi_conflict = true;
786 goto wdt_done;
787 }
788
789 res = wdt_io_res(ICH_RES_IO_SMI);
790 res->start = base_addr + ACPIBASE_SMI_OFF;
791 res->end = base_addr + ACPIBASE_SMI_END;
792 ret = acpi_check_resource_conflict(res);
793 if (ret) {
794 acpi_conflict = true;
795 goto wdt_done;
796 }
797 lpc_ich_enable_acpi_space(dev);
798
799 /*
800 * Get the Memory-Mapped GCS register. To get access to it
801 * we have to read RCBA from PCI Config space 0xf0 and use
802 * it as base. GCS = RCBA + ICH6_GCS(0x3410).
803 */
804 if (lpc_chipset_info[id->driver_data].iTCO_version == 2) {
805 pci_read_config_dword(dev, RCBABASE, &base_addr_cfg);
806 base_addr = base_addr_cfg & 0xffffc000;
807 if (!(base_addr_cfg & 1)) {
808 pr_err("RCBA is disabled by hardware/BIOS, "
809 "device disabled\n");
810 ret = -ENODEV;
811 goto wdt_done;
812 }
813 res = wdt_mem_res(ICH_RES_MEM_GCS);
814 res->start = base_addr + ACPIBASE_GCS_OFF;
815 res->end = base_addr + ACPIBASE_GCS_END;
816 ret = acpi_check_resource_conflict(res);
817 if (ret) {
818 acpi_conflict = true;
819 goto wdt_done;
820 }
821 }
822
823 lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id);
824 ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT],
825 1, NULL, 0);
826
827wdt_done:
828 if (acpi_conflict)
829 pr_warn("Resource conflict(s) found affecting %s\n",
830 lpc_ich_cells[LPC_WDT].name);
831 return ret;
832}
833
669static int __devinit lpc_ich_probe(struct pci_dev *dev, 834static int __devinit lpc_ich_probe(struct pci_dev *dev,
670 const struct pci_device_id *id) 835 const struct pci_device_id *id)
671{ 836{
672 int ret; 837 int ret;
673 bool cell_added = false; 838 bool cell_added = false;
674 839
840 ret = lpc_ich_init_wdt(dev, id);
841 if (!ret)
842 cell_added = true;
843
675 ret = lpc_ich_init_gpio(dev, id); 844 ret = lpc_ich_init_gpio(dev, id);
676 if (!ret) 845 if (!ret)
677 cell_added = true; 846 cell_added = true;