Blame view

drivers/gpio/gpio-pch.c 13.6 KB
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
1
  /*
f4574beb9   Tomoya MORINAGA   pch_gpio: Change ...
2
   * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; version 2 of the License.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
   */
bb207ef1e   Paul Gortmaker   drivers/gpio: Fix...
17
  #include <linux/module.h>
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
18
19
20
  #include <linux/kernel.h>
  #include <linux/pci.h>
  #include <linux/gpio.h>
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
21
22
  #include <linux/interrupt.h>
  #include <linux/irq.h>
349b6c535   Linus Walleij   gpio: pch: add sl...
23
  #include <linux/slab.h>
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
24
25
26
27
28
29
30
31
32
  
  #define PCH_EDGE_FALLING	0
  #define PCH_EDGE_RISING		BIT(0)
  #define PCH_LEVEL_L		BIT(1)
  #define PCH_LEVEL_H		(BIT(0) | BIT(1))
  #define PCH_EDGE_BOTH		BIT(2)
  #define PCH_IM_MASK		(BIT(0) | BIT(1) | BIT(2))
  
  #define PCH_IRQ_BASE		24
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
33

04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
34
35
36
37
38
39
40
41
42
43
44
45
  struct pch_regs {
  	u32	ien;
  	u32	istatus;
  	u32	idisp;
  	u32	iclr;
  	u32	imask;
  	u32	imaskclr;
  	u32	po;
  	u32	pi;
  	u32	pm;
  	u32	im0;
  	u32	im1;
e98bed7f0   Tomoya MORINAGA   gpio-pch: Save re...
46
47
  	u32	reserved[3];
  	u32	gpio_use_sel;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
48
49
  	u32	reset;
  };
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
50
51
  enum pch_type_t {
  	INTEL_EG20T_PCH,
f4574beb9   Tomoya MORINAGA   pch_gpio: Change ...
52
53
  	OKISEMI_ML7223m_IOH, /* LAPIS Semiconductor ML7223 IOH PCIe Bus-m */
  	OKISEMI_ML7223n_IOH  /* LAPIS Semiconductor ML7223 IOH PCIe Bus-n */
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
54
55
56
57
58
59
60
61
  };
  
  /* Specifies number of GPIO PINS */
  static int gpio_pins[] = {
  	[INTEL_EG20T_PCH] = 12,
  	[OKISEMI_ML7223m_IOH] = 8,
  	[OKISEMI_ML7223n_IOH] = 8,
  };
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
62
63
  /**
   * struct pch_gpio_reg_data - The register store data.
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
64
65
   * @ien_reg:	To store contents of IEN register.
   * @imask_reg:	To store contents of IMASK register.
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
66
67
   * @po_reg:	To store contents of PO register.
   * @pm_reg:	To store contents of PM register.
e98bed7f0   Tomoya MORINAGA   gpio-pch: Save re...
68
69
70
71
   * @im0_reg:	To store contents of IM0 register.
   * @im1_reg:	To store contents of IM1 register.
   * @gpio_use_sel_reg : To store contents of GPIO_USE_SEL register.
   *		       (Only ML7223 Bus-n)
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
72
73
   */
  struct pch_gpio_reg_data {
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
74
75
  	u32 ien_reg;
  	u32 imask_reg;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
76
77
  	u32 po_reg;
  	u32 pm_reg;
e98bed7f0   Tomoya MORINAGA   gpio-pch: Save re...
78
79
80
  	u32 im0_reg;
  	u32 im1_reg;
  	u32 gpio_use_sel_reg;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
81
82
83
84
85
86
87
88
89
90
  };
  
  /**
   * struct pch_gpio - GPIO private data structure.
   * @base:			PCI base address of Memory mapped I/O register.
   * @reg:			Memory mapped PCH GPIO register list.
   * @dev:			Pointer to device structure.
   * @gpio:			Data for GPIO infrastructure.
   * @pch_gpio_reg:		Memory mapped Register data is saved here
   *				when suspend.
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
91
92
   * @lock:			Used for register access protection
   * @irq_base:		Save base of IRQ number for interrupt
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
93
   * @ioh:		IOH ID
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
94
   * @spinlock:		Used for register access protection
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
95
96
97
98
99
100
101
   */
  struct pch_gpio {
  	void __iomem *base;
  	struct pch_regs __iomem *reg;
  	struct device *dev;
  	struct gpio_chip gpio;
  	struct pch_gpio_reg_data pch_gpio_reg;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
102
  	int irq_base;
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
103
  	enum pch_type_t ioh;
d568a6814   Tomoya MORINAGA   gpio-pch: add spi...
104
  	spinlock_t spinlock;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
105
106
107
108
109
  };
  
  static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
  {
  	u32 reg_val;
510f48713   Linus Walleij   gpio: pch: use gp...
110
  	struct pch_gpio *chip =	gpiochip_get_data(gpio);
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
111
  	unsigned long flags;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
112

7cb6580c0   Axel Lin   gpio: gpio-pch: U...
113
  	spin_lock_irqsave(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
114
115
116
117
118
119
120
  	reg_val = ioread32(&chip->reg->po);
  	if (val)
  		reg_val |= (1 << nr);
  	else
  		reg_val &= ~(1 << nr);
  
  	iowrite32(reg_val, &chip->reg->po);
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
121
  	spin_unlock_irqrestore(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
122
123
124
125
  }
  
  static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
  {
510f48713   Linus Walleij   gpio: pch: use gp...
126
  	struct pch_gpio *chip =	gpiochip_get_data(gpio);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
127

166814d84   Jean Delvare   gpio: pch: Optimi...
128
  	return (ioread32(&chip->reg->pi) >> nr) & 1;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
129
130
131
132
133
  }
  
  static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
  				     int val)
  {
510f48713   Linus Walleij   gpio: pch: use gp...
134
  	struct pch_gpio *chip =	gpiochip_get_data(gpio);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
135
136
  	u32 pm;
  	u32 reg_val;
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
137
  	unsigned long flags;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
138

7cb6580c0   Axel Lin   gpio: gpio-pch: U...
139
  	spin_lock_irqsave(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
140
141
142
143
144
145
  
  	reg_val = ioread32(&chip->reg->po);
  	if (val)
  		reg_val |= (1 << nr);
  	else
  		reg_val &= ~(1 << nr);
88aab9341   Peter Tyser   gpio/pch_gpio: Fi...
146
  	iowrite32(reg_val, &chip->reg->po);
2ddf6cd67   Daniel Krueger   pch_gpio: set val...
147
148
149
150
  
  	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
  	pm |= (1 << nr);
  	iowrite32(pm, &chip->reg->pm);
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
151
  	spin_unlock_irqrestore(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
152
153
154
155
156
157
  
  	return 0;
  }
  
  static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
  {
510f48713   Linus Walleij   gpio: pch: use gp...
158
  	struct pch_gpio *chip =	gpiochip_get_data(gpio);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
159
  	u32 pm;
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
160
  	unsigned long flags;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
161

7cb6580c0   Axel Lin   gpio: gpio-pch: U...
162
  	spin_lock_irqsave(&chip->spinlock, flags);
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
163
  	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
164
165
  	pm &= ~(1 << nr);
  	iowrite32(pm, &chip->reg->pm);
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
166
  	spin_unlock_irqrestore(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
167
168
169
  
  	return 0;
  }
a092e19b6   Thierry Reding   gpio: pch: Build ...
170
  #ifdef CONFIG_PM
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
171
172
173
174
175
  /*
   * Save register configuration and disable interrupts.
   */
  static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
  {
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
176
177
  	chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien);
  	chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
178
179
  	chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
  	chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
e98bed7f0   Tomoya MORINAGA   gpio-pch: Save re...
180
181
182
183
184
185
  	chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0);
  	if (chip->ioh == INTEL_EG20T_PCH)
  		chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1);
  	if (chip->ioh == OKISEMI_ML7223n_IOH)
  		chip->pch_gpio_reg.gpio_use_sel_reg =\
  					    ioread32(&chip->reg->gpio_use_sel);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
186
187
188
189
190
191
192
  }
  
  /*
   * This function restores the register configuration of the GPIO device.
   */
  static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
  {
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
193
194
  	iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien);
  	iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
195
196
197
198
  	/* to store contents of PO register */
  	iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
  	/* to store contents of PM register */
  	iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
e98bed7f0   Tomoya MORINAGA   gpio-pch: Save re...
199
200
201
202
203
204
  	iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0);
  	if (chip->ioh == INTEL_EG20T_PCH)
  		iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1);
  	if (chip->ioh == OKISEMI_ML7223n_IOH)
  		iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg,
  			  &chip->reg->gpio_use_sel);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
