1c103de24SGrant Likely /* 2c103de24SGrant Likely * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. 3c103de24SGrant Likely * 4c103de24SGrant Likely * This program is free software; you can redistribute it and/or modify 5c103de24SGrant Likely * it under the terms of the GNU General Public License as published by 6c103de24SGrant Likely * the Free Software Foundation; version 2 of the License. 7c103de24SGrant Likely * 8c103de24SGrant Likely * This program is distributed in the hope that it will be useful, 9c103de24SGrant Likely * but WITHOUT ANY WARRANTY; without even the implied warranty of 10c103de24SGrant Likely * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11c103de24SGrant Likely * GNU General Public License for more details. 12c103de24SGrant Likely * 13c103de24SGrant Likely * You should have received a copy of the GNU General Public License 14c103de24SGrant Likely * along with this program; if not, write to the Free Software 15c103de24SGrant Likely * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 16c103de24SGrant Likely */ 17bb207ef1SPaul Gortmaker #include <linux/module.h> 18c103de24SGrant Likely #include <linux/kernel.h> 19c103de24SGrant Likely #include <linux/slab.h> 20c103de24SGrant Likely #include <linux/pci.h> 21c103de24SGrant Likely #include <linux/gpio.h> 2254be5663STomoya MORINAGA #include <linux/interrupt.h> 2354be5663STomoya MORINAGA #include <linux/irq.h> 2454be5663STomoya MORINAGA 2554be5663STomoya MORINAGA #define IOH_EDGE_FALLING 0 2654be5663STomoya MORINAGA #define IOH_EDGE_RISING BIT(0) 2754be5663STomoya MORINAGA #define IOH_LEVEL_L BIT(1) 2854be5663STomoya MORINAGA #define IOH_LEVEL_H (BIT(0) | BIT(1)) 2954be5663STomoya MORINAGA #define IOH_EDGE_BOTH BIT(2) 3054be5663STomoya MORINAGA #define IOH_IM_MASK (BIT(0) | BIT(1) | BIT(2)) 3154be5663STomoya MORINAGA 3254be5663STomoya MORINAGA #define IOH_IRQ_BASE 0 33c103de24SGrant Likely 34c103de24SGrant Likely #define PCI_VENDOR_ID_ROHM 0x10DB 35c103de24SGrant Likely 36c103de24SGrant Likely struct ioh_reg_comn { 37c103de24SGrant Likely u32 ien; 38c103de24SGrant Likely u32 istatus; 39c103de24SGrant Likely u32 idisp; 40c103de24SGrant Likely u32 iclr; 41c103de24SGrant Likely u32 imask; 42c103de24SGrant Likely u32 imaskclr; 43c103de24SGrant Likely u32 po; 44c103de24SGrant Likely u32 pi; 45c103de24SGrant Likely u32 pm; 46c103de24SGrant Likely u32 im_0; 47c103de24SGrant Likely u32 im_1; 48c103de24SGrant Likely u32 reserved; 49c103de24SGrant Likely }; 50c103de24SGrant Likely 51c103de24SGrant Likely struct ioh_regs { 52c103de24SGrant Likely struct ioh_reg_comn regs[8]; 53c103de24SGrant Likely u32 reserve1[16]; 54c103de24SGrant Likely u32 ioh_sel_reg[4]; 55c103de24SGrant Likely u32 reserve2[11]; 56c103de24SGrant Likely u32 srst; 57c103de24SGrant Likely }; 58c103de24SGrant Likely 59c103de24SGrant Likely /** 60c103de24SGrant Likely * struct ioh_gpio_reg_data - The register store data. 6154be5663STomoya MORINAGA * @ien_reg To store contents of interrupt enable register. 6254be5663STomoya MORINAGA * @imask_reg: To store contents of interrupt mask regist 63c103de24SGrant Likely * @po_reg: To store contents of PO register. 64c103de24SGrant Likely * @pm_reg: To store contents of PM register. 6554be5663STomoya MORINAGA * @im0_reg: To store contents of interrupt mode regist0 6654be5663STomoya MORINAGA * @im1_reg: To store contents of interrupt mode regist1 67b490fa0bSTomoya MORINAGA * @use_sel_reg: To store contents of GPIO_USE_SEL0~3 68c103de24SGrant Likely */ 69c103de24SGrant Likely struct ioh_gpio_reg_data { 7054be5663STomoya MORINAGA u32 ien_reg; 7154be5663STomoya MORINAGA u32 imask_reg; 72c103de24SGrant Likely u32 po_reg; 73c103de24SGrant Likely u32 pm_reg; 7454be5663STomoya MORINAGA u32 im0_reg; 7554be5663STomoya MORINAGA u32 im1_reg; 76b490fa0bSTomoya MORINAGA u32 use_sel_reg; 77c103de24SGrant Likely }; 78c103de24SGrant Likely 79c103de24SGrant Likely /** 80c103de24SGrant Likely * struct ioh_gpio - GPIO private data structure. 81c103de24SGrant Likely * @base: PCI base address of Memory mapped I/O register. 82c103de24SGrant Likely * @reg: Memory mapped IOH GPIO register list. 83c103de24SGrant Likely * @dev: Pointer to device structure. 84c103de24SGrant Likely * @gpio: Data for GPIO infrastructure. 85c103de24SGrant Likely * @ioh_gpio_reg: Memory mapped Register data is saved here 86c103de24SGrant Likely * when suspend. 87b490fa0bSTomoya MORINAGA * @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM 88c103de24SGrant Likely * @ch: Indicate GPIO channel 8954be5663STomoya MORINAGA * @irq_base: Save base of IRQ number for interrupt 90*02a6794dSAxel Lin * @spinlock: Used for register access protection 91c103de24SGrant Likely */ 92c103de24SGrant Likely struct ioh_gpio { 93c103de24SGrant Likely void __iomem *base; 94c103de24SGrant Likely struct ioh_regs __iomem *reg; 95c103de24SGrant Likely struct device *dev; 96c103de24SGrant Likely struct gpio_chip gpio; 97c103de24SGrant Likely struct ioh_gpio_reg_data ioh_gpio_reg; 98b490fa0bSTomoya MORINAGA u32 gpio_use_sel; 99c103de24SGrant Likely int ch; 10054be5663STomoya MORINAGA int irq_base; 10154be5663STomoya MORINAGA spinlock_t spinlock; 102c103de24SGrant Likely }; 103c103de24SGrant Likely 104c103de24SGrant Likely static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12}; 105c103de24SGrant Likely 106c103de24SGrant Likely static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) 107c103de24SGrant Likely { 108c103de24SGrant Likely u32 reg_val; 109c103de24SGrant Likely struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); 110*02a6794dSAxel Lin unsigned long flags; 111c103de24SGrant Likely 112*02a6794dSAxel Lin spin_lock_irqsave(&chip->spinlock, flags); 113c103de24SGrant Likely reg_val = ioread32(&chip->reg->regs[chip->ch].po); 114c103de24SGrant Likely if (val) 115c103de24SGrant Likely reg_val |= (1 << nr); 116c103de24SGrant Likely else 117c103de24SGrant Likely reg_val &= ~(1 << nr); 118c103de24SGrant Likely 119c103de24SGrant Likely iowrite32(reg_val, &chip->reg->regs[chip->ch].po); 120*02a6794dSAxel Lin spin_unlock_irqrestore(&chip->spinlock, flags); 121c103de24SGrant Likely } 122c103de24SGrant Likely 123c103de24SGrant Likely static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr) 124c103de24SGrant Likely { 125c103de24SGrant Likely struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); 126c103de24SGrant Likely 127c103de24SGrant Likely return ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr); 128c103de24SGrant Likely } 129c103de24SGrant Likely 130c103de24SGrant Likely static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, 131c103de24SGrant Likely int val) 132c103de24SGrant Likely { 133c103de24SGrant Likely struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); 134c103de24SGrant Likely u32 pm; 135c103de24SGrant Likely u32 reg_val; 136*02a6794dSAxel Lin unsigned long flags; 137c103de24SGrant Likely 138*02a6794dSAxel Lin spin_lock_irqsave(&chip->spinlock, flags); 139c103de24SGrant Likely pm = ioread32(&chip->reg->regs[chip->ch].pm) & 140c103de24SGrant Likely ((1 << num_ports[chip->ch]) - 1); 141c103de24SGrant Likely pm |= (1 << nr); 142c103de24SGrant Likely iowrite32(pm, &chip->reg->regs[chip->ch].pm); 143c103de24SGrant Likely 144c103de24SGrant Likely reg_val = ioread32(&chip->reg->regs[chip->ch].po); 145c103de24SGrant Likely if (val) 146c103de24SGrant Likely reg_val |= (1 << nr); 147c103de24SGrant Likely else 148c103de24SGrant Likely reg_val &= ~(1 << nr); 149c103de24SGrant Likely iowrite32(reg_val, &chip->reg->regs[chip->ch].po); 150c103de24SGrant Likely 151*02a6794dSAxel Lin spin_unlock_irqrestore(&chip->spinlock, flags); 152c103de24SGrant Likely 153c103de24SGrant Likely return 0; 154c103de24SGrant Likely } 155c103de24SGrant Likely 156c103de24SGrant Likely static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) 157c103de24SGrant Likely { 158c103de24SGrant Likely struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); 159c103de24SGrant Likely u32 pm; 160*02a6794dSAxel Lin unsigned long flags; 161c103de24SGrant Likely 162*02a6794dSAxel Lin spin_lock_irqsave(&chip->spinlock, flags); 163c103de24SGrant Likely pm = ioread32(&chip->reg->regs[chip->ch].pm) & 164c103de24SGrant Likely ((1 << num_ports[chip->ch]) - 1); 165c103de24SGrant Likely pm &= ~(1 << nr); 166c103de24SGrant Likely iowrite32(pm, &chip->reg->regs[chip->ch].pm); 167*02a6794dSAxel Lin spin_unlock_irqrestore(&chip->spinlock, flags); 168c103de24SGrant Likely 169c103de24SGrant Likely return 0; 170c103de24SGrant Likely } 171c103de24SGrant Likely 172c103de24SGrant Likely #ifdef CONFIG_PM 173c103de24SGrant Likely /* 174c103de24SGrant Likely * Save register configuration and disable interrupts. 175c103de24SGrant Likely */ 176c103de24SGrant Likely static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip) 177c103de24SGrant Likely { 178b490fa0bSTomoya MORINAGA int i; 179b490fa0bSTomoya MORINAGA 180b490fa0bSTomoya MORINAGA for (i = 0; i < 8; i ++, chip++) { 181b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.po_reg = 182b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].po); 183b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.pm_reg = 184b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].pm); 185b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.ien_reg = 186b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].ien); 187b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.imask_reg = 188b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].imask); 189b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.im0_reg = 190b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].im_0); 191b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.im1_reg = 192b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].im_1); 193b490fa0bSTomoya MORINAGA if (i < 4) 194b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.use_sel_reg = 195b490fa0bSTomoya MORINAGA ioread32(&chip->reg->ioh_sel_reg[i]); 196b490fa0bSTomoya MORINAGA } 197c103de24SGrant Likely } 198c103de24SGrant Likely 199c103de24SGrant Likely /* 200c103de24SGrant Likely * This function restores the register configuration of the GPIO device. 201c103de24SGrant Likely */ 202c103de24SGrant Likely static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) 203c103de24SGrant Likely { 204b490fa0bSTomoya MORINAGA int i; 205b490fa0bSTomoya MORINAGA 206b490fa0bSTomoya MORINAGA for (i = 0; i < 8; i ++, chip++) { 207b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.po_reg, 208b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].po); 209b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.pm_reg, 210b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].pm); 211b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.ien_reg, 212b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].ien); 213b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.imask_reg, 214b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].imask); 215b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.im0_reg, 216b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].im_0); 217b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.im1_reg, 218b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].im_1); 219b490fa0bSTomoya MORINAGA if (i < 4) 220b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.use_sel_reg, 221b490fa0bSTomoya MORINAGA &chip->reg->ioh_sel_reg[i]); 222b490fa0bSTomoya MORINAGA } 223c103de24SGrant Likely } 224c103de24SGrant Likely #endif 225c103de24SGrant Likely 22654be5663STomoya MORINAGA static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) 22754be5663STomoya MORINAGA { 22854be5663STomoya MORINAGA struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); 22954be5663STomoya MORINAGA return chip->irq_base + offset; 23054be5663STomoya MORINAGA } 23154be5663STomoya MORINAGA 232c103de24SGrant Likely static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) 233c103de24SGrant Likely { 234c103de24SGrant Likely struct gpio_chip *gpio = &chip->gpio; 235c103de24SGrant Likely 236c103de24SGrant Likely gpio->label = dev_name(chip->dev); 237c103de24SGrant Likely gpio->owner = THIS_MODULE; 238c103de24SGrant Likely gpio->direction_input = ioh_gpio_direction_input; 239c103de24SGrant Likely gpio->get = ioh_gpio_get; 240c103de24SGrant Likely gpio->direction_output = ioh_gpio_direction_output; 241c103de24SGrant Likely gpio->set = ioh_gpio_set; 242c103de24SGrant Likely gpio->dbg_show = NULL; 243c103de24SGrant Likely gpio->base = -1; 244c103de24SGrant Likely gpio->ngpio = num_port; 245c103de24SGrant Likely gpio->can_sleep = 0; 24654be5663STomoya MORINAGA gpio->to_irq = ioh_gpio_to_irq; 24754be5663STomoya MORINAGA } 24854be5663STomoya MORINAGA 24954be5663STomoya MORINAGA static int ioh_irq_type(struct irq_data *d, unsigned int type) 25054be5663STomoya MORINAGA { 25154be5663STomoya MORINAGA u32 im; 252dd9328a6SMárton Németh void __iomem *im_reg; 25354be5663STomoya MORINAGA u32 ien; 25454be5663STomoya MORINAGA u32 im_pos; 25554be5663STomoya MORINAGA int ch; 25654be5663STomoya MORINAGA unsigned long flags; 25754be5663STomoya MORINAGA u32 val; 25854be5663STomoya MORINAGA int irq = d->irq; 25954be5663STomoya MORINAGA struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 26054be5663STomoya MORINAGA struct ioh_gpio *chip = gc->private; 26154be5663STomoya MORINAGA 26254be5663STomoya MORINAGA ch = irq - chip->irq_base; 26354be5663STomoya MORINAGA if (irq <= chip->irq_base + 7) { 26454be5663STomoya MORINAGA im_reg = &chip->reg->regs[chip->ch].im_0; 26554be5663STomoya MORINAGA im_pos = ch; 26654be5663STomoya MORINAGA } else { 26754be5663STomoya MORINAGA im_reg = &chip->reg->regs[chip->ch].im_1; 26854be5663STomoya MORINAGA im_pos = ch - 8; 26954be5663STomoya MORINAGA } 27054be5663STomoya MORINAGA dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n", 27154be5663STomoya MORINAGA __func__, irq, type, ch, im_pos, type); 27254be5663STomoya MORINAGA 27354be5663STomoya MORINAGA spin_lock_irqsave(&chip->spinlock, flags); 27454be5663STomoya MORINAGA 27554be5663STomoya MORINAGA switch (type) { 27654be5663STomoya MORINAGA case IRQ_TYPE_EDGE_RISING: 27754be5663STomoya MORINAGA val = IOH_EDGE_RISING; 27854be5663STomoya MORINAGA break; 27954be5663STomoya MORINAGA case IRQ_TYPE_EDGE_FALLING: 28054be5663STomoya MORINAGA val = IOH_EDGE_FALLING; 28154be5663STomoya MORINAGA break; 28254be5663STomoya MORINAGA case IRQ_TYPE_EDGE_BOTH: 28354be5663STomoya MORINAGA val = IOH_EDGE_BOTH; 28454be5663STomoya MORINAGA break; 28554be5663STomoya MORINAGA case IRQ_TYPE_LEVEL_HIGH: 28654be5663STomoya MORINAGA val = IOH_LEVEL_H; 28754be5663STomoya MORINAGA break; 28854be5663STomoya MORINAGA case IRQ_TYPE_LEVEL_LOW: 28954be5663STomoya MORINAGA val = IOH_LEVEL_L; 29054be5663STomoya MORINAGA break; 29154be5663STomoya MORINAGA case IRQ_TYPE_PROBE: 29254be5663STomoya MORINAGA goto end; 29354be5663STomoya MORINAGA default: 29454be5663STomoya MORINAGA dev_warn(chip->dev, "%s: unknown type(%dd)", 29554be5663STomoya MORINAGA __func__, type); 29654be5663STomoya MORINAGA goto end; 29754be5663STomoya MORINAGA } 29854be5663STomoya MORINAGA 29954be5663STomoya MORINAGA /* Set interrupt mode */ 30054be5663STomoya MORINAGA im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4)); 30154be5663STomoya MORINAGA iowrite32(im | (val << (im_pos * 4)), im_reg); 30254be5663STomoya MORINAGA 30354be5663STomoya MORINAGA /* iclr */ 30454be5663STomoya MORINAGA iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr); 30554be5663STomoya MORINAGA 30654be5663STomoya MORINAGA /* IMASKCLR */ 30754be5663STomoya MORINAGA iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr); 30854be5663STomoya MORINAGA 30954be5663STomoya MORINAGA /* Enable interrupt */ 31054be5663STomoya MORINAGA ien = ioread32(&chip->reg->regs[chip->ch].ien); 31154be5663STomoya MORINAGA iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien); 31254be5663STomoya MORINAGA end: 31354be5663STomoya MORINAGA spin_unlock_irqrestore(&chip->spinlock, flags); 31454be5663STomoya MORINAGA 31554be5663STomoya MORINAGA return 0; 31654be5663STomoya MORINAGA } 31754be5663STomoya MORINAGA 31854be5663STomoya MORINAGA static void ioh_irq_unmask(struct irq_data *d) 31954be5663STomoya MORINAGA { 32054be5663STomoya MORINAGA struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 32154be5663STomoya MORINAGA struct ioh_gpio *chip = gc->private; 32254be5663STomoya MORINAGA 32354be5663STomoya MORINAGA iowrite32(1 << (d->irq - chip->irq_base), 32454be5663STomoya MORINAGA &chip->reg->regs[chip->ch].imaskclr); 32554be5663STomoya MORINAGA } 32654be5663STomoya MORINAGA 32754be5663STomoya MORINAGA static void ioh_irq_mask(struct irq_data *d) 32854be5663STomoya MORINAGA { 32954be5663STomoya MORINAGA struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 33054be5663STomoya MORINAGA struct ioh_gpio *chip = gc->private; 33154be5663STomoya MORINAGA 33254be5663STomoya MORINAGA iowrite32(1 << (d->irq - chip->irq_base), 33354be5663STomoya MORINAGA &chip->reg->regs[chip->ch].imask); 33454be5663STomoya MORINAGA } 33554be5663STomoya MORINAGA 3364d052213SFeng Tang static void ioh_irq_disable(struct irq_data *d) 3374d052213SFeng Tang { 3384d052213SFeng Tang struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 3394d052213SFeng Tang struct ioh_gpio *chip = gc->private; 3404d052213SFeng Tang unsigned long flags; 3414d052213SFeng Tang u32 ien; 3424d052213SFeng Tang 3434d052213SFeng Tang spin_lock_irqsave(&chip->spinlock, flags); 3444d052213SFeng Tang ien = ioread32(&chip->reg->regs[chip->ch].ien); 3454d052213SFeng Tang ien &= ~(1 << (d->irq - chip->irq_base)); 3464d052213SFeng Tang iowrite32(ien, &chip->reg->regs[chip->ch].ien); 3474d052213SFeng Tang spin_unlock_irqrestore(&chip->spinlock, flags); 3484d052213SFeng Tang } 3494d052213SFeng Tang 3504d052213SFeng Tang static void ioh_irq_enable(struct irq_data *d) 3514d052213SFeng Tang { 3524d052213SFeng Tang struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 3534d052213SFeng Tang struct ioh_gpio *chip = gc->private; 3544d052213SFeng Tang unsigned long flags; 3554d052213SFeng Tang u32 ien; 3564d052213SFeng Tang 3574d052213SFeng Tang spin_lock_irqsave(&chip->spinlock, flags); 3584d052213SFeng Tang ien = ioread32(&chip->reg->regs[chip->ch].ien); 3594d052213SFeng Tang ien |= 1 << (d->irq - chip->irq_base); 3604d052213SFeng Tang iowrite32(ien, &chip->reg->regs[chip->ch].ien); 3614d052213SFeng Tang spin_unlock_irqrestore(&chip->spinlock, flags); 3624d052213SFeng Tang } 3634d052213SFeng Tang 36454be5663STomoya MORINAGA static irqreturn_t ioh_gpio_handler(int irq, void *dev_id) 36554be5663STomoya MORINAGA { 36654be5663STomoya MORINAGA struct ioh_gpio *chip = dev_id; 36754be5663STomoya MORINAGA u32 reg_val; 36854be5663STomoya MORINAGA int i, j; 36954be5663STomoya MORINAGA int ret = IRQ_NONE; 37054be5663STomoya MORINAGA 371f9ea14efSFeng Tang for (i = 0; i < 8; i++, chip++) { 37254be5663STomoya MORINAGA reg_val = ioread32(&chip->reg->regs[i].istatus); 37354be5663STomoya MORINAGA for (j = 0; j < num_ports[i]; j++) { 37454be5663STomoya MORINAGA if (reg_val & BIT(j)) { 37554be5663STomoya MORINAGA dev_dbg(chip->dev, 37654be5663STomoya MORINAGA "%s:[%d]:irq=%d status=0x%x\n", 37754be5663STomoya MORINAGA __func__, j, irq, reg_val); 37854be5663STomoya MORINAGA iowrite32(BIT(j), 37954be5663STomoya MORINAGA &chip->reg->regs[chip->ch].iclr); 38054be5663STomoya MORINAGA generic_handle_irq(chip->irq_base + j); 38154be5663STomoya MORINAGA ret = IRQ_HANDLED; 38254be5663STomoya MORINAGA } 38354be5663STomoya MORINAGA } 38454be5663STomoya MORINAGA } 38554be5663STomoya MORINAGA return ret; 38654be5663STomoya MORINAGA } 38754be5663STomoya MORINAGA 38854be5663STomoya MORINAGA static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip, 38954be5663STomoya MORINAGA unsigned int irq_start, unsigned int num) 39054be5663STomoya MORINAGA { 39154be5663STomoya MORINAGA struct irq_chip_generic *gc; 39254be5663STomoya MORINAGA struct irq_chip_type *ct; 39354be5663STomoya MORINAGA 39454be5663STomoya MORINAGA gc = irq_alloc_generic_chip("ioh_gpio", 1, irq_start, chip->base, 39554be5663STomoya MORINAGA handle_simple_irq); 39654be5663STomoya MORINAGA gc->private = chip; 39754be5663STomoya MORINAGA ct = gc->chip_types; 39854be5663STomoya MORINAGA 39954be5663STomoya MORINAGA ct->chip.irq_mask = ioh_irq_mask; 40054be5663STomoya MORINAGA ct->chip.irq_unmask = ioh_irq_unmask; 40154be5663STomoya MORINAGA ct->chip.irq_set_type = ioh_irq_type; 4024d052213SFeng Tang ct->chip.irq_disable = ioh_irq_disable; 4034d052213SFeng Tang ct->chip.irq_enable = ioh_irq_enable; 40454be5663STomoya MORINAGA 40554be5663STomoya MORINAGA irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, 40654be5663STomoya MORINAGA IRQ_NOREQUEST | IRQ_NOPROBE, 0); 407c103de24SGrant Likely } 408c103de24SGrant Likely 409c103de24SGrant Likely static int __devinit ioh_gpio_probe(struct pci_dev *pdev, 410c103de24SGrant Likely const struct pci_device_id *id) 411c103de24SGrant Likely { 412c103de24SGrant Likely int ret; 41354be5663STomoya MORINAGA int i, j; 414c103de24SGrant Likely struct ioh_gpio *chip; 415c103de24SGrant Likely void __iomem *base; 416dd9328a6SMárton Németh void *chip_save; 41754be5663STomoya MORINAGA int irq_base; 418c103de24SGrant Likely 419c103de24SGrant Likely ret = pci_enable_device(pdev); 420c103de24SGrant Likely if (ret) { 421c103de24SGrant Likely dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__); 422c103de24SGrant Likely goto err_pci_enable; 423c103de24SGrant Likely } 424c103de24SGrant Likely 425c103de24SGrant Likely ret = pci_request_regions(pdev, KBUILD_MODNAME); 426c103de24SGrant Likely if (ret) { 427c103de24SGrant Likely dev_err(&pdev->dev, "pci_request_regions failed-%d", ret); 428c103de24SGrant Likely goto err_request_regions; 429c103de24SGrant Likely } 430c103de24SGrant Likely 431c103de24SGrant Likely base = pci_iomap(pdev, 1, 0); 4322bd1c85eSMárton Németh if (!base) { 433c103de24SGrant Likely dev_err(&pdev->dev, "%s : pci_iomap failed", __func__); 434c103de24SGrant Likely ret = -ENOMEM; 435c103de24SGrant Likely goto err_iomap; 436c103de24SGrant Likely } 437c103de24SGrant Likely 438c103de24SGrant Likely chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL); 439c103de24SGrant Likely if (chip_save == NULL) { 440c103de24SGrant Likely dev_err(&pdev->dev, "%s : kzalloc failed", __func__); 441c103de24SGrant Likely ret = -ENOMEM; 442c103de24SGrant Likely goto err_kzalloc; 443c103de24SGrant Likely } 444c103de24SGrant Likely 445c103de24SGrant Likely chip = chip_save; 446c103de24SGrant Likely for (i = 0; i < 8; i++, chip++) { 447c103de24SGrant Likely chip->dev = &pdev->dev; 448c103de24SGrant Likely chip->base = base; 449c103de24SGrant Likely chip->reg = chip->base; 450c103de24SGrant Likely chip->ch = i; 4517e3a70fbSAxel Lin spin_lock_init(&chip->spinlock); 452c103de24SGrant Likely ioh_gpio_setup(chip, num_ports[i]); 453c103de24SGrant Likely ret = gpiochip_add(&chip->gpio); 454c103de24SGrant Likely if (ret) { 455c103de24SGrant Likely dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n"); 456c103de24SGrant Likely goto err_gpiochip_add; 457c103de24SGrant Likely } 458c103de24SGrant Likely } 459c103de24SGrant Likely 460c103de24SGrant Likely chip = chip_save; 46154be5663STomoya MORINAGA for (j = 0; j < 8; j++, chip++) { 46254be5663STomoya MORINAGA irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j], 463a7aaa4f8STomoya MORINAGA NUMA_NO_NODE); 46454be5663STomoya MORINAGA if (irq_base < 0) { 46554be5663STomoya MORINAGA dev_warn(&pdev->dev, 46654be5663STomoya MORINAGA "ml_ioh_gpio: Failed to get IRQ base num\n"); 46754be5663STomoya MORINAGA chip->irq_base = -1; 46854be5663STomoya MORINAGA goto err_irq_alloc_descs; 46954be5663STomoya MORINAGA } 47054be5663STomoya MORINAGA chip->irq_base = irq_base; 47154be5663STomoya MORINAGA ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]); 47254be5663STomoya MORINAGA } 47354be5663STomoya MORINAGA 47454be5663STomoya MORINAGA chip = chip_save; 47554be5663STomoya MORINAGA ret = request_irq(pdev->irq, ioh_gpio_handler, 47654be5663STomoya MORINAGA IRQF_SHARED, KBUILD_MODNAME, chip); 47754be5663STomoya MORINAGA if (ret != 0) { 47854be5663STomoya MORINAGA dev_err(&pdev->dev, 47954be5663STomoya MORINAGA "%s request_irq failed\n", __func__); 48054be5663STomoya MORINAGA goto err_request_irq; 48154be5663STomoya MORINAGA } 48254be5663STomoya MORINAGA 483c103de24SGrant Likely pci_set_drvdata(pdev, chip); 484c103de24SGrant Likely 485c103de24SGrant Likely return 0; 486c103de24SGrant Likely 48754be5663STomoya MORINAGA err_request_irq: 48854be5663STomoya MORINAGA chip = chip_save; 48954be5663STomoya MORINAGA err_irq_alloc_descs: 49054be5663STomoya MORINAGA while (--j >= 0) { 49154be5663STomoya MORINAGA chip--; 49254be5663STomoya MORINAGA irq_free_descs(chip->irq_base, num_ports[j]); 49354be5663STomoya MORINAGA } 49454be5663STomoya MORINAGA 49554be5663STomoya MORINAGA chip = chip_save; 496c103de24SGrant Likely err_gpiochip_add: 49733300571SAxel Lin while (--i >= 0) { 498c103de24SGrant Likely chip--; 499c103de24SGrant Likely ret = gpiochip_remove(&chip->gpio); 500c103de24SGrant Likely if (ret) 501c103de24SGrant Likely dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i); 502c103de24SGrant Likely } 503c103de24SGrant Likely kfree(chip_save); 504c103de24SGrant Likely 505c103de24SGrant Likely err_kzalloc: 506c103de24SGrant Likely pci_iounmap(pdev, base); 507c103de24SGrant Likely 508c103de24SGrant Likely err_iomap: 509c103de24SGrant Likely pci_release_regions(pdev); 510c103de24SGrant Likely 511c103de24SGrant Likely err_request_regions: 512c103de24SGrant Likely pci_disable_device(pdev); 513c103de24SGrant Likely 514c103de24SGrant Likely err_pci_enable: 515c103de24SGrant Likely 516c103de24SGrant Likely dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret); 517c103de24SGrant Likely return ret; 518c103de24SGrant Likely } 519c103de24SGrant Likely 520c103de24SGrant Likely static void __devexit ioh_gpio_remove(struct pci_dev *pdev) 521c103de24SGrant Likely { 522c103de24SGrant Likely int err; 523c103de24SGrant Likely int i; 524c103de24SGrant Likely struct ioh_gpio *chip = pci_get_drvdata(pdev); 525dd9328a6SMárton Németh void *chip_save; 526c103de24SGrant Likely 527c103de24SGrant Likely chip_save = chip; 52854be5663STomoya MORINAGA 52954be5663STomoya MORINAGA free_irq(pdev->irq, chip); 53054be5663STomoya MORINAGA 531c103de24SGrant Likely for (i = 0; i < 8; i++, chip++) { 53254be5663STomoya MORINAGA irq_free_descs(chip->irq_base, num_ports[i]); 533c103de24SGrant Likely err = gpiochip_remove(&chip->gpio); 534c103de24SGrant Likely if (err) 535c103de24SGrant Likely dev_err(&pdev->dev, "Failed gpiochip_remove\n"); 536c103de24SGrant Likely } 537c103de24SGrant Likely 538c103de24SGrant Likely chip = chip_save; 539c103de24SGrant Likely pci_iounmap(pdev, chip->base); 540c103de24SGrant Likely pci_release_regions(pdev); 541c103de24SGrant Likely pci_disable_device(pdev); 542c103de24SGrant Likely kfree(chip); 543c103de24SGrant Likely } 544c103de24SGrant Likely 545c103de24SGrant Likely #ifdef CONFIG_PM 546c103de24SGrant Likely static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state) 547c103de24SGrant Likely { 548c103de24SGrant Likely s32 ret; 549c103de24SGrant Likely struct ioh_gpio *chip = pci_get_drvdata(pdev); 550b490fa0bSTomoya MORINAGA unsigned long flags; 551c103de24SGrant Likely 552b490fa0bSTomoya MORINAGA spin_lock_irqsave(&chip->spinlock, flags); 553c103de24SGrant Likely ioh_gpio_save_reg_conf(chip); 554b490fa0bSTomoya MORINAGA spin_unlock_irqrestore(&chip->spinlock, flags); 555c103de24SGrant Likely 556c103de24SGrant Likely ret = pci_save_state(pdev); 557c103de24SGrant Likely if (ret) { 558c103de24SGrant Likely dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret); 559c103de24SGrant Likely return ret; 560c103de24SGrant Likely } 561c103de24SGrant Likely pci_disable_device(pdev); 562c103de24SGrant Likely pci_set_power_state(pdev, PCI_D0); 563c103de24SGrant Likely ret = pci_enable_wake(pdev, PCI_D0, 1); 564c103de24SGrant Likely if (ret) 565c103de24SGrant Likely dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret); 566c103de24SGrant Likely 567c103de24SGrant Likely return 0; 568c103de24SGrant Likely } 569c103de24SGrant Likely 570c103de24SGrant Likely static int ioh_gpio_resume(struct pci_dev *pdev) 571c103de24SGrant Likely { 572c103de24SGrant Likely s32 ret; 573c103de24SGrant Likely struct ioh_gpio *chip = pci_get_drvdata(pdev); 574b490fa0bSTomoya MORINAGA unsigned long flags; 575c103de24SGrant Likely 576c103de24SGrant Likely ret = pci_enable_wake(pdev, PCI_D0, 0); 577c103de24SGrant Likely 578c103de24SGrant Likely pci_set_power_state(pdev, PCI_D0); 579c103de24SGrant Likely ret = pci_enable_device(pdev); 580c103de24SGrant Likely if (ret) { 581c103de24SGrant Likely dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret); 582c103de24SGrant Likely return ret; 583c103de24SGrant Likely } 584c103de24SGrant Likely pci_restore_state(pdev); 585c103de24SGrant Likely 586b490fa0bSTomoya MORINAGA spin_lock_irqsave(&chip->spinlock, flags); 587c103de24SGrant Likely iowrite32(0x01, &chip->reg->srst); 588c103de24SGrant Likely iowrite32(0x00, &chip->reg->srst); 589c103de24SGrant Likely ioh_gpio_restore_reg_conf(chip); 590b490fa0bSTomoya MORINAGA spin_unlock_irqrestore(&chip->spinlock, flags); 591c103de24SGrant Likely 592c103de24SGrant Likely return 0; 593c103de24SGrant Likely } 594c103de24SGrant Likely #else 595c103de24SGrant Likely #define ioh_gpio_suspend NULL 596c103de24SGrant Likely #define ioh_gpio_resume NULL 597c103de24SGrant Likely #endif 598c103de24SGrant Likely 599c103de24SGrant Likely static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = { 600c103de24SGrant Likely { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, 601c103de24SGrant Likely { 0, } 602c103de24SGrant Likely }; 603c103de24SGrant Likely MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id); 604c103de24SGrant Likely 605c103de24SGrant Likely static struct pci_driver ioh_gpio_driver = { 606c103de24SGrant Likely .name = "ml_ioh_gpio", 607c103de24SGrant Likely .id_table = ioh_gpio_pcidev_id, 608c103de24SGrant Likely .probe = ioh_gpio_probe, 609c103de24SGrant Likely .remove = __devexit_p(ioh_gpio_remove), 610c103de24SGrant Likely .suspend = ioh_gpio_suspend, 611c103de24SGrant Likely .resume = ioh_gpio_resume 612c103de24SGrant Likely }; 613c103de24SGrant Likely 61493baa65fSAxel Lin module_pci_driver(ioh_gpio_driver); 615c103de24SGrant Likely 616c103de24SGrant Likely MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver"); 617c103de24SGrant Likely MODULE_LICENSE("GPL"); 618