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/pinctrl/consumer.h>
19 #include <linux/platform_device.h>
20 #include <linux/property.h>
22 #define VF610_GPIO_PER_PORT 32
24 struct fsl_gpio_soc_data
{
25 /* SoCs has a Port Data Direction Register (PDDR) */
30 struct vf610_gpio_port
{
33 void __iomem
*gpio_base
;
34 const struct fsl_gpio_soc_data
*sdata
;
35 u8 irqc
[VF610_GPIO_PER_PORT
];
41 #define GPIO_PDOR 0x00
42 #define GPIO_PSOR 0x04
43 #define GPIO_PCOR 0x08
44 #define GPIO_PTOR 0x0c
45 #define GPIO_PDIR 0x10
46 #define GPIO_PDDR 0x14
48 #define PORT_PCR(n) ((n) * 0x4)
49 #define PORT_PCR_IRQC_OFFSET 16
51 #define PORT_ISFR 0xa0
52 #define PORT_DFER 0xc0
53 #define PORT_DFCR 0xc4
54 #define PORT_DFWR 0xc8
56 #define PORT_INT_OFF 0x0
57 #define PORT_INT_LOGIC_ZERO 0x8
58 #define PORT_INT_RISING_EDGE 0x9
59 #define PORT_INT_FALLING_EDGE 0xa
60 #define PORT_INT_EITHER_EDGE 0xb
61 #define PORT_INT_LOGIC_ONE 0xc
63 #define IMX8ULP_GPIO_BASE_OFF 0x40
64 #define IMX8ULP_BASE_OFF 0x80
66 static const struct fsl_gpio_soc_data vf610_data
= {
67 .have_dual_base
= true,
70 static const struct fsl_gpio_soc_data imx_data
= {
72 .have_dual_base
= true,
75 static const struct fsl_gpio_soc_data imx8ulp_data
= {
79 static const struct of_device_id vf610_gpio_dt_ids
[] = {
80 { .compatible
= "fsl,vf610-gpio", .data
= &vf610_data
},
81 { .compatible
= "fsl,imx7ulp-gpio", .data
= &imx_data
, },
82 { .compatible
= "fsl,imx8ulp-gpio", .data
= &imx8ulp_data
, },
86 static inline void vf610_gpio_writel(u32 val
, void __iomem
*reg
)
88 writel_relaxed(val
, reg
);
91 static inline u32
vf610_gpio_readl(void __iomem
*reg
)
93 return readl_relaxed(reg
);
96 static int vf610_gpio_get(struct gpio_chip
*gc
, unsigned int gpio
)
98 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
100 unsigned long offset
= GPIO_PDIR
;
102 if (port
->sdata
->have_paddr
) {
103 mask
&= vf610_gpio_readl(port
->gpio_base
+ GPIO_PDDR
);
108 return !!(vf610_gpio_readl(port
->gpio_base
+ offset
) & BIT(gpio
));
111 static void vf610_gpio_set(struct gpio_chip
*gc
, unsigned int gpio
, int val
)
113 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
114 u32 mask
= BIT(gpio
);
115 unsigned long offset
= val
? GPIO_PSOR
: GPIO_PCOR
;
117 vf610_gpio_writel(mask
, port
->gpio_base
+ offset
);
120 static int vf610_gpio_direction_input(struct gpio_chip
*chip
, unsigned int gpio
)
122 struct vf610_gpio_port
*port
= gpiochip_get_data(chip
);
123 u32 mask
= BIT(gpio
);
126 if (port
->sdata
->have_paddr
) {
127 val
= vf610_gpio_readl(port
->gpio_base
+ GPIO_PDDR
);
129 vf610_gpio_writel(val
, port
->gpio_base
+ GPIO_PDDR
);
132 return pinctrl_gpio_direction_input(chip
, gpio
);
135 static int vf610_gpio_direction_output(struct gpio_chip
*chip
, unsigned int gpio
,
138 struct vf610_gpio_port
*port
= gpiochip_get_data(chip
);
139 u32 mask
= BIT(gpio
);
142 vf610_gpio_set(chip
, gpio
, value
);
144 if (port
->sdata
->have_paddr
) {
145 val
= vf610_gpio_readl(port
->gpio_base
+ GPIO_PDDR
);
147 vf610_gpio_writel(val
, port
->gpio_base
+ GPIO_PDDR
);
150 return pinctrl_gpio_direction_output(chip
, gpio
);
153 static int vf610_gpio_get_direction(struct gpio_chip
*gc
, unsigned int gpio
)
155 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
156 u32 mask
= BIT(gpio
);
158 mask
&= vf610_gpio_readl(port
->gpio_base
+ GPIO_PDDR
);
161 return GPIO_LINE_DIRECTION_OUT
;
163 return GPIO_LINE_DIRECTION_IN
;
166 static void vf610_gpio_irq_handler(struct irq_desc
*desc
)
168 struct vf610_gpio_port
*port
=
169 gpiochip_get_data(irq_desc_get_handler_data(desc
));
170 struct irq_chip
*chip
= irq_desc_get_chip(desc
);
172 unsigned long irq_isfr
;
174 chained_irq_enter(chip
, desc
);
176 irq_isfr
= vf610_gpio_readl(port
->base
+ PORT_ISFR
);
178 for_each_set_bit(pin
, &irq_isfr
, VF610_GPIO_PER_PORT
) {
179 vf610_gpio_writel(BIT(pin
), port
->base
+ PORT_ISFR
);
181 generic_handle_domain_irq(port
->gc
.irq
.domain
, pin
);
184 chained_irq_exit(chip
, desc
);
187 static void vf610_gpio_irq_ack(struct irq_data
*d
)
189 struct vf610_gpio_port
*port
=
190 gpiochip_get_data(irq_data_get_irq_chip_data(d
));
193 vf610_gpio_writel(BIT(gpio
), port
->base
+ PORT_ISFR
);
196 static int vf610_gpio_irq_set_type(struct irq_data
*d
, u32 type
)
198 struct vf610_gpio_port
*port
=
199 gpiochip_get_data(irq_data_get_irq_chip_data(d
));
203 case IRQ_TYPE_EDGE_RISING
:
204 irqc
= PORT_INT_RISING_EDGE
;
206 case IRQ_TYPE_EDGE_FALLING
:
207 irqc
= PORT_INT_FALLING_EDGE
;
209 case IRQ_TYPE_EDGE_BOTH
:
210 irqc
= PORT_INT_EITHER_EDGE
;
212 case IRQ_TYPE_LEVEL_LOW
:
213 irqc
= PORT_INT_LOGIC_ZERO
;
215 case IRQ_TYPE_LEVEL_HIGH
:
216 irqc
= PORT_INT_LOGIC_ONE
;
222 port
->irqc
[d
->hwirq
] = irqc
;
224 if (type
& IRQ_TYPE_LEVEL_MASK
)
225 irq_set_handler_locked(d
, handle_level_irq
);
227 irq_set_handler_locked(d
, handle_edge_irq
);
232 static void vf610_gpio_irq_mask(struct irq_data
*d
)
234 struct gpio_chip
*gc
= irq_data_get_irq_chip_data(d
);
235 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
236 irq_hw_number_t gpio_num
= irqd_to_hwirq(d
);
237 void __iomem
*pcr_base
= port
->base
+ PORT_PCR(gpio_num
);
239 vf610_gpio_writel(0, pcr_base
);
240 gpiochip_disable_irq(gc
, gpio_num
);
243 static void vf610_gpio_irq_unmask(struct irq_data
*d
)
245 struct gpio_chip
*gc
= irq_data_get_irq_chip_data(d
);
246 struct vf610_gpio_port
*port
= gpiochip_get_data(gc
);
247 irq_hw_number_t gpio_num
= irqd_to_hwirq(d
);
248 void __iomem
*pcr_base
= port
->base
+ PORT_PCR(gpio_num
);
250 gpiochip_enable_irq(gc
, gpio_num
);
251 vf610_gpio_writel(port
->irqc
[gpio_num
] << PORT_PCR_IRQC_OFFSET
,
255 static int vf610_gpio_irq_set_wake(struct irq_data
*d
, u32 enable
)
257 struct vf610_gpio_port
*port
=
258 gpiochip_get_data(irq_data_get_irq_chip_data(d
));
261 enable_irq_wake(port
->irq
);
263 disable_irq_wake(port
->irq
);
268 static const struct irq_chip vf610_irqchip
= {
269 .name
= "gpio-vf610",
270 .irq_ack
= vf610_gpio_irq_ack
,
271 .irq_mask
= vf610_gpio_irq_mask
,
272 .irq_unmask
= vf610_gpio_irq_unmask
,
273 .irq_set_type
= vf610_gpio_irq_set_type
,
274 .irq_set_wake
= vf610_gpio_irq_set_wake
,
275 .flags
= IRQCHIP_IMMUTABLE
| IRQCHIP_MASK_ON_SUSPEND
276 | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND
,
277 GPIOCHIP_IRQ_RESOURCE_HELPERS
,
280 static void vf610_gpio_disable_clk(void *data
)
282 clk_disable_unprepare(data
);
285 static int vf610_gpio_probe(struct platform_device
*pdev
)
287 struct device
*dev
= &pdev
->dev
;
288 struct vf610_gpio_port
*port
;
289 struct gpio_chip
*gc
;
290 struct gpio_irq_chip
*girq
;
295 port
= devm_kzalloc(dev
, sizeof(*port
), GFP_KERNEL
);
299 port
->sdata
= device_get_match_data(dev
);
301 dual_base
= port
->sdata
->have_dual_base
;
304 * Handle legacy compatible combinations which used two reg values
305 * for the i.MX8ULP and i.MX93.
307 if (device_is_compatible(dev
, "fsl,imx7ulp-gpio") &&
308 (device_is_compatible(dev
, "fsl,imx93-gpio") ||
309 (device_is_compatible(dev
, "fsl,imx8ulp-gpio"))))
313 port
->base
= devm_platform_ioremap_resource(pdev
, 0);
314 if (IS_ERR(port
->base
))
315 return PTR_ERR(port
->base
);
317 port
->gpio_base
= devm_platform_ioremap_resource(pdev
, 1);
318 if (IS_ERR(port
->gpio_base
))
319 return PTR_ERR(port
->gpio_base
);
321 port
->base
= devm_platform_ioremap_resource(pdev
, 0);
322 if (IS_ERR(port
->base
))
323 return PTR_ERR(port
->base
);
325 port
->gpio_base
= port
->base
+ IMX8ULP_GPIO_BASE_OFF
;
326 port
->base
= port
->base
+ IMX8ULP_BASE_OFF
;
329 port
->irq
= platform_get_irq(pdev
, 0);
333 port
->clk_port
= devm_clk_get(dev
, "port");
334 ret
= PTR_ERR_OR_ZERO(port
->clk_port
);
336 ret
= clk_prepare_enable(port
->clk_port
);
339 ret
= devm_add_action_or_reset(dev
, vf610_gpio_disable_clk
,
343 } else if (ret
== -EPROBE_DEFER
) {
345 * Percolate deferrals, for anything else,
346 * just live without the clocking.
351 port
->clk_gpio
= devm_clk_get(dev
, "gpio");
352 ret
= PTR_ERR_OR_ZERO(port
->clk_gpio
);
354 ret
= clk_prepare_enable(port
->clk_gpio
);
357 ret
= devm_add_action_or_reset(dev
, vf610_gpio_disable_clk
,
361 } else if (ret
== -EPROBE_DEFER
) {
367 gc
->label
= dev_name(dev
);
368 gc
->ngpio
= VF610_GPIO_PER_PORT
;
371 gc
->request
= gpiochip_generic_request
;
372 gc
->free
= gpiochip_generic_free
;
373 gc
->direction_input
= vf610_gpio_direction_input
;
374 gc
->get
= vf610_gpio_get
;
375 gc
->direction_output
= vf610_gpio_direction_output
;
376 gc
->set
= vf610_gpio_set
;
378 * only IP has Port Data Direction Register(PDDR) can
379 * support get direction
381 if (port
->sdata
->have_paddr
)
382 gc
->get_direction
= vf610_gpio_get_direction
;
384 /* Mask all GPIO interrupts */
385 for (i
= 0; i
< gc
->ngpio
; i
++)
386 vf610_gpio_writel(0, port
->base
+ PORT_PCR(i
));
388 /* Clear the interrupt status register for all GPIO's */
389 vf610_gpio_writel(~0, port
->base
+ PORT_ISFR
);
392 gpio_irq_chip_set_chip(girq
, &vf610_irqchip
);
393 girq
->parent_handler
= vf610_gpio_irq_handler
;
394 girq
->num_parents
= 1;
395 girq
->parents
= devm_kcalloc(&pdev
->dev
, 1,
396 sizeof(*girq
->parents
),
400 girq
->parents
[0] = port
->irq
;
401 girq
->default_type
= IRQ_TYPE_NONE
;
402 girq
->handler
= handle_edge_irq
;
404 return devm_gpiochip_add_data(dev
, gc
, port
);
407 static struct platform_driver vf610_gpio_driver
= {
409 .name
= "gpio-vf610",
410 .of_match_table
= vf610_gpio_dt_ids
,
412 .probe
= vf610_gpio_probe
,
415 builtin_platform_driver(vf610_gpio_driver
);