1873e65bcSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2c103de24SGrant Likely /* 3c103de24SGrant Likely * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. 4c103de24SGrant Likely */ 5bb207ef1SPaul Gortmaker #include <linux/module.h> 6c103de24SGrant Likely #include <linux/kernel.h> 7c103de24SGrant Likely #include <linux/slab.h> 8c103de24SGrant Likely #include <linux/pci.h> 985320ab6SLinus Walleij #include <linux/gpio/driver.h> 1054be5663STomoya MORINAGA #include <linux/interrupt.h> 1154be5663STomoya MORINAGA #include <linux/irq.h> 1254be5663STomoya MORINAGA 1354be5663STomoya MORINAGA #define IOH_EDGE_FALLING 0 1454be5663STomoya MORINAGA #define IOH_EDGE_RISING BIT(0) 1554be5663STomoya MORINAGA #define IOH_LEVEL_L BIT(1) 1654be5663STomoya MORINAGA #define IOH_LEVEL_H (BIT(0) | BIT(1)) 1754be5663STomoya MORINAGA #define IOH_EDGE_BOTH BIT(2) 1854be5663STomoya MORINAGA #define IOH_IM_MASK (BIT(0) | BIT(1) | BIT(2)) 1954be5663STomoya MORINAGA 2054be5663STomoya MORINAGA #define IOH_IRQ_BASE 0 21c103de24SGrant Likely 22c103de24SGrant Likely struct ioh_reg_comn { 23c103de24SGrant Likely u32 ien; 24c103de24SGrant Likely u32 istatus; 25c103de24SGrant Likely u32 idisp; 26c103de24SGrant Likely u32 iclr; 27c103de24SGrant Likely u32 imask; 28c103de24SGrant Likely u32 imaskclr; 29c103de24SGrant Likely u32 po; 30c103de24SGrant Likely u32 pi; 31c103de24SGrant Likely u32 pm; 32c103de24SGrant Likely u32 im_0; 33c103de24SGrant Likely u32 im_1; 34c103de24SGrant Likely u32 reserved; 35c103de24SGrant Likely }; 36c103de24SGrant Likely 37c103de24SGrant Likely struct ioh_regs { 38c103de24SGrant Likely struct ioh_reg_comn regs[8]; 39c103de24SGrant Likely u32 reserve1[16]; 40c103de24SGrant Likely u32 ioh_sel_reg[4]; 41c103de24SGrant Likely u32 reserve2[11]; 42c103de24SGrant Likely u32 srst; 43c103de24SGrant Likely }; 44c103de24SGrant Likely 45c103de24SGrant Likely /** 46c103de24SGrant Likely * struct ioh_gpio_reg_data - The register store data. 47*85b565c9SLee Jones * @ien_reg: To store contents of interrupt enable register. 4854be5663STomoya MORINAGA * @imask_reg: To store contents of interrupt mask regist 49c103de24SGrant Likely * @po_reg: To store contents of PO register. 50c103de24SGrant Likely * @pm_reg: To store contents of PM register. 5154be5663STomoya MORINAGA * @im0_reg: To store contents of interrupt mode regist0 5254be5663STomoya MORINAGA * @im1_reg: To store contents of interrupt mode regist1 53b490fa0bSTomoya MORINAGA * @use_sel_reg: To store contents of GPIO_USE_SEL0~3 54c103de24SGrant Likely */ 55c103de24SGrant Likely struct ioh_gpio_reg_data { 5654be5663STomoya MORINAGA u32 ien_reg; 5754be5663STomoya MORINAGA u32 imask_reg; 58c103de24SGrant Likely u32 po_reg; 59c103de24SGrant Likely u32 pm_reg; 6054be5663STomoya MORINAGA u32 im0_reg; 6154be5663STomoya MORINAGA u32 im1_reg; 62b490fa0bSTomoya MORINAGA u32 use_sel_reg; 63c103de24SGrant Likely }; 64c103de24SGrant Likely 65c103de24SGrant Likely /** 66c103de24SGrant Likely * struct ioh_gpio - GPIO private data structure. 67c103de24SGrant Likely * @base: PCI base address of Memory mapped I/O register. 68c103de24SGrant Likely * @reg: Memory mapped IOH GPIO register list. 69c103de24SGrant Likely * @dev: Pointer to device structure. 70c103de24SGrant Likely * @gpio: Data for GPIO infrastructure. 71c103de24SGrant Likely * @ioh_gpio_reg: Memory mapped Register data is saved here 72c103de24SGrant Likely * when suspend. 73b490fa0bSTomoya MORINAGA * @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM 74c103de24SGrant Likely * @ch: Indicate GPIO channel 7554be5663STomoya MORINAGA * @irq_base: Save base of IRQ number for interrupt 7602a6794dSAxel Lin * @spinlock: Used for register access protection 77c103de24SGrant Likely */ 78c103de24SGrant Likely struct ioh_gpio { 79c103de24SGrant Likely void __iomem *base; 80c103de24SGrant Likely struct ioh_regs __iomem *reg; 81c103de24SGrant Likely struct device *dev; 82c103de24SGrant Likely struct gpio_chip gpio; 83c103de24SGrant Likely struct ioh_gpio_reg_data ioh_gpio_reg; 84b490fa0bSTomoya MORINAGA u32 gpio_use_sel; 85c103de24SGrant Likely int ch; 8654be5663STomoya MORINAGA int irq_base; 8754be5663STomoya MORINAGA spinlock_t spinlock; 88c103de24SGrant Likely }; 89c103de24SGrant Likely 90c103de24SGrant Likely static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12}; 91c103de24SGrant Likely 92c103de24SGrant Likely static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) 93c103de24SGrant Likely { 94c103de24SGrant Likely u32 reg_val; 9547315578SLinus Walleij struct ioh_gpio *chip = gpiochip_get_data(gpio); 9602a6794dSAxel Lin unsigned long flags; 97c103de24SGrant Likely 9802a6794dSAxel Lin spin_lock_irqsave(&chip->spinlock, flags); 99c103de24SGrant Likely reg_val = ioread32(&chip->reg->regs[chip->ch].po); 100c103de24SGrant Likely if (val) 101c103de24SGrant Likely reg_val |= (1 << nr); 102c103de24SGrant Likely else 103c103de24SGrant Likely reg_val &= ~(1 << nr); 104c103de24SGrant Likely 105c103de24SGrant Likely iowrite32(reg_val, &chip->reg->regs[chip->ch].po); 10602a6794dSAxel Lin spin_unlock_irqrestore(&chip->spinlock, flags); 107c103de24SGrant Likely } 108c103de24SGrant Likely 109c103de24SGrant Likely static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr) 110c103de24SGrant Likely { 11147315578SLinus Walleij struct ioh_gpio *chip = gpiochip_get_data(gpio); 112c103de24SGrant Likely 1136f14dd69SLinus Walleij return !!(ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr)); 114c103de24SGrant Likely } 115c103de24SGrant Likely 116c103de24SGrant Likely static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, 117c103de24SGrant Likely int val) 118c103de24SGrant Likely { 11947315578SLinus Walleij struct ioh_gpio *chip = gpiochip_get_data(gpio); 120c103de24SGrant Likely u32 pm; 121c103de24SGrant Likely u32 reg_val; 12202a6794dSAxel Lin unsigned long flags; 123c103de24SGrant Likely 12402a6794dSAxel Lin spin_lock_irqsave(&chip->spinlock, flags); 125c103de24SGrant Likely pm = ioread32(&chip->reg->regs[chip->ch].pm) & 126c103de24SGrant Likely ((1 << num_ports[chip->ch]) - 1); 127c103de24SGrant Likely pm |= (1 << nr); 128c103de24SGrant Likely iowrite32(pm, &chip->reg->regs[chip->ch].pm); 129c103de24SGrant Likely 130c103de24SGrant Likely reg_val = ioread32(&chip->reg->regs[chip->ch].po); 131c103de24SGrant Likely if (val) 132c103de24SGrant Likely reg_val |= (1 << nr); 133c103de24SGrant Likely else 134c103de24SGrant Likely reg_val &= ~(1 << nr); 135c103de24SGrant Likely iowrite32(reg_val, &chip->reg->regs[chip->ch].po); 136c103de24SGrant Likely 13702a6794dSAxel Lin spin_unlock_irqrestore(&chip->spinlock, flags); 138c103de24SGrant Likely 139c103de24SGrant Likely return 0; 140c103de24SGrant Likely } 141c103de24SGrant Likely 142c103de24SGrant Likely static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) 143c103de24SGrant Likely { 14447315578SLinus Walleij struct ioh_gpio *chip = gpiochip_get_data(gpio); 145c103de24SGrant Likely u32 pm; 14602a6794dSAxel Lin unsigned long flags; 147c103de24SGrant Likely 14802a6794dSAxel Lin spin_lock_irqsave(&chip->spinlock, flags); 149c103de24SGrant Likely pm = ioread32(&chip->reg->regs[chip->ch].pm) & 150c103de24SGrant Likely ((1 << num_ports[chip->ch]) - 1); 151c103de24SGrant Likely pm &= ~(1 << nr); 152c103de24SGrant Likely iowrite32(pm, &chip->reg->regs[chip->ch].pm); 15302a6794dSAxel Lin spin_unlock_irqrestore(&chip->spinlock, flags); 154c103de24SGrant Likely 155c103de24SGrant Likely return 0; 156c103de24SGrant Likely } 157c103de24SGrant Likely 158c103de24SGrant Likely #ifdef CONFIG_PM 159c103de24SGrant Likely /* 160c103de24SGrant Likely * Save register configuration and disable interrupts. 161c103de24SGrant Likely */ 162c103de24SGrant Likely static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip) 163c103de24SGrant Likely { 164b490fa0bSTomoya MORINAGA int i; 165b490fa0bSTomoya MORINAGA 166b490fa0bSTomoya MORINAGA for (i = 0; i < 8; i ++, chip++) { 167b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.po_reg = 168b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].po); 169b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.pm_reg = 170b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].pm); 171b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.ien_reg = 172b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].ien); 173b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.imask_reg = 174b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].imask); 175b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.im0_reg = 176b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].im_0); 177b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.im1_reg = 178b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].im_1); 179b490fa0bSTomoya MORINAGA if (i < 4) 180b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.use_sel_reg = 181b490fa0bSTomoya MORINAGA ioread32(&chip->reg->ioh_sel_reg[i]); 182b490fa0bSTomoya MORINAGA } 183c103de24SGrant Likely } 184c103de24SGrant Likely 185c103de24SGrant Likely /* 186c103de24SGrant Likely * This function restores the register configuration of the GPIO device. 187c103de24SGrant Likely */ 188c103de24SGrant Likely static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) 189c103de24SGrant Likely { 190b490fa0bSTomoya MORINAGA int i; 191b490fa0bSTomoya MORINAGA 192b490fa0bSTomoya MORINAGA for (i = 0; i < 8; i ++, chip++) { 193b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.po_reg, 194b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].po); 195b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.pm_reg, 196b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].pm); 197b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.ien_reg, 198b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].ien); 199b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.imask_reg, 200b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].imask); 201b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.im0_reg, 202b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].im_0); 203b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.im1_reg, 204b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].im_1); 205b490fa0bSTomoya MORINAGA if (i < 4) 206b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.use_sel_reg, 207b490fa0bSTomoya MORINAGA &chip->reg->ioh_sel_reg[i]); 208b490fa0bSTomoya MORINAGA } 209c103de24SGrant Likely } 210c103de24SGrant Likely #endif 211c103de24SGrant Likely 21254be5663STomoya MORINAGA static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) 21354be5663STomoya MORINAGA { 21447315578SLinus Walleij struct ioh_gpio *chip = gpiochip_get_data(gpio); 21554be5663STomoya MORINAGA return chip->irq_base + offset; 21654be5663STomoya MORINAGA } 21754be5663STomoya MORINAGA 218c103de24SGrant Likely static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) 219c103de24SGrant Likely { 220c103de24SGrant Likely struct gpio_chip *gpio = &chip->gpio; 221c103de24SGrant Likely 222c103de24SGrant Likely gpio->label = dev_name(chip->dev); 223c103de24SGrant Likely gpio->owner = THIS_MODULE; 224c103de24SGrant Likely gpio->direction_input = ioh_gpio_direction_input; 225c103de24SGrant Likely gpio->get = ioh_gpio_get; 226c103de24SGrant Likely gpio->direction_output = ioh_gpio_direction_output; 227c103de24SGrant Likely gpio->set = ioh_gpio_set; 228c103de24SGrant Likely gpio->dbg_show = NULL; 229c103de24SGrant Likely gpio->base = -1; 230c103de24SGrant Likely gpio->ngpio = num_port; 2319fb1f39eSLinus Walleij gpio->can_sleep = false; 23254be5663STomoya MORINAGA gpio->to_irq = ioh_gpio_to_irq; 23354be5663STomoya MORINAGA } 23454be5663STomoya MORINAGA 23554be5663STomoya MORINAGA static int ioh_irq_type(struct irq_data *d, unsigned int type) 23654be5663STomoya MORINAGA { 23754be5663STomoya MORINAGA u32 im; 238dd9328a6SMárton Németh void __iomem *im_reg; 23954be5663STomoya MORINAGA u32 ien; 24054be5663STomoya MORINAGA u32 im_pos; 24154be5663STomoya MORINAGA int ch; 24254be5663STomoya MORINAGA unsigned long flags; 24354be5663STomoya MORINAGA u32 val; 24454be5663STomoya MORINAGA int irq = d->irq; 24554be5663STomoya MORINAGA struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 24654be5663STomoya MORINAGA struct ioh_gpio *chip = gc->private; 24754be5663STomoya MORINAGA 24854be5663STomoya MORINAGA ch = irq - chip->irq_base; 24954be5663STomoya MORINAGA if (irq <= chip->irq_base + 7) { 25054be5663STomoya MORINAGA im_reg = &chip->reg->regs[chip->ch].im_0; 25154be5663STomoya MORINAGA im_pos = ch; 25254be5663STomoya MORINAGA } else { 25354be5663STomoya MORINAGA im_reg = &chip->reg->regs[chip->ch].im_1; 25454be5663STomoya MORINAGA im_pos = ch - 8; 25554be5663STomoya MORINAGA } 25654be5663STomoya MORINAGA dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n", 25754be5663STomoya MORINAGA __func__, irq, type, ch, im_pos, type); 25854be5663STomoya MORINAGA 25954be5663STomoya MORINAGA spin_lock_irqsave(&chip->spinlock, flags); 26054be5663STomoya MORINAGA 26154be5663STomoya MORINAGA switch (type) { 26254be5663STomoya MORINAGA case IRQ_TYPE_EDGE_RISING: 26354be5663STomoya MORINAGA val = IOH_EDGE_RISING; 26454be5663STomoya MORINAGA break; 26554be5663STomoya MORINAGA case IRQ_TYPE_EDGE_FALLING: 26654be5663STomoya MORINAGA val = IOH_EDGE_FALLING; 26754be5663STomoya MORINAGA break; 26854be5663STomoya MORINAGA case IRQ_TYPE_EDGE_BOTH: 26954be5663STomoya MORINAGA val = IOH_EDGE_BOTH; 27054be5663STomoya MORINAGA break; 27154be5663STomoya MORINAGA case IRQ_TYPE_LEVEL_HIGH: 27254be5663STomoya MORINAGA val = IOH_LEVEL_H; 27354be5663STomoya MORINAGA break; 27454be5663STomoya MORINAGA case IRQ_TYPE_LEVEL_LOW: 27554be5663STomoya MORINAGA val = IOH_LEVEL_L; 27654be5663STomoya MORINAGA break; 27754be5663STomoya MORINAGA case IRQ_TYPE_PROBE: 27854be5663STomoya MORINAGA goto end; 27954be5663STomoya MORINAGA default: 28054be5663STomoya MORINAGA dev_warn(chip->dev, "%s: unknown type(%dd)", 28154be5663STomoya MORINAGA __func__, type); 28254be5663STomoya MORINAGA goto end; 28354be5663STomoya MORINAGA } 28454be5663STomoya MORINAGA 28554be5663STomoya MORINAGA /* Set interrupt mode */ 28654be5663STomoya MORINAGA im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4)); 28754be5663STomoya MORINAGA iowrite32(im | (val << (im_pos * 4)), im_reg); 28854be5663STomoya MORINAGA 28954be5663STomoya MORINAGA /* iclr */ 29054be5663STomoya MORINAGA iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr); 29154be5663STomoya MORINAGA 29254be5663STomoya MORINAGA /* IMASKCLR */ 29354be5663STomoya MORINAGA iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr); 29454be5663STomoya MORINAGA 29554be5663STomoya MORINAGA /* Enable interrupt */ 29654be5663STomoya MORINAGA ien = ioread32(&chip->reg->regs[chip->ch].ien); 29754be5663STomoya MORINAGA iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien); 29854be5663STomoya MORINAGA end: 29954be5663STomoya MORINAGA spin_unlock_irqrestore(&chip->spinlock, flags); 30054be5663STomoya MORINAGA 30154be5663STomoya MORINAGA return 0; 30254be5663STomoya MORINAGA } 30354be5663STomoya MORINAGA 30454be5663STomoya MORINAGA static void ioh_irq_unmask(struct irq_data *d) 30554be5663STomoya MORINAGA { 30654be5663STomoya MORINAGA struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 30754be5663STomoya MORINAGA struct ioh_gpio *chip = gc->private; 30854be5663STomoya MORINAGA 30954be5663STomoya MORINAGA iowrite32(1 << (d->irq - chip->irq_base), 31054be5663STomoya MORINAGA &chip->reg->regs[chip->ch].imaskclr); 31154be5663STomoya MORINAGA } 31254be5663STomoya MORINAGA 31354be5663STomoya MORINAGA static void ioh_irq_mask(struct irq_data *d) 31454be5663STomoya MORINAGA { 31554be5663STomoya MORINAGA struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 31654be5663STomoya MORINAGA struct ioh_gpio *chip = gc->private; 31754be5663STomoya MORINAGA 31854be5663STomoya MORINAGA iowrite32(1 << (d->irq - chip->irq_base), 31954be5663STomoya MORINAGA &chip->reg->regs[chip->ch].imask); 32054be5663STomoya MORINAGA } 32154be5663STomoya MORINAGA 3224d052213SFeng Tang static void ioh_irq_disable(struct irq_data *d) 3234d052213SFeng Tang { 3244d052213SFeng Tang struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 3254d052213SFeng Tang struct ioh_gpio *chip = gc->private; 3264d052213SFeng Tang unsigned long flags; 3274d052213SFeng Tang u32 ien; 3284d052213SFeng Tang 3294d052213SFeng Tang spin_lock_irqsave(&chip->spinlock, flags); 3304d052213SFeng Tang ien = ioread32(&chip->reg->regs[chip->ch].ien); 3314d052213SFeng Tang ien &= ~(1 << (d->irq - chip->irq_base)); 3324d052213SFeng Tang iowrite32(ien, &chip->reg->regs[chip->ch].ien); 3334d052213SFeng Tang spin_unlock_irqrestore(&chip->spinlock, flags); 3344d052213SFeng Tang } 3354d052213SFeng Tang 3364d052213SFeng Tang static void ioh_irq_enable(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 35054be5663STomoya MORINAGA static irqreturn_t ioh_gpio_handler(int irq, void *dev_id) 35154be5663STomoya MORINAGA { 35254be5663STomoya MORINAGA struct ioh_gpio *chip = dev_id; 35354be5663STomoya MORINAGA u32 reg_val; 35454be5663STomoya MORINAGA int i, j; 35554be5663STomoya MORINAGA int ret = IRQ_NONE; 35654be5663STomoya MORINAGA 357f9ea14efSFeng Tang for (i = 0; i < 8; i++, chip++) { 35854be5663STomoya MORINAGA reg_val = ioread32(&chip->reg->regs[i].istatus); 35954be5663STomoya MORINAGA for (j = 0; j < num_ports[i]; j++) { 36054be5663STomoya MORINAGA if (reg_val & BIT(j)) { 36154be5663STomoya MORINAGA dev_dbg(chip->dev, 36254be5663STomoya MORINAGA "%s:[%d]:irq=%d status=0x%x\n", 36354be5663STomoya MORINAGA __func__, j, irq, reg_val); 36454be5663STomoya MORINAGA iowrite32(BIT(j), 36554be5663STomoya MORINAGA &chip->reg->regs[chip->ch].iclr); 36654be5663STomoya MORINAGA generic_handle_irq(chip->irq_base + j); 36754be5663STomoya MORINAGA ret = IRQ_HANDLED; 36854be5663STomoya MORINAGA } 36954be5663STomoya MORINAGA } 37054be5663STomoya MORINAGA } 37154be5663STomoya MORINAGA return ret; 37254be5663STomoya MORINAGA } 37354be5663STomoya MORINAGA 374e3fe07e0SBartosz Golaszewski static int ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip, 375e3fe07e0SBartosz Golaszewski unsigned int irq_start, 376e3fe07e0SBartosz Golaszewski unsigned int num) 37754be5663STomoya MORINAGA { 37854be5663STomoya MORINAGA struct irq_chip_generic *gc; 37954be5663STomoya MORINAGA struct irq_chip_type *ct; 380469d5943SBartosz Golaszewski int rv; 38154be5663STomoya MORINAGA 382469d5943SBartosz Golaszewski gc = devm_irq_alloc_generic_chip(chip->dev, "ioh_gpio", 1, irq_start, 383469d5943SBartosz Golaszewski chip->base, handle_simple_irq); 384e3fe07e0SBartosz Golaszewski if (!gc) 385e3fe07e0SBartosz Golaszewski return -ENOMEM; 386e3fe07e0SBartosz Golaszewski 38754be5663STomoya MORINAGA gc->private = chip; 38854be5663STomoya MORINAGA ct = gc->chip_types; 38954be5663STomoya MORINAGA 39054be5663STomoya MORINAGA ct->chip.irq_mask = ioh_irq_mask; 39154be5663STomoya MORINAGA ct->chip.irq_unmask = ioh_irq_unmask; 39254be5663STomoya MORINAGA ct->chip.irq_set_type = ioh_irq_type; 3934d052213SFeng Tang ct->chip.irq_disable = ioh_irq_disable; 3944d052213SFeng Tang ct->chip.irq_enable = ioh_irq_enable; 39554be5663STomoya MORINAGA 396469d5943SBartosz Golaszewski rv = devm_irq_setup_generic_chip(chip->dev, gc, IRQ_MSK(num), 397469d5943SBartosz Golaszewski IRQ_GC_INIT_MASK_CACHE, 39854be5663STomoya MORINAGA IRQ_NOREQUEST | IRQ_NOPROBE, 0); 399e3fe07e0SBartosz Golaszewski 400469d5943SBartosz Golaszewski return rv; 401c103de24SGrant Likely } 402c103de24SGrant Likely 4033836309dSBill Pemberton static int ioh_gpio_probe(struct pci_dev *pdev, 404c103de24SGrant Likely const struct pci_device_id *id) 405c103de24SGrant Likely { 406c103de24SGrant Likely int ret; 40754be5663STomoya MORINAGA int i, j; 408c103de24SGrant Likely struct ioh_gpio *chip; 409c103de24SGrant Likely void __iomem *base; 410dd9328a6SMárton Németh void *chip_save; 41154be5663STomoya MORINAGA int irq_base; 412c103de24SGrant Likely 413c103de24SGrant Likely ret = pci_enable_device(pdev); 414c103de24SGrant Likely if (ret) { 415c103de24SGrant Likely dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__); 416c103de24SGrant Likely goto err_pci_enable; 417c103de24SGrant Likely } 418c103de24SGrant Likely 419c103de24SGrant Likely ret = pci_request_regions(pdev, KBUILD_MODNAME); 420c103de24SGrant Likely if (ret) { 421c103de24SGrant Likely dev_err(&pdev->dev, "pci_request_regions failed-%d", ret); 422c103de24SGrant Likely goto err_request_regions; 423c103de24SGrant Likely } 424c103de24SGrant Likely 425c103de24SGrant Likely base = pci_iomap(pdev, 1, 0); 4262bd1c85eSMárton Németh if (!base) { 427c103de24SGrant Likely dev_err(&pdev->dev, "%s : pci_iomap failed", __func__); 428c103de24SGrant Likely ret = -ENOMEM; 429c103de24SGrant Likely goto err_iomap; 430c103de24SGrant Likely } 431c103de24SGrant Likely 4326396bb22SKees Cook chip_save = kcalloc(8, sizeof(*chip), GFP_KERNEL); 433c103de24SGrant Likely if (chip_save == NULL) { 434c103de24SGrant Likely ret = -ENOMEM; 435c103de24SGrant Likely goto err_kzalloc; 436c103de24SGrant Likely } 437c103de24SGrant Likely 438c103de24SGrant Likely chip = chip_save; 439c103de24SGrant Likely for (i = 0; i < 8; i++, chip++) { 440c103de24SGrant Likely chip->dev = &pdev->dev; 441c103de24SGrant Likely chip->base = base; 442c103de24SGrant Likely chip->reg = chip->base; 443c103de24SGrant Likely chip->ch = i; 4447e3a70fbSAxel Lin spin_lock_init(&chip->spinlock); 445c103de24SGrant Likely ioh_gpio_setup(chip, num_ports[i]); 44647315578SLinus Walleij ret = gpiochip_add_data(&chip->gpio, chip); 447c103de24SGrant Likely if (ret) { 448c103de24SGrant Likely dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n"); 449c103de24SGrant Likely goto err_gpiochip_add; 450c103de24SGrant Likely } 451c103de24SGrant Likely } 452c103de24SGrant Likely 453c103de24SGrant Likely chip = chip_save; 45454be5663STomoya MORINAGA for (j = 0; j < 8; j++, chip++) { 455e971ac9aSBartosz Golaszewski irq_base = devm_irq_alloc_descs(&pdev->dev, -1, IOH_IRQ_BASE, 456e971ac9aSBartosz Golaszewski num_ports[j], NUMA_NO_NODE); 45754be5663STomoya MORINAGA if (irq_base < 0) { 45854be5663STomoya MORINAGA dev_warn(&pdev->dev, 45954be5663STomoya MORINAGA "ml_ioh_gpio: Failed to get IRQ base num\n"); 460df46dce0SWei Yongjun ret = irq_base; 461e971ac9aSBartosz Golaszewski goto err_gpiochip_add; 46254be5663STomoya MORINAGA } 46354be5663STomoya MORINAGA chip->irq_base = irq_base; 464e3fe07e0SBartosz Golaszewski 465e3fe07e0SBartosz Golaszewski ret = ioh_gpio_alloc_generic_chip(chip, 466e3fe07e0SBartosz Golaszewski irq_base, num_ports[j]); 467e3fe07e0SBartosz Golaszewski if (ret) 468e3fe07e0SBartosz Golaszewski goto err_gpiochip_add; 46954be5663STomoya MORINAGA } 47054be5663STomoya MORINAGA 47154be5663STomoya MORINAGA chip = chip_save; 472e971ac9aSBartosz Golaszewski ret = devm_request_irq(&pdev->dev, pdev->irq, ioh_gpio_handler, 47354be5663STomoya MORINAGA IRQF_SHARED, KBUILD_MODNAME, chip); 47454be5663STomoya MORINAGA if (ret != 0) { 47554be5663STomoya MORINAGA dev_err(&pdev->dev, 47654be5663STomoya MORINAGA "%s request_irq failed\n", __func__); 477e971ac9aSBartosz Golaszewski goto err_gpiochip_add; 47854be5663STomoya MORINAGA } 47954be5663STomoya MORINAGA 480c103de24SGrant Likely pci_set_drvdata(pdev, chip); 481c103de24SGrant Likely 482c103de24SGrant Likely return 0; 483c103de24SGrant Likely 484c103de24SGrant Likely err_gpiochip_add: 4854bf4eed4SAnton Vasilyev chip = chip_save; 48633300571SAxel Lin while (--i >= 0) { 4879f5132aeSabdoulaye berthe gpiochip_remove(&chip->gpio); 4884bf4eed4SAnton Vasilyev chip++; 489c103de24SGrant Likely } 490c103de24SGrant Likely kfree(chip_save); 491c103de24SGrant Likely 492c103de24SGrant Likely err_kzalloc: 493c103de24SGrant Likely pci_iounmap(pdev, base); 494c103de24SGrant Likely 495c103de24SGrant Likely err_iomap: 496c103de24SGrant Likely pci_release_regions(pdev); 497c103de24SGrant Likely 498c103de24SGrant Likely err_request_regions: 499c103de24SGrant Likely pci_disable_device(pdev); 500c103de24SGrant Likely 501c103de24SGrant Likely err_pci_enable: 502c103de24SGrant Likely 503c103de24SGrant Likely dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret); 504c103de24SGrant Likely return ret; 505c103de24SGrant Likely } 506c103de24SGrant Likely 507206210ceSBill Pemberton static void ioh_gpio_remove(struct pci_dev *pdev) 508c103de24SGrant Likely { 509c103de24SGrant Likely int i; 510c103de24SGrant Likely struct ioh_gpio *chip = pci_get_drvdata(pdev); 511dd9328a6SMárton Németh void *chip_save; 512c103de24SGrant Likely 513c103de24SGrant Likely chip_save = chip; 51454be5663STomoya MORINAGA 515e971ac9aSBartosz Golaszewski for (i = 0; i < 8; i++, chip++) 5169f5132aeSabdoulaye berthe gpiochip_remove(&chip->gpio); 517c103de24SGrant Likely 518c103de24SGrant Likely chip = chip_save; 519c103de24SGrant Likely pci_iounmap(pdev, chip->base); 520c103de24SGrant Likely pci_release_regions(pdev); 521c103de24SGrant Likely pci_disable_device(pdev); 522c103de24SGrant Likely kfree(chip); 523c103de24SGrant Likely } 524c103de24SGrant Likely 525c103de24SGrant Likely #ifdef CONFIG_PM 526c103de24SGrant Likely static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state) 527c103de24SGrant Likely { 528c103de24SGrant Likely s32 ret; 529c103de24SGrant Likely struct ioh_gpio *chip = pci_get_drvdata(pdev); 530b490fa0bSTomoya MORINAGA unsigned long flags; 531c103de24SGrant Likely 532b490fa0bSTomoya MORINAGA spin_lock_irqsave(&chip->spinlock, flags); 533c103de24SGrant Likely ioh_gpio_save_reg_conf(chip); 534b490fa0bSTomoya MORINAGA spin_unlock_irqrestore(&chip->spinlock, flags); 535c103de24SGrant Likely 536c103de24SGrant Likely ret = pci_save_state(pdev); 537c103de24SGrant Likely if (ret) { 538c103de24SGrant Likely dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret); 539c103de24SGrant Likely return ret; 540c103de24SGrant Likely } 541c103de24SGrant Likely pci_disable_device(pdev); 542c103de24SGrant Likely pci_set_power_state(pdev, PCI_D0); 543c103de24SGrant Likely ret = pci_enable_wake(pdev, PCI_D0, 1); 544c103de24SGrant Likely if (ret) 545c103de24SGrant Likely dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret); 546c103de24SGrant Likely 547c103de24SGrant Likely return 0; 548c103de24SGrant Likely } 549c103de24SGrant Likely 550c103de24SGrant Likely static int ioh_gpio_resume(struct pci_dev *pdev) 551c103de24SGrant Likely { 552c103de24SGrant Likely s32 ret; 553c103de24SGrant Likely struct ioh_gpio *chip = pci_get_drvdata(pdev); 554b490fa0bSTomoya MORINAGA unsigned long flags; 555c103de24SGrant Likely 556c103de24SGrant Likely ret = pci_enable_wake(pdev, PCI_D0, 0); 557c103de24SGrant Likely 558c103de24SGrant Likely pci_set_power_state(pdev, PCI_D0); 559c103de24SGrant Likely ret = pci_enable_device(pdev); 560c103de24SGrant Likely if (ret) { 561c103de24SGrant Likely dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret); 562c103de24SGrant Likely return ret; 563c103de24SGrant Likely } 564c103de24SGrant Likely pci_restore_state(pdev); 565c103de24SGrant Likely 566b490fa0bSTomoya MORINAGA spin_lock_irqsave(&chip->spinlock, flags); 567c103de24SGrant Likely iowrite32(0x01, &chip->reg->srst); 568c103de24SGrant Likely iowrite32(0x00, &chip->reg->srst); 569c103de24SGrant Likely ioh_gpio_restore_reg_conf(chip); 570b490fa0bSTomoya MORINAGA spin_unlock_irqrestore(&chip->spinlock, flags); 571c103de24SGrant Likely 572c103de24SGrant Likely return 0; 573c103de24SGrant Likely } 574c103de24SGrant Likely #else 575c103de24SGrant Likely #define ioh_gpio_suspend NULL 576c103de24SGrant Likely #define ioh_gpio_resume NULL 577c103de24SGrant Likely #endif 578c103de24SGrant Likely 57914f4a883SJingoo Han static const struct pci_device_id ioh_gpio_pcidev_id[] = { 580c103de24SGrant Likely { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, 581c103de24SGrant Likely { 0, } 582c103de24SGrant Likely }; 583c103de24SGrant Likely MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id); 584c103de24SGrant Likely 585c103de24SGrant Likely static struct pci_driver ioh_gpio_driver = { 586c103de24SGrant Likely .name = "ml_ioh_gpio", 587c103de24SGrant Likely .id_table = ioh_gpio_pcidev_id, 588c103de24SGrant Likely .probe = ioh_gpio_probe, 5898283c4ffSBill Pemberton .remove = ioh_gpio_remove, 590c103de24SGrant Likely .suspend = ioh_gpio_suspend, 591c103de24SGrant Likely .resume = ioh_gpio_resume 592c103de24SGrant Likely }; 593c103de24SGrant Likely 59493baa65fSAxel Lin module_pci_driver(ioh_gpio_driver); 595c103de24SGrant Likely 596c103de24SGrant Likely MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver"); 597c103de24SGrant Likely MODULE_LICENSE("GPL"); 598