1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Freescale MU used as MSI controller 4 * 5 * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de> 6 * Copyright 2022 NXP 7 * Frank Li <Frank.Li@nxp.com> 8 * Peng Fan <peng.fan@nxp.com> 9 * 10 * Based on drivers/mailbox/imx-mailbox.c 11 */ 12 13 #include <linux/clk.h> 14 #include <linux/irq.h> 15 #include <linux/irqchip.h> 16 #include <linux/irqchip/chained_irq.h> 17 #include <linux/irqdomain.h> 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/msi.h> 21 #include <linux/of_irq.h> 22 #include <linux/of_platform.h> 23 #include <linux/pm_runtime.h> 24 #include <linux/pm_domain.h> 25 #include <linux/spinlock.h> 26 27 #include <linux/irqchip/irq-msi-lib.h> 28 29 #define IMX_MU_CHANS 4 30 31 enum imx_mu_xcr { 32 IMX_MU_GIER, 33 IMX_MU_GCR, 34 IMX_MU_TCR, 35 IMX_MU_RCR, 36 IMX_MU_xCR_MAX, 37 }; 38 39 enum imx_mu_xsr { 40 IMX_MU_SR, 41 IMX_MU_GSR, 42 IMX_MU_TSR, 43 IMX_MU_RSR, 44 IMX_MU_xSR_MAX 45 }; 46 47 enum imx_mu_type { 48 IMX_MU_V2 = BIT(1), 49 }; 50 51 /* Receive Interrupt Enable */ 52 #define IMX_MU_xCR_RIEn(data, x) ((data->cfg->type) & IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x)))) 53 #define IMX_MU_xSR_RFn(data, x) ((data->cfg->type) & IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x)))) 54 55 struct imx_mu_dcfg { 56 enum imx_mu_type type; 57 u32 xTR; /* Transmit Register0 */ 58 u32 xRR; /* Receive Register0 */ 59 u32 xSR[IMX_MU_xSR_MAX]; /* Status Registers */ 60 u32 xCR[IMX_MU_xCR_MAX]; /* Control Registers */ 61 }; 62 63 struct imx_mu_msi { 64 raw_spinlock_t lock; 65 struct irq_domain *msi_domain; 66 void __iomem *regs; 67 phys_addr_t msiir_addr; 68 const struct imx_mu_dcfg *cfg; 69 unsigned long used; 70 struct clk *clk; 71 }; 72 73 static void imx_mu_write(struct imx_mu_msi *msi_data, u32 val, u32 offs) 74 { 75 iowrite32(val, msi_data->regs + offs); 76 } 77 78 static u32 imx_mu_read(struct imx_mu_msi *msi_data, u32 offs) 79 { 80 return ioread32(msi_data->regs + offs); 81 } 82 83 static u32 imx_mu_xcr_rmw(struct imx_mu_msi *msi_data, enum imx_mu_xcr type, u32 set, u32 clr) 84 { 85 unsigned long flags; 86 u32 val; 87 88 raw_spin_lock_irqsave(&msi_data->lock, flags); 89 val = imx_mu_read(msi_data, msi_data->cfg->xCR[type]); 90 val &= ~clr; 91 val |= set; 92 imx_mu_write(msi_data, val, msi_data->cfg->xCR[type]); 93 raw_spin_unlock_irqrestore(&msi_data->lock, flags); 94 95 return val; 96 } 97 98 static void imx_mu_msi_parent_mask_irq(struct irq_data *data) 99 { 100 struct imx_mu_msi *msi_data = irq_data_get_irq_chip_data(data); 101 102 imx_mu_xcr_rmw(msi_data, IMX_MU_RCR, 0, IMX_MU_xCR_RIEn(msi_data, data->hwirq)); 103 } 104 105 static void imx_mu_msi_parent_unmask_irq(struct irq_data *data) 106 { 107 struct imx_mu_msi *msi_data = irq_data_get_irq_chip_data(data); 108 109 imx_mu_xcr_rmw(msi_data, IMX_MU_RCR, IMX_MU_xCR_RIEn(msi_data, data->hwirq), 0); 110 } 111 112 static void imx_mu_msi_parent_ack_irq(struct irq_data *data) 113 { 114 struct imx_mu_msi *msi_data = irq_data_get_irq_chip_data(data); 115 116 imx_mu_read(msi_data, msi_data->cfg->xRR + data->hwirq * 4); 117 } 118 119 static void imx_mu_msi_parent_compose_msg(struct irq_data *data, 120 struct msi_msg *msg) 121 { 122 struct imx_mu_msi *msi_data = irq_data_get_irq_chip_data(data); 123 u64 addr = msi_data->msiir_addr + 4 * data->hwirq; 124 125 msg->address_hi = upper_32_bits(addr); 126 msg->address_lo = lower_32_bits(addr); 127 msg->data = data->hwirq; 128 } 129 130 static int imx_mu_msi_parent_set_affinity(struct irq_data *irq_data, 131 const struct cpumask *mask, bool force) 132 { 133 return -EINVAL; 134 } 135 136 static struct irq_chip imx_mu_msi_parent_chip = { 137 .name = "MU", 138 .irq_mask = imx_mu_msi_parent_mask_irq, 139 .irq_unmask = imx_mu_msi_parent_unmask_irq, 140 .irq_ack = imx_mu_msi_parent_ack_irq, 141 .irq_compose_msi_msg = imx_mu_msi_parent_compose_msg, 142 .irq_set_affinity = imx_mu_msi_parent_set_affinity, 143 }; 144 145 static int imx_mu_msi_domain_irq_alloc(struct irq_domain *domain, 146 unsigned int virq, 147 unsigned int nr_irqs, 148 void *args) 149 { 150 struct imx_mu_msi *msi_data = domain->host_data; 151 unsigned long flags; 152 int pos, err = 0; 153 154 WARN_ON(nr_irqs != 1); 155 156 raw_spin_lock_irqsave(&msi_data->lock, flags); 157 pos = find_first_zero_bit(&msi_data->used, IMX_MU_CHANS); 158 if (pos < IMX_MU_CHANS) 159 __set_bit(pos, &msi_data->used); 160 else 161 err = -ENOSPC; 162 raw_spin_unlock_irqrestore(&msi_data->lock, flags); 163 164 if (err) 165 return err; 166 167 irq_domain_set_info(domain, virq, pos, 168 &imx_mu_msi_parent_chip, msi_data, 169 handle_edge_irq, NULL, NULL); 170 return 0; 171 } 172 173 static void imx_mu_msi_domain_irq_free(struct irq_domain *domain, 174 unsigned int virq, unsigned int nr_irqs) 175 { 176 struct irq_data *d = irq_domain_get_irq_data(domain, virq); 177 struct imx_mu_msi *msi_data = irq_data_get_irq_chip_data(d); 178 unsigned long flags; 179 180 raw_spin_lock_irqsave(&msi_data->lock, flags); 181 __clear_bit(d->hwirq, &msi_data->used); 182 raw_spin_unlock_irqrestore(&msi_data->lock, flags); 183 } 184 185 static const struct irq_domain_ops imx_mu_msi_domain_ops = { 186 .select = msi_lib_irq_domain_select, 187 .alloc = imx_mu_msi_domain_irq_alloc, 188 .free = imx_mu_msi_domain_irq_free, 189 }; 190 191 static void imx_mu_msi_irq_handler(struct irq_desc *desc) 192 { 193 struct imx_mu_msi *msi_data = irq_desc_get_handler_data(desc); 194 struct irq_chip *chip = irq_desc_get_chip(desc); 195 u32 status; 196 int i; 197 198 status = imx_mu_read(msi_data, msi_data->cfg->xSR[IMX_MU_RSR]); 199 200 chained_irq_enter(chip, desc); 201 for (i = 0; i < IMX_MU_CHANS; i++) { 202 if (status & IMX_MU_xSR_RFn(msi_data, i)) 203 generic_handle_domain_irq(msi_data->msi_domain, i); 204 } 205 chained_irq_exit(chip, desc); 206 } 207 208 #define IMX_MU_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 209 MSI_FLAG_USE_DEF_CHIP_OPS | \ 210 MSI_FLAG_PARENT_PM_DEV) 211 212 #define IMX_MU_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK) 213 214 static const struct msi_parent_ops imx_mu_msi_parent_ops = { 215 .supported_flags = IMX_MU_MSI_FLAGS_SUPPORTED, 216 .required_flags = IMX_MU_MSI_FLAGS_REQUIRED, 217 .chip_flags = MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK, 218 .bus_select_token = DOMAIN_BUS_NEXUS, 219 .bus_select_mask = MATCH_PLATFORM_MSI, 220 .prefix = "MU-MSI-", 221 .init_dev_msi_info = msi_lib_init_dev_msi_info, 222 }; 223 224 static int imx_mu_msi_domains_init(struct imx_mu_msi *msi_data, struct device *dev) 225 { 226 struct fwnode_handle *fwnodes = dev_fwnode(dev); 227 struct irq_domain *parent; 228 229 /* Initialize MSI domain parent */ 230 parent = irq_domain_create_linear(fwnodes, IMX_MU_CHANS, 231 &imx_mu_msi_domain_ops, msi_data); 232 if (!parent) { 233 dev_err(dev, "failed to create IRQ domain\n"); 234 return -ENOMEM; 235 } 236 237 irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); 238 parent->dev = parent->pm_dev = dev; 239 parent->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; 240 parent->msi_parent_ops = &imx_mu_msi_parent_ops; 241 return 0; 242 } 243 244 /* Register offset of different version MU IP */ 245 static const struct imx_mu_dcfg imx_mu_cfg_imx6sx = { 246 .type = 0, 247 .xTR = 0x0, 248 .xRR = 0x10, 249 .xSR = { 250 [IMX_MU_SR] = 0x20, 251 [IMX_MU_GSR] = 0x20, 252 [IMX_MU_TSR] = 0x20, 253 [IMX_MU_RSR] = 0x20, 254 }, 255 .xCR = { 256 [IMX_MU_GIER] = 0x24, 257 [IMX_MU_GCR] = 0x24, 258 [IMX_MU_TCR] = 0x24, 259 [IMX_MU_RCR] = 0x24, 260 }, 261 }; 262 263 static const struct imx_mu_dcfg imx_mu_cfg_imx7ulp = { 264 .type = 0, 265 .xTR = 0x20, 266 .xRR = 0x40, 267 .xSR = { 268 [IMX_MU_SR] = 0x60, 269 [IMX_MU_GSR] = 0x60, 270 [IMX_MU_TSR] = 0x60, 271 [IMX_MU_RSR] = 0x60, 272 }, 273 .xCR = { 274 [IMX_MU_GIER] = 0x64, 275 [IMX_MU_GCR] = 0x64, 276 [IMX_MU_TCR] = 0x64, 277 [IMX_MU_RCR] = 0x64, 278 }, 279 }; 280 281 static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp = { 282 .type = IMX_MU_V2, 283 .xTR = 0x200, 284 .xRR = 0x280, 285 .xSR = { 286 [IMX_MU_SR] = 0xC, 287 [IMX_MU_GSR] = 0x118, 288 [IMX_MU_TSR] = 0x124, 289 [IMX_MU_RSR] = 0x12C, 290 }, 291 .xCR = { 292 [IMX_MU_GIER] = 0x110, 293 [IMX_MU_GCR] = 0x114, 294 [IMX_MU_TCR] = 0x120, 295 [IMX_MU_RCR] = 0x128 296 }, 297 }; 298 299 static int __init imx_mu_of_init(struct device_node *dn, 300 struct device_node *parent, 301 const struct imx_mu_dcfg *cfg) 302 { 303 struct platform_device *pdev = of_find_device_by_node(dn); 304 struct device_link *pd_link_a; 305 struct device_link *pd_link_b; 306 struct imx_mu_msi *msi_data; 307 struct resource *res; 308 struct device *pd_a; 309 struct device *pd_b; 310 struct device *dev; 311 int ret; 312 int irq; 313 314 dev = &pdev->dev; 315 316 msi_data = devm_kzalloc(&pdev->dev, sizeof(*msi_data), GFP_KERNEL); 317 if (!msi_data) 318 return -ENOMEM; 319 320 msi_data->cfg = cfg; 321 322 msi_data->regs = devm_platform_ioremap_resource_byname(pdev, "processor-a-side"); 323 if (IS_ERR(msi_data->regs)) { 324 dev_err(&pdev->dev, "failed to initialize 'regs'\n"); 325 return PTR_ERR(msi_data->regs); 326 } 327 328 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "processor-b-side"); 329 if (!res) 330 return -EIO; 331 332 msi_data->msiir_addr = res->start + msi_data->cfg->xTR; 333 334 irq = platform_get_irq(pdev, 0); 335 if (irq < 0) 336 return irq; 337 338 platform_set_drvdata(pdev, msi_data); 339 340 msi_data->clk = devm_clk_get(dev, NULL); 341 if (IS_ERR(msi_data->clk)) 342 return PTR_ERR(msi_data->clk); 343 344 pd_a = dev_pm_domain_attach_by_name(dev, "processor-a-side"); 345 if (IS_ERR(pd_a)) 346 return PTR_ERR(pd_a); 347 348 pd_b = dev_pm_domain_attach_by_name(dev, "processor-b-side"); 349 if (IS_ERR(pd_b)) 350 return PTR_ERR(pd_b); 351 352 pd_link_a = device_link_add(dev, pd_a, 353 DL_FLAG_STATELESS | 354 DL_FLAG_PM_RUNTIME | 355 DL_FLAG_RPM_ACTIVE); 356 357 if (!pd_link_a) { 358 dev_err(dev, "Failed to add device_link to mu a.\n"); 359 goto err_pd_a; 360 } 361 362 pd_link_b = device_link_add(dev, pd_b, 363 DL_FLAG_STATELESS | 364 DL_FLAG_PM_RUNTIME | 365 DL_FLAG_RPM_ACTIVE); 366 367 368 if (!pd_link_b) { 369 dev_err(dev, "Failed to add device_link to mu a.\n"); 370 goto err_pd_b; 371 } 372 373 ret = imx_mu_msi_domains_init(msi_data, dev); 374 if (ret) 375 goto err_dm_init; 376 377 pm_runtime_enable(dev); 378 379 irq_set_chained_handler_and_data(irq, 380 imx_mu_msi_irq_handler, 381 msi_data); 382 383 return 0; 384 385 err_dm_init: 386 device_link_remove(dev, pd_b); 387 err_pd_b: 388 device_link_remove(dev, pd_a); 389 err_pd_a: 390 return -EINVAL; 391 } 392 393 static int __maybe_unused imx_mu_runtime_suspend(struct device *dev) 394 { 395 struct imx_mu_msi *priv = dev_get_drvdata(dev); 396 397 clk_disable_unprepare(priv->clk); 398 399 return 0; 400 } 401 402 static int __maybe_unused imx_mu_runtime_resume(struct device *dev) 403 { 404 struct imx_mu_msi *priv = dev_get_drvdata(dev); 405 int ret; 406 407 ret = clk_prepare_enable(priv->clk); 408 if (ret) 409 dev_err(dev, "failed to enable clock\n"); 410 411 return ret; 412 } 413 414 static const struct dev_pm_ops imx_mu_pm_ops = { 415 SET_RUNTIME_PM_OPS(imx_mu_runtime_suspend, 416 imx_mu_runtime_resume, NULL) 417 }; 418 419 static int __init imx_mu_imx7ulp_of_init(struct device_node *dn, 420 struct device_node *parent) 421 { 422 return imx_mu_of_init(dn, parent, &imx_mu_cfg_imx7ulp); 423 } 424 425 static int __init imx_mu_imx6sx_of_init(struct device_node *dn, 426 struct device_node *parent) 427 { 428 return imx_mu_of_init(dn, parent, &imx_mu_cfg_imx6sx); 429 } 430 431 static int __init imx_mu_imx8ulp_of_init(struct device_node *dn, 432 struct device_node *parent) 433 { 434 return imx_mu_of_init(dn, parent, &imx_mu_cfg_imx8ulp); 435 } 436 437 IRQCHIP_PLATFORM_DRIVER_BEGIN(imx_mu_msi) 438 IRQCHIP_MATCH("fsl,imx7ulp-mu-msi", imx_mu_imx7ulp_of_init) 439 IRQCHIP_MATCH("fsl,imx6sx-mu-msi", imx_mu_imx6sx_of_init) 440 IRQCHIP_MATCH("fsl,imx8ulp-mu-msi", imx_mu_imx8ulp_of_init) 441 IRQCHIP_PLATFORM_DRIVER_END(imx_mu_msi, .pm = &imx_mu_pm_ops) 442 443 444 MODULE_AUTHOR("Frank Li <Frank.Li@nxp.com>"); 445 MODULE_DESCRIPTION("Freescale MU MSI controller driver"); 446 MODULE_LICENSE("GPL"); 447