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