xref: /openbmc/linux/drivers/soundwire/irq.c (revision 17325a2137ebf015fbb988a6db1a3513ef446d54)
1*3b6c4a11SCharles Keepax // SPDX-License-Identifier: GPL-2.0
2*3b6c4a11SCharles Keepax // Copyright (C) 2023 Cirrus Logic, Inc. and
3*3b6c4a11SCharles Keepax //                    Cirrus Logic International Semiconductor Ltd.
4*3b6c4a11SCharles Keepax 
5*3b6c4a11SCharles Keepax #include <linux/device.h>
6*3b6c4a11SCharles Keepax #include <linux/fwnode.h>
7*3b6c4a11SCharles Keepax #include <linux/irq.h>
8*3b6c4a11SCharles Keepax #include <linux/irqdomain.h>
9*3b6c4a11SCharles Keepax #include <linux/soundwire/sdw.h>
10*3b6c4a11SCharles Keepax #include "irq.h"
11*3b6c4a11SCharles Keepax 
sdw_irq_map(struct irq_domain * h,unsigned int virq,irq_hw_number_t hw)12*3b6c4a11SCharles Keepax static int sdw_irq_map(struct irq_domain *h, unsigned int virq,
13*3b6c4a11SCharles Keepax 		       irq_hw_number_t hw)
14*3b6c4a11SCharles Keepax {
15*3b6c4a11SCharles Keepax 	struct sdw_bus *bus = h->host_data;
16*3b6c4a11SCharles Keepax 
17*3b6c4a11SCharles Keepax 	irq_set_chip_data(virq, bus);
18*3b6c4a11SCharles Keepax 	irq_set_chip(virq, &bus->irq_chip);
19*3b6c4a11SCharles Keepax 	irq_set_nested_thread(virq, 1);
20*3b6c4a11SCharles Keepax 	irq_set_noprobe(virq);
21*3b6c4a11SCharles Keepax 
22*3b6c4a11SCharles Keepax 	return 0;
23*3b6c4a11SCharles Keepax }
24*3b6c4a11SCharles Keepax 
25*3b6c4a11SCharles Keepax static const struct irq_domain_ops sdw_domain_ops = {
26*3b6c4a11SCharles Keepax 	.map	= sdw_irq_map,
27*3b6c4a11SCharles Keepax };
28*3b6c4a11SCharles Keepax 
sdw_irq_create(struct sdw_bus * bus,struct fwnode_handle * fwnode)29*3b6c4a11SCharles Keepax int sdw_irq_create(struct sdw_bus *bus,
30*3b6c4a11SCharles Keepax 		   struct fwnode_handle *fwnode)
31*3b6c4a11SCharles Keepax {
32*3b6c4a11SCharles Keepax 	bus->irq_chip.name = dev_name(bus->dev);
33*3b6c4a11SCharles Keepax 
34*3b6c4a11SCharles Keepax 	bus->domain = irq_domain_create_linear(fwnode, SDW_MAX_DEVICES,
35*3b6c4a11SCharles Keepax 					       &sdw_domain_ops, bus);
36*3b6c4a11SCharles Keepax 	if (!bus->domain) {
37*3b6c4a11SCharles Keepax 		dev_err(bus->dev, "Failed to add IRQ domain\n");
38*3b6c4a11SCharles Keepax 		return -EINVAL;
39*3b6c4a11SCharles Keepax 	}
40*3b6c4a11SCharles Keepax 
41*3b6c4a11SCharles Keepax 	return 0;
42*3b6c4a11SCharles Keepax }
43*3b6c4a11SCharles Keepax 
sdw_irq_delete(struct sdw_bus * bus)44*3b6c4a11SCharles Keepax void sdw_irq_delete(struct sdw_bus *bus)
45*3b6c4a11SCharles Keepax {
46*3b6c4a11SCharles Keepax 	irq_domain_remove(bus->domain);
47*3b6c4a11SCharles Keepax }
48*3b6c4a11SCharles Keepax 
sdw_irq_create_mapping(struct sdw_slave * slave)49*3b6c4a11SCharles Keepax void sdw_irq_create_mapping(struct sdw_slave *slave)
50*3b6c4a11SCharles Keepax {
51*3b6c4a11SCharles Keepax 	slave->irq = irq_create_mapping(slave->bus->domain, slave->dev_num);
52*3b6c4a11SCharles Keepax 	if (!slave->irq)
53*3b6c4a11SCharles Keepax 		dev_warn(&slave->dev, "Failed to map IRQ\n");
54*3b6c4a11SCharles Keepax }
55*3b6c4a11SCharles Keepax 
sdw_irq_dispose_mapping(struct sdw_slave * slave)56*3b6c4a11SCharles Keepax void sdw_irq_dispose_mapping(struct sdw_slave *slave)
57*3b6c4a11SCharles Keepax {
58*3b6c4a11SCharles Keepax 	irq_dispose_mapping(irq_find_mapping(slave->bus->domain, slave->dev_num));
59*3b6c4a11SCharles Keepax }
60