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 int aplic_pm_notifier(struct notifier_block *nb, unsigned long action, void *data) 120 { 121 struct aplic_priv *priv = container_of(nb, struct aplic_priv, genpd_nb); 122 123 switch (action) { 124 case GENPD_NOTIFY_PRE_OFF: 125 aplic_save_states(priv); 126 break; 127 case GENPD_NOTIFY_ON: 128 aplic_restore_states(priv); 129 break; 130 default: 131 break; 132 } 133 134 return 0; 135 } 136 137 static void aplic_pm_remove(void *data) 138 { 139 struct aplic_priv *priv = data; 140 struct device *dev = priv->dev; 141 142 list_del(&priv->head); 143 if (dev->pm_domain) 144 dev_pm_genpd_remove_notifier(dev); 145 } 146 147 static int aplic_pm_add(struct device *dev, struct aplic_priv *priv) 148 { 149 struct aplic_src_ctrl *srcs; 150 int ret; 151 152 srcs = devm_kzalloc(dev, (priv->nr_irqs + 1) * sizeof(*srcs), GFP_KERNEL); 153 if (!srcs) 154 return -ENOMEM; 155 156 priv->saved_hw_regs.srcs = srcs; 157 list_add(&priv->head, &aplics); 158 if (dev->pm_domain) { 159 priv->genpd_nb.notifier_call = aplic_pm_notifier; 160 ret = dev_pm_genpd_add_notifier(dev, &priv->genpd_nb); 161 if (ret) 162 goto remove_head; 163 164 ret = devm_pm_runtime_enable(dev); 165 if (ret) 166 goto remove_notifier; 167 } 168 169 return devm_add_action_or_reset(dev, aplic_pm_remove, priv); 170 171 remove_notifier: 172 dev_pm_genpd_remove_notifier(dev); 173 remove_head: 174 list_del(&priv->head); 175 return ret; 176 } 177 178 void aplic_irq_unmask(struct irq_data *d) 179 { 180 struct aplic_priv *priv = irq_data_get_irq_chip_data(d); 181 182 writel(d->hwirq, priv->regs + APLIC_SETIENUM); 183 } 184 185 void aplic_irq_mask(struct irq_data *d) 186 { 187 struct aplic_priv *priv = irq_data_get_irq_chip_data(d); 188 189 writel(d->hwirq, priv->regs + APLIC_CLRIENUM); 190 } 191 192 int aplic_irq_set_type(struct irq_data *d, unsigned int type) 193 { 194 struct aplic_priv *priv = irq_data_get_irq_chip_data(d); 195 void __iomem *sourcecfg; 196 u32 val = 0; 197 198 switch (type) { 199 case IRQ_TYPE_NONE: 200 val = APLIC_SOURCECFG_SM_INACTIVE; 201 break; 202 case IRQ_TYPE_LEVEL_LOW: 203 val = APLIC_SOURCECFG_SM_LEVEL_LOW; 204 break; 205 case IRQ_TYPE_LEVEL_HIGH: 206 val = APLIC_SOURCECFG_SM_LEVEL_HIGH; 207 break; 208 case IRQ_TYPE_EDGE_FALLING: 209 val = APLIC_SOURCECFG_SM_EDGE_FALL; 210 break; 211 case IRQ_TYPE_EDGE_RISING: 212 val = APLIC_SOURCECFG_SM_EDGE_RISE; 213 break; 214 default: 215 return -EINVAL; 216 } 217 218 sourcecfg = priv->regs + APLIC_SOURCECFG_BASE; 219 sourcecfg += (d->hwirq - 1) * sizeof(u32); 220 writel(val, sourcecfg); 221 222 priv->saved_hw_regs.srcs[d->hwirq - 1].sourcecfg = val; 223 224 return 0; 225 } 226 227 int aplic_irqdomain_translate(struct irq_fwspec *fwspec, u32 gsi_base, 228 unsigned long *hwirq, unsigned int *type) 229 { 230 if (WARN_ON(fwspec->param_count < 2)) 231 return -EINVAL; 232 if (WARN_ON(!fwspec->param[0])) 233 return -EINVAL; 234 235 /* For DT, gsi_base is always zero. */ 236 *hwirq = fwspec->param[0] - gsi_base; 237 *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; 238 239 WARN_ON(*type == IRQ_TYPE_NONE); 240 241 return 0; 242 } 243 244 void aplic_init_hw_global(struct aplic_priv *priv, bool msi_mode) 245 { 246 struct aplic_saved_regs *saved_regs = &priv->saved_hw_regs; 247 u32 val; 248 #ifdef CONFIG_RISCV_M_MODE 249 u32 valh; 250 251 if (msi_mode) { 252 val = lower_32_bits(priv->msicfg.base_ppn); 253 valh = FIELD_PREP(APLIC_xMSICFGADDRH_BAPPN, upper_32_bits(priv->msicfg.base_ppn)); 254 valh |= FIELD_PREP(APLIC_xMSICFGADDRH_LHXW, priv->msicfg.lhxw); 255 valh |= FIELD_PREP(APLIC_xMSICFGADDRH_HHXW, priv->msicfg.hhxw); 256 valh |= FIELD_PREP(APLIC_xMSICFGADDRH_LHXS, priv->msicfg.lhxs); 257 valh |= FIELD_PREP(APLIC_xMSICFGADDRH_HHXS, priv->msicfg.hhxs); 258 writel(val, priv->regs + APLIC_xMSICFGADDR); 259 writel(valh, priv->regs + APLIC_xMSICFGADDRH); 260 saved_regs->msiaddr = val; 261 saved_regs->msiaddrh = valh; 262 } 263 #endif 264 265 /* Setup APLIC domaincfg register */ 266 val = readl(priv->regs + APLIC_DOMAINCFG); 267 val |= APLIC_DOMAINCFG_IE; 268 if (msi_mode) 269 val |= APLIC_DOMAINCFG_DM; 270 writel(val, priv->regs + APLIC_DOMAINCFG); 271 if (readl(priv->regs + APLIC_DOMAINCFG) != val) 272 dev_warn(priv->dev, "unable to write 0x%x in domaincfg\n", val); 273 274 saved_regs->domaincfg = val; 275 } 276 277 static void aplic_init_hw_irqs(struct aplic_priv *priv) 278 { 279 int i; 280 281 /* Disable all interrupts */ 282 for (i = 0; i <= priv->nr_irqs; i += 32) 283 writel(-1U, priv->regs + APLIC_CLRIE_BASE + (i / 32) * sizeof(u32)); 284 285 /* Set interrupt type and default priority for all interrupts */ 286 for (i = 1; i <= priv->nr_irqs; i++) { 287 writel(0, priv->regs + APLIC_SOURCECFG_BASE + (i - 1) * sizeof(u32)); 288 writel(APLIC_DEFAULT_PRIORITY, 289 priv->regs + APLIC_TARGET_BASE + (i - 1) * sizeof(u32)); 290 } 291 292 /* Clear APLIC domaincfg */ 293 writel(0, priv->regs + APLIC_DOMAINCFG); 294 } 295 296 #ifdef CONFIG_ACPI 297 static const struct acpi_device_id aplic_acpi_match[] = { 298 { "RSCV0002", 0 }, 299 {} 300 }; 301 MODULE_DEVICE_TABLE(acpi, aplic_acpi_match); 302 303 #endif 304 305 int aplic_setup_priv(struct aplic_priv *priv, struct device *dev, void __iomem *regs) 306 { 307 struct device_node *np = to_of_node(dev->fwnode); 308 struct of_phandle_args parent; 309 int rc; 310 311 /* Save device pointer and register base */ 312 priv->dev = dev; 313 priv->regs = regs; 314 315 if (np) { 316 /* Find out number of interrupt sources */ 317 rc = of_property_read_u32(np, "riscv,num-sources", &priv->nr_irqs); 318 if (rc) { 319 dev_err(dev, "failed to get number of interrupt sources\n"); 320 return rc; 321 } 322 323 /* 324 * Find out number of IDCs based on parent interrupts 325 * 326 * If "msi-parent" property is present then we ignore the 327 * APLIC IDCs which forces the APLIC driver to use MSI mode. 328 */ 329 if (!of_property_present(np, "msi-parent")) { 330 while (!of_irq_parse_one(np, priv->nr_idcs, &parent)) 331 priv->nr_idcs++; 332 } 333 } else { 334 rc = riscv_acpi_get_gsi_info(dev->fwnode, &priv->gsi_base, &priv->acpi_aplic_id, 335 &priv->nr_irqs, &priv->nr_idcs); 336 if (rc) { 337 dev_err(dev, "failed to find GSI mapping\n"); 338 return rc; 339 } 340 } 341 342 /* Setup initial state APLIC interrupts */ 343 aplic_init_hw_irqs(priv); 344 345 return aplic_pm_add(dev, priv); 346 } 347 348 static int aplic_probe(struct platform_device *pdev) 349 { 350 struct device *dev = &pdev->dev; 351 bool msi_mode = false; 352 void __iomem *regs; 353 int rc; 354 355 /* Map the MMIO registers */ 356 regs = devm_platform_ioremap_resource(pdev, 0); 357 if (IS_ERR(regs)) { 358 dev_err(dev, "failed map MMIO registers\n"); 359 return PTR_ERR(regs); 360 } 361 362 /* 363 * If msi-parent property is present then setup APLIC MSI 364 * mode otherwise setup APLIC direct mode. 365 */ 366 if (is_of_node(dev->fwnode)) 367 msi_mode = of_property_present(to_of_node(dev->fwnode), "msi-parent"); 368 else 369 msi_mode = imsic_acpi_get_fwnode(NULL) ? 1 : 0; 370 371 if (msi_mode) 372 rc = aplic_msi_setup(dev, regs); 373 else 374 rc = aplic_direct_setup(dev, regs); 375 if (rc) 376 dev_err_probe(dev, rc, "failed to setup APLIC in %s mode\n", 377 msi_mode ? "MSI" : "direct"); 378 else 379 register_syscore(&aplic_syscore); 380 381 #ifdef CONFIG_ACPI 382 if (!acpi_disabled) 383 acpi_dev_clear_dependencies(ACPI_COMPANION(dev)); 384 #endif 385 386 return rc; 387 } 388 389 static const struct of_device_id aplic_match[] = { 390 { .compatible = "riscv,aplic" }, 391 {} 392 }; 393 394 static struct platform_driver aplic_driver = { 395 .driver = { 396 .name = "riscv-aplic", 397 .of_match_table = aplic_match, 398 .acpi_match_table = ACPI_PTR(aplic_acpi_match), 399 }, 400 .probe = aplic_probe, 401 }; 402 builtin_platform_driver(aplic_driver); 403