2 * GPIO driver for NXP LPC18xx/43xx.
4 * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
12 #include <linux/clk.h>
13 #include <linux/gpio/driver.h>
15 #include <linux/module.h>
17 #include <linux/of_gpio.h>
18 #include <linux/pinctrl/consumer.h>
19 #include <linux/platform_device.h>
21 /* LPC18xx GPIO register offsets */
22 #define LPC18XX_REG_DIR(n) (0x2000 + n * sizeof(u32))
24 #define LPC18XX_MAX_PORTS 8
25 #define LPC18XX_PINS_PER_PORT 32
27 struct lpc18xx_gpio_chip
{
28 struct gpio_chip gpio
;
34 static inline struct lpc18xx_gpio_chip
*to_lpc18xx_gpio(struct gpio_chip
*chip
)
36 return container_of(chip
, struct lpc18xx_gpio_chip
, gpio
);
39 static void lpc18xx_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
41 struct lpc18xx_gpio_chip
*gc
= to_lpc18xx_gpio(chip
);
42 writeb(value
? 1 : 0, gc
->base
+ offset
);
45 static int lpc18xx_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
47 struct lpc18xx_gpio_chip
*gc
= to_lpc18xx_gpio(chip
);
48 return !!readb(gc
->base
+ offset
);
51 static int lpc18xx_gpio_direction(struct gpio_chip
*chip
, unsigned offset
,
54 struct lpc18xx_gpio_chip
*gc
= to_lpc18xx_gpio(chip
);
58 port
= offset
/ LPC18XX_PINS_PER_PORT
;
59 pin
= offset
% LPC18XX_PINS_PER_PORT
;
61 spin_lock_irqsave(&gc
->lock
, flags
);
62 dir
= readl(gc
->base
+ LPC18XX_REG_DIR(port
));
67 writel(dir
, gc
->base
+ LPC18XX_REG_DIR(port
));
68 spin_unlock_irqrestore(&gc
->lock
, flags
);
73 static int lpc18xx_gpio_direction_input(struct gpio_chip
*chip
,
76 return lpc18xx_gpio_direction(chip
, offset
, false);
79 static int lpc18xx_gpio_direction_output(struct gpio_chip
*chip
,
80 unsigned offset
, int value
)
82 lpc18xx_gpio_set(chip
, offset
, value
);
83 return lpc18xx_gpio_direction(chip
, offset
, true);
86 static struct gpio_chip lpc18xx_chip
= {
87 .label
= "lpc18xx/43xx-gpio",
88 .request
= gpiochip_generic_request
,
89 .free
= gpiochip_generic_free
,
90 .direction_input
= lpc18xx_gpio_direction_input
,
91 .direction_output
= lpc18xx_gpio_direction_output
,
92 .set
= lpc18xx_gpio_set
,
93 .get
= lpc18xx_gpio_get
,
94 .ngpio
= LPC18XX_MAX_PORTS
* LPC18XX_PINS_PER_PORT
,
98 static int lpc18xx_gpio_probe(struct platform_device
*pdev
)
100 struct lpc18xx_gpio_chip
*gc
;
101 struct resource
*res
;
104 gc
= devm_kzalloc(&pdev
->dev
, sizeof(*gc
), GFP_KERNEL
);
108 gc
->gpio
= lpc18xx_chip
;
109 platform_set_drvdata(pdev
, gc
);
111 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
112 gc
->base
= devm_ioremap_resource(&pdev
->dev
, res
);
113 if (IS_ERR(gc
->base
))
114 return PTR_ERR(gc
->base
);
116 gc
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
117 if (IS_ERR(gc
->clk
)) {
118 dev_err(&pdev
->dev
, "input clock not found\n");
119 return PTR_ERR(gc
->clk
);
122 ret
= clk_prepare_enable(gc
->clk
);
124 dev_err(&pdev
->dev
, "unable to enable clock\n");
128 spin_lock_init(&gc
->lock
);
130 gc
->gpio
.dev
= &pdev
->dev
;
132 ret
= gpiochip_add(&gc
->gpio
);
134 dev_err(&pdev
->dev
, "failed to add gpio chip\n");
135 clk_disable_unprepare(gc
->clk
);
142 static int lpc18xx_gpio_remove(struct platform_device
*pdev
)
144 struct lpc18xx_gpio_chip
*gc
= platform_get_drvdata(pdev
);
146 gpiochip_remove(&gc
->gpio
);
147 clk_disable_unprepare(gc
->clk
);
152 static const struct of_device_id lpc18xx_gpio_match
[] = {
153 { .compatible
= "nxp,lpc1850-gpio" },
156 MODULE_DEVICE_TABLE(of
, lpc18xx_gpio_match
);
158 static struct platform_driver lpc18xx_gpio_driver
= {
159 .probe
= lpc18xx_gpio_probe
,
160 .remove
= lpc18xx_gpio_remove
,
162 .name
= "lpc18xx-gpio",
163 .of_match_table
= lpc18xx_gpio_match
,
166 module_platform_driver(lpc18xx_gpio_driver
);
168 MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
169 MODULE_DESCRIPTION("GPIO driver for LPC18xx/43xx");
170 MODULE_LICENSE("GPL v2");