blob: 4ac69bd7ad4a4032c8b0129304eabc2d8c05f719 [file] [log] [blame]
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -07001/*
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
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070021struct pch_regs {
22 u32 ien;
23 u32 istatus;
24 u32 idisp;
25 u32 iclr;
26 u32 imask;
27 u32 imaskclr;
28 u32 po;
29 u32 pi;
30 u32 pm;
31 u32 im0;
32 u32 im1;
33 u32 reserved[4];
34 u32 reset;
35};
36
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +090037enum pch_type_t {
38 INTEL_EG20T_PCH,
39 OKISEMI_ML7223m_IOH, /* OKISEMI ML7223 IOH PCIe Bus-m */
40 OKISEMI_ML7223n_IOH /* OKISEMI ML7223 IOH PCIe Bus-n */
41};
42
43/* Specifies number of GPIO PINS */
44static int gpio_pins[] = {
45 [INTEL_EG20T_PCH] = 12,
46 [OKISEMI_ML7223m_IOH] = 8,
47 [OKISEMI_ML7223n_IOH] = 8,
48};
49
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070050/**
51 * struct pch_gpio_reg_data - The register store data.
52 * @po_reg: To store contents of PO register.
53 * @pm_reg: To store contents of PM register.
54 */
55struct pch_gpio_reg_data {
56 u32 po_reg;
57 u32 pm_reg;
58};
59
60/**
61 * struct pch_gpio - GPIO private data structure.
62 * @base: PCI base address of Memory mapped I/O register.
63 * @reg: Memory mapped PCH GPIO register list.
64 * @dev: Pointer to device structure.
65 * @gpio: Data for GPIO infrastructure.
66 * @pch_gpio_reg: Memory mapped Register data is saved here
67 * when suspend.
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +090068 * @ioh: IOH ID
Tomoya MORINAGAd568a682011-07-21 09:19:55 +090069 * @spinlock: Used for register access protection in
70 * interrupt context pch_irq_mask,
71 * pch_irq_unmask and pch_irq_type;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070072 */
73struct pch_gpio {
74 void __iomem *base;
75 struct pch_regs __iomem *reg;
76 struct device *dev;
77 struct gpio_chip gpio;
78 struct pch_gpio_reg_data pch_gpio_reg;
79 struct mutex lock;
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +090080 enum pch_type_t ioh;
Tomoya MORINAGAd568a682011-07-21 09:19:55 +090081 spinlock_t spinlock;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070082};
83
84static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
85{
86 u32 reg_val;
87 struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
88
89 mutex_lock(&chip->lock);
90 reg_val = ioread32(&chip->reg->po);
91 if (val)
92 reg_val |= (1 << nr);
93 else
94 reg_val &= ~(1 << nr);
95
96 iowrite32(reg_val, &chip->reg->po);
97 mutex_unlock(&chip->lock);
98}
99
100static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
101{
102 struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
103
104 return ioread32(&chip->reg->pi) & (1 << nr);
105}
106
107static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
108 int val)
109{
110 struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
111 u32 pm;
112 u32 reg_val;
113
114 mutex_lock(&chip->lock);
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +0900115 pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700116 pm |= (1 << nr);
117 iowrite32(pm, &chip->reg->pm);
118
119 reg_val = ioread32(&chip->reg->po);
120 if (val)
121 reg_val |= (1 << nr);
122 else
123 reg_val &= ~(1 << nr);
Peter Tyser88aab932011-03-25 10:04:00 -0500124 iowrite32(reg_val, &chip->reg->po);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700125
126 mutex_unlock(&chip->lock);
127
128 return 0;
129}
130
131static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
132{
133 struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
134 u32 pm;
135
136 mutex_lock(&chip->lock);
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +0900137 pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700138 pm &= ~(1 << nr);
139 iowrite32(pm, &chip->reg->pm);
140 mutex_unlock(&chip->lock);
141
142 return 0;
143}
144
145/*
146 * Save register configuration and disable interrupts.
147 */
148static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
149{
150 chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
151 chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
152}
153
154/*
155 * This function restores the register configuration of the GPIO device.
156 */
157static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
158{
159 /* to store contents of PO register */
160 iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
161 /* to store contents of PM register */
162 iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
163}
164
165static void pch_gpio_setup(struct pch_gpio *chip)
166{
167 struct gpio_chip *gpio = &chip->gpio;
168
169 gpio->label = dev_name(chip->dev);
170 gpio->owner = THIS_MODULE;
171 gpio->direction_input = pch_gpio_direction_input;
172 gpio->get = pch_gpio_get;
173 gpio->direction_output = pch_gpio_direction_output;
174 gpio->set = pch_gpio_set;
175 gpio->dbg_show = NULL;
176 gpio->base = -1;
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +0900177 gpio->ngpio = gpio_pins[chip->ioh];
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700178 gpio->can_sleep = 0;
179}
180
181static int __devinit pch_gpio_probe(struct pci_dev *pdev,
182 const struct pci_device_id *id)
183{
184 s32 ret;
185 struct pch_gpio *chip;
186
187 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
188 if (chip == NULL)
189 return -ENOMEM;
190
191 chip->dev = &pdev->dev;
192 ret = pci_enable_device(pdev);
193 if (ret) {
194 dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
195 goto err_pci_enable;
196 }
197
198 ret = pci_request_regions(pdev, KBUILD_MODNAME);
199 if (ret) {
200 dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
201 goto err_request_regions;
202 }
203
204 chip->base = pci_iomap(pdev, 1, 0);
205 if (chip->base == 0) {
206 dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
207 ret = -ENOMEM;
208 goto err_iomap;
209 }
210
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +0900211 if (pdev->device == 0x8803)
212 chip->ioh = INTEL_EG20T_PCH;
213 else if (pdev->device == 0x8014)
214 chip->ioh = OKISEMI_ML7223m_IOH;
215 else if (pdev->device == 0x8043)
216 chip->ioh = OKISEMI_ML7223n_IOH;
217
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700218 chip->reg = chip->base;
219 pci_set_drvdata(pdev, chip);
220 mutex_init(&chip->lock);
221 pch_gpio_setup(chip);
222 ret = gpiochip_add(&chip->gpio);
223 if (ret) {
224 dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
225 goto err_gpiochip_add;
226 }
227
228 return 0;
229
230err_gpiochip_add:
231 pci_iounmap(pdev, chip->base);
232
233err_iomap:
234 pci_release_regions(pdev);
235
236err_request_regions:
237 pci_disable_device(pdev);
238
239err_pci_enable:
240 kfree(chip);
241 dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
242 return ret;
243}
244
245static void __devexit pch_gpio_remove(struct pci_dev *pdev)
246{
247 int err;
248 struct pch_gpio *chip = pci_get_drvdata(pdev);
249
250 err = gpiochip_remove(&chip->gpio);
251 if (err)
252 dev_err(&pdev->dev, "Failed gpiochip_remove\n");
253
254 pci_iounmap(pdev, chip->base);
255 pci_release_regions(pdev);
256 pci_disable_device(pdev);
257 kfree(chip);
258}
259
260#ifdef CONFIG_PM
261static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
262{
263 s32 ret;
264 struct pch_gpio *chip = pci_get_drvdata(pdev);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900265 unsigned long flags;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700266
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900267 spin_lock_irqsave(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700268 pch_gpio_save_reg_conf(chip);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900269 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700270
271 ret = pci_save_state(pdev);
272 if (ret) {
273 dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
274 return ret;
275 }
276 pci_disable_device(pdev);
277 pci_set_power_state(pdev, PCI_D0);
278 ret = pci_enable_wake(pdev, PCI_D0, 1);
279 if (ret)
280 dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
281
282 return 0;
283}
284
285static int pch_gpio_resume(struct pci_dev *pdev)
286{
287 s32 ret;
288 struct pch_gpio *chip = pci_get_drvdata(pdev);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900289 unsigned long flags;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700290
291 ret = pci_enable_wake(pdev, PCI_D0, 0);
292
293 pci_set_power_state(pdev, PCI_D0);
294 ret = pci_enable_device(pdev);
295 if (ret) {
296 dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
297 return ret;
298 }
299 pci_restore_state(pdev);
300
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900301 spin_lock_irqsave(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700302 iowrite32(0x01, &chip->reg->reset);
303 iowrite32(0x00, &chip->reg->reset);
304 pch_gpio_restore_reg_conf(chip);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900305 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700306
307 return 0;
308}
309#else
310#define pch_gpio_suspend NULL
311#define pch_gpio_resume NULL
312#endif
313
Tomoya MORINAGAbc786cc2011-05-09 19:58:49 +0900314#define PCI_VENDOR_ID_ROHM 0x10DB
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700315static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
316 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
Tomoya MORINAGAbc786cc2011-05-09 19:58:49 +0900317 { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
Tomoya MORINAGAc3520a12011-07-21 09:19:56 +0900318 { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700319 { 0, }
320};
Axel Lin19234cd2011-03-11 14:58:30 -0800321MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700322
323static struct pci_driver pch_gpio_driver = {
324 .name = "pch_gpio",
325 .id_table = pch_gpio_pcidev_id,
326 .probe = pch_gpio_probe,
327 .remove = __devexit_p(pch_gpio_remove),
328 .suspend = pch_gpio_suspend,
329 .resume = pch_gpio_resume
330};
331
332static int __init pch_gpio_pci_init(void)
333{
334 return pci_register_driver(&pch_gpio_driver);
335}
336module_init(pch_gpio_pci_init);
337
338static void __exit pch_gpio_pci_exit(void)
339{
340 pci_unregister_driver(&pch_gpio_driver);
341}
342module_exit(pch_gpio_pci_exit);
343
344MODULE_DESCRIPTION("PCH GPIO PCI Driver");
345MODULE_LICENSE("GPL");