205
  }
a092e19b6   Thierry Reding   gpio: pch: Build ...
206
  #endif
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
207

38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
208
209
  static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
  {
510f48713   Linus Walleij   gpio: pch: use gp...
210
  	struct pch_gpio *chip = gpiochip_get_data(gpio);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
211
212
  	return chip->irq_base + offset;
  }
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
213
214
215
216
217
  static void pch_gpio_setup(struct pch_gpio *chip)
  {
  	struct gpio_chip *gpio = &chip->gpio;
  
  	gpio->label = dev_name(chip->dev);
58383c784   Linus Walleij   gpio: change memb...
218
  	gpio->parent = chip->dev;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
219
220
221
222
223
224
225
  	gpio->owner = THIS_MODULE;
  	gpio->direction_input = pch_gpio_direction_input;
  	gpio->get = pch_gpio_get;
  	gpio->direction_output = pch_gpio_direction_output;
  	gpio->set = pch_gpio_set;
  	gpio->dbg_show = NULL;
  	gpio->base = -1;
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
226
  	gpio->ngpio = gpio_pins[chip->ioh];
9fb1f39eb   Linus Walleij   gpio/pinctrl: mak...
227
  	gpio->can_sleep = false;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
228
229
230
231
232
  	gpio->to_irq = pch_gpio_to_irq;
  }
  
  static int pch_irq_type(struct irq_data *d, unsigned int type)
  {
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
233
234
  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
  	struct pch_gpio *chip = gc->private;
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
235
236
237
238
  	u32 im, im_pos, val;
  	u32 __iomem *im_reg;
  	unsigned long flags;
  	int ch, irq = d->irq;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  
  	ch = irq - chip->irq_base;
  	if (irq <= chip->irq_base + 7) {
  		im_reg = &chip->reg->im0;
  		im_pos = ch;
  	} else {
  		im_reg = &chip->reg->im1;
  		im_pos = ch - 8;
  	}
  	dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d
  ",
  		__func__, irq, type, ch, im_pos);
  
  	spin_lock_irqsave(&chip->spinlock, flags);
  
  	switch (type) {
  	case IRQ_TYPE_EDGE_RISING:
  		val = PCH_EDGE_RISING;
  		break;
  	case IRQ_TYPE_EDGE_FALLING:
  		val = PCH_EDGE_FALLING;
  		break;
  	case IRQ_TYPE_EDGE_BOTH:
  		val = PCH_EDGE_BOTH;
  		break;
  	case IRQ_TYPE_LEVEL_HIGH:
  		val = PCH_LEVEL_H;
  		break;
  	case IRQ_TYPE_LEVEL_LOW:
  		val = PCH_LEVEL_L;
  		break;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
270
  	default:
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
271
  		goto unlock;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
272
273
274
275
276
  	}
  
  	/* Set interrupt mode */
  	im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
  	iowrite32(im | (val << (im_pos * 4)), im_reg);
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
277
278
  	/* And the handler */
  	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
