Blame view

drivers/gpio/gpio-pch.c 13.7 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
23
24
25
26
27
28
29
30
31
  #include <linux/interrupt.h>
  #include <linux/irq.h>
  
  #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...
32

04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
33
34
35
36
37
38
39
40
41
42
43
44
  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...
45
46
  	u32	reserved[3];
  	u32	gpio_use_sel;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
47
48
  	u32	reset;
  };
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
49
50
  enum pch_type_t {
  	INTEL_EG20T_PCH,
f4574beb9   Tomoya MORINAGA   pch_gpio: Change ...
51
52
  	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 ...
53
54
55
56
57
58
59
60
  };
  
  /* 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...
61
62
  /**
   * struct pch_gpio_reg_data - The register store data.
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
63
64
   * @ien_reg:	To store contents of IEN register.
   * @imask_reg:	To store contents of IMASK register.
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
65
66
   * @po_reg:	To store contents of PO register.
   * @pm_reg:	To store contents of PM register.
e98bed7f0   Tomoya MORINAGA   gpio-pch: Save re...
67
68
69
70
   * @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...
71
72
   */
  struct pch_gpio_reg_data {
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
73
74
  	u32 ien_reg;
  	u32 imask_reg;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
75
76
  	u32 po_reg;
  	u32 pm_reg;
e98bed7f0   Tomoya MORINAGA   gpio-pch: Save re...
77
78
79
  	u32 im0_reg;
  	u32 im1_reg;
  	u32 gpio_use_sel_reg;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
80
81
82
83
84
85
86
87
88
89
  };
  
  /**
   * 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...
90
91
   * @lock:			Used for register access protection
   * @irq_base:		Save base of IRQ number for interrupt
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
92
   * @ioh:		IOH ID
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
93
   * @spinlock:		Used for register access protection
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
94
95
96
97
98
99
100
   */
  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...
101
  	int irq_base;
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
102
  	enum pch_type_t ioh;
d568a6814   Tomoya MORINAGA   gpio-pch: add spi...
103
  	spinlock_t spinlock;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
104
105
106
107
108
109
  };
  
  static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
  {
  	u32 reg_val;
  	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
110
  	unsigned long flags;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
111

7cb6580c0   Axel Lin   gpio: gpio-pch: U...
112
  	spin_lock_irqsave(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
113
114
115
116
117
118
119
  	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...
120
  	spin_unlock_irqrestore(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  }
  
  static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
  {
  	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
  
  	return ioread32(&chip->reg->pi) & (1 << nr);
  }
  
  static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
  				     int val)
  {
  	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
  	u32 pm;
  	u32 reg_val;
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
136
  	unsigned long flags;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
137

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

7cb6580c0   Axel Lin   gpio: gpio-pch: U...
161
  	spin_lock_irqsave(&chip->spinlock, flags);
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
162
  	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
163
164
  	pm &= ~(1 << nr);
  	iowrite32(pm, &chip->reg->pm);
7cb6580c0   Axel Lin   gpio: gpio-pch: U...
165
  	spin_unlock_irqrestore(&chip->spinlock, flags);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
166
167
168
169
170
171
172
173
174
  
  	return 0;
  }
  
  /*
   * Save register configuration and disable interrupts.
   */
  static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
  {
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
175
176
  	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...
177
178
  	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...
179
180
181
182
183
184
  	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...
185
186
187
188
189
190
191
  }
  
  /*
   * 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...
192
193
  	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...
194
195
196
197
  	/* 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...
198
199
200
201
202
203
  	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...
204
  }
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
205
206
207
208
209
  static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
  {
  	struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
  	return chip->irq_base + offset;
  }
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
210
211
212
213
214
  static void pch_gpio_setup(struct pch_gpio *chip)
  {
  	struct gpio_chip *gpio = &chip->gpio;
  
  	gpio->label = dev_name(chip->dev);
5c868fc62   Alexander Stein   gpio-pch: Set par...
215
  	gpio->dev = chip->dev;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
216
217
218
219
220
221
222
  	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 ...
223
  	gpio->ngpio = gpio_pins[chip->ioh];
9fb1f39eb   Linus Walleij   gpio/pinctrl: mak...
224
  	gpio->can_sleep = false;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
225
226
227
228
229
  	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...
230
231
  	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...
232
233
234
235
  	u32 im, im_pos, val;
  	u32 __iomem *im_reg;
  	unsigned long flags;
  	int ch, irq = d->irq;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
236
237
238
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
  
  	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...
267
  	default:
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
268
  		goto unlock;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
269
270
271
272
273
  	}
  
  	/* 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...
274
275
276
277
278
  	/* And the handler */
  	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
  		__irq_set_handler_locked(d->irq, handle_level_irq);
  	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
  		__irq_set_handler_locked(d->irq, handle_edge_irq);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
279

df9541a60   Thomas Gleixner   gpio: pch9: Use p...
280
  unlock:
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
281
  	spin_unlock_irqrestore(&chip->spinlock, flags);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
  	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...
300
301
302
303
304
305
306
  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...
307
308
309
310
  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...
311
  	int i, ret = IRQ_NONE;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
312
313
314
315
316
317
  
  	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...
318
319
320
321
322
323
  			generic_handle_irq(chip->irq_base + i);
  			ret = IRQ_HANDLED;
  		}
  	}
  	return ret;
  }
