xref: /linux/drivers/gpio/gpio-cadence.c (revision 0cf6d425d39cfc1b676fbf9dea36ecd68eeb27ee)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 /*
4  * Copyright 2017-2018 Cadence
5  *
6  * Authors:
7  *  Jan Kotas <jank@cadence.com>
8  *  Boris Brezillon <boris.brezillon@free-electrons.com>
9  */
10 
11 #include <linux/cleanup.h>
12 #include <linux/clk.h>
13 #include <linux/gpio/driver.h>
14 #include <linux/interrupt.h>
15 #include <linux/gpio/driver.h>
16 #include <linux/gpio/generic.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/spinlock.h>
21 
22 #define CDNS_GPIO_BYPASS_MODE		0x00
23 #define CDNS_GPIO_DIRECTION_MODE	0x04
24 #define CDNS_GPIO_OUTPUT_EN		0x08
25 #define CDNS_GPIO_OUTPUT_VALUE		0x0c
26 #define CDNS_GPIO_INPUT_VALUE		0x10
27 #define CDNS_GPIO_IRQ_MASK		0x14
28 #define CDNS_GPIO_IRQ_EN		0x18
29 #define CDNS_GPIO_IRQ_DIS		0x1c
30 #define CDNS_GPIO_IRQ_STATUS		0x20
31 #define CDNS_GPIO_IRQ_TYPE		0x24
32 #define CDNS_GPIO_IRQ_VALUE		0x28
33 #define CDNS_GPIO_IRQ_ANY_EDGE		0x2c
34 
35 struct cdns_gpio_chip {
36 	struct gpio_generic_chip gen_gc;
37 	void __iomem *regs;
38 	u32 bypass_orig;
39 };
40 
41 static int cdns_gpio_request(struct gpio_chip *chip, unsigned int offset)
42 {
43 	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
44 
45 	guard(gpio_generic_lock)(&cgpio->gen_gc);
46 
47 	iowrite32(ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE) & ~BIT(offset),
48 		  cgpio->regs + CDNS_GPIO_BYPASS_MODE);
49 
50 	return 0;
51 }
52 
53 static void cdns_gpio_free(struct gpio_chip *chip, unsigned int offset)
54 {
55 	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
56 
57 	guard(gpio_generic_lock)(&cgpio->gen_gc);
58 
59 	iowrite32(ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE) |
60 		  (BIT(offset) & cgpio->bypass_orig),
61 		  cgpio->regs + CDNS_GPIO_BYPASS_MODE);
62 }
63 
64 static void cdns_gpio_irq_mask(struct irq_data *d)
65 {
66 	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
67 	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
68 
69 	iowrite32(BIT(d->hwirq), cgpio->regs + CDNS_GPIO_IRQ_DIS);
70 	gpiochip_disable_irq(chip, irqd_to_hwirq(d));
71 }
72 
73 static void cdns_gpio_irq_unmask(struct irq_data *d)
74 {
75 	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
76 	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
77 
78 	gpiochip_enable_irq(chip, irqd_to_hwirq(d));
79 	iowrite32(BIT(d->hwirq), cgpio->regs + CDNS_GPIO_IRQ_EN);
80 }
81 
82 static int cdns_gpio_irq_set_type(struct irq_data *d, unsigned int type)
83 {
84 	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
85 	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
86 	u32 int_value;
87 	u32 int_type;
88 	u32 mask = BIT(d->hwirq);
89 	int ret = 0;
90 
91 	guard(gpio_generic_lock)(&cgpio->gen_gc);
92 
93 	int_value = ioread32(cgpio->regs + CDNS_GPIO_IRQ_VALUE) & ~mask;
94 	int_type = ioread32(cgpio->regs + CDNS_GPIO_IRQ_TYPE) & ~mask;
95 
96 	/*
97 	 * The GPIO controller doesn't have an ACK register.
98 	 * All interrupt statuses are cleared on a status register read.
99 	 * Don't support edge interrupts for now.
100 	 */
101 
102 	if (type == IRQ_TYPE_LEVEL_HIGH) {
103 		int_type |= mask;
104 		int_value |= mask;
105 	} else if (type == IRQ_TYPE_LEVEL_LOW) {
106 		int_type |= mask;
107 	} else {
108 		return -EINVAL;
109 	}
110 
111 	iowrite32(int_value, cgpio->regs + CDNS_GPIO_IRQ_VALUE);
112 	iowrite32(int_type, cgpio->regs + CDNS_GPIO_IRQ_TYPE);
113 
114 	return ret;
115 }
116 
117 static void cdns_gpio_irq_handler(struct irq_desc *desc)
118 {
119 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
120 	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
121 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
122 	unsigned long status;
123 	int hwirq;
124 
125 	chained_irq_enter(irqchip, desc);
126 
127 	status = ioread32(cgpio->regs + CDNS_GPIO_IRQ_STATUS) &
128 		~ioread32(cgpio->regs + CDNS_GPIO_IRQ_MASK);
129 
130 	for_each_set_bit(hwirq, &status, chip->ngpio)
131 		generic_handle_domain_irq(chip->irq.domain, hwirq);
132 
133 	chained_irq_exit(irqchip, desc);
134 }
135 
136 static const struct irq_chip cdns_gpio_irqchip = {
137 	.name		= "cdns-gpio",
138 	.irq_mask	= cdns_gpio_irq_mask,
139 	.irq_unmask	= cdns_gpio_irq_unmask,
140 	.irq_set_type	= cdns_gpio_irq_set_type,
141 	.flags		= IRQCHIP_IMMUTABLE,
142 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
143 };
144 
145 static int cdns_gpio_probe(struct platform_device *pdev)
146 {
147 	struct gpio_generic_chip_config config = { };
148 	struct cdns_gpio_chip *cgpio;
149 	int ret, irq;
150 	u32 dir_prev;
151 	u32 num_gpios = 32;
152 	struct clk *clk;
153 
154 	cgpio = devm_kzalloc(&pdev->dev, sizeof(*cgpio), GFP_KERNEL);
155 	if (!cgpio)
156 		return -ENOMEM;
157 
158 	cgpio->regs = devm_platform_ioremap_resource(pdev, 0);
159 	if (IS_ERR(cgpio->regs))
160 		return PTR_ERR(cgpio->regs);
161 
162 	of_property_read_u32(pdev->dev.of_node, "ngpios", &num_gpios);
163 
164 	if (num_gpios > 32) {
165 		dev_err(&pdev->dev, "ngpios must be less or equal 32\n");
166 		return -EINVAL;
167 	}
168 
169 	/*
170 	 * Set all pins as inputs by default, otherwise:
171 	 * gpiochip_lock_as_irq:
172 	 * tried to flag a GPIO set as output for IRQ
173 	 * Generic GPIO driver stores the direction value internally,
174 	 * so it needs to be changed before gpio_generic_chip_init() is called.
175 	 */
176 	dir_prev = ioread32(cgpio->regs + CDNS_GPIO_DIRECTION_MODE);
177 	iowrite32(GENMASK(num_gpios - 1, 0),
178 		  cgpio->regs + CDNS_GPIO_DIRECTION_MODE);
179 
180 	config.dev = &pdev->dev;
181 	config.sz = 4;
182 	config.dat = cgpio->regs + CDNS_GPIO_INPUT_VALUE;
183 	config.set = cgpio->regs + CDNS_GPIO_OUTPUT_VALUE;
184 	config.dirin = cgpio->regs + CDNS_GPIO_DIRECTION_MODE;
185 	config.flags = BGPIOF_READ_OUTPUT_REG_SET;
186 
187 	ret = gpio_generic_chip_init(&cgpio->gen_gc, &config);
188 	if (ret) {
189 		dev_err(&pdev->dev, "Failed to register generic gpio, %d\n",
190 			ret);
191 		goto err_revert_dir;
192 	}
193 
194 	cgpio->gen_gc.gc.label = dev_name(&pdev->dev);
195 	cgpio->gen_gc.gc.ngpio = num_gpios;
196 	cgpio->gen_gc.gc.parent = &pdev->dev;
197 	cgpio->gen_gc.gc.base = -1;
198 	cgpio->gen_gc.gc.owner = THIS_MODULE;
199 	cgpio->gen_gc.gc.request = cdns_gpio_request;
200 	cgpio->gen_gc.gc.free = cdns_gpio_free;
201 
202 	clk = devm_clk_get_enabled(&pdev->dev, NULL);
203 	if (IS_ERR(clk)) {
204 		ret = PTR_ERR(clk);
205 		dev_err(&pdev->dev,
206 			"Failed to retrieve peripheral clock, %d\n", ret);
207 		goto err_revert_dir;
208 	}
209 
210 	/*
211 	 * Optional irq_chip support
212 	 */
213 	irq = platform_get_irq(pdev, 0);
214 	if (irq >= 0) {
215 		struct gpio_irq_chip *girq;
216 
217 		girq = &cgpio->gen_gc.gc.irq;
218 		gpio_irq_chip_set_chip(girq, &cdns_gpio_irqchip);
219 		girq->parent_handler = cdns_gpio_irq_handler;
220 		girq->num_parents = 1;
221 		girq->parents = devm_kcalloc(&pdev->dev, 1,
222 					     sizeof(*girq->parents),
223 					     GFP_KERNEL);
224 		if (!girq->parents) {
225 			ret = -ENOMEM;
226 			goto err_revert_dir;
227 		}
228 		girq->parents[0] = irq;
229 		girq->default_type = IRQ_TYPE_NONE;
230 		girq->handler = handle_level_irq;
231 	}
232 
233 	ret = devm_gpiochip_add_data(&pdev->dev, &cgpio->gen_gc.gc, cgpio);
234 	if (ret < 0) {
235 		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
236 		goto err_revert_dir;
237 	}
238 
239 	cgpio->bypass_orig = ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE);
240 
241 	/*
242 	 * Enable gpio outputs, ignored for input direction
243 	 */
244 	iowrite32(GENMASK(num_gpios - 1, 0),
245 		  cgpio->regs + CDNS_GPIO_OUTPUT_EN);
246 	iowrite32(0, cgpio->regs + CDNS_GPIO_BYPASS_MODE);
247 
248 	platform_set_drvdata(pdev, cgpio);
249 	return 0;
250 
251 err_revert_dir:
252 	iowrite32(dir_prev, cgpio->regs + CDNS_GPIO_DIRECTION_MODE);
253 
254 	return ret;
255 }
256 
257 static void cdns_gpio_remove(struct platform_device *pdev)
258 {
259 	struct cdns_gpio_chip *cgpio = platform_get_drvdata(pdev);
260 
261 	iowrite32(cgpio->bypass_orig, cgpio->regs + CDNS_GPIO_BYPASS_MODE);
262 }
263 
264 static const struct of_device_id cdns_of_ids[] = {
265 	{ .compatible = "cdns,gpio-r1p02" },
266 	{ /* sentinel */ },
267 };
268 MODULE_DEVICE_TABLE(of, cdns_of_ids);
269 
270 static struct platform_driver cdns_gpio_driver = {
271 	.driver = {
272 		.name = "cdns-gpio",
273 		.of_match_table = cdns_of_ids,
274 	},
275 	.probe = cdns_gpio_probe,
276 	.remove = cdns_gpio_remove,
277 };
278 module_platform_driver(cdns_gpio_driver);
279 
280 MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
281 MODULE_DESCRIPTION("Cadence GPIO driver");
282 MODULE_LICENSE("GPL v2");
283 MODULE_ALIAS("platform:cdns-gpio");
284