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(virq, bus); 18 irq_set_chip(virq, &bus->irq_chip); 19 irq_set_nested_thread(virq, 1); 20 irq_set_noprobe(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(bus->dev); 33 34 bus->domain = irq_domain_create_linear(fwnode, SDW_MAX_DEVICES, 35 &sdw_domain_ops, 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(bus->domain); 47 } 48 49 void sdw_irq_create_mapping(struct sdw_slave *slave) 50 { 51 slave->irq = irq_create_mapping(slave->bus->domain, 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(irq_find_mapping(slave->bus->domain, slave->dev_num)); 59 } 60