3836309d9   Bill Pemberton   gpio: remove use ...
324
  static void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
325
326
327
328
329
330
331
332
333
  				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...
334
  	ct->chip.irq_ack = pch_irq_ack;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
335
336
337
338
339
340
  	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...
341
  }
3836309d9   Bill Pemberton   gpio: remove use ...
342
  static int pch_gpio_probe(struct pci_dev *pdev,
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
343
344
345
346
  				    const struct pci_device_id *id)
  {
  	s32 ret;
  	struct pch_gpio *chip;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
347
  	int irq_base;
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
348
  	u32 msk;
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
  
  	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...
368
  	if (!chip->base) {
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
369
370
371
372
  		dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
  		ret = -ENOMEM;
  		goto err_iomap;
  	}
d4260e6dd   Tomoya MORINAGA   gpio-pch: modify ...
373
374
375
376
377
378
  	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...
379
380
  	chip->reg = chip->base;
  	pci_set_drvdata(pdev, chip);
d166370ad   Axel Lin   gpio: Add missing...
381
  	spin_lock_init(&chip->spinlock);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
382
383
384
385
386
387
388
  	pch_gpio_setup(chip);
  	ret = gpiochip_add(&chip->gpio);
  	if (ret) {
  		dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO
  ");
  		goto err_gpiochip_add;
  	}
2824bc9c3   Tomoya MORINAGA   gpio-pch: Use NUM...
389
  	irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
390
391
392
393
394
395
396
  	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...
397
398
399
400
  	/* 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...
401
  	ret = request_irq(pdev->irq, pch_gpio_handler,
df9541a60   Thomas Gleixner   gpio: pch9: Use p...
402
  			  IRQF_SHARED, KBUILD_MODNAME, chip);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
403
404
405
406
407
408
409
410
  	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...
411
  end:
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
412
  	return 0;
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
413
414
  err_request_irq:
  	irq_free_descs(irq_base, gpio_pins[chip->ioh]);
cfb10898e   Axel Lin   gpio: Don't overr...
415
  	if (gpiochip_remove(&chip->gpio))
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
416
417
  		dev_err(&pdev->dev, "%s gpiochip_remove failed
  ", __func__);
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
  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 ...
433
  static void pch_gpio_remove(struct pci_dev *pdev)
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
434
435
436
  {
  	int err;
  	struct pch_gpio *chip = pci_get_drvdata(pdev);
38eb18a6f   Tomoya MORINAGA   gpio-pch: Support...
437
438
439
440
441
  	if (chip->irq_base != -1) {
  		free_irq(pdev->irq, chip);
  
  		irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
  	}
04c17aa89   Tomoya MORINAGA   gpio: add Topclif...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  	err = gpiochip_remove(&chip->gpio);
  	if (err)
  		dev_err(&pdev->dev, "Failed gpiochip_remove
  ");
  
  	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");