blob: 3a0bd87957419c161484b748804fc6cec1de153e [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{
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600349 struct device *dev = &pdev->dev;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700350 s32 ret;
351 struct pch_gpio *chip;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900352 int irq_base;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700353
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600354 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700355 if (chip == NULL)
356 return -ENOMEM;
357
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600358 chip->dev = dev;
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200359 ret = pcim_enable_device(pdev);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700360 if (ret) {
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600361 dev_err(dev, "pci_enable_device FAILED");
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200362 return ret;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700363 }
364
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300365 ret = pcim_iomap_regions(pdev, BIT(1), KBUILD_MODNAME);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700366 if (ret) {
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600367 dev_err(dev, "pci_request_regions FAILED-%d", ret);
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200368 return ret;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700369 }
370
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200371 chip->base = pcim_iomap_table(pdev)[1];
Bjorn Helgaas82b2cd42021-11-30 16:08:37 -0600372 chip->ioh = id->driver_data;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700373 chip->reg = chip->base;
374 pci_set_drvdata(pdev, chip);
Axel Lind1663702012-02-01 10:51:53 +0800375 spin_lock_init(&chip->spinlock);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700376 pch_gpio_setup(chip);
Andy Shevchenkoa3bb44b2018-11-07 21:29:53 +0200377
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600378 ret = devm_gpiochip_add_data(dev, &chip->gpio, chip);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700379 if (ret) {
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600380 dev_err(dev, "PCH gpio: Failed to register GPIO\n");
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200381 return ret;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700382 }
383
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600384 irq_base = devm_irq_alloc_descs(dev, -1, 0,
Bartosz Golaszewskif57f3e62017-03-04 17:23:32 +0100385 gpio_pins[chip->ioh], NUMA_NO_NODE);
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900386 if (irq_base < 0) {
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600387 dev_warn(dev, "PCH gpio: Failed to get IRQ base num\n");
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900388 chip->irq_base = -1;
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200389 return 0;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900390 }
391 chip->irq_base = irq_base;
392
Thomas Gleixnerdf9541a2012-04-28 10:13:45 +0200393 /* Mask all interrupts, but enable them */
Andy Shevchenko5c85418ab2020-04-14 20:48:57 +0300394 iowrite32(BIT(gpio_pins[chip->ioh]) - 1, &chip->reg->imask);
395 iowrite32(BIT(gpio_pins[chip->ioh]) - 1, &chip->reg->ien);
Thomas Gleixnerdf9541a2012-04-28 10:13:45 +0200396
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600397 ret = devm_request_irq(dev, pdev->irq, pch_gpio_handler,
Bartosz Golaszewskif57f3e62017-03-04 17:23:32 +0100398 IRQF_SHARED, KBUILD_MODNAME, chip);
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200399 if (ret) {
Bjorn Helgaas2822b022021-11-30 16:08:38 -0600400 dev_err(dev, "request_irq failed\n");
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200401 return ret;
Tomoya MORINAGA38eb18a2011-07-21 09:19:59 +0900402 }
403
Andy Shevchenko6ad02b22018-11-07 21:18:04 +0200404 return pch_gpio_alloc_generic_chip(chip, irq_base, gpio_pins[chip->ioh]);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700405}
406
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200407static int __maybe_unused pch_gpio_suspend(struct device *dev)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700408{
Chuhong Yuana7db2852019-07-23 16:39:24 +0800409 struct pch_gpio *chip = dev_get_drvdata(dev);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900410 unsigned long flags;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700411
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900412 spin_lock_irqsave(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700413 pch_gpio_save_reg_conf(chip);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900414 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700415
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700416 return 0;
417}
418
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200419static int __maybe_unused pch_gpio_resume(struct device *dev)
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700420{
Chuhong Yuana7db2852019-07-23 16:39:24 +0800421 struct pch_gpio *chip = dev_get_drvdata(dev);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900422 unsigned long flags;
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700423
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900424 spin_lock_irqsave(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700425 iowrite32(0x01, &chip->reg->reset);
426 iowrite32(0x00, &chip->reg->reset);
427 pch_gpio_restore_reg_conf(chip);
Tomoya MORINAGAd568a682011-07-21 09:19:55 +0900428 spin_unlock_irqrestore(&chip->spinlock, flags);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700429
430 return 0;
431}
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200432
433static SIMPLE_DEV_PM_OPS(pch_gpio_pm_ops, pch_gpio_suspend, pch_gpio_resume);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700434
Jingoo Han14f4a882013-12-03 08:08:45 +0900435static const struct pci_device_id pch_gpio_pcidev_id[] = {
Bjorn Helgaas82b2cd42021-11-30 16:08:37 -0600436 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803),
437 .driver_data = INTEL_EG20T_PCH },
438 { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014),
439 .driver_data = OKISEMI_ML7223m_IOH },
440 { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043),
441 .driver_data = OKISEMI_ML7223n_IOH },
442 { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803),
443 .driver_data = INTEL_EG20T_PCH },
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700444 { 0, }
445};
Axel Lin19234cd2011-03-11 14:58:30 -0800446MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700447
448static struct pci_driver pch_gpio_driver = {
449 .name = "pch_gpio",
450 .id_table = pch_gpio_pcidev_id,
451 .probe = pch_gpio_probe,
Andy Shevchenko226e6b82018-11-07 21:19:45 +0200452 .driver = {
453 .pm = &pch_gpio_pm_ops,
454 },
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700455};
456
Axel Lin93baa652012-04-06 20:13:30 +0800457module_pci_driver(pch_gpio_driver);
Tomoya MORINAGA04c17aa82010-10-27 15:33:21 -0700458
459MODULE_DESCRIPTION("PCH GPIO PCI Driver");
Andy Shevchenko9b8bf5b2018-11-06 14:11:42 +0200460MODULE_LICENSE("GPL v2");