1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2024 NXP 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/interrupt.h> 8 #include <linux/irq.h> 9 #include <linux/irqchip/chained_irq.h> 10 #include <linux/irqdomain.h> 11 #include <linux/of.h> 12 #include <linux/of_irq.h> 13 #include <linux/platform_device.h> 14 #include <linux/pm_runtime.h> 15 #include <linux/regmap.h> 16 17 #define USERINTERRUPTMASK(n) (0x8 + 4 * (n)) 18 #define INTERRUPTENABLE(n) (0x10 + 4 * (n)) 19 #define INTERRUPTPRESET(n) (0x18 + 4 * (n)) 20 #define INTERRUPTCLEAR(n) (0x20 + 4 * (n)) 21 #define INTERRUPTSTATUS(n) (0x28 + 4 * (n)) 22 #define USERINTERRUPTENABLE(n) (0x40 + 4 * (n)) 23 #define USERINTERRUPTPRESET(n) (0x48 + 4 * (n)) 24 #define USERINTERRUPTCLEAR(n) (0x50 + 4 * (n)) 25 #define USERINTERRUPTSTATUS(n) (0x58 + 4 * (n)) 26 27 #define IRQ_COUNT 49 28 #define IRQ_RESERVED 35 29 #define REG_NUM 2 30 31 struct dc_ic_data { 32 struct regmap *regs; 33 struct clk *clk_axi; 34 int irq[IRQ_COUNT]; 35 struct irq_domain *domain; 36 }; 37 38 struct dc_ic_entry { 39 struct dc_ic_data *data; 40 int irq; 41 }; 42 43 static const struct regmap_range dc_ic_regmap_write_ranges[] = { 44 regmap_reg_range(USERINTERRUPTMASK(0), INTERRUPTCLEAR(1)), 45 regmap_reg_range(USERINTERRUPTENABLE(0), USERINTERRUPTCLEAR(1)), 46 }; 47 48 static const struct regmap_access_table dc_ic_regmap_write_table = { 49 .yes_ranges = dc_ic_regmap_write_ranges, 50 .n_yes_ranges = ARRAY_SIZE(dc_ic_regmap_write_ranges), 51 }; 52 53 static const struct regmap_range dc_ic_regmap_read_ranges[] = { 54 regmap_reg_range(USERINTERRUPTMASK(0), INTERRUPTENABLE(1)), 55 regmap_reg_range(INTERRUPTSTATUS(0), INTERRUPTSTATUS(1)), 56 regmap_reg_range(USERINTERRUPTENABLE(0), USERINTERRUPTENABLE(1)), 57 regmap_reg_range(USERINTERRUPTSTATUS(0), USERINTERRUPTSTATUS(1)), 58 }; 59 60 static const struct regmap_access_table dc_ic_regmap_read_table = { 61 .yes_ranges = dc_ic_regmap_read_ranges, 62 .n_yes_ranges = ARRAY_SIZE(dc_ic_regmap_read_ranges), 63 }; 64 65 static const struct regmap_range dc_ic_regmap_volatile_ranges[] = { 66 regmap_reg_range(INTERRUPTPRESET(0), INTERRUPTCLEAR(1)), 67 regmap_reg_range(USERINTERRUPTPRESET(0), USERINTERRUPTCLEAR(1)), 68 }; 69 70 static const struct regmap_access_table dc_ic_regmap_volatile_table = { 71 .yes_ranges = dc_ic_regmap_volatile_ranges, 72 .n_yes_ranges = ARRAY_SIZE(dc_ic_regmap_volatile_ranges), 73 }; 74 75 static const struct regmap_config dc_ic_regmap_config = { 76 .reg_bits = 32, 77 .reg_stride = 4, 78 .val_bits = 32, 79 .fast_io = true, 80 .wr_table = &dc_ic_regmap_write_table, 81 .rd_table = &dc_ic_regmap_read_table, 82 .volatile_table = &dc_ic_regmap_volatile_table, 83 .max_register = USERINTERRUPTSTATUS(1), 84 }; 85 86 static void dc_ic_irq_handler(struct irq_desc *desc) 87 { 88 struct dc_ic_entry *entry = irq_desc_get_handler_data(desc); 89 struct dc_ic_data *data = entry->data; 90 unsigned int status, enable; 91 unsigned int virq; 92 93 chained_irq_enter(irq_desc_get_chip(desc), desc); 94 95 regmap_read(data->regs, USERINTERRUPTSTATUS(entry->irq / 32), &status); 96 regmap_read(data->regs, USERINTERRUPTENABLE(entry->irq / 32), &enable); 97 98 status &= enable; 99 100 if (status & BIT(entry->irq % 32)) { 101 virq = irq_find_mapping(data->domain, entry->irq); 102 if (virq) 103 generic_handle_irq(virq); 104 } 105 106 chained_irq_exit(irq_desc_get_chip(desc), desc); 107 } 108 109 static const unsigned long unused_irq[REG_NUM] = {0x00000000, 0xfffe0008}; 110 111 static int dc_ic_probe(struct platform_device *pdev) 112 { 113 struct device *dev = &pdev->dev; 114 struct irq_chip_generic *gc; 115 struct dc_ic_entry *entry; 116 struct irq_chip_type *ct; 117 struct dc_ic_data *data; 118 void __iomem *base; 119 int i, ret; 120 121 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 122 if (!data) 123 return -ENOMEM; 124 125 entry = devm_kcalloc(dev, IRQ_COUNT, sizeof(*entry), GFP_KERNEL); 126 if (!entry) 127 return -ENOMEM; 128 129 base = devm_platform_ioremap_resource(pdev, 0); 130 if (IS_ERR(base)) { 131 dev_err(dev, "failed to initialize reg\n"); 132 return PTR_ERR(base); 133 } 134 135 data->regs = devm_regmap_init_mmio(dev, base, &dc_ic_regmap_config); 136 if (IS_ERR(data->regs)) 137 return PTR_ERR(data->regs); 138 139 data->clk_axi = devm_clk_get(dev, NULL); 140 if (IS_ERR(data->clk_axi)) 141 return dev_err_probe(dev, PTR_ERR(data->clk_axi), 142 "failed to get AXI clock\n"); 143 144 for (i = 0; i < IRQ_COUNT; i++) { 145 /* skip the reserved IRQ */ 146 if (i == IRQ_RESERVED) 147 continue; 148 149 ret = platform_get_irq(pdev, i); 150 if (ret < 0) 151 return ret; 152 } 153 154 dev_set_drvdata(dev, data); 155 156 ret = devm_pm_runtime_enable(dev); 157 if (ret) 158 return ret; 159 160 ret = pm_runtime_resume_and_get(dev); 161 if (ret < 0) { 162 dev_err(dev, "failed to get runtime PM sync: %d\n", ret); 163 return ret; 164 } 165 166 for (i = 0; i < REG_NUM; i++) { 167 /* mask and clear all interrupts */ 168 regmap_write(data->regs, USERINTERRUPTENABLE(i), 0x0); 169 regmap_write(data->regs, INTERRUPTENABLE(i), 0x0); 170 regmap_write(data->regs, USERINTERRUPTCLEAR(i), 0xffffffff); 171 regmap_write(data->regs, INTERRUPTCLEAR(i), 0xffffffff); 172 173 /* set all interrupts to user mode */ 174 regmap_write(data->regs, USERINTERRUPTMASK(i), 0xffffffff); 175 } 176 177 data->domain = irq_domain_add_linear(dev->of_node, IRQ_COUNT, 178 &irq_generic_chip_ops, data); 179 if (!data->domain) { 180 dev_err(dev, "failed to create IRQ domain\n"); 181 pm_runtime_put(dev); 182 return -ENOMEM; 183 } 184 irq_domain_set_pm_device(data->domain, dev); 185 186 ret = irq_alloc_domain_generic_chips(data->domain, 32, 1, "DC", 187 handle_level_irq, 0, 0, 0); 188 if (ret) { 189 dev_err(dev, "failed to alloc generic IRQ chips: %d\n", ret); 190 irq_domain_remove(data->domain); 191 pm_runtime_put(dev); 192 return ret; 193 } 194 195 for (i = 0; i < IRQ_COUNT; i += 32) { 196 gc = irq_get_domain_generic_chip(data->domain, i); 197 gc->reg_base = base; 198 gc->unused = unused_irq[i / 32]; 199 ct = gc->chip_types; 200 ct->chip.irq_ack = irq_gc_ack_set_bit; 201 ct->chip.irq_mask = irq_gc_mask_clr_bit; 202 ct->chip.irq_unmask = irq_gc_mask_set_bit; 203 ct->regs.ack = USERINTERRUPTCLEAR(i / 32); 204 ct->regs.mask = USERINTERRUPTENABLE(i / 32); 205 } 206 207 for (i = 0; i < IRQ_COUNT; i++) { 208 /* skip the reserved IRQ */ 209 if (i == IRQ_RESERVED) 210 continue; 211 212 data->irq[i] = irq_of_parse_and_map(dev->of_node, i); 213 214 entry[i].data = data; 215 entry[i].irq = i; 216 217 irq_set_chained_handler_and_data(data->irq[i], 218 dc_ic_irq_handler, &entry[i]); 219 } 220 221 return 0; 222 } 223 224 static void dc_ic_remove(struct platform_device *pdev) 225 { 226 struct dc_ic_data *data = dev_get_drvdata(&pdev->dev); 227 int i; 228 229 for (i = 0; i < IRQ_COUNT; i++) { 230 if (i == IRQ_RESERVED) 231 continue; 232 233 irq_set_chained_handler_and_data(data->irq[i], NULL, NULL); 234 } 235 236 irq_domain_remove(data->domain); 237 238 pm_runtime_put_sync(&pdev->dev); 239 } 240 241 static int dc_ic_runtime_suspend(struct device *dev) 242 { 243 struct dc_ic_data *data = dev_get_drvdata(dev); 244 245 clk_disable_unprepare(data->clk_axi); 246 247 return 0; 248 } 249 250 static int dc_ic_runtime_resume(struct device *dev) 251 { 252 struct dc_ic_data *data = dev_get_drvdata(dev); 253 int ret; 254 255 ret = clk_prepare_enable(data->clk_axi); 256 if (ret) 257 dev_err(dev, "failed to enable AXI clock: %d\n", ret); 258 259 return ret; 260 } 261 262 static const struct dev_pm_ops dc_ic_pm_ops = { 263 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 264 pm_runtime_force_resume) 265 RUNTIME_PM_OPS(dc_ic_runtime_suspend, dc_ic_runtime_resume, NULL) 266 }; 267 268 static const struct of_device_id dc_ic_dt_ids[] = { 269 { .compatible = "fsl,imx8qxp-dc-intc", }, 270 { /* sentinel */ } 271 }; 272 273 struct platform_driver dc_ic_driver = { 274 .probe = dc_ic_probe, 275 .remove = dc_ic_remove, 276 .driver = { 277 .name = "imx8-dc-intc", 278 .suppress_bind_attrs = true, 279 .of_match_table = dc_ic_dt_ids, 280 .pm = pm_sleep_ptr(&dc_ic_pm_ops), 281 }, 282 }; 283