/** * struct sg204x_msi_chipdata - chip data for the SG204x MSI IRQ controller * @reg_clr: clear reg, see TRM, 10.1.33, GP_INTR0_CLR * @doorbell_addr: see TRM, 10.1.32, GP_INTR0_SET * @irq_first: First vectors number that MSIs starts * @num_irqs: Number of vectors for MSIs * @msi_map: mapping for allocated MSI vectors. * @msi_map_lock: Lock for msi_map * @chip_info: chip specific infomations
*/ struct sg204x_msi_chipdata { void __iomem *reg_clr;
phys_addr_t doorbell_addr;
u32 irq_first;
u32 num_irqs;
unsignedlong *msi_map; struct mutex msi_map_lock;
conststruct sg204x_msi_chip_info *chip_info;
};
staticint sg204x_msi_allocate_hwirq(struct sg204x_msi_chipdata *data, int num_req)
{ int first;
guard(mutex)(&data->msi_map_lock);
first = bitmap_find_free_region(data->msi_map, data->num_irqs,
get_count_order(num_req)); return first >= 0 ? first : -ENOSPC;
}
staticvoid sg204x_msi_free_hwirq(struct sg204x_msi_chipdata *data, int hwirq, int num_req)
{
guard(mutex)(&data->msi_map_lock);
bitmap_release_region(data->msi_map, hwirq, get_count_order(num_req));
}
data = devm_kzalloc(dev, sizeof(struct sg204x_msi_chipdata), GFP_KERNEL); if (!data) return -ENOMEM;
data->chip_info = device_get_match_data(&pdev->dev); if (!data->chip_info) {
dev_err(&pdev->dev, "Failed to get irqchip\n"); return -EINVAL;
}
data->reg_clr = devm_platform_ioremap_resource_byname(pdev, "clr"); if (IS_ERR(data->reg_clr)) {
dev_err(dev, "Failed to map clear register\n"); return PTR_ERR(data->reg_clr);
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "doorbell"); if (!res) {
dev_err(dev, "Failed get resource from set\n"); return -EINVAL;
}
data->doorbell_addr = res->start;
ret = fwnode_property_get_reference_args(dev_fwnode(dev), "msi-ranges", "#interrupt-cells", 0, 0, &args); if (ret) {
dev_err(dev, "Unable to parse MSI vec base\n"); return ret;
}
fwnode_handle_put(args.fwnode);
ret = fwnode_property_get_reference_args(dev_fwnode(dev), "msi-ranges", NULL,
args.nargs + 1, 0, &args); if (ret) {
dev_err(dev, "Unable to parse MSI vec number\n"); return ret;
}
plic_domain = irq_find_matching_fwnode(args.fwnode, DOMAIN_BUS_ANY);
fwnode_handle_put(args.fwnode); if (!plic_domain) {
pr_err("Failed to find the PLIC domain\n"); return -ENXIO;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.