1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * SPEAr platform PLGPIO driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2012 ST Microelectronics
5*4882a593Smuzhiyun * Viresh Kumar <viresh.kumar@linaro.org>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * This file is licensed under the terms of the GNU General Public
8*4882a593Smuzhiyun * License version 2. This program is licensed "as is" without any
9*4882a593Smuzhiyun * warranty of any kind, whether express or implied.
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/clk.h>
13*4882a593Smuzhiyun #include <linux/err.h>
14*4882a593Smuzhiyun #include <linux/gpio/driver.h>
15*4882a593Smuzhiyun #include <linux/io.h>
16*4882a593Smuzhiyun #include <linux/init.h>
17*4882a593Smuzhiyun #include <linux/of.h>
18*4882a593Smuzhiyun #include <linux/of_platform.h>
19*4882a593Smuzhiyun #include <linux/pinctrl/consumer.h>
20*4882a593Smuzhiyun #include <linux/platform_device.h>
21*4882a593Smuzhiyun #include <linux/pm.h>
22*4882a593Smuzhiyun #include <linux/spinlock.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define MAX_GPIO_PER_REG 32
25*4882a593Smuzhiyun #define PIN_OFFSET(pin) (pin % MAX_GPIO_PER_REG)
26*4882a593Smuzhiyun #define REG_OFFSET(base, reg, pin) (base + reg + (pin / MAX_GPIO_PER_REG) \
27*4882a593Smuzhiyun * sizeof(int *))
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun * plgpio pins in all machines are not one to one mapped, bitwise with registers
31*4882a593Smuzhiyun * bits. These set of macros define register masks for which below functions
32*4882a593Smuzhiyun * (pin_to_offset and offset_to_pin) are required to be called.
33*4882a593Smuzhiyun */
34*4882a593Smuzhiyun #define PTO_ENB_REG 0x001
35*4882a593Smuzhiyun #define PTO_WDATA_REG 0x002
36*4882a593Smuzhiyun #define PTO_DIR_REG 0x004
37*4882a593Smuzhiyun #define PTO_IE_REG 0x008
38*4882a593Smuzhiyun #define PTO_RDATA_REG 0x010
39*4882a593Smuzhiyun #define PTO_MIS_REG 0x020
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun struct plgpio_regs {
42*4882a593Smuzhiyun u32 enb; /* enable register */
43*4882a593Smuzhiyun u32 wdata; /* write data register */
44*4882a593Smuzhiyun u32 dir; /* direction set register */
45*4882a593Smuzhiyun u32 rdata; /* read data register */
46*4882a593Smuzhiyun u32 ie; /* interrupt enable register */
47*4882a593Smuzhiyun u32 mis; /* mask interrupt status register */
48*4882a593Smuzhiyun u32 eit; /* edge interrupt type */
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun /*
52*4882a593Smuzhiyun * struct plgpio: plgpio driver specific structure
53*4882a593Smuzhiyun *
54*4882a593Smuzhiyun * lock: lock for guarding gpio registers
55*4882a593Smuzhiyun * base: base address of plgpio block
56*4882a593Smuzhiyun * chip: gpio framework specific chip information structure
57*4882a593Smuzhiyun * p2o: function ptr for pin to offset conversion. This is required only for
58*4882a593Smuzhiyun * machines where mapping b/w pin and offset is not 1-to-1.
59*4882a593Smuzhiyun * o2p: function ptr for offset to pin conversion. This is required only for
60*4882a593Smuzhiyun * machines where mapping b/w pin and offset is not 1-to-1.
61*4882a593Smuzhiyun * p2o_regs: mask of registers for which p2o and o2p are applicable
62*4882a593Smuzhiyun * regs: register offsets
63*4882a593Smuzhiyun * csave_regs: context save registers for standby/sleep/hibernate cases
64*4882a593Smuzhiyun */
65*4882a593Smuzhiyun struct plgpio {
66*4882a593Smuzhiyun spinlock_t lock;
67*4882a593Smuzhiyun void __iomem *base;
68*4882a593Smuzhiyun struct clk *clk;
69*4882a593Smuzhiyun struct gpio_chip chip;
70*4882a593Smuzhiyun int (*p2o)(int pin); /* pin_to_offset */
71*4882a593Smuzhiyun int (*o2p)(int offset); /* offset_to_pin */
72*4882a593Smuzhiyun u32 p2o_regs;
73*4882a593Smuzhiyun struct plgpio_regs regs;
74*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
75*4882a593Smuzhiyun struct plgpio_regs *csave_regs;
76*4882a593Smuzhiyun #endif
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /* register manipulation inline functions */
is_plgpio_set(void __iomem * base,u32 pin,u32 reg)80*4882a593Smuzhiyun static inline u32 is_plgpio_set(void __iomem *base, u32 pin, u32 reg)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun u32 offset = PIN_OFFSET(pin);
83*4882a593Smuzhiyun void __iomem *reg_off = REG_OFFSET(base, reg, pin);
84*4882a593Smuzhiyun u32 val = readl_relaxed(reg_off);
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun return !!(val & (1 << offset));
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
plgpio_reg_set(void __iomem * base,u32 pin,u32 reg)89*4882a593Smuzhiyun static inline void plgpio_reg_set(void __iomem *base, u32 pin, u32 reg)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun u32 offset = PIN_OFFSET(pin);
92*4882a593Smuzhiyun void __iomem *reg_off = REG_OFFSET(base, reg, pin);
93*4882a593Smuzhiyun u32 val = readl_relaxed(reg_off);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun writel_relaxed(val | (1 << offset), reg_off);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
plgpio_reg_reset(void __iomem * base,u32 pin,u32 reg)98*4882a593Smuzhiyun static inline void plgpio_reg_reset(void __iomem *base, u32 pin, u32 reg)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun u32 offset = PIN_OFFSET(pin);
101*4882a593Smuzhiyun void __iomem *reg_off = REG_OFFSET(base, reg, pin);
102*4882a593Smuzhiyun u32 val = readl_relaxed(reg_off);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun writel_relaxed(val & ~(1 << offset), reg_off);
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* gpio framework specific routines */
plgpio_direction_input(struct gpio_chip * chip,unsigned offset)108*4882a593Smuzhiyun static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(chip);
111*4882a593Smuzhiyun unsigned long flags;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /* get correct offset for "offset" pin */
114*4882a593Smuzhiyun if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) {
115*4882a593Smuzhiyun offset = plgpio->p2o(offset);
116*4882a593Smuzhiyun if (offset == -1)
117*4882a593Smuzhiyun return -EINVAL;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun spin_lock_irqsave(&plgpio->lock, flags);
121*4882a593Smuzhiyun plgpio_reg_set(plgpio->base, offset, plgpio->regs.dir);
122*4882a593Smuzhiyun spin_unlock_irqrestore(&plgpio->lock, flags);
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun return 0;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
plgpio_direction_output(struct gpio_chip * chip,unsigned offset,int value)127*4882a593Smuzhiyun static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,
128*4882a593Smuzhiyun int value)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(chip);
131*4882a593Smuzhiyun unsigned long flags;
132*4882a593Smuzhiyun unsigned dir_offset = offset, wdata_offset = offset, tmp;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /* get correct offset for "offset" pin */
135*4882a593Smuzhiyun if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) {
136*4882a593Smuzhiyun tmp = plgpio->p2o(offset);
137*4882a593Smuzhiyun if (tmp == -1)
138*4882a593Smuzhiyun return -EINVAL;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (plgpio->p2o_regs & PTO_DIR_REG)
141*4882a593Smuzhiyun dir_offset = tmp;
142*4882a593Smuzhiyun if (plgpio->p2o_regs & PTO_WDATA_REG)
143*4882a593Smuzhiyun wdata_offset = tmp;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun spin_lock_irqsave(&plgpio->lock, flags);
147*4882a593Smuzhiyun if (value)
148*4882a593Smuzhiyun plgpio_reg_set(plgpio->base, wdata_offset,
149*4882a593Smuzhiyun plgpio->regs.wdata);
150*4882a593Smuzhiyun else
151*4882a593Smuzhiyun plgpio_reg_reset(plgpio->base, wdata_offset,
152*4882a593Smuzhiyun plgpio->regs.wdata);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun plgpio_reg_reset(plgpio->base, dir_offset, plgpio->regs.dir);
155*4882a593Smuzhiyun spin_unlock_irqrestore(&plgpio->lock, flags);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun return 0;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
plgpio_get_value(struct gpio_chip * chip,unsigned offset)160*4882a593Smuzhiyun static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(chip);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun if (offset >= chip->ngpio)
165*4882a593Smuzhiyun return -EINVAL;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun /* get correct offset for "offset" pin */
168*4882a593Smuzhiyun if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) {
169*4882a593Smuzhiyun offset = plgpio->p2o(offset);
170*4882a593Smuzhiyun if (offset == -1)
171*4882a593Smuzhiyun return -EINVAL;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun return is_plgpio_set(plgpio->base, offset, plgpio->regs.rdata);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
plgpio_set_value(struct gpio_chip * chip,unsigned offset,int value)177*4882a593Smuzhiyun static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(chip);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun if (offset >= chip->ngpio)
182*4882a593Smuzhiyun return;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /* get correct offset for "offset" pin */
185*4882a593Smuzhiyun if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) {
186*4882a593Smuzhiyun offset = plgpio->p2o(offset);
187*4882a593Smuzhiyun if (offset == -1)
188*4882a593Smuzhiyun return;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun if (value)
192*4882a593Smuzhiyun plgpio_reg_set(plgpio->base, offset, plgpio->regs.wdata);
193*4882a593Smuzhiyun else
194*4882a593Smuzhiyun plgpio_reg_reset(plgpio->base, offset, plgpio->regs.wdata);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
plgpio_request(struct gpio_chip * chip,unsigned offset)197*4882a593Smuzhiyun static int plgpio_request(struct gpio_chip *chip, unsigned offset)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(chip);
200*4882a593Smuzhiyun int gpio = chip->base + offset;
201*4882a593Smuzhiyun unsigned long flags;
202*4882a593Smuzhiyun int ret = 0;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun if (offset >= chip->ngpio)
205*4882a593Smuzhiyun return -EINVAL;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun ret = pinctrl_gpio_request(gpio);
208*4882a593Smuzhiyun if (ret)
209*4882a593Smuzhiyun return ret;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (!IS_ERR(plgpio->clk)) {
212*4882a593Smuzhiyun ret = clk_enable(plgpio->clk);
213*4882a593Smuzhiyun if (ret)
214*4882a593Smuzhiyun goto err0;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun if (plgpio->regs.enb == -1)
218*4882a593Smuzhiyun return 0;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /*
221*4882a593Smuzhiyun * put gpio in IN mode before enabling it. This make enabling gpio safe
222*4882a593Smuzhiyun */
223*4882a593Smuzhiyun ret = plgpio_direction_input(chip, offset);
224*4882a593Smuzhiyun if (ret)
225*4882a593Smuzhiyun goto err1;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /* get correct offset for "offset" pin */
228*4882a593Smuzhiyun if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
229*4882a593Smuzhiyun offset = plgpio->p2o(offset);
230*4882a593Smuzhiyun if (offset == -1) {
231*4882a593Smuzhiyun ret = -EINVAL;
232*4882a593Smuzhiyun goto err1;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun spin_lock_irqsave(&plgpio->lock, flags);
237*4882a593Smuzhiyun plgpio_reg_set(plgpio->base, offset, plgpio->regs.enb);
238*4882a593Smuzhiyun spin_unlock_irqrestore(&plgpio->lock, flags);
239*4882a593Smuzhiyun return 0;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun err1:
242*4882a593Smuzhiyun if (!IS_ERR(plgpio->clk))
243*4882a593Smuzhiyun clk_disable(plgpio->clk);
244*4882a593Smuzhiyun err0:
245*4882a593Smuzhiyun pinctrl_gpio_free(gpio);
246*4882a593Smuzhiyun return ret;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
plgpio_free(struct gpio_chip * chip,unsigned offset)249*4882a593Smuzhiyun static void plgpio_free(struct gpio_chip *chip, unsigned offset)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(chip);
252*4882a593Smuzhiyun int gpio = chip->base + offset;
253*4882a593Smuzhiyun unsigned long flags;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun if (offset >= chip->ngpio)
256*4882a593Smuzhiyun return;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun if (plgpio->regs.enb == -1)
259*4882a593Smuzhiyun goto disable_clk;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /* get correct offset for "offset" pin */
262*4882a593Smuzhiyun if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
263*4882a593Smuzhiyun offset = plgpio->p2o(offset);
264*4882a593Smuzhiyun if (offset == -1)
265*4882a593Smuzhiyun return;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun spin_lock_irqsave(&plgpio->lock, flags);
269*4882a593Smuzhiyun plgpio_reg_reset(plgpio->base, offset, plgpio->regs.enb);
270*4882a593Smuzhiyun spin_unlock_irqrestore(&plgpio->lock, flags);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun disable_clk:
273*4882a593Smuzhiyun if (!IS_ERR(plgpio->clk))
274*4882a593Smuzhiyun clk_disable(plgpio->clk);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun pinctrl_gpio_free(gpio);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun /* PLGPIO IRQ */
plgpio_irq_disable(struct irq_data * d)280*4882a593Smuzhiyun static void plgpio_irq_disable(struct irq_data *d)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
283*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(gc);
284*4882a593Smuzhiyun int offset = d->hwirq;
285*4882a593Smuzhiyun unsigned long flags;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun /* get correct offset for "offset" pin */
288*4882a593Smuzhiyun if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
289*4882a593Smuzhiyun offset = plgpio->p2o(offset);
290*4882a593Smuzhiyun if (offset == -1)
291*4882a593Smuzhiyun return;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun spin_lock_irqsave(&plgpio->lock, flags);
295*4882a593Smuzhiyun plgpio_reg_set(plgpio->base, offset, plgpio->regs.ie);
296*4882a593Smuzhiyun spin_unlock_irqrestore(&plgpio->lock, flags);
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
plgpio_irq_enable(struct irq_data * d)299*4882a593Smuzhiyun static void plgpio_irq_enable(struct irq_data *d)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
302*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(gc);
303*4882a593Smuzhiyun int offset = d->hwirq;
304*4882a593Smuzhiyun unsigned long flags;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /* get correct offset for "offset" pin */
307*4882a593Smuzhiyun if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
308*4882a593Smuzhiyun offset = plgpio->p2o(offset);
309*4882a593Smuzhiyun if (offset == -1)
310*4882a593Smuzhiyun return;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun spin_lock_irqsave(&plgpio->lock, flags);
314*4882a593Smuzhiyun plgpio_reg_reset(plgpio->base, offset, plgpio->regs.ie);
315*4882a593Smuzhiyun spin_unlock_irqrestore(&plgpio->lock, flags);
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
plgpio_irq_set_type(struct irq_data * d,unsigned trigger)318*4882a593Smuzhiyun static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
321*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(gc);
322*4882a593Smuzhiyun int offset = d->hwirq;
323*4882a593Smuzhiyun void __iomem *reg_off;
324*4882a593Smuzhiyun unsigned int supported_type = 0, val;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun if (offset >= plgpio->chip.ngpio)
327*4882a593Smuzhiyun return -EINVAL;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun if (plgpio->regs.eit == -1)
330*4882a593Smuzhiyun supported_type = IRQ_TYPE_LEVEL_HIGH;
331*4882a593Smuzhiyun else
332*4882a593Smuzhiyun supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (!(trigger & supported_type))
335*4882a593Smuzhiyun return -EINVAL;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun if (plgpio->regs.eit == -1)
338*4882a593Smuzhiyun return 0;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun reg_off = REG_OFFSET(plgpio->base, plgpio->regs.eit, offset);
341*4882a593Smuzhiyun val = readl_relaxed(reg_off);
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun offset = PIN_OFFSET(offset);
344*4882a593Smuzhiyun if (trigger & IRQ_TYPE_EDGE_RISING)
345*4882a593Smuzhiyun writel_relaxed(val | (1 << offset), reg_off);
346*4882a593Smuzhiyun else
347*4882a593Smuzhiyun writel_relaxed(val & ~(1 << offset), reg_off);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun return 0;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun static struct irq_chip plgpio_irqchip = {
353*4882a593Smuzhiyun .name = "PLGPIO",
354*4882a593Smuzhiyun .irq_enable = plgpio_irq_enable,
355*4882a593Smuzhiyun .irq_disable = plgpio_irq_disable,
356*4882a593Smuzhiyun .irq_set_type = plgpio_irq_set_type,
357*4882a593Smuzhiyun };
358*4882a593Smuzhiyun
plgpio_irq_handler(struct irq_desc * desc)359*4882a593Smuzhiyun static void plgpio_irq_handler(struct irq_desc *desc)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun struct gpio_chip *gc = irq_desc_get_handler_data(desc);
362*4882a593Smuzhiyun struct plgpio *plgpio = gpiochip_get_data(gc);
363*4882a593Smuzhiyun struct irq_chip *irqchip = irq_desc_get_chip(desc);
364*4882a593Smuzhiyun int regs_count, count, pin, offset, i = 0;
365*4882a593Smuzhiyun unsigned long pending;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun count = plgpio->chip.ngpio;
368*4882a593Smuzhiyun regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun chained_irq_enter(irqchip, desc);
371*4882a593Smuzhiyun /* check all plgpio MIS registers for a possible interrupt */
372*4882a593Smuzhiyun for (; i < regs_count; i++) {
373*4882a593Smuzhiyun pending = readl_relaxed(plgpio->base + plgpio->regs.mis +
374*4882a593Smuzhiyun i * sizeof(int *));
375*4882a593Smuzhiyun if (!pending)
376*4882a593Smuzhiyun continue;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun /* clear interrupts */
379*4882a593Smuzhiyun writel_relaxed(~pending, plgpio->base + plgpio->regs.mis +
380*4882a593Smuzhiyun i * sizeof(int *));
381*4882a593Smuzhiyun /*
382*4882a593Smuzhiyun * clear extra bits in last register having gpios < MAX/REG
383*4882a593Smuzhiyun * ex: Suppose there are max 102 plgpios. then last register
384*4882a593Smuzhiyun * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits
385*4882a593Smuzhiyun * so, we must not take other 28 bits into consideration for
386*4882a593Smuzhiyun * checking interrupt. so clear those bits.
387*4882a593Smuzhiyun */
388*4882a593Smuzhiyun count = count - i * MAX_GPIO_PER_REG;
389*4882a593Smuzhiyun if (count < MAX_GPIO_PER_REG)
390*4882a593Smuzhiyun pending &= (1 << count) - 1;
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun for_each_set_bit(offset, &pending, MAX_GPIO_PER_REG) {
393*4882a593Smuzhiyun /* get correct pin for "offset" */
394*4882a593Smuzhiyun if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) {
395*4882a593Smuzhiyun pin = plgpio->o2p(offset);
396*4882a593Smuzhiyun if (pin == -1)
397*4882a593Smuzhiyun continue;
398*4882a593Smuzhiyun } else
399*4882a593Smuzhiyun pin = offset;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun /* get correct irq line number */
402*4882a593Smuzhiyun pin = i * MAX_GPIO_PER_REG + pin;
403*4882a593Smuzhiyun generic_handle_irq(
404*4882a593Smuzhiyun irq_find_mapping(gc->irq.domain, pin));
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun chained_irq_exit(irqchip, desc);
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun /*
411*4882a593Smuzhiyun * pin to offset and offset to pin converter functions
412*4882a593Smuzhiyun *
413*4882a593Smuzhiyun * In spear310 there is inconsistency among bit positions in plgpio regiseters,
414*4882a593Smuzhiyun * for different plgpio pins. For example: for pin 27, bit offset is 23, pin
415*4882a593Smuzhiyun * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1
416*4882a593Smuzhiyun */
spear310_p2o(int pin)417*4882a593Smuzhiyun static int spear310_p2o(int pin)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun int offset = pin;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun if (pin <= 27)
422*4882a593Smuzhiyun offset += 4;
423*4882a593Smuzhiyun else if (pin <= 33)
424*4882a593Smuzhiyun offset = -1;
425*4882a593Smuzhiyun else if (pin <= 97)
426*4882a593Smuzhiyun offset -= 2;
427*4882a593Smuzhiyun else if (pin <= 101)
428*4882a593Smuzhiyun offset = 101 - pin;
429*4882a593Smuzhiyun else
430*4882a593Smuzhiyun offset = -1;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun return offset;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
spear310_o2p(int offset)435*4882a593Smuzhiyun static int spear310_o2p(int offset)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun if (offset <= 3)
438*4882a593Smuzhiyun return 101 - offset;
439*4882a593Smuzhiyun else if (offset <= 31)
440*4882a593Smuzhiyun return offset - 4;
441*4882a593Smuzhiyun else
442*4882a593Smuzhiyun return offset + 2;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
plgpio_probe_dt(struct platform_device * pdev,struct plgpio * plgpio)445*4882a593Smuzhiyun static int plgpio_probe_dt(struct platform_device *pdev, struct plgpio *plgpio)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
448*4882a593Smuzhiyun int ret = -EINVAL;
449*4882a593Smuzhiyun u32 val;
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun if (of_machine_is_compatible("st,spear310")) {
452*4882a593Smuzhiyun plgpio->p2o = spear310_p2o;
453*4882a593Smuzhiyun plgpio->o2p = spear310_o2p;
454*4882a593Smuzhiyun plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG |
455*4882a593Smuzhiyun PTO_RDATA_REG | PTO_MIS_REG;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) {
459*4882a593Smuzhiyun plgpio->chip.ngpio = val;
460*4882a593Smuzhiyun } else {
461*4882a593Smuzhiyun dev_err(&pdev->dev, "DT: Invalid ngpio field\n");
462*4882a593Smuzhiyun goto end;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val))
466*4882a593Smuzhiyun plgpio->regs.enb = val;
467*4882a593Smuzhiyun else
468*4882a593Smuzhiyun plgpio->regs.enb = -1;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) {
471*4882a593Smuzhiyun plgpio->regs.wdata = val;
472*4882a593Smuzhiyun } else {
473*4882a593Smuzhiyun dev_err(&pdev->dev, "DT: Invalid wdata reg\n");
474*4882a593Smuzhiyun goto end;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) {
478*4882a593Smuzhiyun plgpio->regs.dir = val;
479*4882a593Smuzhiyun } else {
480*4882a593Smuzhiyun dev_err(&pdev->dev, "DT: Invalid dir reg\n");
481*4882a593Smuzhiyun goto end;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) {
485*4882a593Smuzhiyun plgpio->regs.ie = val;
486*4882a593Smuzhiyun } else {
487*4882a593Smuzhiyun dev_err(&pdev->dev, "DT: Invalid ie reg\n");
488*4882a593Smuzhiyun goto end;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) {
492*4882a593Smuzhiyun plgpio->regs.rdata = val;
493*4882a593Smuzhiyun } else {
494*4882a593Smuzhiyun dev_err(&pdev->dev, "DT: Invalid rdata reg\n");
495*4882a593Smuzhiyun goto end;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) {
499*4882a593Smuzhiyun plgpio->regs.mis = val;
500*4882a593Smuzhiyun } else {
501*4882a593Smuzhiyun dev_err(&pdev->dev, "DT: Invalid mis reg\n");
502*4882a593Smuzhiyun goto end;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val))
506*4882a593Smuzhiyun plgpio->regs.eit = val;
507*4882a593Smuzhiyun else
508*4882a593Smuzhiyun plgpio->regs.eit = -1;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun return 0;
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun end:
513*4882a593Smuzhiyun return ret;
514*4882a593Smuzhiyun }
plgpio_probe(struct platform_device * pdev)515*4882a593Smuzhiyun static int plgpio_probe(struct platform_device *pdev)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun struct plgpio *plgpio;
518*4882a593Smuzhiyun int ret, irq;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
521*4882a593Smuzhiyun if (!plgpio)
522*4882a593Smuzhiyun return -ENOMEM;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun plgpio->base = devm_platform_ioremap_resource(pdev, 0);
525*4882a593Smuzhiyun if (IS_ERR(plgpio->base))
526*4882a593Smuzhiyun return PTR_ERR(plgpio->base);
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun ret = plgpio_probe_dt(pdev, plgpio);
529*4882a593Smuzhiyun if (ret) {
530*4882a593Smuzhiyun dev_err(&pdev->dev, "DT probe failed\n");
531*4882a593Smuzhiyun return ret;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun plgpio->clk = devm_clk_get(&pdev->dev, NULL);
535*4882a593Smuzhiyun if (IS_ERR(plgpio->clk))
536*4882a593Smuzhiyun dev_warn(&pdev->dev, "clk_get() failed, work without it\n");
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
539*4882a593Smuzhiyun plgpio->csave_regs = devm_kcalloc(&pdev->dev,
540*4882a593Smuzhiyun DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
541*4882a593Smuzhiyun sizeof(*plgpio->csave_regs),
542*4882a593Smuzhiyun GFP_KERNEL);
543*4882a593Smuzhiyun if (!plgpio->csave_regs)
544*4882a593Smuzhiyun return -ENOMEM;
545*4882a593Smuzhiyun #endif
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun platform_set_drvdata(pdev, plgpio);
548*4882a593Smuzhiyun spin_lock_init(&plgpio->lock);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun plgpio->chip.base = -1;
551*4882a593Smuzhiyun plgpio->chip.request = plgpio_request;
552*4882a593Smuzhiyun plgpio->chip.free = plgpio_free;
553*4882a593Smuzhiyun plgpio->chip.direction_input = plgpio_direction_input;
554*4882a593Smuzhiyun plgpio->chip.direction_output = plgpio_direction_output;
555*4882a593Smuzhiyun plgpio->chip.get = plgpio_get_value;
556*4882a593Smuzhiyun plgpio->chip.set = plgpio_set_value;
557*4882a593Smuzhiyun plgpio->chip.label = dev_name(&pdev->dev);
558*4882a593Smuzhiyun plgpio->chip.parent = &pdev->dev;
559*4882a593Smuzhiyun plgpio->chip.owner = THIS_MODULE;
560*4882a593Smuzhiyun plgpio->chip.of_node = pdev->dev.of_node;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun if (!IS_ERR(plgpio->clk)) {
563*4882a593Smuzhiyun ret = clk_prepare(plgpio->clk);
564*4882a593Smuzhiyun if (ret) {
565*4882a593Smuzhiyun dev_err(&pdev->dev, "clk prepare failed\n");
566*4882a593Smuzhiyun return ret;
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun irq = platform_get_irq(pdev, 0);
571*4882a593Smuzhiyun if (irq > 0) {
572*4882a593Smuzhiyun struct gpio_irq_chip *girq;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun girq = &plgpio->chip.irq;
575*4882a593Smuzhiyun girq->chip = &plgpio_irqchip;
576*4882a593Smuzhiyun girq->parent_handler = plgpio_irq_handler;
577*4882a593Smuzhiyun girq->num_parents = 1;
578*4882a593Smuzhiyun girq->parents = devm_kcalloc(&pdev->dev, 1,
579*4882a593Smuzhiyun sizeof(*girq->parents),
580*4882a593Smuzhiyun GFP_KERNEL);
581*4882a593Smuzhiyun if (!girq->parents)
582*4882a593Smuzhiyun return -ENOMEM;
583*4882a593Smuzhiyun girq->parents[0] = irq;
584*4882a593Smuzhiyun girq->default_type = IRQ_TYPE_NONE;
585*4882a593Smuzhiyun girq->handler = handle_simple_irq;
586*4882a593Smuzhiyun dev_info(&pdev->dev, "PLGPIO registering with IRQs\n");
587*4882a593Smuzhiyun } else {
588*4882a593Smuzhiyun dev_info(&pdev->dev, "PLGPIO registering without IRQs\n");
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun ret = gpiochip_add_data(&plgpio->chip, plgpio);
592*4882a593Smuzhiyun if (ret) {
593*4882a593Smuzhiyun dev_err(&pdev->dev, "unable to add gpio chip\n");
594*4882a593Smuzhiyun goto unprepare_clk;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun return 0;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun unprepare_clk:
600*4882a593Smuzhiyun if (!IS_ERR(plgpio->clk))
601*4882a593Smuzhiyun clk_unprepare(plgpio->clk);
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun return ret;
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
plgpio_suspend(struct device * dev)607*4882a593Smuzhiyun static int plgpio_suspend(struct device *dev)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun struct plgpio *plgpio = dev_get_drvdata(dev);
610*4882a593Smuzhiyun int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
611*4882a593Smuzhiyun void __iomem *off;
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun for (i = 0; i < reg_count; i++) {
614*4882a593Smuzhiyun off = plgpio->base + i * sizeof(int *);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun if (plgpio->regs.enb != -1)
617*4882a593Smuzhiyun plgpio->csave_regs[i].enb =
618*4882a593Smuzhiyun readl_relaxed(plgpio->regs.enb + off);
619*4882a593Smuzhiyun if (plgpio->regs.eit != -1)
620*4882a593Smuzhiyun plgpio->csave_regs[i].eit =
621*4882a593Smuzhiyun readl_relaxed(plgpio->regs.eit + off);
622*4882a593Smuzhiyun plgpio->csave_regs[i].wdata = readl_relaxed(plgpio->regs.wdata +
623*4882a593Smuzhiyun off);
624*4882a593Smuzhiyun plgpio->csave_regs[i].dir = readl_relaxed(plgpio->regs.dir +
625*4882a593Smuzhiyun off);
626*4882a593Smuzhiyun plgpio->csave_regs[i].ie = readl_relaxed(plgpio->regs.ie + off);
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun return 0;
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun /*
633*4882a593Smuzhiyun * This is used to correct the values in end registers. End registers contain
634*4882a593Smuzhiyun * extra bits that might be used for other purpose in platform. So, we shouldn't
635*4882a593Smuzhiyun * overwrite these bits. This macro, reads given register again, preserves other
636*4882a593Smuzhiyun * bit values (non-plgpio bits), and retain captured value (plgpio bits).
637*4882a593Smuzhiyun */
638*4882a593Smuzhiyun #define plgpio_prepare_reg(__reg, _off, _mask, _tmp) \
639*4882a593Smuzhiyun { \
640*4882a593Smuzhiyun _tmp = readl_relaxed(plgpio->regs.__reg + _off); \
641*4882a593Smuzhiyun _tmp &= ~_mask; \
642*4882a593Smuzhiyun plgpio->csave_regs[i].__reg = \
643*4882a593Smuzhiyun _tmp | (plgpio->csave_regs[i].__reg & _mask); \
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
plgpio_resume(struct device * dev)646*4882a593Smuzhiyun static int plgpio_resume(struct device *dev)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun struct plgpio *plgpio = dev_get_drvdata(dev);
649*4882a593Smuzhiyun int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
650*4882a593Smuzhiyun void __iomem *off;
651*4882a593Smuzhiyun u32 mask, tmp;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun for (i = 0; i < reg_count; i++) {
654*4882a593Smuzhiyun off = plgpio->base + i * sizeof(int *);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun if (i == reg_count - 1) {
657*4882a593Smuzhiyun mask = (1 << (plgpio->chip.ngpio - i *
658*4882a593Smuzhiyun MAX_GPIO_PER_REG)) - 1;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun if (plgpio->regs.enb != -1)
661*4882a593Smuzhiyun plgpio_prepare_reg(enb, off, mask, tmp);
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun if (plgpio->regs.eit != -1)
664*4882a593Smuzhiyun plgpio_prepare_reg(eit, off, mask, tmp);
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun plgpio_prepare_reg(wdata, off, mask, tmp);
667*4882a593Smuzhiyun plgpio_prepare_reg(dir, off, mask, tmp);
668*4882a593Smuzhiyun plgpio_prepare_reg(ie, off, mask, tmp);
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun writel_relaxed(plgpio->csave_regs[i].wdata, plgpio->regs.wdata +
672*4882a593Smuzhiyun off);
673*4882a593Smuzhiyun writel_relaxed(plgpio->csave_regs[i].dir, plgpio->regs.dir +
674*4882a593Smuzhiyun off);
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun if (plgpio->regs.eit != -1)
677*4882a593Smuzhiyun writel_relaxed(plgpio->csave_regs[i].eit,
678*4882a593Smuzhiyun plgpio->regs.eit + off);
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun writel_relaxed(plgpio->csave_regs[i].ie, plgpio->regs.ie + off);
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun if (plgpio->regs.enb != -1)
683*4882a593Smuzhiyun writel_relaxed(plgpio->csave_regs[i].enb,
684*4882a593Smuzhiyun plgpio->regs.enb + off);
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun return 0;
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun #endif
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume);
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun static const struct of_device_id plgpio_of_match[] = {
694*4882a593Smuzhiyun { .compatible = "st,spear-plgpio" },
695*4882a593Smuzhiyun {}
696*4882a593Smuzhiyun };
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun static struct platform_driver plgpio_driver = {
699*4882a593Smuzhiyun .probe = plgpio_probe,
700*4882a593Smuzhiyun .driver = {
701*4882a593Smuzhiyun .name = "spear-plgpio",
702*4882a593Smuzhiyun .pm = &plgpio_dev_pm_ops,
703*4882a593Smuzhiyun .of_match_table = plgpio_of_match,
704*4882a593Smuzhiyun },
705*4882a593Smuzhiyun };
706*4882a593Smuzhiyun
plgpio_init(void)707*4882a593Smuzhiyun static int __init plgpio_init(void)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun return platform_driver_register(&plgpio_driver);
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun subsys_initcall(plgpio_init);
712