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 irq_domain_info info = { 227 .ops = &imx_mu_msi_domain_ops, 228 .fwnode = dev_fwnode(dev), 229 .size = IMX_MU_CHANS, 230 .host_data = msi_data, 231 }; 232 struct irq_domain *parent; 233 234 /* Initialize MSI domain parent */ 235 parent = msi_create_parent_irq_domain(&info, &imx_mu_msi_parent_ops); 236 if (!parent) { 237 dev_err(dev, "failed to create IRQ domain\n"); 238 return -ENOMEM; 239 } 240 parent->dev = parent->pm_dev = dev; 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 imx_mu_probe(struct platform_device *pdev, struct device_node *parent, 300 const struct imx_mu_dcfg *cfg) 301 { 302 struct device_link *pd_link_a; 303 struct device_link *pd_link_b; 304 struct imx_mu_msi *msi_data; 305 struct resource *res; 306 struct device *pd_a; 307 struct device *pd_b; 308 struct device *dev; 309 int ret; 310 int irq; 311 312 dev = &pdev->dev; 313 314 msi_data = devm_kzalloc(&pdev->dev, sizeof(*msi_data), GFP_KERNEL); 315 if (!msi_data) 316 return -ENOMEM; 317 318 msi_data->cfg = cfg; 319 320 msi_data->regs = devm_platform_ioremap_resource_byname(pdev, "processor-a-side"); 321 if (IS_ERR(msi_data->regs)) { 322 dev_err(&pdev->dev, "failed to initialize 'regs'\n"); 323 return PTR_ERR(msi_data->regs); 324 } 325 326 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "processor-b-side"); 327 if (!res) 328 return -EIO; 329 330 msi_data->msiir_addr = res->start + msi_data->cfg->xTR; 331 332 irq = platform_get_irq(pdev, 0); 333 if (irq < 0) 334 return irq; 335 336 platform_set_drvdata(pdev, msi_data); 337 338 msi_data->clk = devm_clk_get(dev, NULL); 339 if (IS_ERR(msi_data->clk)) 340 return PTR_ERR(msi_data->clk); 341 342 pd_a = dev_pm_domain_attach_by_name(dev, "processor-a-side"); 343 if (IS_ERR(pd_a)) 344 return PTR_ERR(pd_a); 345 346 pd_b = dev_pm_domain_attach_by_name(dev, "processor-b-side"); 347 if (IS_ERR(pd_b)) 348 return PTR_ERR(pd_b); 349 350 pd_link_a = device_link_add(dev, pd_a, 351 DL_FLAG_STATELESS | 352 DL_FLAG_PM_RUNTIME | 353 DL_FLAG_RPM_ACTIVE); 354 355 if (!pd_link_a) { 356 dev_err(dev, "Failed to add device_link to mu a.\n"); 357 goto err_pd_a; 358 } 359 360 pd_link_b = device_link_add(dev, pd_b, 361 DL_FLAG_STATELESS | 362 DL_FLAG_PM_RUNTIME | 363 DL_FLAG_RPM_ACTIVE); 364 365 366 if (!pd_link_b) { 367 dev_err(dev, "Failed to add device_link to mu a.\n"); 368 goto err_pd_b; 369 } 370 371 ret = imx_mu_msi_domains_init(msi_data, dev); 372 if (ret) 373 goto err_dm_init; 374 375 pm_runtime_enable(dev); 376 377 irq_set_chained_handler_and_data(irq, 378 imx_mu_msi_irq_handler, 379 msi_data); 380 381 return 0; 382 383 err_dm_init: 384 device_link_remove(dev, pd_b); 385 err_pd_b: 386 device_link_remove(dev, pd_a); 387 err_pd_a: 388 return -EINVAL; 389 } 390 391 static int __maybe_unused imx_mu_runtime_suspend(struct device *dev) 392 { 393 struct imx_mu_msi *priv = dev_get_drvdata(dev); 394 395 clk_disable_unprepare(priv->clk); 396 397 return 0; 398 } 399 400 static int __maybe_unused imx_mu_runtime_resume(struct device *dev) 401 { 402 struct imx_mu_msi *priv = dev_get_drvdata(dev); 403 int ret; 404 405 ret = clk_prepare_enable(priv->clk); 406 if (ret) 407 dev_err(dev, "failed to enable clock\n"); 408 409 return ret; 410 } 411 412 static const struct dev_pm_ops imx_mu_pm_ops = { 413 SET_RUNTIME_PM_OPS(imx_mu_runtime_suspend, 414 imx_mu_runtime_resume, NULL) 415 }; 416 417 static int imx_mu_imx7ulp_probe(struct platform_device *pdev, struct device_node *parent) 418 { 419 return imx_mu_probe(pdev, parent, &imx_mu_cfg_imx7ulp); 420 } 421 422 static int imx_mu_imx6sx_probe(struct platform_device *pdev, struct device_node *parent) 423 { 424 return imx_mu_probe(pdev, parent, &imx_mu_cfg_imx6sx); 425 } 426 427 static int imx_mu_imx8ulp_probe(struct platform_device *pdev, struct device_node *parent) 428 { 429 return imx_mu_probe(pdev, parent, &imx_mu_cfg_imx8ulp); 430 } 431 432 IRQCHIP_PLATFORM_DRIVER_BEGIN(imx_mu_msi) 433 IRQCHIP_MATCH("fsl,imx7ulp-mu-msi", imx_mu_imx7ulp_probe) 434 IRQCHIP_MATCH("fsl,imx6sx-mu-msi", imx_mu_imx6sx_probe) 435 IRQCHIP_MATCH("fsl,imx8ulp-mu-msi", imx_mu_imx8ulp_probe) 436 IRQCHIP_PLATFORM_DRIVER_END(imx_mu_msi, .pm = &imx_mu_pm_ops) 437 438 MODULE_AUTHOR("Frank Li <Frank.Li@nxp.com>"); 439 MODULE_DESCRIPTION("Freescale MU MSI controller driver"); 440 MODULE_LICENSE("GPL"); 441