blob: a552df298a974c6dbbc84cab2890ed4b6f8967f3 [file] [log] [blame]
Andy Shevchenko9b8bf5b2018-11-06 14:11:42 +02001// SPDX-License-Identifier: GPL-2.0
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -07002/*
Tomoya MORINAGAf4574be2011-10-28 09:23:33 +09003 * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -07004 */
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +03005#include <linux/bits.h>
Linus Walleij5db1f872018-05-24 14:29:30 +02006#include <linux/gpio/driver.h>
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +09007#include <linux/interrupt.h>
8#include <linux/irq.h>
Andy Shevchenko3e1884f2018-09-04 14:26:25 +03009#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/pci.h>
Linus Walleij349b6c52014-05-27 15:15:21 +020012#include <linux/slab.h>
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +090013
14#define PCH_EDGE_FALLING 0
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +030015#define PCH_EDGE_RISING 1
16#define PCH_LEVEL_L 2
17#define PCH_LEVEL_H 3
18#define PCH_EDGE_BOTH 4
19#define PCH_IM_MASK GENMASK(2, 0)
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +090020
21#define PCH_IRQ_BASE 24
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070022
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070023struct pch_regs {
24 u32 ien;
25 u32 istatus;
26 u32 idisp;
27 u32 iclr;
28 u32 imask;
29 u32 imaskclr;
30 u32 po;
31 u32 pi;
32 u32 pm;
33 u32 im0;
34 u32 im1;
Tomoya MORINAGAe98bed72011-07-21 09:19:58 +090035 u32 reserved[3];
36 u32 gpio_use_sel;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070037 u32 reset;
38};
39
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +090040enum pch_type_t {
41 INTEL_EG20T_PCH,
Tomoya MORINAGAf4574be2011-10-28 09:23:33 +090042 OKISEMI_ML7223m_IOH, /* LAPIS Semiconductor ML7223 IOH PCIe Bus-m */
43 OKISEMI_ML7223n_IOH /* LAPIS Semiconductor ML7223 IOH PCIe Bus-n */
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +090044};
45
46/* Specifies number of GPIO PINS */
47static int gpio_pins[] = {
48 [INTEL_EG20T_PCH] = 12,
49 [OKISEMI_ML7223m_IOH] = 8,
50 [OKISEMI_ML7223n_IOH] = 8,
51};
52
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070053/**
54 * struct pch_gpio_reg_data - The register store data.
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +090055 * @ien_reg: To store contents of IEN register.
56 * @imask_reg: To store contents of IMASK register.
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070057 * @po_reg: To store contents of PO register.
58 * @pm_reg: To store contents of PM register.
Tomoya MORINAGAe98bed72011-07-21 09:19:58 +090059 * @im0_reg: To store contents of IM0 register.
60 * @im1_reg: To store contents of IM1 register.
61 * @gpio_use_sel_reg : To store contents of GPIO_USE_SEL register.
62 * (Only ML7223 Bus-n)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070063 */
64struct pch_gpio_reg_data {
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +090065 u32 ien_reg;
66 u32 imask_reg;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070067 u32 po_reg;
68 u32 pm_reg;
Tomoya MORINAGAe98bed72011-07-21 09:19:58 +090069 u32 im0_reg;
70 u32 im1_reg;
71 u32 gpio_use_sel_reg;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070072};
73
74/**
75 * struct pch_gpio - GPIO private data structure.
76 * @base: PCI base address of Memory mapped I/O register.
77 * @reg: Memory mapped PCH GPIO register list.
78 * @dev: Pointer to device structure.
79 * @gpio: Data for GPIO infrastructure.
80 * @pch_gpio_reg: Memory mapped Register data is saved here
81 * when suspend.
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +090082 * @lock: Used for register access protection
83 * @irq_base: Save base of IRQ number for interrupt
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +090084 * @ioh: IOH ID
Axel Lin7cb65802012-07-29 10:55:54 +080085 * @spinlock: Used for register access protection
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070086 */
87struct pch_gpio {
88 void __iomem *base;
89 struct pch_regs __iomem *reg;
90 struct device *dev;
91 struct gpio_chip gpio;
92 struct pch_gpio_reg_data pch_gpio_reg;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +090093 int irq_base;
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +090094 enum pch_type_t ioh;
Tomoya MORINAGAd568a682011-07-21 09:19:55 +090095 spinlock_t spinlock;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070096};
97
Abanoub Sameh0c106a22020-07-21 16:50:45 +020098static void pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -070099{
100 u32 reg_val;
Linus Walleij510f4872015-12-07 11:34:53 +0100101 struct pch_gpio *chip = gpiochip_get_data(gpio);
Axel Lin7cb65802012-07-29 10:55:54 +0800102 unsigned long flags;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700103
Axel Lin7cb65802012-07-29 10:55:54 +0800104 spin_lock_irqsave(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700105 reg_val = ioread32(&chip->reg->po);
106 if (val)
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300107 reg_val |= BIT(nr);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700108 else
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300109 reg_val &= ~BIT(nr);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700110
111 iowrite32(reg_val, &chip->reg->po);
Axel Lin7cb65802012-07-29 10:55:54 +0800112 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700113}
114
Abanoub Sameh0c106a22020-07-21 16:50:45 +0200115static int pch_gpio_get(struct gpio_chip *gpio, unsigned int nr)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700116{
Linus Walleij510f4872015-12-07 11:34:53 +0100117 struct pch_gpio *chip = gpiochip_get_data(gpio);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700118
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300119 return !!(ioread32(&chip->reg->pi) & BIT(nr));
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700120}
121
Abanoub Sameh0c106a22020-07-21 16:50:45 +0200122static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned int nr,
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700123 int val)
124{
Linus Walleij510f4872015-12-07 11:34:53 +0100125 struct pch_gpio *chip = gpiochip_get_data(gpio);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700126 u32 pm;
127 u32 reg_val;
Axel Lin7cb65802012-07-29 10:55:54 +0800128 unsigned long flags;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700129
Axel Lin7cb65802012-07-29 10:55:54 +0800130 spin_lock_irqsave(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700131
132 reg_val = ioread32(&chip->reg->po);
133 if (val)
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300134 reg_val |= BIT(nr);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700135 else
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300136 reg_val &= ~BIT(nr);
Peter Tyser88aab932011-03-25 10:04:00 -0500137 iowrite32(reg_val, &chip->reg->po);
Daniel Krueger2ddf6cd2014-03-25 10:32:47 +0100138
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300139 pm = ioread32(&chip->reg->pm);
140 pm &= BIT(gpio_pins[chip->ioh]) - 1;
141 pm |= BIT(nr);
Daniel Krueger2ddf6cd2014-03-25 10:32:47 +0100142 iowrite32(pm, &chip->reg->pm);
143
Axel Lin7cb65802012-07-29 10:55:54 +0800144 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700145
146 return 0;
147}
148
Abanoub Sameh0c106a22020-07-21 16:50:45 +0200149static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned int nr)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700150{
Linus Walleij510f4872015-12-07 11:34:53 +0100151 struct pch_gpio *chip = gpiochip_get_data(gpio);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700152 u32 pm;
Axel Lin7cb65802012-07-29 10:55:54 +0800153 unsigned long flags;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700154
Axel Lin7cb65802012-07-29 10:55:54 +0800155 spin_lock_irqsave(&chip->spinlock, flags);
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300156 pm = ioread32(&chip->reg->pm);
157 pm &= BIT(gpio_pins[chip->ioh]) - 1;
158 pm &= ~BIT(nr);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700159 iowrite32(pm, &chip->reg->pm);
Axel Lin7cb65802012-07-29 10:55:54 +0800160 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700161
162 return 0;
163}
164
165/*
166 * Save register configuration and disable interrupts.
167 */
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200168static void __maybe_unused pch_gpio_save_reg_conf(struct pch_gpio *chip)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700169{
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900170 chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien);
171 chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700172 chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
173 chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
Tomoya MORINAGAe98bed72011-07-21 09:19:58 +0900174 chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0);
175 if (chip->ioh == INTEL_EG20T_PCH)
176 chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1);
177 if (chip->ioh == OKISEMI_ML7223n_IOH)
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200178 chip->pch_gpio_reg.gpio_use_sel_reg = ioread32(&chip->reg->gpio_use_sel);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700179}
180
181/*
182 * This function restores the register configuration of the GPIO device.
183 */
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200184static void __maybe_unused pch_gpio_restore_reg_conf(struct pch_gpio *chip)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700185{
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900186 iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien);
187 iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700188 /* to store contents of PO register */
189 iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
190 /* to store contents of PM register */
191 iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
Tomoya MORINAGAe98bed72011-07-21 09:19:58 +0900192 iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0);
193 if (chip->ioh == INTEL_EG20T_PCH)
194 iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1);
195 if (chip->ioh == OKISEMI_ML7223n_IOH)
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200196 iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg, &chip->reg->gpio_use_sel);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700197}
198
Abanoub Sameh0c106a22020-07-21 16:50:45 +0200199static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned int offset)
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900200{
Linus Walleij510f4872015-12-07 11:34:53 +0100201 struct pch_gpio *chip = gpiochip_get_data(gpio);
Abanoub Sameh37ceab72020-07-21 16:50:46 +0200202
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900203 return chip->irq_base + offset;
204}
205
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700206static void pch_gpio_setup(struct pch_gpio *chip)
207{
208 struct gpio_chip *gpio = &chip->gpio;
209
210 gpio->label = dev_name(chip->dev);
Linus Walleij58383c782015-11-04 09:56:26 +0100211 gpio->parent = chip->dev;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700212 gpio->owner = THIS_MODULE;
213 gpio->direction_input = pch_gpio_direction_input;
214 gpio->get = pch_gpio_get;
215 gpio->direction_output = pch_gpio_direction_output;
216 gpio->set = pch_gpio_set;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700217 gpio->base = -1;
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +0900218 gpio->ngpio = gpio_pins[chip->ioh];
Linus Walleij9fb1f392013-12-04 14:42:46 +0100219 gpio->can_sleep = false;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900220 gpio->to_irq = pch_gpio_to_irq;
221}
222
223static int pch_irq_type(struct irq_data *d, unsigned int type)
224{
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900225 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
226 struct pch_gpio *chip = gc->private;
Thomas Gleixnerdf9541a2012-04-28 10:13:45 +0200227 u32 im, im_pos, val;
228 u32 __iomem *im_reg;
229 unsigned long flags;
230 int ch, irq = d->irq;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900231
232 ch = irq - chip->irq_base;
Andy Shevchenko368b8432020-04-14 20:48:59 +0300233 if (irq < chip->irq_base + 8) {
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900234 im_reg = &chip->reg->im0;
Andy Shevchenko368b8432020-04-14 20:48:59 +0300235 im_pos = ch - 0;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900236 } else {
237 im_reg = &chip->reg->im1;
238 im_pos = ch - 8;
239 }
Andy Shevchenko0511e112018-12-07 17:33:07 +0200240 dev_dbg(chip->dev, "irq=%d type=%d ch=%d pos=%d\n", irq, type, ch, im_pos);
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900241
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900242 switch (type) {
243 case IRQ_TYPE_EDGE_RISING:
244 val = PCH_EDGE_RISING;
245 break;
246 case IRQ_TYPE_EDGE_FALLING:
247 val = PCH_EDGE_FALLING;
248 break;
249 case IRQ_TYPE_EDGE_BOTH:
250 val = PCH_EDGE_BOTH;
251 break;
252 case IRQ_TYPE_LEVEL_HIGH:
253 val = PCH_LEVEL_H;
254 break;
255 case IRQ_TYPE_LEVEL_LOW:
256 val = PCH_LEVEL_L;
257 break;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900258 default:
Andy Shevchenko368b8432020-04-14 20:48:59 +0300259 return 0;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900260 }
261
Andy Shevchenko368b8432020-04-14 20:48:59 +0300262 spin_lock_irqsave(&chip->spinlock, flags);
263
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900264 /* Set interrupt mode */
265 im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
266 iowrite32(im | (val << (im_pos * 4)), im_reg);
267
Thomas Gleixnerdf9541a2012-04-28 10:13:45 +0200268 /* And the handler */
Andy Shevchenko5376b0b2020-04-14 20:49:00 +0300269 if (type & IRQ_TYPE_LEVEL_MASK)
Thomas Gleixner2456d862015-06-23 15:52:40 +0200270 irq_set_handler_locked(d, handle_level_irq);
Andy Shevchenko5376b0b2020-04-14 20:49:00 +0300271 else if (type & IRQ_TYPE_EDGE_BOTH)
Thomas Gleixner2456d862015-06-23 15:52:40 +0200272 irq_set_handler_locked(d, handle_edge_irq);
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900273
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900274 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900275 return 0;
276}
277
278static void pch_irq_unmask(struct irq_data *d)
279{
280 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
281 struct pch_gpio *chip = gc->private;
282
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300283 iowrite32(BIT(d->irq - chip->irq_base), &chip->reg->imaskclr);
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900284}
285
286static void pch_irq_mask(struct irq_data *d)
287{
288 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
289 struct pch_gpio *chip = gc->private;
290
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300291 iowrite32(BIT(d->irq - chip->irq_base), &chip->reg->imask);
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900292}
293
Thomas Gleixnerdf9541a2012-04-28 10:13:45 +0200294static void pch_irq_ack(struct irq_data *d)
295{
296 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
297 struct pch_gpio *chip = gc->private;
298
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300299 iowrite32(BIT(d->irq - chip->irq_base), &chip->reg->iclr);
Thomas Gleixnerdf9541a2012-04-28 10:13:45 +0200300}
301
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900302static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
303{
304 struct pch_gpio *chip = dev_id;
Andy Shevchenko9be93e12018-11-06 14:38:55 +0200305 unsigned long reg_val = ioread32(&chip->reg->istatus);
Andy Shevchenko5a4245d2020-04-14 20:48:58 +0300306 int i;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900307
Andy Shevchenko532e7622020-07-01 18:20:46 +0300308 dev_vdbg(chip->dev, "irq=%d status=0x%lx\n", irq, reg_val);
Andy Shevchenko5a4245d2020-04-14 20:48:58 +0300309
310 reg_val &= BIT(gpio_pins[chip->ioh]) - 1;
Andy Shevchenko532e7622020-07-01 18:20:46 +0300311
Andy Shevchenko5a4245d2020-04-14 20:48:58 +0300312 for_each_set_bit(i, &reg_val, gpio_pins[chip->ioh])
Andy Shevchenko9be93e12018-11-06 14:38:55 +0200313 generic_handle_irq(chip->irq_base + i);
Andy Shevchenko5a4245d2020-04-14 20:48:58 +0300314
315 return IRQ_RETVAL(reg_val);
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900316}
317
Bartosz Golaszewski09445a12017-05-25 10:37:36 +0200318static int pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
319 unsigned int irq_start,
320 unsigned int num)
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900321{
322 struct irq_chip_generic *gc;
323 struct irq_chip_type *ct;
Bartosz Golaszewskie0fc5a12017-08-09 14:25:05 +0200324 int rv;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900325
Bartosz Golaszewskie0fc5a12017-08-09 14:25:05 +0200326 gc = devm_irq_alloc_generic_chip(chip->dev, "pch_gpio", 1, irq_start,
327 chip->base, handle_simple_irq);
Bartosz Golaszewski09445a12017-05-25 10:37:36 +0200328 if (!gc)
329 return -ENOMEM;
330
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900331 gc->private = chip;
332 ct = gc->chip_types;
333
Thomas Gleixnerdf9541a2012-04-28 10:13:45 +0200334 ct->chip.irq_ack = pch_irq_ack;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900335 ct->chip.irq_mask = pch_irq_mask;
336 ct->chip.irq_unmask = pch_irq_unmask;
337 ct->chip.irq_set_type = pch_irq_type;
338
Bartosz Golaszewskie0fc5a12017-08-09 14:25:05 +0200339 rv = devm_irq_setup_generic_chip(chip->dev, gc, IRQ_MSK(num),
340 IRQ_GC_INIT_MASK_CACHE,
341 IRQ_NOREQUEST | IRQ_NOPROBE, 0);
Bartosz Golaszewski09445a12017-05-25 10:37:36 +0200342
Bartosz Golaszewskie0fc5a12017-08-09 14:25:05 +0200343 return rv;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700344}
345
Bill Pemberton38363092012-11-19 13:22:34 -0500346static int pch_gpio_probe(struct pci_dev *pdev,
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700347 const struct pci_device_id *id)
348{
349 s32 ret;
350 struct pch_gpio *chip;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900351 int irq_base;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700352
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200353 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700354 if (chip == NULL)
355 return -ENOMEM;
356
357 chip->dev = &pdev->dev;
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200358 ret = pcim_enable_device(pdev);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700359 if (ret) {
Andy Shevchenko0511e112018-12-07 17:33:07 +0200360 dev_err(&pdev->dev, "pci_enable_device FAILED");
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200361 return ret;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700362 }
363
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300364 ret = pcim_iomap_regions(pdev, BIT(1), KBUILD_MODNAME);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700365 if (ret) {
366 dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200367 return ret;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700368 }
369
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200370 chip->base = pcim_iomap_table(pdev)[1];
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700371
Tomoya MORINAGAd4260e62011-07-21 09:19:57 +0900372 if (pdev->device == 0x8803)
373 chip->ioh = INTEL_EG20T_PCH;
374 else if (pdev->device == 0x8014)
375 chip->ioh = OKISEMI_ML7223m_IOH;
376 else if (pdev->device == 0x8043)
377 chip->ioh = OKISEMI_ML7223n_IOH;
378
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700379 chip->reg = chip->base;
380 pci_set_drvdata(pdev, chip);
Axel Lind1663702012-02-01 10:51:53 +0800381 spin_lock_init(&chip->spinlock);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700382 pch_gpio_setup(chip);
Andy Shevchenkoa3bb44b2018-11-07 21:29:53 +0200383
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200384 ret = devm_gpiochip_add_data(&pdev->dev, &chip->gpio, chip);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700385 if (ret) {
386 dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200387 return ret;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700388 }
389
Bartosz Golaszewskif57f3e62017-03-04 17:23:32 +0100390 irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0,
391 gpio_pins[chip->ioh], NUMA_NO_NODE);
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900392 if (irq_base < 0) {
393 dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
394 chip->irq_base = -1;
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200395 return 0;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900396 }
397 chip->irq_base = irq_base;
398
Thomas Gleixnerdf9541a2012-04-28 10:13:45 +0200399 /* Mask all interrupts, but enable them */
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300400 iowrite32(BIT(gpio_pins[chip->ioh]) - 1, &chip->reg->imask);
401 iowrite32(BIT(gpio_pins[chip->ioh]) - 1, &chip->reg->ien);
Thomas Gleixnerdf9541a2012-04-28 10:13:45 +0200402
Bartosz Golaszewskif57f3e62017-03-04 17:23:32 +0100403 ret = devm_request_irq(&pdev->dev, pdev->irq, pch_gpio_handler,
404 IRQF_SHARED, KBUILD_MODNAME, chip);
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200405 if (ret) {
Andy Shevchenko0511e112018-12-07 17:33:07 +0200406 dev_err(&pdev->dev, "request_irq failed\n");
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200407 return ret;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900408 }
409
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200410 return pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700411}
412
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200413static int __maybe_unused pch_gpio_suspend(struct device *dev)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700414{
Chuhong Yuana7db2852019-07-23 16:39:24 +0800415 struct pch_gpio *chip = dev_get_drvdata(dev);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900416 unsigned long flags;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700417
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900418 spin_lock_irqsave(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700419 pch_gpio_save_reg_conf(chip);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900420 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700421
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700422 return 0;
423}
424
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200425static int __maybe_unused pch_gpio_resume(struct device *dev)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700426{
Chuhong Yuana7db2852019-07-23 16:39:24 +0800427 struct pch_gpio *chip = dev_get_drvdata(dev);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900428 unsigned long flags;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700429
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900430 spin_lock_irqsave(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700431 iowrite32(0x01, &chip->reg->reset);
432 iowrite32(0x00, &chip->reg->reset);
433 pch_gpio_restore_reg_conf(chip);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900434 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700435
436 return 0;
437}
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200438
439static SIMPLE_DEV_PM_OPS(pch_gpio_pm_ops, pch_gpio_suspend, pch_gpio_resume);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700440
Jingoo Han14f4a882013-12-03 08:08:45 +0900441static const struct pci_device_id pch_gpio_pcidev_id[] = {
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700442 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
Tomoya MORINAGAbc786cc2011-05-09 19:58:49 +0900443 { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
Tomoya MORINAGAc3520a12011-07-21 09:19:56 +0900444 { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
Tomoya MORINAGA868fea02011-10-28 09:23:32 +0900445 { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803) },
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700446 { 0, }
447};
Axel Lin19234cd2011-03-11 14:58:30 -0800448MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700449
450static struct pci_driver pch_gpio_driver = {
451 .name = "pch_gpio",
452 .id_table = pch_gpio_pcidev_id,
453 .probe = pch_gpio_probe,
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200454 .driver = {
455 .pm = &pch_gpio_pm_ops,
456 },
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700457};
458
Axel Lin93baa652012-04-06 20:13:30 +0800459module_pci_driver(pch_gpio_driver);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700460
461MODULE_DESCRIPTION("PCH GPIO PCI Driver");
Andy Shevchenko9b8bf5b2018-11-06 14:11:42 +0200462MODULE_LICENSE("GPL v2");