diff options
-rw-r--r-- | drivers/mfd/Kconfig | 9 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 1 | ||||
-rw-r--r-- | drivers/mfd/lpc_sch.c | 133 |
3 files changed, 143 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 84a68d260772..9b25fe28233e 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -389,6 +389,15 @@ config MFD_TIMBERDALE | |||
389 | 389 | ||
390 | The timberdale FPGA can be found on the Intel Atom development board | 390 | The timberdale FPGA can be found on the Intel Atom development board |
391 | for in-vehicle infontainment, called Russellville. | 391 | for in-vehicle infontainment, called Russellville. |
392 | |||
393 | config LPC_SCH | ||
394 | tristate "Intel SCH LPC" | ||
395 | depends on PCI | ||
396 | select MFD_CORE | ||
397 | help | ||
398 | LPC bridge function of the Intel SCH provides support for | ||
399 | System Management Bus and General Purpose I/O. | ||
400 | |||
392 | endmenu | 401 | endmenu |
393 | 402 | ||
394 | menu "Multimedia Capabilities Port drivers" | 403 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 878cac691067..22715add99a7 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -62,3 +62,4 @@ obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o | |||
62 | obj-$(CONFIG_AB4500_CORE) += ab4500-core.o | 62 | obj-$(CONFIG_AB4500_CORE) += ab4500-core.o |
63 | obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o | 63 | obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o |
64 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o | 64 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o |
65 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o \ No newline at end of file | ||
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c new file mode 100644 index 000000000000..51b2f6065a0b --- /dev/null +++ b/drivers/mfd/lpc_sch.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * lpc_sch.c - LPC interface for Intel Poulsbo SCH | ||
3 | * | ||
4 | * LPC bridge function of the Intel SCH 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 | * Copyright (c) 2010 CompuLab Ltd | ||
10 | * Author: Denis Turischev <denis@compulab.co.il> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License 2 as published | ||
14 | * by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; see the file COPYING. If not, write to | ||
23 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/acpi.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/mfd/core.h> | ||
33 | |||
34 | #define SMBASE 0x40 | ||
35 | #define SMBUS_IO_SIZE 64 | ||
36 | |||
37 | #define GPIOBASE 0x44 | ||
38 | #define GPIO_IO_SIZE 64 | ||
39 | |||
40 | static struct resource smbus_sch_resource = { | ||
41 | .flags = IORESOURCE_IO, | ||
42 | }; | ||
43 | |||
44 | |||
45 | static struct resource gpio_sch_resource = { | ||
46 | .flags = IORESOURCE_IO, | ||
47 | }; | ||
48 | |||
49 | static struct mfd_cell lpc_sch_cells[] = { | ||
50 | { | ||
51 | .name = "isch_smbus", | ||
52 | .num_resources = 1, | ||
53 | .resources = &smbus_sch_resource, | ||
54 | }, | ||
55 | { | ||
56 | .name = "sch_gpio", | ||
57 | .num_resources = 1, | ||
58 | .resources = &gpio_sch_resource, | ||
59 | }, | ||
60 | }; | ||
61 | |||
62 | static struct pci_device_id lpc_sch_ids[] = { | ||
63 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) }, | ||
64 | { 0, } | ||
65 | }; | ||
66 | MODULE_DEVICE_TABLE(pci, lpc_sch_ids); | ||
67 | |||
68 | static int __devinit lpc_sch_probe(struct pci_dev *dev, | ||
69 | const struct pci_device_id *id) | ||
70 | { | ||
71 | unsigned int base_addr_cfg; | ||
72 | unsigned short base_addr; | ||
73 | |||
74 | pci_read_config_dword(dev, SMBASE, &base_addr_cfg); | ||
75 | if (!(base_addr_cfg & (1 << 31))) { | ||
76 | dev_err(&dev->dev, "Decode of the SMBus I/O range disabled\n"); | ||
77 | return -ENODEV; | ||
78 | } | ||
79 | base_addr = (unsigned short)base_addr_cfg; | ||
80 | if (base_addr == 0) { | ||
81 | dev_err(&dev->dev, "I/O space for SMBus uninitialized\n"); | ||
82 | return -ENODEV; | ||
83 | } | ||
84 | |||
85 | smbus_sch_resource.start = base_addr; | ||
86 | smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1; | ||
87 | |||
88 | pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg); | ||
89 | if (!(base_addr_cfg & (1 << 31))) { | ||
90 | dev_err(&dev->dev, "Decode of the GPIO I/O range disabled\n"); | ||
91 | return -ENODEV; | ||
92 | } | ||
93 | base_addr = (unsigned short)base_addr_cfg; | ||
94 | if (base_addr == 0) { | ||
95 | dev_err(&dev->dev, "I/O space for GPIO uninitialized\n"); | ||
96 | return -ENODEV; | ||
97 | } | ||
98 | |||
99 | gpio_sch_resource.start = base_addr; | ||
100 | gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1; | ||
101 | |||
102 | return mfd_add_devices(&dev->dev, -1, | ||
103 | lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0); | ||
104 | } | ||
105 | |||
106 | static void __devexit lpc_sch_remove(struct pci_dev *dev) | ||
107 | { | ||
108 | mfd_remove_devices(&dev->dev); | ||
109 | } | ||
110 | |||
111 | static struct pci_driver lpc_sch_driver = { | ||
112 | .name = "lpc_sch", | ||
113 | .id_table = lpc_sch_ids, | ||
114 | .probe = lpc_sch_probe, | ||
115 | .remove = __devexit_p(lpc_sch_remove), | ||
116 | }; | ||
117 | |||
118 | static int __init lpc_sch_init(void) | ||
119 | { | ||
120 | return pci_register_driver(&lpc_sch_driver); | ||
121 | } | ||
122 | |||
123 | static void __exit lpc_sch_exit(void) | ||
124 | { | ||
125 | pci_unregister_driver(&lpc_sch_driver); | ||
126 | } | ||
127 | |||
128 | module_init(lpc_sch_init); | ||
129 | module_exit(lpc_sch_exit); | ||
130 | |||
131 | MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); | ||
132 | MODULE_DESCRIPTION("LPC interface for Intel Poulsbo SCH"); | ||
133 | MODULE_LICENSE("GPL"); | ||