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. 4785b565c9SLee 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 /* 159c103de24SGrant Likely * Save register configuration and disable interrupts. 160c103de24SGrant Likely */ 161*40bb0e3eSVaibhav Gupta static void __maybe_unused ioh_gpio_save_reg_conf(struct ioh_gpio *chip) 162c103de24SGrant Likely { 163b490fa0bSTomoya MORINAGA int i; 164b490fa0bSTomoya MORINAGA 165b490fa0bSTomoya MORINAGA for (i = 0; i < 8; i ++, chip++) { 166b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.po_reg = 167b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].po); 168b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.pm_reg = 169b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].pm); 170b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.ien_reg = 171b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].ien); 172b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.imask_reg = 173b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].imask); 174b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.im0_reg = 175b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].im_0); 176b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.im1_reg = 177b490fa0bSTomoya MORINAGA ioread32(&chip->reg->regs[chip->ch].im_1); 178b490fa0bSTomoya MORINAGA if (i < 4) 179b490fa0bSTomoya MORINAGA chip->ioh_gpio_reg.use_sel_reg = 180b490fa0bSTomoya MORINAGA ioread32(&chip->reg->ioh_sel_reg[i]); 181b490fa0bSTomoya MORINAGA } 182c103de24SGrant Likely } 183c103de24SGrant Likely 184c103de24SGrant Likely /* 185c103de24SGrant Likely * This function restores the register configuration of the GPIO device. 186c103de24SGrant Likely */ 187*40bb0e3eSVaibhav Gupta static void __maybe_unused ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) 188c103de24SGrant Likely { 189b490fa0bSTomoya MORINAGA int i; 190b490fa0bSTomoya MORINAGA 191b490fa0bSTomoya MORINAGA for (i = 0; i < 8; i ++, chip++) { 192b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.po_reg, 193b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].po); 194b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.pm_reg, 195b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].pm); 196b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.ien_reg, 197b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].ien); 198b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.imask_reg, 199b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].imask); 200b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.im0_reg, 201b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].im_0); 202b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.im1_reg, 203b490fa0bSTomoya MORINAGA &chip->reg->regs[chip->ch].im_1); 204b490fa0bSTomoya MORINAGA if (i < 4) 205b490fa0bSTomoya MORINAGA iowrite32(chip->ioh_gpio_reg.use_sel_reg, 206b490fa0bSTomoya MORINAGA &chip->reg->ioh_sel_reg[i]); 207b490fa0bSTomoya MORINAGA } 208c103de24SGrant Likely } 209c103de24SGrant Likely 21054be5663STomoya MORINAGA static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) 21154be5663STomoya MORINAGA { 21247315578SLinus Walleij struct ioh_gpio *chip = gpiochip_get_data(gpio); 21354be5663STomoya MORINAGA return chip->irq_base + offset; 21454be5663STomoya MORINAGA } 21554be5663STomoya MORINAGA 216c103de24SGrant Likely static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) 217c103de24SGrant Likely { 218c103de24SGrant Likely struct gpio_chip *gpio = &chip->gpio; 219c103de24SGrant Likely 220c103de24SGrant Likely gpio->label = dev_name(chip->dev); 221c103de24SGrant Likely gpio->owner = THIS_MODULE; 222c103de24SGrant Likely gpio->direction_input = ioh_gpio_direction_input; 223c103de24SGrant Likely gpio->get = ioh_gpio_get; 224c103de24SGrant Likely gpio->direction_output = ioh_gpio_direction_output; 225c103de24SGrant Likely gpio->set = ioh_gpio_set; 226c103de24SGrant Likely gpio->dbg_show = NULL; 227c103de24SGrant Likely gpio->base = -1; 228c103de24SGrant Likely gpio->ngpio = num_port; 2299fb1f39eSLinus Walleij gpio->can_sleep = false; 23054be5663STomoya MORINAGA gpio->to_irq = ioh_gpio_to_irq; 23154be5663STomoya MORINAGA } 23254be5663STomoya MORINAGA 23354be5663STomoya MORINAGA static int ioh_irq_type(struct irq_data *d, unsigned int type) 23454be5663STomoya MORINAGA { 23554be5663STomoya MORINAGA u32 im; 236dd9328a6SMárton Németh void __iomem *im_reg; 23754be5663STomoya MORINAGA u32 ien; 23854be5663STomoya MORINAGA u32 im_pos; 23954be5663STomoya MORINAGA int ch; 24054be5663STomoya MORINAGA unsigned long flags; 24154be5663STomoya MORINAGA u32 val; 24254be5663STomoya MORINAGA int irq = d->irq; 24354be5663STomoya MORINAGA struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 24454be5663STomoya MORINAGA struct ioh_gpio *chip = gc->private; 24554be5663STomoya MORINAGA 24654be5663STomoya MORINAGA ch = irq - chip->irq_base; 24754be5663STomoya MORINAGA if (irq <= chip->irq_base + 7) { 24854be5663STomoya MORINAGA im_reg = &chip->reg->regs[chip->ch].im_0; 24954be5663STomoya MORINAGA im_pos = ch; 25054be5663STomoya MORINAGA } else { 25154be5663STomoya MORINAGA im_reg = &chip->reg->regs[chip->ch].im_1; 25254be5663STomoya MORINAGA im_pos = ch - 8; 25354be5663STomoya MORINAGA } 25454be5663STomoya MORINAGA dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n", 25554be5663STomoya MORINAGA __func__, irq, type, ch, im_pos, type); 25654be5663STomoya MORINAGA 25754be5663STomoya MORINAGA spin_lock_irqsave(&chip->spinlock, flags); 25854be5663STomoya MORINAGA 25954be5663STomoya MORINAGA switch (type) { 26054be5663STomoya MORINAGA case IRQ_TYPE_EDGE_RISING: 26154be5663STomoya MORINAGA val = IOH_EDGE_RISING; 26254be5663STomoya MORINAGA break; 26354be5663STomoya MORINAGA case IRQ_TYPE_EDGE_FALLING: 26454be5663STomoya MORINAGA val = IOH_EDGE_FALLING; 26554be5663STomoya MORINAGA break; 26654be5663STomoya MORINAGA case IRQ_TYPE_EDGE_BOTH: 26754be5663STomoya MORINAGA val = IOH_EDGE_BOTH; 26854be5663STomoya MORINAGA break; 26954be5663STomoya MORINAGA case IRQ_TYPE_LEVEL_HIGH: 27054be5663STomoya MORINAGA val = IOH_LEVEL_H; 27154be5663STomoya MORINAGA break; 27254be5663STomoya MORINAGA case IRQ_TYPE_LEVEL_LOW: 27354be5663STomoya MORINAGA val = IOH_LEVEL_L; 27454be5663STomoya MORINAGA break; 27554be5663STomoya MORINAGA case IRQ_TYPE_PROBE: 27654be5663STomoya MORINAGA goto end; 27754be5663STomoya MORINAGA default: 27854be5663STomoya MORINAGA dev_warn(chip->dev, "%s: unknown type(%dd)", 27954be5663STomoya MORINAGA __func__, type); 28054be5663STomoya MORINAGA goto end; 28154be5663STomoya MORINAGA } 28254be5663STomoya MORINAGA 28354be5663STomoya MORINAGA /* Set interrupt mode */ 28454be5663STomoya MORINAGA im = ioread32(im_reg) & ~(IOH_IM_MASK << (im_pos * 4)); 28554be5663STomoya MORINAGA iowrite32(im | (val << (im_pos * 4)), im_reg); 28654be5663STomoya MORINAGA 28754be5663STomoya MORINAGA /* iclr */ 28854be5663STomoya MORINAGA iowrite32(BIT(ch), &chip->reg->regs[chip->ch].iclr); 28954be5663STomoya MORINAGA 29054be5663STomoya MORINAGA /* IMASKCLR */ 29154be5663STomoya MORINAGA iowrite32(BIT(ch), &chip->reg->regs[chip->ch].imaskclr); 29254be5663STomoya MORINAGA 29354be5663STomoya MORINAGA /* Enable interrupt */ 29454be5663STomoya MORINAGA ien = ioread32(&chip->reg->regs[chip->ch].ien); 29554be5663STomoya MORINAGA iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien); 29654be5663STomoya MORINAGA end: 29754be5663STomoya MORINAGA spin_unlock_irqrestore(&chip->spinlock, flags); 29854be5663STomoya MORINAGA 29954be5663STomoya MORINAGA return 0; 30054be5663STomoya MORINAGA } 30154be5663STomoya MORINAGA 30254be5663STomoya MORINAGA static void ioh_irq_unmask(struct irq_data *d) 30354be5663STomoya MORINAGA { 30454be5663STomoya MORINAGA struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 30554be5663STomoya MORINAGA struct ioh_gpio *chip = gc->private; 30654be5663STomoya MORINAGA 30754be5663STomoya MORINAGA iowrite32(1 << (d->irq - chip->irq_base), 30854be5663STomoya MORINAGA &chip->reg->regs[chip->ch].imaskclr); 30954be5663STomoya MORINAGA } 31054be5663STomoya MORINAGA 31154be5663STomoya MORINAGA static void ioh_irq_mask(struct irq_data *d) 31254be5663STomoya MORINAGA { 31354be5663STomoya MORINAGA struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 31454be5663STomoya MORINAGA struct ioh_gpio *chip = gc->private; 31554be5663STomoya MORINAGA 31654be5663STomoya MORINAGA iowrite32(1 << (d->irq - chip->irq_base), 31754be5663STomoya MORINAGA &chip->reg->regs[chip->ch].imask); 31854be5663STomoya MORINAGA } 31954be5663STomoya MORINAGA 3204d052213SFeng Tang static void ioh_irq_disable(struct irq_data *d) 3214d052213SFeng Tang { 3224d052213SFeng Tang struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 3234d052213SFeng Tang struct ioh_gpio *chip = gc->private; 3244d052213SFeng Tang unsigned long flags; 3254d052213SFeng Tang u32 ien; 3264d052213SFeng Tang 3274d052213SFeng Tang spin_lock_irqsave(&chip->spinlock, flags); 3284d052213SFeng Tang ien = ioread32(&chip->reg->regs[chip->ch].ien); 3294d052213SFeng Tang ien &= ~(1 << (d->irq - chip->irq_base)); 3304d052213SFeng Tang iowrite32(ien, &chip->reg->regs[chip->ch].ien); 3314d052213SFeng Tang spin_unlock_irqrestore(&chip->spinlock, flags); 3324d052213SFeng Tang } 3334d052213SFeng Tang 3344d052213SFeng Tang static void ioh_irq_enable(struct irq_data *d) 3354d052213SFeng Tang { 3364d052213SFeng Tang struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 3374d052213SFeng Tang struct ioh_gpio *chip = gc->private; 3384d052213SFeng Tang unsigned long flags; 3394d052213SFeng Tang u32 ien; 3404d052213SFeng Tang 3414d052213SFeng Tang spin_lock_irqsave(&chip->spinlock, flags); 3424d052213SFeng Tang ien = ioread32(&chip->reg->regs[chip->ch].ien); 3434d052213SFeng Tang ien |= 1 << (d->irq - chip->irq_base); 3444d052213SFeng Tang iowrite32(ien, &chip->reg->regs[chip->ch].ien); 3454d052213SFeng Tang spin_unlock_irqrestore(&chip->spinlock, flags); 3464d052213SFeng Tang } 3474d052213SFeng Tang 34854be5663STomoya MORINAGA static irqreturn_t ioh_gpio_handler(int irq, void *dev_id) 34954be5663STomoya MORINAGA { 35054be5663STomoya MORINAGA struct ioh_gpio *chip = dev_id; 35154be5663STomoya MORINAGA u32 reg_val; 35254be5663STomoya MORINAGA int i, j; 35354be5663STomoya MORINAGA int ret = IRQ_NONE; 35454be5663STomoya MORINAGA 355f9ea14efSFeng Tang for (i = 0; i < 8; i++, chip++) { 35654be5663STomoya MORINAGA reg_val = ioread32(&chip->reg->regs[i].istatus); 35754be5663STomoya MORINAGA for (j = 0; j < num_ports[i]; j++) { 35854be5663STomoya MORINAGA if (reg_val & BIT(j)) { 35954be5663STomoya MORINAGA dev_dbg(chip->dev, 36054be5663STomoya MORINAGA "%s:[%d]:irq=%d status=0x%x\n", 36154be5663STomoya MORINAGA __func__, j, irq, reg_val); 36254be5663STomoya MORINAGA iowrite32(BIT(j), 36354be5663STomoya MORINAGA &chip->reg->regs[chip->ch].iclr); 36454be5663STomoya MORINAGA generic_handle_irq(chip->irq_base + j); 36554be5663STomoya MORINAGA ret = IRQ_HANDLED; 36654be5663STomoya MORINAGA } 36754be5663STomoya MORINAGA } 36854be5663STomoya MORINAGA } 36954be5663STomoya MORINAGA return ret; 37054be5663STomoya MORINAGA } 37154be5663STomoya MORINAGA 372e3fe07e0SBartosz Golaszewski static int ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip, 373e3fe07e0SBartosz Golaszewski unsigned int irq_start, 374e3fe07e0SBartosz Golaszewski unsigned int num) 37554be5663STomoya MORINAGA { 37654be5663STomoya MORINAGA struct irq_chip_generic *gc; 37754be5663STomoya MORINAGA struct irq_chip_type *ct; 378469d5943SBartosz Golaszewski int rv; 37954be5663STomoya MORINAGA 380469d5943SBartosz Golaszewski gc = devm_irq_alloc_generic_chip(chip->dev, "ioh_gpio", 1, irq_start, 381469d5943SBartosz Golaszewski chip->base, handle_simple_irq); 382e3fe07e0SBartosz Golaszewski if (!gc) 383e3fe07e0SBartosz Golaszewski return -ENOMEM; 384e3fe07e0SBartosz Golaszewski 38554be5663STomoya MORINAGA gc->private = chip; 38654be5663STomoya MORINAGA ct = gc->chip_types; 38754be5663STomoya MORINAGA 38854be5663STomoya MORINAGA ct->chip.irq_mask = ioh_irq_mask; 38954be5663STomoya MORINAGA ct->chip.irq_unmask = ioh_irq_unmask; 39054be5663STomoya MORINAGA ct->chip.irq_set_type = ioh_irq_type; 3914d052213SFeng Tang ct->chip.irq_disable = ioh_irq_disable; 3924d052213SFeng Tang ct->chip.irq_enable = ioh_irq_enable; 39354be5663STomoya MORINAGA 394469d5943SBartosz Golaszewski rv = devm_irq_setup_generic_chip(chip->dev, gc, IRQ_MSK(num), 395469d5943SBartosz Golaszewski IRQ_GC_INIT_MASK_CACHE, 39654be5663STomoya MORINAGA IRQ_NOREQUEST | IRQ_NOPROBE, 0); 397e3fe07e0SBartosz Golaszewski 398469d5943SBartosz Golaszewski return rv; 399c103de24SGrant Likely } 400c103de24SGrant Likely 4013836309dSBill Pemberton static int ioh_gpio_probe(struct pci_dev *pdev, 402c103de24SGrant Likely const struct pci_device_id *id) 403c103de24SGrant Likely { 404c103de24SGrant Likely int ret; 40554be5663STomoya MORINAGA int i, j; 406c103de24SGrant Likely struct ioh_gpio *chip; 407c103de24SGrant Likely void __iomem *base; 408dd9328a6SMárton Németh void *chip_save; 40954be5663STomoya MORINAGA int irq_base; 410c103de24SGrant Likely 411c103de24SGrant Likely ret = pci_enable_device(pdev); 412c103de24SGrant Likely if (ret) { 413c103de24SGrant Likely dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__); 414c103de24SGrant Likely goto err_pci_enable; 415c103de24SGrant Likely } 416c103de24SGrant Likely 417c103de24SGrant Likely ret = pci_request_regions(pdev, KBUILD_MODNAME); 418c103de24SGrant Likely if (ret) { 419c103de24SGrant Likely dev_err(&pdev->dev, "pci_request_regions failed-%d", ret); 420c103de24SGrant Likely goto err_request_regions; 421c103de24SGrant Likely } 422c103de24SGrant Likely 423c103de24SGrant Likely base = pci_iomap(pdev, 1, 0); 4242bd1c85eSMárton Németh if (!base) { 425c103de24SGrant Likely dev_err(&pdev->dev, "%s : pci_iomap failed", __func__); 426c103de24SGrant Likely ret = -ENOMEM; 427c103de24SGrant Likely goto err_iomap; 428c103de24SGrant Likely } 429c103de24SGrant Likely 4306396bb22SKees Cook chip_save = kcalloc(8, sizeof(*chip), GFP_KERNEL); 431c103de24SGrant Likely if (chip_save == NULL) { 432c103de24SGrant Likely ret = -ENOMEM; 433c103de24SGrant Likely goto err_kzalloc; 434c103de24SGrant Likely } 435c103de24SGrant Likely 436c103de24SGrant Likely chip = chip_save; 437c103de24SGrant Likely for (i = 0; i < 8; i++, chip++) { 438c103de24SGrant Likely chip->dev = &pdev->dev; 439c103de24SGrant Likely chip->base = base; 440c103de24SGrant Likely chip->reg = chip->base; 441c103de24SGrant Likely chip->ch = i; 4427e3a70fbSAxel Lin spin_lock_init(&chip->spinlock); 443c103de24SGrant Likely ioh_gpio_setup(chip, num_ports[i]); 44447315578SLinus Walleij ret = gpiochip_add_data(&chip->gpio, chip); 445c103de24SGrant Likely if (ret) { 446c103de24SGrant Likely dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n"); 447c103de24SGrant Likely goto err_gpiochip_add; 448c103de24SGrant Likely } 449c103de24SGrant Likely } 450c103de24SGrant Likely 451c103de24SGrant Likely chip = chip_save; 45254be5663STomoya MORINAGA for (j = 0; j < 8; j++, chip++) { 453e971ac9aSBartosz Golaszewski irq_base = devm_irq_alloc_descs(&pdev->dev, -1, IOH_IRQ_BASE, 454e971ac9aSBartosz Golaszewski num_ports[j], NUMA_NO_NODE); 45554be5663STomoya MORINAGA if (irq_base < 0) { 45654be5663STomoya MORINAGA dev_warn(&pdev->dev, 45754be5663STomoya MORINAGA "ml_ioh_gpio: Failed to get IRQ base num\n"); 458df46dce0SWei Yongjun ret = irq_base; 459e971ac9aSBartosz Golaszewski goto err_gpiochip_add; 46054be5663STomoya MORINAGA } 46154be5663STomoya MORINAGA chip->irq_base = irq_base; 462e3fe07e0SBartosz Golaszewski 463e3fe07e0SBartosz Golaszewski ret = ioh_gpio_alloc_generic_chip(chip, 464e3fe07e0SBartosz Golaszewski irq_base, num_ports[j]); 465e3fe07e0SBartosz Golaszewski if (ret) 466e3fe07e0SBartosz Golaszewski goto err_gpiochip_add; 46754be5663STomoya MORINAGA } 46854be5663STomoya MORINAGA 46954be5663STomoya MORINAGA chip = chip_save; 470e971ac9aSBartosz Golaszewski ret = devm_request_irq(&pdev->dev, pdev->irq, ioh_gpio_handler, 47154be5663STomoya MORINAGA IRQF_SHARED, KBUILD_MODNAME, chip); 47254be5663STomoya MORINAGA if (ret != 0) { 47354be5663STomoya MORINAGA dev_err(&pdev->dev, 47454be5663STomoya MORINAGA "%s request_irq failed\n", __func__); 475e971ac9aSBartosz Golaszewski goto err_gpiochip_add; 47654be5663STomoya MORINAGA } 47754be5663STomoya MORINAGA 478c103de24SGrant Likely pci_set_drvdata(pdev, chip); 479c103de24SGrant Likely 480c103de24SGrant Likely return 0; 481c103de24SGrant Likely 482c103de24SGrant Likely err_gpiochip_add: 4834bf4eed4SAnton Vasilyev chip = chip_save; 48433300571SAxel Lin while (--i >= 0) { 4859f5132aeSabdoulaye berthe gpiochip_remove(&chip->gpio); 4864bf4eed4SAnton Vasilyev chip++; 487c103de24SGrant Likely } 488c103de24SGrant Likely kfree(chip_save); 489c103de24SGrant Likely 490c103de24SGrant Likely err_kzalloc: 491c103de24SGrant Likely pci_iounmap(pdev, base); 492c103de24SGrant Likely 493c103de24SGrant Likely err_iomap: 494c103de24SGrant Likely pci_release_regions(pdev); 495c103de24SGrant Likely 496c103de24SGrant Likely err_request_regions: 497c103de24SGrant Likely pci_disable_device(pdev); 498c103de24SGrant Likely 499c103de24SGrant Likely err_pci_enable: 500c103de24SGrant Likely 501c103de24SGrant Likely dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret); 502c103de24SGrant Likely return ret; 503c103de24SGrant Likely } 504c103de24SGrant Likely 505206210ceSBill Pemberton static void ioh_gpio_remove(struct pci_dev *pdev) 506c103de24SGrant Likely { 507c103de24SGrant Likely int i; 508c103de24SGrant Likely struct ioh_gpio *chip = pci_get_drvdata(pdev); 509dd9328a6SMárton Németh void *chip_save; 510c103de24SGrant Likely 511c103de24SGrant Likely chip_save = chip; 51254be5663STomoya MORINAGA 513e971ac9aSBartosz Golaszewski for (i = 0; i < 8; i++, chip++) 5149f5132aeSabdoulaye berthe gpiochip_remove(&chip->gpio); 515c103de24SGrant Likely 516c103de24SGrant Likely chip = chip_save; 517c103de24SGrant Likely pci_iounmap(pdev, chip->base); 518c103de24SGrant Likely pci_release_regions(pdev); 519c103de24SGrant Likely pci_disable_device(pdev); 520c103de24SGrant Likely kfree(chip); 521c103de24SGrant Likely } 522c103de24SGrant Likely 523*40bb0e3eSVaibhav Gupta static int __maybe_unused ioh_gpio_suspend(struct device *dev) 524c103de24SGrant Likely { 525*40bb0e3eSVaibhav Gupta struct ioh_gpio *chip = dev_get_drvdata(dev); 526b490fa0bSTomoya MORINAGA unsigned long flags; 527c103de24SGrant Likely 528b490fa0bSTomoya MORINAGA spin_lock_irqsave(&chip->spinlock, flags); 529c103de24SGrant Likely ioh_gpio_save_reg_conf(chip); 530b490fa0bSTomoya MORINAGA spin_unlock_irqrestore(&chip->spinlock, flags); 531c103de24SGrant Likely 532c103de24SGrant Likely return 0; 533c103de24SGrant Likely } 534c103de24SGrant Likely 535*40bb0e3eSVaibhav Gupta static int __maybe_unused ioh_gpio_resume(struct device *dev) 536c103de24SGrant Likely { 537*40bb0e3eSVaibhav Gupta struct ioh_gpio *chip = dev_get_drvdata(dev); 538b490fa0bSTomoya MORINAGA unsigned long flags; 539c103de24SGrant Likely 540b490fa0bSTomoya MORINAGA spin_lock_irqsave(&chip->spinlock, flags); 541c103de24SGrant Likely iowrite32(0x01, &chip->reg->srst); 542c103de24SGrant Likely iowrite32(0x00, &chip->reg->srst); 543c103de24SGrant Likely ioh_gpio_restore_reg_conf(chip); 544b490fa0bSTomoya MORINAGA spin_unlock_irqrestore(&chip->spinlock, flags); 545c103de24SGrant Likely 546c103de24SGrant Likely return 0; 547c103de24SGrant Likely } 548*40bb0e3eSVaibhav Gupta 549*40bb0e3eSVaibhav Gupta static SIMPLE_DEV_PM_OPS(ioh_gpio_pm_ops, ioh_gpio_suspend, ioh_gpio_resume); 550c103de24SGrant Likely 55114f4a883SJingoo Han static const struct pci_device_id ioh_gpio_pcidev_id[] = { 552c103de24SGrant Likely { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, 553c103de24SGrant Likely { 0, } 554c103de24SGrant Likely }; 555c103de24SGrant Likely MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id); 556c103de24SGrant Likely 557c103de24SGrant Likely static struct pci_driver ioh_gpio_driver = { 558c103de24SGrant Likely .name = "ml_ioh_gpio", 559c103de24SGrant Likely .id_table = ioh_gpio_pcidev_id, 560c103de24SGrant Likely .probe = ioh_gpio_probe, 5618283c4ffSBill Pemberton .remove = ioh_gpio_remove, 562*40bb0e3eSVaibhav Gupta .driver = { 563*40bb0e3eSVaibhav Gupta .pm = &ioh_gpio_pm_ops, 564*40bb0e3eSVaibhav Gupta }, 565c103de24SGrant Likely }; 566c103de24SGrant Likely 56793baa65fSAxel Lin module_pci_driver(ioh_gpio_driver); 568c103de24SGrant Likely 569c103de24SGrant Likely MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver"); 570c103de24SGrant Likely MODULE_LICENSE("GPL"); 571