[go: nahoru, domu]

149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA/*
249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA *
449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * This program is free software; you can redistribute it and/or modify
549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * it under the terms of the GNU General Public License as published by
649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * the Free Software Foundation; version 2 of the License.
749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA *
849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * This program is distributed in the hope that it will be useful,
949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * but WITHOUT ANY WARRANTY; without even the implied warranty of
1049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * GNU General Public License for more details.
1249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA *
1349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * You should have received a copy of the GNU General Public License
1449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * along with this program; if not, write to the Free Software
1549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
1649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA */
17bb207ef1e84ffc4afe89f3a5b84788bac0f968e7Paul Gortmaker#include <linux/module.h>
1849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA#include <linux/kernel.h>
19545554e7c5bb93bfbf134f9f12889701c0aadf97Andrew Morton#include <linux/slab.h>
2049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA#include <linux/pci.h>
2149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA#include <linux/gpio.h>
2254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA#include <linux/interrupt.h>
2354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA#include <linux/irq.h>
2454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
2554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA#define IOH_EDGE_FALLING	0
2654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA#define IOH_EDGE_RISING		BIT(0)
2754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA#define IOH_LEVEL_L		BIT(1)
2854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA#define IOH_LEVEL_H		(BIT(0) | BIT(1))
2954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA#define IOH_EDGE_BOTH		BIT(2)
3054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA#define IOH_IM_MASK		(BIT(0) | BIT(1) | BIT(2))
3154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
3254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA#define IOH_IRQ_BASE		0
3349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
3449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA#define PCI_VENDOR_ID_ROHM             0x10DB
3549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
3649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstruct ioh_reg_comn {
3749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	ien;
3849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	istatus;
3949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	idisp;
4049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	iclr;
4149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	imask;
4249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	imaskclr;
4349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	po;
4449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	pi;
4549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	pm;
4649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	im_0;
4749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	im_1;
4849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32	reserved;
4949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA};
5049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
5149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstruct ioh_regs {
5249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_reg_comn regs[8];
5349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 reserve1[16];
5449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 ioh_sel_reg[4];
5549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 reserve2[11];
5649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 srst;
5749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA};
5849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
5949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA/**
6049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * struct ioh_gpio_reg_data - The register store data.
6154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA * @ien_reg	To store contents of interrupt enable register.
6254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA * @imask_reg:	To store contents of interrupt mask regist
6349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * @po_reg:	To store contents of PO register.
6449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * @pm_reg:	To store contents of PM register.
6554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA * @im0_reg:	To store contents of interrupt mode regist0
6654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA * @im1_reg:	To store contents of interrupt mode regist1
67b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA * @use_sel_reg: To store contents of GPIO_USE_SEL0~3
6849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA */
6949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstruct ioh_gpio_reg_data {
7054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	u32 ien_reg;
7154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	u32 imask_reg;
7249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 po_reg;
7349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 pm_reg;
7454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	u32 im0_reg;
7554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	u32 im1_reg;
76b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	u32 use_sel_reg;
7749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA};
7849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
7949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA/**
8049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * struct ioh_gpio - GPIO private data structure.
8149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * @base:			PCI base address of Memory mapped I/O register.
8249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * @reg:			Memory mapped IOH GPIO register list.
8349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * @dev:			Pointer to device structure.
8449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * @gpio:			Data for GPIO infrastructure.
8549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * @ioh_gpio_reg:		Memory mapped Register data is saved here
8649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA *				when suspend.
87b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA * @gpio_use_sel:		Save GPIO_USE_SEL1~4 register for PM
8849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * @ch:				Indicate GPIO channel
8954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA * @irq_base:		Save base of IRQ number for interrupt
9002a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin * @spinlock:		Used for register access protection
9149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA */
9249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstruct ioh_gpio {
9349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	void __iomem *base;
9449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_regs __iomem *reg;
9549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct device *dev;
9649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct gpio_chip gpio;
9749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_gpio_reg_data ioh_gpio_reg;
98b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	u32 gpio_use_sel;
9949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	int ch;
10054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	int irq_base;
10154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	spinlock_t spinlock;
10249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA};
10349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
10449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
10549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
10649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
10749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
10849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 reg_val;
10949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
11002a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin	unsigned long flags;
11149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
11202a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin	spin_lock_irqsave(&chip->spinlock, flags);
11349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	reg_val = ioread32(&chip->reg->regs[chip->ch].po);
11449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	if (val)
11549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		reg_val |= (1 << nr);
11649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	else
11749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		reg_val &= ~(1 << nr);
11849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
11949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
12002a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin	spin_unlock_irqrestore(&chip->spinlock, flags);
12149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
12249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
12349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr)
12449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
12549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
12649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
12749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	return ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr);
12849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
12949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
13049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
13149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA				     int val)
13249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
13349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
13449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 pm;
13549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 reg_val;
13602a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin	unsigned long flags;
13749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
13802a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin	spin_lock_irqsave(&chip->spinlock, flags);
13949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
14049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA					((1 << num_ports[chip->ch]) - 1);
14149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pm |= (1 << nr);
14249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	iowrite32(pm, &chip->reg->regs[chip->ch].pm);
14349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
14449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	reg_val = ioread32(&chip->reg->regs[chip->ch].po);
14549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	if (val)
14649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		reg_val |= (1 << nr);
14749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	else
14849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		reg_val &= ~(1 << nr);
149ba43861277f1858472de4adfc0b28a047484da83Peter Tyser	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
15049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
15102a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin	spin_unlock_irqrestore(&chip->spinlock, flags);
15249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
15349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	return 0;
15449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
15549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
15649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
15749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
15849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
15949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	u32 pm;
16002a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin	unsigned long flags;
16149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
16202a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin	spin_lock_irqsave(&chip->spinlock, flags);
16349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
16449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA				((1 << num_ports[chip->ch]) - 1);
16549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pm &= ~(1 << nr);
16649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	iowrite32(pm, &chip->reg->regs[chip->ch].pm);
16702a6794d57ce54b96b13db80831f35d66e0caf31Axel Lin	spin_unlock_irqrestore(&chip->spinlock, flags);
16849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
16949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	return 0;
17049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
17149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
172545554e7c5bb93bfbf134f9f12889701c0aadf97Andrew Morton#ifdef CONFIG_PM
17349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA/*
17449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * Save register configuration and disable interrupts.
17549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA */
17649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
17749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
178b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	int i;
179b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA
180b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	for (i = 0; i < 8; i ++, chip++) {
181b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		chip->ioh_gpio_reg.po_reg =
182b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA					ioread32(&chip->reg->regs[chip->ch].po);
183b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		chip->ioh_gpio_reg.pm_reg =
184b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA					ioread32(&chip->reg->regs[chip->ch].pm);
185b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		chip->ioh_gpio_reg.ien_reg =
186b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA				       ioread32(&chip->reg->regs[chip->ch].ien);
187b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		chip->ioh_gpio_reg.imask_reg =
188b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA				     ioread32(&chip->reg->regs[chip->ch].imask);
189b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		chip->ioh_gpio_reg.im0_reg =
190b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA				      ioread32(&chip->reg->regs[chip->ch].im_0);
191b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		chip->ioh_gpio_reg.im1_reg =
192b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA				      ioread32(&chip->reg->regs[chip->ch].im_1);
193b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		if (i < 4)
194b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA			chip->ioh_gpio_reg.use_sel_reg =
195b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA					   ioread32(&chip->reg->ioh_sel_reg[i]);
196b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	}
19749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
19849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
19949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA/*
20049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA * This function restores the register configuration of the GPIO device.
20149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA */
20249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
20349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
204b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	int i;
205b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA
206b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	for (i = 0; i < 8; i ++, chip++) {
207b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		iowrite32(chip->ioh_gpio_reg.po_reg,
208b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA			  &chip->reg->regs[chip->ch].po);
209b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		iowrite32(chip->ioh_gpio_reg.pm_reg,
210b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA			  &chip->reg->regs[chip->ch].pm);
211b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		iowrite32(chip->ioh_gpio_reg.ien_reg,
212b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA			  &chip->reg->regs[chip->ch].ien);
213b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		iowrite32(chip->ioh_gpio_reg.imask_reg,
214b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA			  &chip->reg->regs[chip->ch].imask);
215b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		iowrite32(chip->ioh_gpio_reg.im0_reg,
216b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA			  &chip->reg->regs[chip->ch].im_0);
217b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		iowrite32(chip->ioh_gpio_reg.im1_reg,
218b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA			  &chip->reg->regs[chip->ch].im_1);
219b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA		if (i < 4)
220b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA			iowrite32(chip->ioh_gpio_reg.use_sel_reg,
221b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA				  &chip->reg->ioh_sel_reg[i]);
222b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	}
22349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
224545554e7c5bb93bfbf134f9f12889701c0aadf97Andrew Morton#endif
22549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
22654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGAstatic int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
22754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA{
22854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio);
22954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	return chip->irq_base + offset;
23054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA}
23154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
23249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
23349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
23449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct gpio_chip *gpio = &chip->gpio;
23549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
23649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	gpio->label = dev_name(chip->dev);
23749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	gpio->owner = THIS_MODULE;
23849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	gpio->direction_input = ioh_gpio_direction_input;
23949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	gpio->get = ioh_gpio_get;
24049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	gpio->direction_output = ioh_gpio_direction_output;
24149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	gpio->set = ioh_gpio_set;
24249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	gpio->dbg_show = NULL;
24349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	gpio->base = -1;
24449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	gpio->ngpio = num_port;
2459fb1f39eb2d6707d265087ee186376e24995f55aLinus Walleij	gpio->can_sleep = false;
24654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	gpio->to_irq = ioh_gpio_to_irq;
24754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA}
24854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
24954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGAstatic int ioh_irq_type(struct irq_data *d, unsigned int type)
25054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA{
25154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	u32 im;
252dd9328a6b026060699d4136d8f926e39281c8a18Márton Németh	void __iomem *im_reg;
25354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	u32 ien;
25454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	u32 im_pos;
25554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	int ch;
25654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	unsigned long flags;
25754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	u32 val;
25854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	int irq = d->irq;
25954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
26054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct ioh_gpio *chip = gc->private;
26154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
26254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	ch = irq - chip->irq_base;
26354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	if (irq <= chip->irq_base + 7) {
26454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		im_reg = &chip->reg->regs[chip->ch].im_0;
26554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		im_pos = ch;
26654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	} else {
26754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		im_reg = &chip->reg->regs[chip->ch].im_1;
26854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		im_pos = ch - 8;
26954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	}
27054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n",
27154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		__func__, irq, type, ch, im_pos, type);
27254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
27354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	spin_lock_irqsave(&chip->spinlock, flags);
27454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
27554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	switch (type) {
27654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	case IRQ_TYPE_EDGE_RISING:
27754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		val = IOH_EDGE_RISING;
27854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		break;
27954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	case IRQ_TYPE_EDGE_FALLING:
28054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		val = IOH_EDGE_FALLING;
28154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		break;
28254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	case IRQ_TYPE_EDGE_BOTH:
28354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		val = IOH_EDGE_BOTH;
28454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		break;
28554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	case IRQ_TYPE_LEVEL_HIGH:
28654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		val = IOH_LEVEL_H;
28754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		break;
28854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	case IRQ_TYPE_LEVEL_LOW:
28954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		val = IOH_LEVEL_L;
29054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		break;
29154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	case IRQ_TYPE_PROBE:
29254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		goto end;
29354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	default:
29454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		dev_warn(chip->dev, "%s: unknown type(%dd)",
29554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA			__func__, type);
29654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		goto end;
29754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	}
29854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
29954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	/* Set interrupt mode */
30054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4));
30154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	iowrite32(im | (val << (im_pos * 4)), im_reg);
30254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
30354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	/* iclr */
30454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr);
30554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
30654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	/* IMASKCLR */
30754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr);
30854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
30954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	/* Enable interrupt */
31054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	ien = ioread32(&chip->reg->regs[chip->ch].ien);
31154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien);
31254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGAend:
31354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	spin_unlock_irqrestore(&chip->spinlock, flags);
31454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
31554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	return 0;
31654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA}
31754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
31854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGAstatic void ioh_irq_unmask(struct irq_data *d)
31954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA{
32054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
32154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct ioh_gpio *chip = gc->private;
32254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
32354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	iowrite32(1 << (d->irq - chip->irq_base),
32454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		  &chip->reg->regs[chip->ch].imaskclr);
32554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA}
32654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
32754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGAstatic void ioh_irq_mask(struct irq_data *d)
32854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA{
32954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
33054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct ioh_gpio *chip = gc->private;
33154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
33254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	iowrite32(1 << (d->irq - chip->irq_base),
33354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		  &chip->reg->regs[chip->ch].imask);
33454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA}
33554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
3364d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tangstatic void ioh_irq_disable(struct irq_data *d)
3374d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang{
3384d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
3394d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	struct ioh_gpio *chip = gc->private;
3404d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	unsigned long flags;
3414d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	u32 ien;
3424d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang
3434d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	spin_lock_irqsave(&chip->spinlock, flags);
3444d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	ien = ioread32(&chip->reg->regs[chip->ch].ien);
3454d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	ien &= ~(1 << (d->irq - chip->irq_base));
3464d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	iowrite32(ien, &chip->reg->regs[chip->ch].ien);
3474d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	spin_unlock_irqrestore(&chip->spinlock, flags);
3484d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang}
3494d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang
3504d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tangstatic void ioh_irq_enable(struct irq_data *d)
3514d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang{
3524d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
3534d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	struct ioh_gpio *chip = gc->private;
3544d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	unsigned long flags;
3554d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	u32 ien;
3564d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang
3574d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	spin_lock_irqsave(&chip->spinlock, flags);
3584d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	ien = ioread32(&chip->reg->regs[chip->ch].ien);
3594d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	ien |= 1 << (d->irq - chip->irq_base);
3604d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	iowrite32(ien, &chip->reg->regs[chip->ch].ien);
3614d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	spin_unlock_irqrestore(&chip->spinlock, flags);
3624d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang}
3634d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang
36454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGAstatic irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
36554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA{
36654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct ioh_gpio *chip = dev_id;
36754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	u32 reg_val;
36854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	int i, j;
36954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	int ret = IRQ_NONE;
37054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
371f9ea14efa5277c47efec341dee2c408b6b80f854Feng Tang	for (i = 0; i < 8; i++, chip++) {
37254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		reg_val = ioread32(&chip->reg->regs[i].istatus);
37354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		for (j = 0; j < num_ports[i]; j++) {
37454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA			if (reg_val & BIT(j)) {
37554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA				dev_dbg(chip->dev,
37654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA					"%s:[%d]:irq=%d status=0x%x\n",
37754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA					__func__, j, irq, reg_val);
37854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA				iowrite32(BIT(j),
37954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA					  &chip->reg->regs[chip->ch].iclr);
38054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA				generic_handle_irq(chip->irq_base + j);
38154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA				ret = IRQ_HANDLED;
38254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA			}
38354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		}
38454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	}
38554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	return ret;
38654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA}
38754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
3883836309d93462bbf34851c078be6e5e77d888e3dBill Pembertonstatic void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
38954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA				unsigned int irq_start, unsigned int num)
39054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA{
39154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct irq_chip_generic *gc;
39254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	struct irq_chip_type *ct;
39354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
39454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base,
39554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA				    handle_simple_irq);
39654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	gc->private = chip;
39754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	ct = gc->chip_types;
39854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
39954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	ct->chip.irq_mask = ioh_irq_mask;
40054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	ct->chip.irq_unmask = ioh_irq_unmask;
40154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	ct->chip.irq_set_type = ioh_irq_type;
4024d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	ct->chip.irq_disable = ioh_irq_disable;
4034d052213ff8f71a4a70fc4eed71b773cfde51fcfFeng Tang	ct->chip.irq_enable = ioh_irq_enable;
40454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
40554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
40654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
40749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
40849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
4093836309d93462bbf34851c078be6e5e77d888e3dBill Pembertonstatic int ioh_gpio_probe(struct pci_dev *pdev,
41049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA				    const struct pci_device_id *id)
41149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
41249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	int ret;
41354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	int i, j;
41449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_gpio *chip;
41549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	void __iomem *base;
416dd9328a6b026060699d4136d8f926e39281c8a18Márton Németh	void *chip_save;
41754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	int irq_base;
41849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
41949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	ret = pci_enable_device(pdev);
42049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	if (ret) {
42149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__);
42249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		goto err_pci_enable;
42349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	}
42449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
42549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	ret = pci_request_regions(pdev, KBUILD_MODNAME);
42649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	if (ret) {
42749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		dev_err(&pdev->dev, "pci_request_regions failed-%d", ret);
42849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		goto err_request_regions;
42949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	}
43049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
43149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	base = pci_iomap(pdev, 1, 0);
4322bd1c85e855c94da564e151cb54553e6cfc2f04bMárton Németh	if (!base) {
43349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		dev_err(&pdev->dev, "%s : pci_iomap failed", __func__);
43449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		ret = -ENOMEM;
43549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		goto err_iomap;
43649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	}
43749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
43849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL);
43949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	if (chip_save == NULL) {
44049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		dev_err(&pdev->dev, "%s : kzalloc failed", __func__);
44149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		ret = -ENOMEM;
44249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		goto err_kzalloc;
44349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	}
44449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
44549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	chip = chip_save;
44649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	for (i = 0; i < 8; i++, chip++) {
44749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		chip->dev = &pdev->dev;
44849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		chip->base = base;
44949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		chip->reg = chip->base;
45049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		chip->ch = i;
4517e3a70fb7bccada029c188c89bfbf3c0a63c1500Axel Lin		spin_lock_init(&chip->spinlock);
45249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		ioh_gpio_setup(chip, num_ports[i]);
45349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		ret = gpiochip_add(&chip->gpio);
45449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		if (ret) {
45549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA			dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n");
45649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA			goto err_gpiochip_add;
45749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		}
45849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	}
45949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
46049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	chip = chip_save;
46154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	for (j = 0; j < 8; j++, chip++) {
46254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j],
463a7aaa4f888968b1261c2701cc66f18a3d4b9777bTomoya MORINAGA					   NUMA_NO_NODE);
46454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		if (irq_base < 0) {
46554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA			dev_warn(&pdev->dev,
46654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA				"ml_ioh_gpio: Failed to get IRQ base num\n");
46754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA			chip->irq_base = -1;
468df46dce09113ea0a52ce7403d35087e167f3a460Wei Yongjun			ret = irq_base;
46954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA			goto err_irq_alloc_descs;
47054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		}
47154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		chip->irq_base = irq_base;
47254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
47354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	}
47454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
47554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	chip = chip_save;
47654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	ret = request_irq(pdev->irq, ioh_gpio_handler,
47754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA			     IRQF_SHARED, KBUILD_MODNAME, chip);
47854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	if (ret != 0) {
47954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		dev_err(&pdev->dev,
48054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA			"%s request_irq failed\n", __func__);
48154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		goto err_request_irq;
48254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	}
48354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
48449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_set_drvdata(pdev, chip);
48549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
48649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	return 0;
48749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
48854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGAerr_request_irq:
48954be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	chip = chip_save;
49054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGAerr_irq_alloc_descs:
49154be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	while (--j >= 0) {
49254be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		chip--;
49354be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		irq_free_descs(chip->irq_base, num_ports[j]);
49454be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	}
49554be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
49654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	chip = chip_save;
49749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAerr_gpiochip_add:
49833300571b1111264fd0c5701733f7576323f3e35Axel Lin	while (--i >= 0) {
49949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		chip--;
5009f5132ae82fdbb047cc187bf689a81c8cc0de7faabdoulaye berthe		gpiochip_remove(&chip->gpio);
50149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	}
50249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	kfree(chip_save);
50349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
50449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAerr_kzalloc:
50549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_iounmap(pdev, base);
50649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
50749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAerr_iomap:
50849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_release_regions(pdev);
50949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
51049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAerr_request_regions:
51149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_disable_device(pdev);
51249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
51349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAerr_pci_enable:
51449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
51549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
51649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	return ret;
51749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
51849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
519206210ce68c1feb1d9d05839ceacc97ad1b0b324Bill Pembertonstatic void ioh_gpio_remove(struct pci_dev *pdev)
52049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
52149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	int i;
52249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_gpio *chip = pci_get_drvdata(pdev);
523dd9328a6b026060699d4136d8f926e39281c8a18Márton Németh	void *chip_save;
52449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
52549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	chip_save = chip;
52654be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
52754be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA	free_irq(pdev->irq, chip);
52854be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA
52949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	for (i = 0; i < 8; i++, chip++) {
53054be566317b6aece2389a95bb19ea209af9359beTomoya MORINAGA		irq_free_descs(chip->irq_base, num_ports[i]);
5319f5132ae82fdbb047cc187bf689a81c8cc0de7faabdoulaye berthe		gpiochip_remove(&chip->gpio);
53249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	}
53349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
53449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	chip = chip_save;
53549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_iounmap(pdev, chip->base);
53649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_release_regions(pdev);
53749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_disable_device(pdev);
53849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	kfree(chip);
53949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
54049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
54149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA#ifdef CONFIG_PM
54249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
54349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
54449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	s32 ret;
54549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_gpio *chip = pci_get_drvdata(pdev);
546b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	unsigned long flags;
54749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
548b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	spin_lock_irqsave(&chip->spinlock, flags);
54949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	ioh_gpio_save_reg_conf(chip);
550b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	spin_unlock_irqrestore(&chip->spinlock, flags);
55149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
55249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	ret = pci_save_state(pdev);
55349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	if (ret) {
55449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
55549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		return ret;
55649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	}
55749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_disable_device(pdev);
55849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_set_power_state(pdev, PCI_D0);
55949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	ret = pci_enable_wake(pdev, PCI_D0, 1);
56049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	if (ret)
56149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
56249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
56349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	return 0;
56449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
56549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
56649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic int ioh_gpio_resume(struct pci_dev *pdev)
56749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA{
56849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	s32 ret;
56949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	struct ioh_gpio *chip = pci_get_drvdata(pdev);
570b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	unsigned long flags;
57149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
57249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	ret = pci_enable_wake(pdev, PCI_D0, 0);
57349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
57449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_set_power_state(pdev, PCI_D0);
57549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	ret = pci_enable_device(pdev);
57649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	if (ret) {
57749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
57849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA		return ret;
57949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	}
58049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	pci_restore_state(pdev);
58149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
582b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	spin_lock_irqsave(&chip->spinlock, flags);
58349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	iowrite32(0x01, &chip->reg->srst);
58449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	iowrite32(0x00, &chip->reg->srst);
58549a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	ioh_gpio_restore_reg_conf(chip);
586b490fa0bf86edbc06562024cbace5e84f0e2cf0eTomoya MORINAGA	spin_unlock_irqrestore(&chip->spinlock, flags);
58749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
58849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	return 0;
58949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA}
59049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA#else
59149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA#define ioh_gpio_suspend NULL
59249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA#define ioh_gpio_resume NULL
59349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA#endif
59449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
59514f4a8838acac0fe6bf710ec08fc4cce57c0011bJingoo Hanstatic const struct pci_device_id ioh_gpio_pcidev_id[] = {
59649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },
59749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	{ 0, }
59849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA};
59919234cdda517396e5e0b10e77493afa9e30095c3Axel LinMODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id);
60049a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
60149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAstatic struct pci_driver ioh_gpio_driver = {
60249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	.name = "ml_ioh_gpio",
60349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	.id_table = ioh_gpio_pcidev_id,
60449a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	.probe = ioh_gpio_probe,
6058283c4ff57bdf3c1d8985c86e4ef44e1bb70f1f6Bill Pemberton	.remove = ioh_gpio_remove,
60649a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	.suspend = ioh_gpio_suspend,
60749a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA	.resume = ioh_gpio_resume
60849a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA};
60949a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
61093baa65fe50a83056c97973de2300337b000472eAxel Linmodule_pci_driver(ioh_gpio_driver);
61149a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGA
61249a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAMODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver");
61349a367937fe4250144e24440e5a11ae4344202b1Tomoya MORINAGAMODULE_LICENSE("GPL");
614