2456d869c   Thomas Gleixner   gpio/pch: Use irq...
279
  		irq_set_handler_locked(d, handle_level_irq);
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
280
  	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
2456d869c   Thomas Gleixner   gpio/pch: Use irq...
281
  		irq_set_handler_locked(d, handle_edge_irq);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
282

df9541a60   Thomas Gleixner   gpio: pch9: Use p...
283
  unlock:
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
284
  	spin_unlock_irqrestore(&chip->spinlock, flags);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  	return 0;
  }
  
  static void pch_irq_unmask(struct irq_data *d)
  {
  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
  	struct pch_gpio *chip = gc->private;
  
  	iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr);
  }
  
  static void pch_irq_mask(struct irq_data *d)
  {
  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
  	struct pch_gpio *chip = gc->private;
  
  	iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask);
  }
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
303
304
305
306
307
308
309
  static void pch_irq_ack(struct irq_data *d)
  {
  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
  	struct pch_gpio *chip = gc->private;
  
  	iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->iclr);
  }
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
310
311
312
313
  static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
  {
  	struct pch_gpio *chip = dev_id;
  	u32 reg_val = ioread32(&chip->reg->istatus);
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
314
  	int i, ret = IRQ_NONE;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
315
316
317
318
319
320
  
  	for (i = 0; i < gpio_pins[chip->ioh]; i++) {
  		if (reg_val & BIT(i)) {
  			dev_dbg(chip->dev, "%s:[%d]:irq=%d  status=0x%x
  ",
  				__func__, i, irq, reg_val);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
321
322
323
324
325
326
  			generic_handle_irq(chip->irq_base + i);
  			ret = IRQ_HANDLED;
  		}
  	}
  	return ret;
  }
3836309d9   Bill Pemberton   gpio: remove use ...
327
  static void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
