1 // SPDX-License-Identifier: GPL-2.0+
3 * Freescale vf610 GPIO support through PORT and GPIO
5 * Copyright (c) 2014 Toradex AG.
7 * Author: Stefan Agner <stefan@agner.ch>.
9 #include <linux/bitops.h>
10 #include <linux/clk.h>
11 #include <linux/err.h>
12 #include <linux/gpio/driver.h>
13 #include <linux/init.h>
14 #include <linux/interrupt.h>
16 #include <linux/ioport.h>
17 #include <linux/irq.h>
18 #include <linux/platform_device.h>
20 #include <linux/of_irq.h>
21 #include <linux/pinctrl/consumer.h>
23 #define VF610_GPIO_PER_PORT 32
25 struct fsl_gpio_soc_data
{
26 /* SoCs has a Port Data Direction Register (PDDR) */
31 struct vf610_gpio_port
{
34 void __iomem
*gpio_base
;
35 const struct fsl_gpio_soc_data
*sdata
;
36 u8 irqc
[VF610_GPIO_PER_PORT
];
42 #define GPIO_PDOR 0x00
43 #define GPIO_PSOR 0x04
44 #define GPIO_PCOR 0x08
45 #define GPIO_PTOR 0x0c
46 #define GPIO_PDIR 0x10
47 #define GPIO_PDDR 0x14
49 #define PORT_PCR(n) ((n) * 0x4)
50 #define PORT_PCR_IRQC_OFFSET 16
52 #define PORT_ISFR 0xa0
53 #define PORT_DFER 0xc0
54 #define PORT_DFCR 0xc4
55 #define PORT_DFWR 0xc8
57 #define PORT_INT_OFF 0x0
58 #define PORT_INT_LOGIC_ZERO 0x8
59 #define PORT_INT_RISING_EDGE 0x9
60 #define PORT_INT_FALLING_EDGE 0xa
61 #define PORT_INT_EITHER_EDGE 0xb
62 #define PORT_INT_LOGIC_ONE 0xc
64 #define IMX8ULP_GPIO_BASE_OFF 0x40
65 #define IMX8ULP_BASE_OFF 0x80
67 static const struct fsl_gpio_soc_data vf610_data
= {
68 .have_dual_base
= true,
71 static const struct fsl_gpio_soc_data imx_data
= {
73 .have_dual_base
= true,
76 static const struct fsl_gpio_soc_data imx8ulp_data
= {
80 static const struct of_device_id vf610_gpio_dt_ids
[] = {
81 { .compatible
= "fsl,vf610-gpio", .data
= &vf610_data
},
82 { .compatible
= "fsl,imx7ulp-gpio", .data
= &imx_data
, },
83 { .compatible
= "fsl,imx8ulp-gpio", .data
= &imx8ulp_data
, },
87 static inline void vf610_gpio_writel(u32 val
, void __iomem
*reg
)
89 writel_relaxed(val
, reg
);
92 static inline u32
vf610_gpio_readl(void __iomem
*reg
)
94 return readl_relaxed(reg
);
97 static int vf610_gpio_get(struct gpio_chip
*gc
, unsigned int gpio
)
99 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
100 u32 mask
= BIT(gpio
);
101 unsigned long offset
= GPIO_PDIR
;
103 if (port
->sdata
->have_paddr
) {
104 mask
&= vf610_gpio_readl(port
->gpio_base
+ GPIO_PDDR
);
109 return !!(vf610_gpio_readl(port
->gpio_base
+ offset
) & BIT(gpio
));
112 static void vf610_gpio_set(struct gpio_chip
*gc
, unsigned int gpio
, int val
)
114 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
115 u32 mask
= BIT(gpio
);
116 unsigned long offset
= val
? GPIO_PSOR
: GPIO_PCOR
;
118 vf610_gpio_writel(mask
, port
->gpio_base
+ offset
);
121 static int vf610_gpio_direction_input(struct gpio_chip
*chip
, unsigned int gpio
)
123 struct vf610_gpio_port
*port
= gpiochip_get_data(chip
);
124 u32 mask
= BIT(gpio
);
127 if (port
->sdata
->have_paddr
) {
128 val
= vf610_gpio_readl(port
->gpio_base
+ GPIO_PDDR
);
130 vf610_gpio_writel(val
, port
->gpio_base
+ GPIO_PDDR
);
133 return pinctrl_gpio_direction_input(chip
, gpio
);
136 static int vf610_gpio_direction_output(struct gpio_chip
*chip
, unsigned int gpio
,
139 struct vf610_gpio_port
*port
= gpiochip_get_data(chip
);
140 u32 mask
= BIT(gpio
);
143 vf610_gpio_set(chip
, gpio
, value
);
145 if (port
->sdata
->have_paddr
) {
146 val
= vf610_gpio_readl(port
->gpio_base
+ GPIO_PDDR
);
148 vf610_gpio_writel(val
, port
->gpio_base
+ GPIO_PDDR
);
151 return pinctrl_gpio_direction_output(chip
, gpio
);
154 static int vf610_gpio_get_direction(struct gpio_chip
*gc
, unsigned int gpio
)
156 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
157 u32 mask
= BIT(gpio
);
159 mask
&= vf610_gpio_readl(port
->gpio_base
+ GPIO_PDDR
);
162 return GPIO_LINE_DIRECTION_OUT
;
164 return GPIO_LINE_DIRECTION_IN
;
167 static void vf610_gpio_irq_handler(struct irq_desc
*desc
)
169 struct vf610_gpio_port
*port
=
170 gpiochip_get_data(irq_desc_get_handler_data(desc
));
171 struct irq_chip
*chip
= irq_desc_get_chip(desc
);
173 unsigned long irq_isfr
;
175 chained_irq_enter(chip
, desc
);
177 irq_isfr
= vf610_gpio_readl(port
->base
+ PORT_ISFR
);
179 for_each_set_bit(pin
, &irq_isfr
, VF610_GPIO_PER_PORT
) {
180 vf610_gpio_writel(BIT(pin
), port
->base
+ PORT_ISFR
);
182 generic_handle_domain_irq(port
->gc
.irq
.domain
, pin
);
185 chained_irq_exit(chip
, desc
);
188 static void vf610_gpio_irq_ack(struct irq_data
*d
)
190 struct vf610_gpio_port
*port
=
191 gpiochip_get_data(irq_data_get_irq_chip_data(d
));
194 vf610_gpio_writel(BIT(gpio
), port
->base
+ PORT_ISFR
);
197 static int vf610_gpio_irq_set_type(struct irq_data
*d
, u32 type
)
199 struct vf610_gpio_port
*port
=
200 gpiochip_get_data(irq_data_get_irq_chip_data(d
));
204 case IRQ_TYPE_EDGE_RISING
:
205 irqc
= PORT_INT_RISING_EDGE
;
207 case IRQ_TYPE_EDGE_FALLING
:
208 irqc
= PORT_INT_FALLING_EDGE
;
210 case IRQ_TYPE_EDGE_BOTH
:
211 irqc
= PORT_INT_EITHER_EDGE
;
213 case IRQ_TYPE_LEVEL_LOW
:
214 irqc
= PORT_INT_LOGIC_ZERO
;
216 case IRQ_TYPE_LEVEL_HIGH
:
217 irqc
= PORT_INT_LOGIC_ONE
;
223 port
->irqc
[d
->hwirq
] = irqc
;
225 if (type
& IRQ_TYPE_LEVEL_MASK
)
226 irq_set_handler_locked(d
, handle_level_irq
);
228 irq_set_handler_locked(d
, handle_edge_irq
);
233 static void vf610_gpio_irq_mask(struct irq_data
*d
)
235 struct gpio_chip
*gc
= irq_data_get_irq_chip_data(d
);
236 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
237 irq_hw_number_t gpio_num
= irqd_to_hwirq(d
);
238 void __iomem
*pcr_base
= port
->base
+ PORT_PCR(gpio_num
);
240 vf610_gpio_writel(0, pcr_base
);
241 gpiochip_disable_irq(gc
, gpio_num
);
244 static void vf610_gpio_irq_unmask(struct irq_data
*d
)
246 struct gpio_chip
*gc
= irq_data_get_irq_chip_data(d
);
247 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
248 irq_hw_number_t gpio_num
= irqd_to_hwirq(d
);
249 void __iomem
*pcr_base
= port
->base
+ PORT_PCR(gpio_num
);
251 gpiochip_enable_irq(gc
, gpio_num
);
252 vf610_gpio_writel(port
->irqc
[gpio_num
] << PORT_PCR_IRQC_OFFSET
,
256 static int vf610_gpio_irq_set_wake(struct irq_data
*d
, u32 enable
)
258 struct vf610_gpio_port
*port
=
259 gpiochip_get_data(irq_data_get_irq_chip_data(d
));
262 enable_irq_wake(port
->irq
);
264 disable_irq_wake(port
->irq
);
269 static const struct irq_chip vf610_irqchip
= {
270 .name
= "gpio-vf610",
271 .irq_ack
= vf610_gpio_irq_ack
,
272 .irq_mask
= vf610_gpio_irq_mask
,
273 .irq_unmask
= vf610_gpio_irq_unmask
,
274 .irq_set_type
= vf610_gpio_irq_set_type
,
275 .irq_set_wake
= vf610_gpio_irq_set_wake
,
276 .flags
= IRQCHIP_IMMUTABLE
| IRQCHIP_MASK_ON_SUSPEND
277 | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND
,
278 GPIOCHIP_IRQ_RESOURCE_HELPERS
,
281 static void vf610_gpio_disable_clk(void *data
)
283 clk_disable_unprepare(data
);
286 static int vf610_gpio_probe(struct platform_device
*pdev
)
288 struct device
*dev
= &pdev
->dev
;
289 struct vf610_gpio_port
*port
;
290 struct gpio_chip
*gc
;
291 struct gpio_irq_chip
*girq
;
296 port
= devm_kzalloc(dev
, sizeof(*port
), GFP_KERNEL
);
300 port
->sdata
= of_device_get_match_data(dev
);
302 dual_base
= port
->sdata
->have_dual_base
;
305 * Handle legacy compatible combinations which used two reg values
306 * for the i.MX8ULP and i.MX93.
308 if (device_is_compatible(dev
, "fsl,imx7ulp-gpio") &&
309 (device_is_compatible(dev
, "fsl,imx93-gpio") ||
310 (device_is_compatible(dev
, "fsl,imx8ulp-gpio"))))
314 port
->base
= devm_platform_ioremap_resource(pdev
, 0);
315 if (IS_ERR(port
->base
))
316 return PTR_ERR(port
->base
);
318 port
->gpio_base
= devm_platform_ioremap_resource(pdev
, 1);
319 if (IS_ERR(port
->gpio_base
))
320 return PTR_ERR(port
->gpio_base
);
322 port
->base
= devm_platform_ioremap_resource(pdev
, 0);
323 if (IS_ERR(port
->base
))
324 return PTR_ERR(port
->base
);
326 port
->gpio_base
= port
->base
+ IMX8ULP_GPIO_BASE_OFF
;
327 port
->base
= port
->base
+ IMX8ULP_BASE_OFF
;
330 port
->irq
= platform_get_irq(pdev
, 0);
334 port
->clk_port
= devm_clk_get(dev
, "port");
335 ret
= PTR_ERR_OR_ZERO(port
->clk_port
);
337 ret
= clk_prepare_enable(port
->clk_port
);
340 ret
= devm_add_action_or_reset(dev
, vf610_gpio_disable_clk
,
344 } else if (ret
== -EPROBE_DEFER
) {
346 * Percolate deferrals, for anything else,
347 * just live without the clocking.
352 port
->clk_gpio
= devm_clk_get(dev
, "gpio");
353 ret
= PTR_ERR_OR_ZERO(port
->clk_gpio
);
355 ret
= clk_prepare_enable(port
->clk_gpio
);
358 ret
= devm_add_action_or_reset(dev
, vf610_gpio_disable_clk
,
362 } else if (ret
== -EPROBE_DEFER
) {
368 gc
->label
= dev_name(dev
);
369 gc
->ngpio
= VF610_GPIO_PER_PORT
;
372 gc
->request
= gpiochip_generic_request
;
373 gc
->free
= gpiochip_generic_free
;
374 gc
->direction_input
= vf610_gpio_direction_input
;
375 gc
->get
= vf610_gpio_get
;
376 gc
->direction_output
= vf610_gpio_direction_output
;
377 gc
->set
= vf610_gpio_set
;
379 * only IP has Port Data Direction Register(PDDR) can
380 * support get direction
382 if (port
->sdata
->have_paddr
)
383 gc
->get_direction
= vf610_gpio_get_direction
;
385 /* Mask all GPIO interrupts */
386 for (i
= 0; i
< gc
->ngpio
; i
++)
387 vf610_gpio_writel(0, port
->base
+ PORT_PCR(i
));
389 /* Clear the interrupt status register for all GPIO's */
390 vf610_gpio_writel(~0, port
->base
+ PORT_ISFR
);
393 gpio_irq_chip_set_chip(girq
, &vf610_irqchip
);
394 girq
->parent_handler
= vf610_gpio_irq_handler
;
395 girq
->num_parents
= 1;
396 girq
->parents
= devm_kcalloc(&pdev
->dev
, 1,
397 sizeof(*girq
->parents
),
401 girq
->parents
[0] = port
->irq
;
402 girq
->default_type
= IRQ_TYPE_NONE
;
403 girq
->handler
= handle_edge_irq
;
405 return devm_gpiochip_add_data(dev
, gc
, port
);
408 static struct platform_driver vf610_gpio_driver
= {
410 .name
= "gpio-vf610",
411 .of_match_table
= vf610_gpio_dt_ids
,
413 .probe
= vf610_gpio_probe
,
416 builtin_platform_driver(vf610_gpio_driver
);