aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTomoya MORINAGA <tomoya-linux@dsn.okisemi.com>2010-10-27 18:33:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-27 21:03:07 -0400
commit04c17aa89380addf8d7df6f0fd269fc2bd87796c (patch)
treefaffaaf88052da07c90fe15b7869c4326441b637 /drivers
parentdc5ae4f2f58cfa98b67d2be379fc99080a8967af (diff)
gpio: add Topcliff PCH GPIO driver
Topcliff PCH is the platform controller hub that is going to be used in Intel's upcoming general embedded platform. All IO peripherals in Topcliff PCH are actually devices sitting on AMBA bus. Topcliff PCH has GPIO I/F. Using this I/F, it is able to access system devices connected to GPIO. [akpm@linux-foundation.org: ese DEFINE_PCI_DEVICE_TABLE (per Joe Perches)] Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Cc: Rabin Vincent <rabin.vincent@stericsson.com> Cc: Samuel Ortiz <sameo@linux.intel.com> Cc: Linus Walleij <linus.walleij@stericsson.com> Cc: Tomoya MORINAGA <morinaga526@dsn.okisemi.com> Cc: Joe Perches <joe@perches.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig8
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/pch_gpio.c312
3 files changed, 321 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 3f3181dac8d7..dd9b4ba8d32d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -313,6 +313,14 @@ config GPIO_LANGWELL
313 help 313 help
314 Say Y here to support Intel Langwell/Penwell GPIO. 314 Say Y here to support Intel Langwell/Penwell GPIO.
315 315
316config GPIO_PCH
317 tristate "PCH GPIO of Intel Topcliff"
318 depends on PCI
319 help
320 This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
321 which is an IOH(Input/Output Hub) for x86 embedded processor.
322 This driver can access PCH GPIO device.
323
316config GPIO_TIMBERDALE 324config GPIO_TIMBERDALE
317 bool "Support for timberdale GPIO IP" 325 bool "Support for timberdale GPIO IP"
318 depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM 326 depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 0c23a4dd45e5..da2ecde5abdd 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
21obj-$(CONFIG_GPIO_74X164) += 74x164.o 21obj-$(CONFIG_GPIO_74X164) += 74x164.o
22obj-$(CONFIG_GPIO_PCA953X) += pca953x.o 22obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
23obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o 23obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
24obj-$(CONFIG_GPIO_PCH) += pch_gpio.o
24obj-$(CONFIG_GPIO_PL061) += pl061.o 25obj-$(CONFIG_GPIO_PL061) += pl061.o
25obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o 26obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o
26obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o 27obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o
diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c
new file mode 100644
index 000000000000..0eba0a75c804
--- /dev/null
+++ b/drivers/gpio/pch_gpio.c
@@ -0,0 +1,312 @@
1/*
2 * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
16 */
17#include <linux/kernel.h>
18#include <linux/pci.h>
19#include <linux/gpio.h>
20
21#define PCH_GPIO_ALL_PINS 0xfff /* Mask for GPIO pins 0 to 11 */
22#define GPIO_NUM_PINS 12 /* Specifies number of GPIO PINS GPIO0-GPIO11 */
23
24struct pch_regs {
25 u32 ien;
26 u32 istatus;
27 u32 idisp;
28 u32 iclr;
29 u32 imask;
30 u32 imaskclr;
31 u32 po;
32 u32 pi;
33 u32 pm;
34 u32 im0;
35 u32 im1;
36 u32 reserved[4];
37 u32 reset;
38};
39
40/**
41 * struct pch_gpio_reg_data - The register store data.
42 * @po_reg: To store contents of PO register.
43 * @pm_reg: To store contents of PM register.
44 */
45struct pch_gpio_reg_data {
46 u32 po_reg;
47 u32 pm_reg;
48};
49
50/**
51 * struct pch_gpio - GPIO private data structure.
52 * @base: PCI base address of Memory mapped I/O register.
53 * @reg: Memory mapped PCH GPIO register list.
54 * @dev: Pointer to device structure.
55 * @gpio: Data for GPIO infrastructure.
56 * @pch_gpio_reg: Memory mapped Register data is saved here
57 * when suspend.
58 */
59struct pch_gpio {
60 void __iomem *base;
61 struct pch_regs __iomem *reg;
62 struct device *dev;
63 struct gpio_chip gpio;
64 struct pch_gpio_reg_data pch_gpio_reg;
65 struct mutex lock;
66};
67
68static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
69{
70 u32 reg_val;
71 struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
72
73 mutex_lock(&chip->lock);
74 reg_val = ioread32(&chip->reg->po);
75 if (val)
76 reg_val |= (1 << nr);
77 else
78 reg_val &= ~(1 << nr);
79
80 iowrite32(reg_val, &chip->reg->po);
81 mutex_unlock(&chip->lock);
82}
83
84static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
85{
86 struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
87
88 return ioread32(&chip->reg->pi) & (1 << nr);
89}
90
91static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
92 int val)
93{
94 struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
95 u32 pm;
96 u32 reg_val;
97
98 mutex_lock(&chip->lock);
99 pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
100 pm |= (1 << nr);
101 iowrite32(pm, &chip->reg->pm);
102
103 reg_val = ioread32(&chip->reg->po);
104 if (val)
105 reg_val |= (1 << nr);
106 else
107 reg_val &= ~(1 << nr);
108
109 mutex_unlock(&chip->lock);
110
111 return 0;
112}
113
114static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
115{
116 struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
117 u32 pm;
118
119 mutex_lock(&chip->lock);
120 pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
121 pm &= ~(1 << nr);
122 iowrite32(pm, &chip->reg->pm);
123 mutex_unlock(&chip->lock);
124
125 return 0;
126}
127
128/*
129 * Save register configuration and disable interrupts.
130 */
131static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
132{
133 chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
134 chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
135}
136
137/*
138 * This function restores the register configuration of the GPIO device.
139 */
140static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
141{
142 /* to store contents of PO register */
143 iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
144 /* to store contents of PM register */
145 iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
146}
147
148static void pch_gpio_setup(struct pch_gpio *chip)
149{
150 struct gpio_chip *gpio = &chip->gpio;
151
152 gpio->label = dev_name(chip->dev);
153 gpio->owner = THIS_MODULE;
154 gpio->direction_input = pch_gpio_direction_input;
155 gpio->get = pch_gpio_get;
156 gpio->direction_output = pch_gpio_direction_output;
157 gpio->set = pch_gpio_set;
158 gpio->dbg_show = NULL;
159 gpio->base = -1;
160 gpio->ngpio = GPIO_NUM_PINS;
161 gpio->can_sleep = 0;
162}
163
164static int __devinit pch_gpio_probe(struct pci_dev *pdev,
165 const struct pci_device_id *id)
166{
167 s32 ret;
168 struct pch_gpio *chip;
169
170 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
171 if (chip == NULL)
172 return -ENOMEM;
173
174 chip->dev = &pdev->dev;
175 ret = pci_enable_device(pdev);
176 if (ret) {
177 dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
178 goto err_pci_enable;
179 }
180
181 ret = pci_request_regions(pdev, KBUILD_MODNAME);
182 if (ret) {
183 dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
184 goto err_request_regions;
185 }
186
187 chip->base = pci_iomap(pdev, 1, 0);
188 if (chip->base == 0) {
189 dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
190 ret = -ENOMEM;
191 goto err_iomap;
192 }
193
194 chip->reg = chip->base;
195 pci_set_drvdata(pdev, chip);
196 mutex_init(&chip->lock);
197 pch_gpio_setup(chip);
198 ret = gpiochip_add(&chip->gpio);
199 if (ret) {
200 dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
201 goto err_gpiochip_add;
202 }
203
204 return 0;
205
206err_gpiochip_add:
207 pci_iounmap(pdev, chip->base);
208
209err_iomap:
210 pci_release_regions(pdev);
211
212err_request_regions:
213 pci_disable_device(pdev);
214
215err_pci_enable:
216 kfree(chip);
217 dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
218 return ret;
219}
220
221static void __devexit pch_gpio_remove(struct pci_dev *pdev)
222{
223 int err;
224 struct pch_gpio *chip = pci_get_drvdata(pdev);
225
226 err = gpiochip_remove(&chip->gpio);
227 if (err)
228 dev_err(&pdev->dev, "Failed gpiochip_remove\n");
229
230 pci_iounmap(pdev, chip->base);
231 pci_release_regions(pdev);
232 pci_disable_device(pdev);
233 kfree(chip);
234}
235
236#ifdef CONFIG_PM
237static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
238{
239 s32 ret;
240 struct pch_gpio *chip = pci_get_drvdata(pdev);
241
242 pch_gpio_save_reg_conf(chip);
243 pch_gpio_restore_reg_conf(chip);
244
245 ret = pci_save_state(pdev);
246 if (ret) {
247 dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
248 return ret;
249 }
250 pci_disable_device(pdev);
251 pci_set_power_state(pdev, PCI_D0);
252 ret = pci_enable_wake(pdev, PCI_D0, 1);
253 if (ret)
254 dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
255
256 return 0;
257}
258
259static int pch_gpio_resume(struct pci_dev *pdev)
260{
261 s32 ret;
262 struct pch_gpio *chip = pci_get_drvdata(pdev);
263
264 ret = pci_enable_wake(pdev, PCI_D0, 0);
265
266 pci_set_power_state(pdev, PCI_D0);
267 ret = pci_enable_device(pdev);
268 if (ret) {
269 dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
270 return ret;
271 }
272 pci_restore_state(pdev);
273
274 iowrite32(0x01, &chip->reg->reset);
275 iowrite32(0x00, &chip->reg->reset);
276 pch_gpio_restore_reg_conf(chip);
277
278 return 0;
279}
280#else
281#define pch_gpio_suspend NULL
282#define pch_gpio_resume NULL
283#endif
284
285static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
286 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
287 { 0, }
288};
289
290static struct pci_driver pch_gpio_driver = {
291 .name = "pch_gpio",
292 .id_table = pch_gpio_pcidev_id,
293 .probe = pch_gpio_probe,
294 .remove = __devexit_p(pch_gpio_remove),
295 .suspend = pch_gpio_suspend,
296 .resume = pch_gpio_resume
297};
298
299static int __init pch_gpio_pci_init(void)
300{
301 return pci_register_driver(&pch_gpio_driver);
302}
303module_init(pch_gpio_pci_init);
304
305static void __exit pch_gpio_pci_exit(void)
306{
307 pci_unregister_driver(&pch_gpio_driver);
308}
309module_exit(pch_gpio_pci_exit);
310
311MODULE_DESCRIPTION("PCH GPIO PCI Driver");
312MODULE_LICENSE("GPL");