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 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 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 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 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 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