328
329
330
331
332
333
334
335
336
  				unsigned int irq_start, unsigned int num)
  {
  	struct irq_chip_generic *gc;
  	struct irq_chip_type *ct;
  
  	gc = irq_alloc_generic_chip("pch_gpio", 1, irq_start, chip->base,
  				    handle_simple_irq);
  	gc->private = chip;
  	ct = gc->chip_types;
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
337
  	ct->chip.irq_ack = pch_irq_ack;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
338
339
340
341
342
343
  	ct->chip.irq_mask = pch_irq_mask;
  	ct->chip.irq_unmask = pch_irq_unmask;
  	ct->chip.irq_set_type = pch_irq_type;
  
  	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
  			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
344
  }
3836309d9   Bill Pemberton   gpio: remove use ...
345
  static int pch_gpio_probe(struct pci_dev *pdev,
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
346
347
348
349
  				    const struct pci_device_id *id)
  {
  	s32 ret;
  	struct pch_gpio *chip;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
350
  	int irq_base;
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
351
  	u32 msk;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
  
  	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
  	if (chip == NULL)
  		return -ENOMEM;
  
  	chip->dev = &pdev->dev;
  	ret = pci_enable_device(pdev);
  	if (ret) {
  		dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
  		goto err_pci_enable;
  	}
  
  	ret = pci_request_regions(pdev, KBUILD_MODNAME);
  	if (ret) {
  		dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
  		goto err_request_regions;
  	}
  
  	chip->base = pci_iomap(pdev, 1, 0);
c4addcb55   Márton Németh   gpio-pch: cleanup...
371
  	if (!chip->base) {
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
372
373
374
375
  		dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
  		ret = -ENOMEM;
  		goto err_iomap;
  	}
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
376
377
378
379
380
381
  	if (pdev->device == 0x8803)
  		chip->ioh = INTEL_EG20T_PCH;
  	else if (pdev->device == 0x8014)
  		chip->ioh = OKISEMI_ML7223m_IOH;
  	else if (pdev->device == 0x8043)
  		chip->ioh = OKISEMI_ML7223n_IOH;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
382
383
  	chip->reg = chip->base;
  	pci_set_drvdata(pdev, chip);
d166370ad   Axel Lin   gpio: Add missing...
384
  	spin_lock_init(&chip->spinlock);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
385
  	pch_gpio_setup(chip);
a9f1a3e4c   Linus Walleij   gpio: pch: fix no...
386
  #ifdef CONFIG_OF_GPIO
1cfadea8f   Paul Burton   gpio: pch: allow ...
387
  	chip->gpio.of_node = pdev->dev.of_node;
a9f1a3e4c   Linus Walleij   gpio: pch: fix no...
388
  #endif
510f48713   Linus Walleij   gpio: pch: use gp...
389
  	ret = gpiochip_add_data(&chip->gpio, chip);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
390
391
392
393
394
  	if (ret) {
  		dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO
  ");
  		goto err_gpiochip_add;
  	}
2824bc9c3   Tomoya MORINAGA   gpio-pch: Use NUM...
395
  	irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
396
397
398
399
400
401
402
  	if (irq_base < 0) {
  		dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num
  ");
  		chip->irq_base = -1;
  		goto end;
  	}
  	chip->irq_base = irq_base;
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
403
404
405
406
  	/* Mask all interrupts, but enable them */
  	msk = (1 << gpio_pins[chip->ioh]) - 1;
  	iowrite32(msk, &chip->reg->imask);
  	iowrite32(msk, &chip->reg->ien);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
407
  	ret = request_irq(pdev->irq, pch_gpio_handler,
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
408
  			  IRQF_SHARED, KBUILD_MODNAME, chip);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
409
410
411
412
413
414
415
416
  	if (ret != 0) {
  		dev_err(&pdev->dev,
  			"%s request_irq failed
  ", __func__);
  		goto err_request_irq;
  	}
  
  	pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
417
  end:
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
418
  	return 0;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
419
420
  err_request_irq:
  	irq_free_descs(irq_base, gpio_pins[chip->ioh]);
9f5132ae8   abdoulaye berthe   gpio: remove all ...
421
  	gpiochip_remove(&chip->gpio);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
422

04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  err_gpiochip_add:
  	pci_iounmap(pdev, chip->base);
  
  err_iomap:
  	pci_release_regions(pdev);
  
  err_request_regions:
  	pci_disable_device(pdev);
  
  err_pci_enable:
  	kfree(chip);
  	dev_err(&pdev->dev, "%s Failed returns %d
  ", __func__, ret);
  	return ret;
  }
206210ce6   Bill Pemberton   gpio: remove use ...
438
  static void pch_gpio_remove(struct pci_dev *pdev)
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
439
  {
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
440
  	struct pch_gpio *chip = pci_get_drvdata(pdev);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
441
442
443
444
445
  	if (chip->irq_base != -1) {
  		free_irq(pdev->irq, chip);
  
  		irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
  	}
9f5132ae8   abdoulaye berthe   gpio: remove all ...
446
  	gpiochip_remove(&chip->gpio);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
447
448
449
450
451
452
453
454
455
456
457
  	pci_iounmap(pdev, chip->base);
  	pci_release_regions(pdev);
  	pci_disable_device(pdev);
  	kfree(chip);
  }
  
  #ifdef CONFIG_PM
  static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
  {
  	s32 ret;
  	struct pch_gpio *chip = pci_get_drvdata(pdev);
d568a6814   Tomoya MORINAGA   gpio-pch: add spi...
458
  	unsigned long flags;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
459

d568a6814   Tomoya MORINAGA   gpio-pch: add spi...
460
  	spin_lock_irqsave(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
461
  	pch_gpio_save_reg_conf(chip);
d568a6814   Tomoya MORINAGA   gpio-pch: add spi...
462
  	spin_unlock_irqrestore(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
  
  	ret = pci_save_state(pdev);
  	if (ret) {
  		dev_err(&pdev->dev, "pci_save_state Failed-%d
  ", ret);
  		return ret;
  	}
  	pci_disable_device(pdev);
  	pci_set_power_state(pdev, PCI_D0);
  	ret = pci_enable_wake(pdev, PCI_D0, 1);
  	if (ret)
  		dev_err(&pdev->dev, "pci_enable_wake Failed -%d
  ", ret);
  
  	return 0;
  }
  
  static int pch_gpio_resume(struct pci_dev *pdev)
  {
  	s32 ret;
  	struct pch_gpio *chip = pci_get_drvdata(pdev);
d568a6814   Tomoya MORINAGA   gpio-pch: add spi...
484
  	unsigned long flags;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
485
486
487
488
489
490
491
492
493
494
  
  	ret = pci_enable_wake(pdev, PCI_D0, 0);
  
  	pci_set_power_state(pdev, PCI_D0);
  	ret = pci_enable_device(pdev);
  	if (ret) {
  		dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
  		return ret;
  	}
  	pci_restore_state(pdev);
d568a6814   Tomoya MORINAGA   gpio-pch: add spi...
495
  	spin_lock_irqsave(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
496
497
498
  	iowrite32(0x01, &chip->reg->reset);
  	iowrite32(0x00, &chip->reg->reset);
  	pch_gpio_restore_reg_conf(chip);
d568a6814   Tomoya MORINAGA   gpio-pch: add spi...
499
  	spin_unlock_irqrestore(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
500
501
502
503
504
505
506
  
  	return 0;
  }
  #else
  #define pch_gpio_suspend NULL
  #define pch_gpio_resume NULL
  #endif
bc786ccea   Tomoya MORINAGA   gpio/pch_gpio: Su...
507
  #define PCI_VENDOR_ID_ROHM             0x10DB
14f4a8838   Jingoo Han   gpio: remove DEFI...
508
  static const struct pci_device_id pch_gpio_pcidev_id[] = {
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
509
  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
bc786ccea   Tomoya MORINAGA   gpio/pch_gpio: Su...
510
  	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
c3520a1a8   Tomoya MORINAGA   gpio-pch: support...
511
  	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
868fea050   Tomoya MORINAGA   pch_gpio: Support...
512
  	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803) },
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
513
514
  	{ 0, }
  };
19234cdda   Axel Lin   gpio: add MODULE_...
515
  MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
516
517
518
519
520
  
  static struct pci_driver pch_gpio_driver = {
  	.name = "pch_gpio",
  	.id_table = pch_gpio_pcidev_id,
  	.probe = pch_gpio_probe,
8283c4ff5   Bill Pemberton   gpio: remove use ...
521
  	.remove = pch_gpio_remove,
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
522
523
524
  	.suspend = pch_gpio_suspend,
  	.resume = pch_gpio_resume
  };
93baa65fe   Axel Lin   gpio: Convert dri...
525
  module_pci_driver(pch_gpio_driver);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
526
527
528
  
  MODULE_DESCRIPTION("PCH GPIO PCI Driver");
  MODULE_LICENSE("GPL");