| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- // SPDX-License-Identifier: GPL-2.0
- // Copyright (C) 2023 Cirrus Logic, Inc. and
- // Cirrus Logic International Semiconductor Ltd.
- #include <linux/device.h>
- #include <linux/fwnode.h>
- #include <linux/irq.h>
- #include <linux/irqdomain.h>
- #include <linux/soundwire/sdw.h>
- #include "irq.h"
- static int sdw_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
- {
- struct sdw_bus *bus = h->host_data;
- irq_set_chip_data(virq, bus);
- irq_set_chip(virq, &bus->irq_chip);
- irq_set_nested_thread(virq, 1);
- irq_set_noprobe(virq);
- return 0;
- }
- static const struct irq_domain_ops sdw_domain_ops = {
- .map = sdw_irq_map,
- };
- int sdw_irq_create(struct sdw_bus *bus,
- struct fwnode_handle *fwnode)
- {
- bus->irq_chip.name = dev_name(bus->dev);
- bus->domain = irq_domain_create_linear(fwnode, SDW_FW_MAX_DEVICES,
- &sdw_domain_ops, bus);
- if (!bus->domain) {
- dev_err(bus->dev, "Failed to add IRQ domain\n");
- return -EINVAL;
- }
- return 0;
- }
- void sdw_irq_delete(struct sdw_bus *bus)
- {
- irq_domain_remove(bus->domain);
- }
- static void sdw_irq_dispose_mapping(void *data)
- {
- struct sdw_slave *slave = data;
- irq_dispose_mapping(slave->irq);
- }
- void sdw_irq_create_mapping(struct sdw_slave *slave)
- {
- slave->irq = irq_create_mapping(slave->bus->domain, slave->index);
- if (!slave->irq)
- dev_warn(&slave->dev, "Failed to map IRQ\n");
- devm_add_action_or_reset(&slave->dev, sdw_irq_dispose_mapping, slave);
- }
|