1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 Western Digital Corporation or its affiliates. 4 * Copyright (C) 2022 Ventana Micro Systems Inc. 5 */ 6 7 #include <linux/acpi.h> 8 #include <linux/bitfield.h> 9 #include <linux/irqchip/riscv-aplic.h> 10 #include <linux/irqchip/riscv-imsic.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_irq.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_domain.h> 16 #include <linux/pm_runtime.h> 17 #include <linux/printk.h> 18 #include <linux/syscore_ops.h> 19 20 #include "irq-riscv-aplic-main.h" 21 22 static LIST_HEAD(aplics); 23 24 static void aplic_restore_states(struct aplic_priv *priv) 25 { 26 struct aplic_saved_regs *saved_regs = &priv->saved_hw_regs; 27 struct aplic_src_ctrl *srcs; 28 void __iomem *regs; 29 u32 nr_irqs, i; 30 31 regs = priv->regs; 32 writel(saved_regs->domaincfg, regs + APLIC_DOMAINCFG); 33 #ifdef CONFIG_RISCV_M_MODE 34 writel(saved_regs->msiaddr, regs + APLIC_xMSICFGADDR); 35 writel(saved_regs->msiaddrh, regs + APLIC_xMSICFGADDRH); 36 #endif 37 /* 38 * The sourcecfg[i] has to be restored prior to the target[i], interrupt-pending and 39 * interrupt-enable bits. The AIA specification states that "Whenever interrupt source i is 40 * inactive in an interrupt domain, the corresponding interrupt-pending and interrupt-enable 41 * bits within the domain are read-only zeros, and register target[i] is also read-only 42 * zero." 43 */ 44 nr_irqs = priv->nr_irqs; 45 for (i = 0; i < nr_irqs; i++) { 46 srcs = &priv->saved_hw_regs.srcs[i]; 47 writel(srcs->sourcecfg, regs + APLIC_SOURCECFG_BASE + i * sizeof(u32)); 48 writel(srcs->target, regs + APLIC_TARGET_BASE + i * sizeof(u32)); 49 } 50 51 for (i = 0; i <= nr_irqs; i += 32) { 52 srcs = &priv->saved_hw_regs.srcs[i]; 53 writel(-1U, regs + APLIC_CLRIE_BASE + (i / 32) * sizeof(u32)); 54 writel(srcs->ie, regs + APLIC_SETIE_BASE + (i / 32) * sizeof(u32)); 55 56 /* Re-trigger the interrupts if it forwards interrupts to target harts by MSIs */ 57 if (!priv->nr_idcs) 58 writel(readl(regs + APLIC_CLRIP_BASE + (i / 32) * sizeof(u32)), 59 regs + APLIC_SETIP_BASE + (i / 32) * sizeof(u32)); 60 } 61 62 if (priv->nr_idcs) 63 aplic_direct_restore_states(priv); 64 } 65 66 static void aplic_save_states(struct aplic_priv *priv) 67 { 68 struct aplic_src_ctrl *srcs; 69 void __iomem *regs; 70 u32 i, nr_irqs; 71 72 regs = priv->regs; 73 nr_irqs = priv->nr_irqs; 74 /* The valid interrupt source IDs range from 1 to N, where N is priv->nr_irqs */ 75 for (i = 0; i < nr_irqs; i++) { 76 srcs = &priv->saved_hw_regs.srcs[i]; 77 srcs->target = readl(regs + APLIC_TARGET_BASE + i * sizeof(u32)); 78 79 if (i % 32) 80 continue; 81 82 srcs->ie = readl(regs + APLIC_SETIE_BASE + (i / 32) * sizeof(u32)); 83 } 84 85 /* Save the nr_irqs bit if needed */ 86 if (!(nr_irqs % 32)) { 87 srcs = &priv->saved_hw_regs.srcs[nr_irqs]; 88 srcs->ie = readl(regs + APLIC_SETIE_BASE + (nr_irqs / 32) * sizeof(u32)); 89 } 90 } 91 92 static int aplic_syscore_suspend(void *data) 93 { 94 struct aplic_priv *priv; 95 96 list_for_each_entry(priv, &aplics, head) 97 aplic_save_states(priv); 98 99 return 0; 100 } 101 102 static void aplic_syscore_resume(void *data) 103 { 104 struct aplic_priv *priv; 105 106 list_for_each_entry(priv, &aplics, head) 107 aplic_restore_states(priv); 108 } 109 110 static struct syscore_ops aplic_syscore_ops = { 111 .suspend = aplic_syscore_suspend, 112 .resume = aplic_syscore_resume, 113 }; 114 115 static struct syscore aplic_syscore = { 116 .ops = &aplic_syscore_ops, 117 }; 118 119 static bool aplic_syscore_registered __ro_after_init; 120 121 static void aplic_syscore_init(void) 122 { 123 if (!aplic_syscore_registered) { 124 register_syscore(&aplic_syscore); 125 aplic_syscore_registered = true; 126 } 127 } 128 129 static int aplic_pm_notifier(struct notifier_block *nb, unsigned long action, void *data) 130 { 131 struct aplic_priv *priv = container_of(nb, struct aplic_priv, genpd_nb); 132 133 switch (action) { 134 case GENPD_NOTIFY_PRE_OFF: 135 aplic_save_states(priv); 136 break; 137 case GENPD_NOTIFY_ON: 138 aplic_restore_states(priv); 139 break; 140 default: 141 break; 142 } 143 144 return 0; 145 } 146 147 static void aplic_pm_remove(void *data) 148 { 149 struct aplic_priv *priv = data; 150 struct device *dev = priv->dev; 151 152 list_del(&priv->head); 153 if (dev->pm_domain) 154 dev_pm_genpd_remove_notifier(dev); 155 } 156 157 static int aplic_pm_add(struct device *dev, struct aplic_priv *priv) 158 { 159 struct aplic_src_ctrl *srcs; 160 int ret; 161 162 srcs = devm_kzalloc(dev, (priv->nr_irqs + 1) * sizeof(*srcs), GFP_KERNEL); 163 if (!srcs) 164 return -ENOMEM; 165 166 priv->saved_hw_regs.srcs = srcs; 167 list_add(&priv->head, &aplics); 168 if (dev->pm_domain) { 169 priv->genpd_nb.notifier_call = aplic_pm_notifier; 170 ret = dev_pm_genpd_add_notifier(dev, &priv->genpd_nb); 171 if (ret) 172 goto remove_head; 173 174 ret = devm_pm_runtime_enable(dev); 175 if (ret) 176 goto remove_notifier; 177 } 178 179 return devm_add_action_or_reset(dev, aplic_pm_remove, priv); 180 181 remove_notifier: 182 dev_pm_genpd_remove_notifier(dev); 183 remove_head: 184 list_del(&priv->head); 185 return ret; 186 } 187 188 void aplic_irq_unmask(struct irq_data *d) 189 { 190 struct aplic_priv *priv = irq_data_get_irq_chip_data(d); 191 192 writel(d->hwirq, priv->regs + APLIC_SETIENUM); 193 } 194 195 void aplic_irq_mask(struct irq_data *d) 196 { 197 struct aplic_priv *priv = irq_data_get_irq_chip_data(d); 198 199 writel(d->hwirq, priv->regs + APLIC_CLRIENUM); 200 } 201 202 int aplic_irq_set_type(struct irq_data *d, unsigned int type) 203 { 204 struct aplic_priv *priv = irq_data_get_irq_chip_data(d); 205 void __iomem *sourcecfg; 206 u32 val = 0; 207 208 switch (type) { 209 case IRQ_TYPE_NONE: 210 val = APLIC_SOURCECFG_SM_INACTIVE; 211 break; 212 case IRQ_TYPE_LEVEL_LOW: 213 val = APLIC_SOURCECFG_SM_LEVEL_LOW; 214 break; 215 case IRQ_TYPE_LEVEL_HIGH: 216 val = APLIC_SOURCECFG_SM_LEVEL_HIGH; 217 break; 218 case IRQ_TYPE_EDGE_FALLING: 219 val = APLIC_SOURCECFG_SM_EDGE_FALL; 220 break; 221 case IRQ_TYPE_EDGE_RISING: 222 val = APLIC_SOURCECFG_SM_EDGE_RISE; 223 break; 224 default: 225 return -EINVAL; 226 } 227 228 sourcecfg = priv->regs + APLIC_SOURCECFG_BASE; 229 sourcecfg += (d->hwirq - 1) * sizeof(u32); 230 writel(val, sourcecfg); 231 232 priv->saved_hw_regs.srcs[d->hwirq - 1].sourcecfg = val; 233 234 return 0; 235 } 236 237 int aplic_irqdomain_translate(struct irq_fwspec *fwspec, u32 gsi_base, 238 unsigned long *hwirq, unsigned int *type) 239 { 240 if (WARN_ON(fwspec->param_count < 2)) 241 return -EINVAL; 242 if (WARN_ON(!fwspec->param[0])) 243 return -EINVAL; 244 245 /* For DT, gsi_base is always zero. */ 246 *hwirq = fwspec->param[0] - gsi_base; 247 *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; 248 249 WARN_ON(*type == IRQ_TYPE_NONE); 250 251 return 0; 252 } 253 254 void aplic_init_hw_global(struct aplic_priv *priv, bool msi_mode) 255 { 256 struct aplic_saved_regs *saved_regs = &priv->saved_hw_regs; 257 u32 val; 258 #ifdef CONFIG_RISCV_M_MODE 259 u32 valh; 260 261 if (msi_mode) { 262 val = lower_32_bits(priv->msicfg.base_ppn); 263 valh = FIELD_PREP(APLIC_xMSICFGADDRH_BAPPN, upper_32_bits(priv->msicfg.base_ppn)); 264 valh |= FIELD_PREP(APLIC_xMSICFGADDRH_LHXW, priv->msicfg.lhxw); 265 valh |= FIELD_PREP(APLIC_xMSICFGADDRH_HHXW, priv->msicfg.hhxw); 266 valh |= FIELD_PREP(APLIC_xMSICFGADDRH_LHXS, priv->msicfg.lhxs); 267 valh |= FIELD_PREP(APLIC_xMSICFGADDRH_HHXS, priv->msicfg.hhxs); 268 writel(val, priv->regs + APLIC_xMSICFGADDR); 269 writel(valh, priv->regs + APLIC_xMSICFGADDRH); 270 saved_regs->msiaddr = val; 271 saved_regs->msiaddrh = valh; 272 } 273 #endif 274 275 /* Setup APLIC domaincfg register */ 276 val = readl(priv->regs + APLIC_DOMAINCFG); 277 val |= APLIC_DOMAINCFG_IE; 278 if (msi_mode) 279 val |= APLIC_DOMAINCFG_DM; 280 writel(val, priv->regs + APLIC_DOMAINCFG); 281 if (readl(priv->regs + APLIC_DOMAINCFG) != val) 282 dev_warn(priv->dev, "unable to write 0x%x in domaincfg\n", val); 283 284 saved_regs->domaincfg = val; 285 } 286 287 static void aplic_init_hw_irqs(struct aplic_priv *priv) 288 { 289 int i; 290 291 /* Disable all interrupts */ 292 for (i = 0; i <= priv->nr_irqs; i += 32) 293 writel(-1U, priv->regs + APLIC_CLRIE_BASE + (i / 32) * sizeof(u32)); 294 295 /* Set interrupt type and default priority for all interrupts */ 296 for (i = 1; i <= priv->nr_irqs; i++) { 297 writel(0, priv->regs + APLIC_SOURCECFG_BASE + (i - 1) * sizeof(u32)); 298 writel(APLIC_DEFAULT_PRIORITY, 299 priv->regs + APLIC_TARGET_BASE + (i - 1) * sizeof(u32)); 300 } 301 302 /* Clear APLIC domaincfg */ 303 writel(0, priv->regs + APLIC_DOMAINCFG); 304 } 305 306 #ifdef CONFIG_ACPI 307 static const struct acpi_device_id aplic_acpi_match[] = { 308 { "RSCV0002", 0 }, 309 {} 310 }; 311 MODULE_DEVICE_TABLE(acpi, aplic_acpi_match); 312 313 #endif 314 315 int aplic_setup_priv(struct aplic_priv *priv, struct device *dev, void __iomem *regs) 316 { 317 struct device_node *np = to_of_node(dev->fwnode); 318 struct of_phandle_args parent; 319 int rc; 320 321 /* Save device pointer and register base */ 322 priv->dev = dev; 323 priv->regs = regs; 324 325 if (np) { 326 /* Find out number of interrupt sources */ 327 rc = of_property_read_u32(np, "riscv,num-sources", &priv->nr_irqs); 328 if (rc) { 329 dev_err(dev, "failed to get number of interrupt sources\n"); 330 return rc; 331 } 332 333 /* 334 * Find out number of IDCs based on parent interrupts 335 * 336 * If "msi-parent" property is present then we ignore the 337 * APLIC IDCs which forces the APLIC driver to use MSI mode. 338 */ 339 if (!of_property_present(np, "msi-parent")) { 340 while (!of_irq_parse_one(np, priv->nr_idcs, &parent)) 341 priv->nr_idcs++; 342 } 343 } else { 344 rc = riscv_acpi_get_gsi_info(dev->fwnode, &priv->gsi_base, &priv->acpi_aplic_id, 345 &priv->nr_irqs, &priv->nr_idcs); 346 if (rc) { 347 dev_err(dev, "failed to find GSI mapping\n"); 348 return rc; 349 } 350 } 351 352 /* Setup initial state APLIC interrupts */ 353 aplic_init_hw_irqs(priv); 354 355 return aplic_pm_add(dev, priv); 356 } 357 358 static int aplic_probe(struct platform_device *pdev) 359 { 360 struct device *dev = &pdev->dev; 361 bool msi_mode = false; 362 void __iomem *regs; 363 int rc; 364 365 /* Map the MMIO registers */ 366 regs = devm_platform_ioremap_resource(pdev, 0); 367 if (IS_ERR(regs)) { 368 dev_err(dev, "failed map MMIO registers\n"); 369 return PTR_ERR(regs); 370 } 371 372 /* 373 * If msi-parent property is present then setup APLIC MSI 374 * mode otherwise setup APLIC direct mode. 375 */ 376 if (is_of_node(dev->fwnode)) 377 msi_mode = of_property_present(to_of_node(dev->fwnode), "msi-parent"); 378 else 379 msi_mode = imsic_acpi_get_fwnode(NULL) ? 1 : 0; 380 381 if (msi_mode) 382 rc = aplic_msi_setup(dev, regs); 383 else 384 rc = aplic_direct_setup(dev, regs); 385 386 if (rc) { 387 dev_err_probe(dev, rc, "failed to setup APLIC in %s mode\n", 388 msi_mode ? "MSI" : "direct"); 389 return rc; 390 } 391 392 aplic_syscore_init(); 393 394 #ifdef CONFIG_ACPI 395 if (!acpi_disabled) 396 acpi_dev_clear_dependencies(ACPI_COMPANION(dev)); 397 #endif 398 399 return 0; 400 } 401 402 static const struct of_device_id aplic_match[] = { 403 { .compatible = "riscv,aplic" }, 404 {} 405 }; 406 407 static struct platform_driver aplic_driver = { 408 .driver = { 409 .name = "riscv-aplic", 410 .of_match_table = aplic_match, 411 .acpi_match_table = ACPI_PTR(aplic_acpi_match), 412 }, 413 .probe = aplic_probe, 414 }; 415 builtin_platform_driver(aplic_driver); 416