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