File Index
Files and directories
Sign in
FILE

gpio-grgpio.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpio/gpio-grgpio.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Driver for Aeroflex Gaisler GRGPIO General Purpose I/O cores.
  4 *
  5 * 2013 (c) Aeroflex Gaisler AB
  6 *
  7 * This driver supports the GRGPIO GPIO core available in the GRLIB VHDL
  8 * IP core library.
  9 *
 10 * Full documentation of the GRGPIO core can be found here:
 11 * http://www.gaisler.com/products/grlib/grip.pdf
 12 *
 13 * See "Documentation/devicetree/bindings/gpio/gpio-grgpio.txt" for
 14 * information on open firmware properties.
 15 *
 16 * Contributors: Andreas Larsson <andreas@gaisler.com>
 17 */
 18
 19#include <linux/bitops.h>
 20#include <linux/err.h>
 21#include <linux/gpio/driver.h>
 22#include <linux/gpio/generic.h>
 23#include <linux/init.h>
 24#include <linux/interrupt.h>
 25#include <linux/io.h>
 26#include <linux/irq.h>
 27#include <linux/irqdomain.h>
 28#include <linux/kernel.h>
 29#include <linux/module.h>
 30#include <linux/of.h>
 31#include <linux/platform_device.h>
 32#include <linux/slab.h>
 33#include <linux/spinlock.h>
 34#include <linux/string_choices.h>
 35
 36#define GRGPIO_MAX_NGPIO 32
 37
 38#define GRGPIO_DATA		0x00
 39#define GRGPIO_OUTPUT		0x04
 40#define GRGPIO_DIR		0x08
 41#define GRGPIO_IMASK		0x0c
 42#define GRGPIO_IPOL		0x10
 43#define GRGPIO_IEDGE		0x14
 44#define GRGPIO_BYPASS		0x18
 45#define GRGPIO_IMAP_BASE	0x20
 46
 47/* Structure for an irq of the core - called an underlying irq */
 48struct grgpio_uirq {
 49	atomic_t refcnt; /* Reference counter to manage requesting/freeing of uirq */
 50	u8 uirq; /* Underlying irq of the gpio driver */
 51};
 52
 53/*
 54 * Structure for an irq of a gpio line handed out by this driver. The index is
 55 * used to map to the corresponding underlying irq.
 56 */
 57struct grgpio_lirq {
 58	s8 index; /* Index into struct grgpio_priv's uirqs, or -1 */
 59	u8 irq; /* irq for the gpio line */
 60};
 61
 62struct grgpio_priv {
 63	struct gpio_generic_chip chip;
 64	void __iomem *regs;
 65	struct device *dev;
 66
 67	u32 imask; /* irq mask shadow register */
 68
 69	/*
 70	 * The grgpio core can have multiple "underlying" irqs. The gpio lines
 71	 * can be mapped to any one or none of these underlying irqs
 72	 * independently of each other. This driver sets up an irq domain and
 73	 * hands out separate irqs to each gpio line
 74	 */
 75	struct irq_domain *domain;
 76
 77	/*
 78	 * This array contains information on each underlying irq, each
 79	 * irq of the grgpio core itself.
 80	 */
 81	struct grgpio_uirq uirqs[GRGPIO_MAX_NGPIO];
 82
 83	/*
 84	 * This array contains information for each gpio line on the irqs
 85	 * obtains from this driver. An index value of -1 for a certain gpio
 86	 * line indicates that the line has no irq. Otherwise the index connects
 87	 * the irq to the underlying irq by pointing into the uirqs array.
 88	 */
 89	struct grgpio_lirq lirqs[GRGPIO_MAX_NGPIO];
 90};
 91
 92static void grgpio_set_imask(struct grgpio_priv *priv, unsigned int offset,
 93			     int val)
 94{
 95	if (val)
 96		priv->imask |= BIT(offset);
 97	else
 98		priv->imask &= ~BIT(offset);
 99
100	gpio_generic_write_reg(&priv->chip, priv->regs + GRGPIO_IMASK, priv->imask);
101}
102
103static int grgpio_to_irq(struct gpio_chip *gc, unsigned offset)
104{
105	struct grgpio_priv *priv = gpiochip_get_data(gc);
106
107	if (offset >= gc->ngpio)
108		return -ENXIO;
109
110	if (priv->lirqs[offset].index < 0)
111		return -ENXIO;
112
113	return irq_create_mapping(priv->domain, offset);
114}
115
116/* -------------------- IRQ chip functions -------------------- */
117
118static int grgpio_irq_set_type(struct irq_data *d, unsigned int type)
119{
120	struct grgpio_priv *priv = irq_data_get_irq_chip_data(d);
121	u32 mask = BIT(d->hwirq);
122	u32 ipol;
123	u32 iedge;
124	u32 pol;
125	u32 edge;
126
127	switch (type) {
128	case IRQ_TYPE_LEVEL_LOW:
129		pol = 0;
130		edge = 0;
131		break;
132	case IRQ_TYPE_LEVEL_HIGH:
133		pol = mask;
134		edge = 0;
135		break;
136	case IRQ_TYPE_EDGE_FALLING:
137		pol = 0;
138		edge = mask;
139		break;
140	case IRQ_TYPE_EDGE_RISING:
141		pol = mask;
142		edge = mask;
143		break;
144	default:
145		return -EINVAL;
146	}
147
148	guard(gpio_generic_lock_irqsave)(&priv->chip);
149
150	ipol = gpio_generic_read_reg(&priv->chip, priv->regs + GRGPIO_IPOL) & ~mask;
151	iedge = gpio_generic_read_reg(&priv->chip, priv->regs + GRGPIO_IEDGE) & ~mask;
152
153	gpio_generic_write_reg(&priv->chip, priv->regs + GRGPIO_IPOL, ipol | pol);
154	gpio_generic_write_reg(&priv->chip, priv->regs + GRGPIO_IEDGE, iedge | edge);
155
156	return 0;
157}
158
159static void grgpio_irq_mask(struct irq_data *d)
160{
161	struct grgpio_priv *priv = irq_data_get_irq_chip_data(d);
162	int offset = d->hwirq;
163
164	scoped_guard(gpio_generic_lock_irqsave, &priv->chip)
165		grgpio_set_imask(priv, offset, 0);
166
167	gpiochip_disable_irq(&priv->chip.gc, d->hwirq);
168}
169
170static void grgpio_irq_unmask(struct irq_data *d)
171{
172	struct grgpio_priv *priv = irq_data_get_irq_chip_data(d);
173	int offset = d->hwirq;
174
175	gpiochip_enable_irq(&priv->chip.gc, d->hwirq);
176
177	guard(gpio_generic_lock_irqsave)(&priv->chip);
178
179	grgpio_set_imask(priv, offset, 1);
180}
181
182static const struct irq_chip grgpio_irq_chip = {
183	.name			= "grgpio",
184	.irq_mask		= grgpio_irq_mask,
185	.irq_unmask		= grgpio_irq_unmask,
186	.irq_set_type		= grgpio_irq_set_type,
187	.flags = IRQCHIP_IMMUTABLE,
188	GPIOCHIP_IRQ_RESOURCE_HELPERS,
189};
190
191static irqreturn_t grgpio_irq_handler(int irq, void *dev)
192{
193	struct grgpio_priv *priv = dev;
194	int ngpio = priv->chip.gc.ngpio;
195	int i;
196	int match = 0;
197
198	guard(gpio_generic_lock_irqsave)(&priv->chip);
199
200	/*
201	 * For each gpio line, call its interrupt handler if it its underlying
202	 * irq matches the current irq that is handled.
203	 */
204	for (i = 0; i < ngpio; i++) {
205		struct grgpio_lirq *lirq = &priv->lirqs[i];
206
207		if (priv->imask & BIT(i) && lirq->index >= 0 &&
208		    priv->uirqs[lirq->index].uirq == irq) {
209			generic_handle_irq(lirq->irq);
210			match = 1;
211		}
212	}
213
214	if (!match)
215		dev_warn(priv->dev, "No gpio line matched irq %d\n", irq);
216
217	return IRQ_HANDLED;
218}
219
220/*
221 * This function will be called as a consequence of the call to
222 * irq_create_mapping in grgpio_to_irq
223 */
224static int grgpio_irq_map(struct irq_domain *d, unsigned int irq,
225			  irq_hw_number_t hwirq)
226{
227	struct grgpio_priv *priv = d->host_data;
228	struct grgpio_lirq *lirq;
229	struct grgpio_uirq *uirq;
230	unsigned long flags;
231	int offset = hwirq;
232	int ret = 0;
233
234	if (!priv)
235		return -EINVAL;
236
237	lirq = &priv->lirqs[offset];
238	if (lirq->index < 0)
239		return -EINVAL;
240
241	dev_dbg(priv->dev, "Mapping irq %d for gpio line %d\n",
242		irq, offset);
243
244	gpio_generic_chip_lock_irqsave(&priv->chip, flags);
245	lirq->irq = irq;
246	uirq = &priv->uirqs[lirq->index];
247	gpio_generic_chip_unlock_irqrestore(&priv->chip, flags);
248
249	/* Request underlying irq if not already requested */
250	if (atomic_fetch_add(1, &uirq->refcnt) == 0) {
251		ret = request_irq(uirq->uirq, grgpio_irq_handler, 0,
252				  dev_name(priv->dev), priv);
253		if (ret) {
254			dev_err(priv->dev,
255				"Could not request underlying irq %d\n",
256				uirq->uirq);
257			atomic_dec(&uirq->refcnt); /* rollback */
258			return ret;
259		}
260	}
261
262	/* Setup irq  */
263	irq_set_chip_data(irq, priv);
264	irq_set_chip_and_handler(irq, &grgpio_irq_chip,
265				 handle_simple_irq);
266	irq_set_noprobe(irq);
267
268	return ret;
269}
270
271static void grgpio_irq_unmap(struct irq_domain *d, unsigned int irq)
272{
273	struct grgpio_priv *priv = d->host_data;
274	int index;
275	struct grgpio_lirq *lirq;
276	struct grgpio_uirq *uirq;
277	unsigned long flags;
278	int ngpio = priv->chip.gc.ngpio;
279	int i;
280
281	irq_set_chip_and_handler(irq, NULL, NULL);
282	irq_set_chip_data(irq, NULL);
283
284	gpio_generic_chip_lock_irqsave(&priv->chip, flags);
285
286	/* Free underlying irq if last user unmapped */
287	index = -1;
288	for (i = 0; i < ngpio; i++) {
289		lirq = &priv->lirqs[i];
290		if (lirq->irq == irq) {
291			grgpio_set_imask(priv, i, 0);
292			lirq->irq = 0;
293			index = lirq->index;
294			break;
295		}
296	}
297	WARN_ON(index < 0);
298
299	if (index >= 0) {
300		uirq = &priv->uirqs[lirq->index];
301		if (atomic_dec_and_test(&uirq->refcnt)) {
302			gpio_generic_chip_unlock_irqrestore(&priv->chip, flags);
303			free_irq(uirq->uirq, priv);
304			return;
305		}
306	}
307
308	gpio_generic_chip_unlock_irqrestore(&priv->chip, flags);
309}
310
311static void grgpio_irq_domain_remove(void *data)
312{
313	struct irq_domain *domain = data;
314
315	irq_domain_remove(domain);
316}
317
318static const struct irq_domain_ops grgpio_irq_domain_ops = {
319	.map	= grgpio_irq_map,
320	.unmap	= grgpio_irq_unmap,
321};
322
323/* ------------------------------------------------------------ */
324
325static int grgpio_probe(struct platform_device *ofdev)
326{
327	struct device_node *np = ofdev->dev.of_node;
328	struct gpio_generic_chip_config config;
329	struct device *dev = &ofdev->dev;
330	void  __iomem *regs;
331	struct gpio_chip *gc;
332	struct grgpio_priv *priv;
333	int err;
334	u32 prop;
335	s32 *irqmap;
336	int size;
337	int i;
338
339	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
340	if (!priv)
341		return -ENOMEM;
342
343	regs = devm_platform_ioremap_resource(ofdev, 0);
344	if (IS_ERR(regs))
345		return PTR_ERR(regs);
346
347	config = (struct gpio_generic_chip_config) {
348		.dev = dev,
349		.sz = 4,
350		.dat = regs + GRGPIO_DATA,
351		.set = regs + GRGPIO_OUTPUT,
352		.dirout = regs + GRGPIO_DIR,
353		.flags = GPIO_GENERIC_BIG_ENDIAN_BYTE_ORDER,
354	};
355
356	gc = &priv->chip.gc;
357	err = gpio_generic_chip_init(&priv->chip, &config);
358	if (err) {
359		dev_err(dev, "failed to initialize the generic GPIO chip\n");
360		return err;
361	}
362
363	priv->regs = regs;
364	priv->imask = gpio_generic_read_reg(&priv->chip, regs + GRGPIO_IMASK);
365	priv->dev = dev;
366
367	gc->owner = THIS_MODULE;
368	gc->to_irq = grgpio_to_irq;
369	gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
370	if (!gc->label)
371		return -ENOMEM;
372
373	gc->base = -1;
374
375	err = of_property_read_u32(np, "nbits", &prop);
376	if (err || prop <= 0 || prop > GRGPIO_MAX_NGPIO) {
377		gc->ngpio = GRGPIO_MAX_NGPIO;
378		dev_dbg(dev, "No or invalid nbits property: assume %d\n",
379			gc->ngpio);
380	} else {
381		gc->ngpio = prop;
382	}
383
384	/*
385	 * The irqmap contains the index values indicating which underlying irq,
386	 * if anyone, is connected to that line
387	 */
388	irqmap = (s32 *)of_get_property(np, "irqmap", &size);
389	if (irqmap) {
390		if (size < gc->ngpio) {
391			dev_err(dev,
392				"irqmap shorter than ngpio (%d < %d)\n",
393				size, gc->ngpio);
394			return -EINVAL;
395		}
396
397		priv->domain = irq_domain_create_linear(dev_fwnode(&ofdev->dev), gc->ngpio,
398							&grgpio_irq_domain_ops, priv);
399		if (!priv->domain) {
400			dev_err(dev, "Could not add irq domain\n");
401			return -EINVAL;
402		}
403
404		err = devm_add_action_or_reset(dev, grgpio_irq_domain_remove,
405					       priv->domain);
406		if (err)
407			return err;
408
409		for (i = 0; i < gc->ngpio; i++) {
410			struct grgpio_lirq *lirq;
411			int ret;
412
413			lirq = &priv->lirqs[i];
414			lirq->index = irqmap[i];
415
416			if (lirq->index < 0)
417				continue;
418
419			ret = platform_get_irq(ofdev, lirq->index);
420			if (ret <= 0) {
421				/*
422				 * Continue without irq functionality for that
423				 * gpio line
424				 */
425				continue;
426			}
427			priv->uirqs[lirq->index].uirq = ret;
428			atomic_set(&priv->uirqs[lirq->index].refcnt, 0);
429		}
430	}
431
432	err = devm_gpiochip_add_data(dev, gc, priv);
433	if (err) {
434		dev_err(dev, "Could not add gpiochip\n");
435		return err;
436	}
437
438	dev_info(dev, "regs=0x%p, base=%d, ngpio=%d, irqs=%s\n",
439		 priv->regs, gc->base, gc->ngpio, str_on_off(priv->domain));
440
441	return 0;
442}
443
444static const struct of_device_id grgpio_match[] = {
445	{.name = "GAISLER_GPIO"},
446	{.name = "01_01a"},
447	{},
448};
449
450MODULE_DEVICE_TABLE(of, grgpio_match);
451
452static struct platform_driver grgpio_driver = {
453	.driver = {
454		.name = "grgpio",
455		.of_match_table = grgpio_match,
456	},
457	.probe = grgpio_probe,
458};
459module_platform_driver(grgpio_driver);
460
461MODULE_AUTHOR("Aeroflex Gaisler AB.");
462MODULE_DESCRIPTION("Driver for Aeroflex Gaisler GRGPIO");
463MODULE_LICENSE("GPL");
~/ Read-only file preview.