0001
0002
0003
0004
0005
0006 #include <linux/arm-smccc.h>
0007 #include <linux/clk.h>
0008 #include <linux/err.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mailbox_client.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/module.h>
0014 #include <linux/of_address.h>
0015 #include <linux/of_reserved_mem.h>
0016 #include <linux/of_device.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/regmap.h>
0019 #include <linux/remoteproc.h>
0020 #include <linux/workqueue.h>
0021
0022 #include "imx_rproc.h"
0023 #include "remoteproc_internal.h"
0024
0025 #define IMX7D_SRC_SCR 0x0C
0026 #define IMX7D_ENABLE_M4 BIT(3)
0027 #define IMX7D_SW_M4P_RST BIT(2)
0028 #define IMX7D_SW_M4C_RST BIT(1)
0029 #define IMX7D_SW_M4C_NON_SCLR_RST BIT(0)
0030
0031 #define IMX7D_M4_RST_MASK (IMX7D_ENABLE_M4 | IMX7D_SW_M4P_RST \
0032 | IMX7D_SW_M4C_RST \
0033 | IMX7D_SW_M4C_NON_SCLR_RST)
0034
0035 #define IMX7D_M4_START (IMX7D_ENABLE_M4 | IMX7D_SW_M4P_RST \
0036 | IMX7D_SW_M4C_RST)
0037 #define IMX7D_M4_STOP (IMX7D_ENABLE_M4 | IMX7D_SW_M4C_RST | \
0038 IMX7D_SW_M4C_NON_SCLR_RST)
0039
0040
0041 #define IMX6SX_SRC_SCR 0x00
0042 #define IMX6SX_ENABLE_M4 BIT(22)
0043 #define IMX6SX_SW_M4P_RST BIT(12)
0044 #define IMX6SX_SW_M4C_NON_SCLR_RST BIT(4)
0045 #define IMX6SX_SW_M4C_RST BIT(3)
0046
0047 #define IMX6SX_M4_START (IMX6SX_ENABLE_M4 | IMX6SX_SW_M4P_RST \
0048 | IMX6SX_SW_M4C_RST)
0049 #define IMX6SX_M4_STOP (IMX6SX_ENABLE_M4 | IMX6SX_SW_M4C_RST | \
0050 IMX6SX_SW_M4C_NON_SCLR_RST)
0051 #define IMX6SX_M4_RST_MASK (IMX6SX_ENABLE_M4 | IMX6SX_SW_M4P_RST \
0052 | IMX6SX_SW_M4C_NON_SCLR_RST \
0053 | IMX6SX_SW_M4C_RST)
0054
0055 #define IMX_RPROC_MEM_MAX 32
0056
0057 #define IMX_SIP_RPROC 0xC2000005
0058 #define IMX_SIP_RPROC_START 0x00
0059 #define IMX_SIP_RPROC_STARTED 0x01
0060 #define IMX_SIP_RPROC_STOP 0x02
0061
0062
0063
0064
0065
0066
0067
0068 struct imx_rproc_mem {
0069 void __iomem *cpu_addr;
0070 phys_addr_t sys_addr;
0071 size_t size;
0072 };
0073
0074
0075
0076 #define ATT_OWN BIT(1)
0077 #define ATT_IOMEM BIT(2)
0078
0079 struct imx_rproc {
0080 struct device *dev;
0081 struct regmap *regmap;
0082 struct rproc *rproc;
0083 const struct imx_rproc_dcfg *dcfg;
0084 struct imx_rproc_mem mem[IMX_RPROC_MEM_MAX];
0085 struct clk *clk;
0086 struct mbox_client cl;
0087 struct mbox_chan *tx_ch;
0088 struct mbox_chan *rx_ch;
0089 struct work_struct rproc_work;
0090 struct workqueue_struct *workqueue;
0091 void __iomem *rsc_table;
0092 };
0093
0094 static const struct imx_rproc_att imx_rproc_att_imx93[] = {
0095
0096
0097 { 0x0FFC0000, 0x201C0000, 0x00020000, ATT_OWN | ATT_IOMEM },
0098 { 0x0FFE0000, 0x201E0000, 0x00020000, ATT_OWN | ATT_IOMEM },
0099
0100
0101 { 0x1FFC0000, 0x201C0000, 0x00020000, ATT_OWN | ATT_IOMEM },
0102 { 0x1FFE0000, 0x201E0000, 0x00020000, ATT_OWN | ATT_IOMEM },
0103
0104
0105 { 0x20000000, 0x20200000, 0x00020000, ATT_OWN | ATT_IOMEM },
0106 { 0x20020000, 0x20220000, 0x00020000, ATT_OWN | ATT_IOMEM },
0107
0108
0109 { 0x30000000, 0x20200000, 0x00020000, ATT_OWN | ATT_IOMEM },
0110 { 0x30020000, 0x20220000, 0x00020000, ATT_OWN | ATT_IOMEM },
0111
0112
0113 { 0x80000000, 0x80000000, 0x10000000, 0 },
0114 { 0x90000000, 0x80000000, 0x10000000, 0 },
0115
0116 { 0xC0000000, 0xa0000000, 0x10000000, 0 },
0117 { 0xD0000000, 0xa0000000, 0x10000000, 0 },
0118 };
0119
0120 static const struct imx_rproc_att imx_rproc_att_imx8mn[] = {
0121
0122
0123 { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM },
0124
0125 { 0x00180000, 0x00180000, 0x00009000, 0 },
0126
0127 { 0x00900000, 0x00900000, 0x00020000, 0 },
0128
0129 { 0x00920000, 0x00920000, 0x00020000, 0 },
0130
0131 { 0x00940000, 0x00940000, 0x00050000, 0 },
0132
0133 { 0x08000000, 0x08000000, 0x08000000, 0 },
0134
0135 { 0x10000000, 0x40000000, 0x0FFE0000, 0 },
0136
0137 { 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM },
0138
0139 { 0x20180000, 0x00180000, 0x00008000, ATT_OWN },
0140
0141 { 0x20200000, 0x00900000, 0x00020000, ATT_OWN },
0142
0143 { 0x20220000, 0x00920000, 0x00020000, ATT_OWN },
0144
0145 { 0x20240000, 0x00940000, 0x00040000, ATT_OWN },
0146
0147 { 0x40000000, 0x40000000, 0x80000000, 0 },
0148 };
0149
0150 static const struct imx_rproc_att imx_rproc_att_imx8mq[] = {
0151
0152
0153 { 0x00000000, 0x007e0000, 0x00020000, ATT_IOMEM},
0154
0155 { 0x00180000, 0x00180000, 0x00008000, 0 },
0156
0157 { 0x00900000, 0x00900000, 0x00020000, 0 },
0158
0159 { 0x00920000, 0x00920000, 0x00020000, 0 },
0160
0161 { 0x08000000, 0x08000000, 0x08000000, 0 },
0162
0163 { 0x10000000, 0x80000000, 0x0FFE0000, 0 },
0164
0165 { 0x1FFE0000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM},
0166
0167 { 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM},
0168
0169 { 0x20180000, 0x00180000, 0x00008000, ATT_OWN },
0170
0171 { 0x20200000, 0x00900000, 0x00020000, ATT_OWN },
0172
0173 { 0x20220000, 0x00920000, 0x00020000, ATT_OWN },
0174
0175 { 0x40000000, 0x40000000, 0x80000000, 0 },
0176 };
0177
0178 static const struct imx_rproc_att imx_rproc_att_imx8ulp[] = {
0179 {0x1FFC0000, 0x1FFC0000, 0xC0000, ATT_OWN},
0180 {0x21000000, 0x21000000, 0x10000, ATT_OWN},
0181 {0x80000000, 0x80000000, 0x60000000, 0}
0182 };
0183
0184 static const struct imx_rproc_att imx_rproc_att_imx7ulp[] = {
0185 {0x1FFD0000, 0x1FFD0000, 0x30000, ATT_OWN},
0186 {0x20000000, 0x20000000, 0x10000, ATT_OWN},
0187 {0x2F000000, 0x2F000000, 0x20000, ATT_OWN},
0188 {0x2F020000, 0x2F020000, 0x20000, ATT_OWN},
0189 {0x60000000, 0x60000000, 0x40000000, 0}
0190 };
0191
0192 static const struct imx_rproc_att imx_rproc_att_imx7d[] = {
0193
0194
0195 { 0x00000000, 0x00180000, 0x00008000, 0 },
0196
0197 { 0x00180000, 0x00180000, 0x00008000, ATT_OWN },
0198
0199 { 0x00900000, 0x00900000, 0x00020000, 0 },
0200
0201 { 0x00920000, 0x00920000, 0x00020000, 0 },
0202
0203 { 0x00940000, 0x00940000, 0x00008000, 0 },
0204
0205 { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM },
0206
0207 { 0x10000000, 0x80000000, 0x0FFF0000, 0 },
0208
0209
0210 { 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM },
0211
0212 { 0x20200000, 0x00900000, 0x00020000, 0 },
0213
0214 { 0x20220000, 0x00920000, 0x00020000, 0 },
0215
0216 { 0x20240000, 0x00940000, 0x00008000, 0 },
0217
0218 { 0x80000000, 0x80000000, 0x60000000, 0 },
0219 };
0220
0221 static const struct imx_rproc_att imx_rproc_att_imx6sx[] = {
0222
0223
0224 { 0x00000000, 0x007F8000, 0x00008000, ATT_IOMEM },
0225
0226 { 0x00180000, 0x008F8000, 0x00004000, 0 },
0227
0228 { 0x00180000, 0x008FC000, 0x00004000, 0 },
0229
0230 { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM },
0231
0232 { 0x10000000, 0x80000000, 0x0FFF8000, 0 },
0233
0234
0235 { 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM },
0236
0237 { 0x208F8000, 0x008F8000, 0x00004000, 0 },
0238
0239 { 0x80000000, 0x80000000, 0x60000000, 0 },
0240 };
0241
0242 static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = {
0243 .att = imx_rproc_att_imx8mn,
0244 .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn),
0245 .method = IMX_RPROC_SMC,
0246 };
0247
0248 static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = {
0249 .src_reg = IMX7D_SRC_SCR,
0250 .src_mask = IMX7D_M4_RST_MASK,
0251 .src_start = IMX7D_M4_START,
0252 .src_stop = IMX7D_M4_STOP,
0253 .att = imx_rproc_att_imx8mq,
0254 .att_size = ARRAY_SIZE(imx_rproc_att_imx8mq),
0255 .method = IMX_RPROC_MMIO,
0256 };
0257
0258 static const struct imx_rproc_dcfg imx_rproc_cfg_imx8ulp = {
0259 .att = imx_rproc_att_imx8ulp,
0260 .att_size = ARRAY_SIZE(imx_rproc_att_imx8ulp),
0261 .method = IMX_RPROC_NONE,
0262 };
0263
0264 static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = {
0265 .att = imx_rproc_att_imx7ulp,
0266 .att_size = ARRAY_SIZE(imx_rproc_att_imx7ulp),
0267 .method = IMX_RPROC_NONE,
0268 };
0269
0270 static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = {
0271 .src_reg = IMX7D_SRC_SCR,
0272 .src_mask = IMX7D_M4_RST_MASK,
0273 .src_start = IMX7D_M4_START,
0274 .src_stop = IMX7D_M4_STOP,
0275 .att = imx_rproc_att_imx7d,
0276 .att_size = ARRAY_SIZE(imx_rproc_att_imx7d),
0277 .method = IMX_RPROC_MMIO,
0278 };
0279
0280 static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = {
0281 .src_reg = IMX6SX_SRC_SCR,
0282 .src_mask = IMX6SX_M4_RST_MASK,
0283 .src_start = IMX6SX_M4_START,
0284 .src_stop = IMX6SX_M4_STOP,
0285 .att = imx_rproc_att_imx6sx,
0286 .att_size = ARRAY_SIZE(imx_rproc_att_imx6sx),
0287 .method = IMX_RPROC_MMIO,
0288 };
0289
0290 static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = {
0291 .att = imx_rproc_att_imx93,
0292 .att_size = ARRAY_SIZE(imx_rproc_att_imx93),
0293 .method = IMX_RPROC_SMC,
0294 };
0295
0296 static int imx_rproc_start(struct rproc *rproc)
0297 {
0298 struct imx_rproc *priv = rproc->priv;
0299 const struct imx_rproc_dcfg *dcfg = priv->dcfg;
0300 struct device *dev = priv->dev;
0301 struct arm_smccc_res res;
0302 int ret;
0303
0304 switch (dcfg->method) {
0305 case IMX_RPROC_MMIO:
0306 ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask,
0307 dcfg->src_start);
0308 break;
0309 case IMX_RPROC_SMC:
0310 arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res);
0311 ret = res.a0;
0312 break;
0313 default:
0314 return -EOPNOTSUPP;
0315 }
0316
0317 if (ret)
0318 dev_err(dev, "Failed to enable remote core!\n");
0319
0320 return ret;
0321 }
0322
0323 static int imx_rproc_stop(struct rproc *rproc)
0324 {
0325 struct imx_rproc *priv = rproc->priv;
0326 const struct imx_rproc_dcfg *dcfg = priv->dcfg;
0327 struct device *dev = priv->dev;
0328 struct arm_smccc_res res;
0329 int ret;
0330
0331 switch (dcfg->method) {
0332 case IMX_RPROC_MMIO:
0333 ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask,
0334 dcfg->src_stop);
0335 break;
0336 case IMX_RPROC_SMC:
0337 arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res);
0338 ret = res.a0;
0339 if (res.a1)
0340 dev_info(dev, "Not in wfi, force stopped\n");
0341 break;
0342 default:
0343 return -EOPNOTSUPP;
0344 }
0345
0346 if (ret)
0347 dev_err(dev, "Failed to stop remote core\n");
0348
0349 return ret;
0350 }
0351
0352 static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
0353 size_t len, u64 *sys, bool *is_iomem)
0354 {
0355 const struct imx_rproc_dcfg *dcfg = priv->dcfg;
0356 int i;
0357
0358
0359 for (i = 0; i < dcfg->att_size; i++) {
0360 const struct imx_rproc_att *att = &dcfg->att[i];
0361
0362 if (da >= att->da && da + len < att->da + att->size) {
0363 unsigned int offset = da - att->da;
0364
0365 *sys = att->sa + offset;
0366 if (is_iomem)
0367 *is_iomem = att->flags & ATT_IOMEM;
0368 return 0;
0369 }
0370 }
0371
0372 dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%zx\n",
0373 da, len);
0374 return -ENOENT;
0375 }
0376
0377 static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
0378 {
0379 struct imx_rproc *priv = rproc->priv;
0380 void *va = NULL;
0381 u64 sys;
0382 int i;
0383
0384 if (len == 0)
0385 return NULL;
0386
0387
0388
0389
0390
0391 if (imx_rproc_da_to_sys(priv, da, len, &sys, is_iomem))
0392 return NULL;
0393
0394 for (i = 0; i < IMX_RPROC_MEM_MAX; i++) {
0395 if (sys >= priv->mem[i].sys_addr && sys + len <
0396 priv->mem[i].sys_addr + priv->mem[i].size) {
0397 unsigned int offset = sys - priv->mem[i].sys_addr;
0398
0399 va = (__force void *)(priv->mem[i].cpu_addr + offset);
0400 break;
0401 }
0402 }
0403
0404 dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%zx va = 0x%p\n",
0405 da, len, va);
0406
0407 return va;
0408 }
0409
0410 static int imx_rproc_mem_alloc(struct rproc *rproc,
0411 struct rproc_mem_entry *mem)
0412 {
0413 struct device *dev = rproc->dev.parent;
0414 void *va;
0415
0416 dev_dbg(dev, "map memory: %p+%zx\n", &mem->dma, mem->len);
0417 va = ioremap_wc(mem->dma, mem->len);
0418 if (IS_ERR_OR_NULL(va)) {
0419 dev_err(dev, "Unable to map memory region: %p+%zx\n",
0420 &mem->dma, mem->len);
0421 return -ENOMEM;
0422 }
0423
0424
0425 mem->va = va;
0426
0427 return 0;
0428 }
0429
0430 static int imx_rproc_mem_release(struct rproc *rproc,
0431 struct rproc_mem_entry *mem)
0432 {
0433 dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma);
0434 iounmap(mem->va);
0435
0436 return 0;
0437 }
0438
0439 static int imx_rproc_prepare(struct rproc *rproc)
0440 {
0441 struct imx_rproc *priv = rproc->priv;
0442 struct device_node *np = priv->dev->of_node;
0443 struct of_phandle_iterator it;
0444 struct rproc_mem_entry *mem;
0445 struct reserved_mem *rmem;
0446 u32 da;
0447
0448
0449 of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
0450 while (of_phandle_iterator_next(&it) == 0) {
0451
0452
0453
0454
0455 if (!strcmp(it.node->name, "vdev0buffer"))
0456 continue;
0457
0458 if (!strcmp(it.node->name, "rsc-table"))
0459 continue;
0460
0461 rmem = of_reserved_mem_lookup(it.node);
0462 if (!rmem) {
0463 dev_err(priv->dev, "unable to acquire memory-region\n");
0464 return -EINVAL;
0465 }
0466
0467
0468 da = rmem->base;
0469
0470
0471 mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)rmem->base, rmem->size, da,
0472 imx_rproc_mem_alloc, imx_rproc_mem_release,
0473 it.node->name);
0474
0475 if (mem)
0476 rproc_coredump_add_segment(rproc, da, rmem->size);
0477 else
0478 return -ENOMEM;
0479
0480 rproc_add_carveout(rproc, mem);
0481 }
0482
0483 return 0;
0484 }
0485
0486 static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
0487 {
0488 int ret;
0489
0490 ret = rproc_elf_load_rsc_table(rproc, fw);
0491 if (ret)
0492 dev_info(&rproc->dev, "No resource table in elf\n");
0493
0494 return 0;
0495 }
0496
0497 static void imx_rproc_kick(struct rproc *rproc, int vqid)
0498 {
0499 struct imx_rproc *priv = rproc->priv;
0500 int err;
0501 __u32 mmsg;
0502
0503 if (!priv->tx_ch) {
0504 dev_err(priv->dev, "No initialized mbox tx channel\n");
0505 return;
0506 }
0507
0508
0509
0510
0511
0512 mmsg = vqid << 16;
0513
0514 err = mbox_send_message(priv->tx_ch, (void *)&mmsg);
0515 if (err < 0)
0516 dev_err(priv->dev, "%s: failed (%d, err:%d)\n",
0517 __func__, vqid, err);
0518 }
0519
0520 static int imx_rproc_attach(struct rproc *rproc)
0521 {
0522 return 0;
0523 }
0524
0525 static struct resource_table *imx_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz)
0526 {
0527 struct imx_rproc *priv = rproc->priv;
0528
0529
0530 if (!priv->rsc_table)
0531 return NULL;
0532
0533 *table_sz = SZ_1K;
0534 return (struct resource_table *)priv->rsc_table;
0535 }
0536
0537 static const struct rproc_ops imx_rproc_ops = {
0538 .prepare = imx_rproc_prepare,
0539 .attach = imx_rproc_attach,
0540 .start = imx_rproc_start,
0541 .stop = imx_rproc_stop,
0542 .kick = imx_rproc_kick,
0543 .da_to_va = imx_rproc_da_to_va,
0544 .load = rproc_elf_load_segments,
0545 .parse_fw = imx_rproc_parse_fw,
0546 .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
0547 .get_loaded_rsc_table = imx_rproc_get_loaded_rsc_table,
0548 .sanity_check = rproc_elf_sanity_check,
0549 .get_boot_addr = rproc_elf_get_boot_addr,
0550 };
0551
0552 static int imx_rproc_addr_init(struct imx_rproc *priv,
0553 struct platform_device *pdev)
0554 {
0555 const struct imx_rproc_dcfg *dcfg = priv->dcfg;
0556 struct device *dev = &pdev->dev;
0557 struct device_node *np = dev->of_node;
0558 int a, b = 0, err, nph;
0559
0560
0561 for (a = 0; a < dcfg->att_size; a++) {
0562 const struct imx_rproc_att *att = &dcfg->att[a];
0563
0564 if (!(att->flags & ATT_OWN))
0565 continue;
0566
0567 if (b >= IMX_RPROC_MEM_MAX)
0568 break;
0569
0570 if (att->flags & ATT_IOMEM)
0571 priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev,
0572 att->sa, att->size);
0573 else
0574 priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev,
0575 att->sa, att->size);
0576 if (!priv->mem[b].cpu_addr) {
0577 dev_err(dev, "failed to remap %#x bytes from %#x\n", att->size, att->sa);
0578 return -ENOMEM;
0579 }
0580 priv->mem[b].sys_addr = att->sa;
0581 priv->mem[b].size = att->size;
0582 b++;
0583 }
0584
0585
0586 nph = of_count_phandle_with_args(np, "memory-region", NULL);
0587 if (nph <= 0)
0588 return 0;
0589
0590
0591 for (a = 0; a < nph; a++) {
0592 struct device_node *node;
0593 struct resource res;
0594
0595 node = of_parse_phandle(np, "memory-region", a);
0596
0597 if (!strncmp(node->name, "vdev", strlen("vdev"))) {
0598 of_node_put(node);
0599 continue;
0600 }
0601 err = of_address_to_resource(node, 0, &res);
0602 of_node_put(node);
0603 if (err) {
0604 dev_err(dev, "unable to resolve memory region\n");
0605 return err;
0606 }
0607
0608 if (b >= IMX_RPROC_MEM_MAX)
0609 break;
0610
0611
0612 priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res));
0613 if (!priv->mem[b].cpu_addr) {
0614 dev_err(dev, "failed to remap %pr\n", &res);
0615 return -ENOMEM;
0616 }
0617 priv->mem[b].sys_addr = res.start;
0618 priv->mem[b].size = resource_size(&res);
0619 if (!strcmp(node->name, "rsc-table"))
0620 priv->rsc_table = priv->mem[b].cpu_addr;
0621 b++;
0622 }
0623
0624 return 0;
0625 }
0626
0627 static void imx_rproc_vq_work(struct work_struct *work)
0628 {
0629 struct imx_rproc *priv = container_of(work, struct imx_rproc,
0630 rproc_work);
0631
0632 rproc_vq_interrupt(priv->rproc, 0);
0633 rproc_vq_interrupt(priv->rproc, 1);
0634 }
0635
0636 static void imx_rproc_rx_callback(struct mbox_client *cl, void *msg)
0637 {
0638 struct rproc *rproc = dev_get_drvdata(cl->dev);
0639 struct imx_rproc *priv = rproc->priv;
0640
0641 queue_work(priv->workqueue, &priv->rproc_work);
0642 }
0643
0644 static int imx_rproc_xtr_mbox_init(struct rproc *rproc)
0645 {
0646 struct imx_rproc *priv = rproc->priv;
0647 struct device *dev = priv->dev;
0648 struct mbox_client *cl;
0649 int ret;
0650
0651 if (!of_get_property(dev->of_node, "mbox-names", NULL))
0652 return 0;
0653
0654 cl = &priv->cl;
0655 cl->dev = dev;
0656 cl->tx_block = true;
0657 cl->tx_tout = 100;
0658 cl->knows_txdone = false;
0659 cl->rx_callback = imx_rproc_rx_callback;
0660
0661 priv->tx_ch = mbox_request_channel_byname(cl, "tx");
0662 if (IS_ERR(priv->tx_ch)) {
0663 ret = PTR_ERR(priv->tx_ch);
0664 return dev_err_probe(cl->dev, ret,
0665 "failed to request tx mailbox channel: %d\n", ret);
0666 }
0667
0668 priv->rx_ch = mbox_request_channel_byname(cl, "rx");
0669 if (IS_ERR(priv->rx_ch)) {
0670 mbox_free_channel(priv->tx_ch);
0671 ret = PTR_ERR(priv->rx_ch);
0672 return dev_err_probe(cl->dev, ret,
0673 "failed to request rx mailbox channel: %d\n", ret);
0674 }
0675
0676 return 0;
0677 }
0678
0679 static void imx_rproc_free_mbox(struct rproc *rproc)
0680 {
0681 struct imx_rproc *priv = rproc->priv;
0682
0683 mbox_free_channel(priv->tx_ch);
0684 mbox_free_channel(priv->rx_ch);
0685 }
0686
0687 static int imx_rproc_detect_mode(struct imx_rproc *priv)
0688 {
0689 struct regmap_config config = { .name = "imx-rproc" };
0690 const struct imx_rproc_dcfg *dcfg = priv->dcfg;
0691 struct device *dev = priv->dev;
0692 struct regmap *regmap;
0693 struct arm_smccc_res res;
0694 int ret;
0695 u32 val;
0696
0697 switch (dcfg->method) {
0698 case IMX_RPROC_NONE:
0699 priv->rproc->state = RPROC_DETACHED;
0700 return 0;
0701 case IMX_RPROC_SMC:
0702 arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res);
0703 if (res.a0)
0704 priv->rproc->state = RPROC_DETACHED;
0705 return 0;
0706 default:
0707 break;
0708 }
0709
0710 regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
0711 if (IS_ERR(regmap)) {
0712 dev_err(dev, "failed to find syscon\n");
0713 return PTR_ERR(regmap);
0714 }
0715
0716 priv->regmap = regmap;
0717 regmap_attach_dev(dev, regmap, &config);
0718
0719 ret = regmap_read(regmap, dcfg->src_reg, &val);
0720 if (ret) {
0721 dev_err(dev, "Failed to read src\n");
0722 return ret;
0723 }
0724
0725 if ((val & dcfg->src_mask) != dcfg->src_stop)
0726 priv->rproc->state = RPROC_DETACHED;
0727
0728 return 0;
0729 }
0730
0731 static int imx_rproc_clk_enable(struct imx_rproc *priv)
0732 {
0733 const struct imx_rproc_dcfg *dcfg = priv->dcfg;
0734 struct device *dev = priv->dev;
0735 int ret;
0736
0737
0738 if (dcfg->method == IMX_RPROC_NONE)
0739 return 0;
0740
0741 priv->clk = devm_clk_get(dev, NULL);
0742 if (IS_ERR(priv->clk)) {
0743 dev_err(dev, "Failed to get clock\n");
0744 return PTR_ERR(priv->clk);
0745 }
0746
0747
0748
0749
0750
0751 ret = clk_prepare_enable(priv->clk);
0752 if (ret) {
0753 dev_err(dev, "Failed to enable clock\n");
0754 return ret;
0755 }
0756
0757 return 0;
0758 }
0759
0760 static int imx_rproc_probe(struct platform_device *pdev)
0761 {
0762 struct device *dev = &pdev->dev;
0763 struct device_node *np = dev->of_node;
0764 struct imx_rproc *priv;
0765 struct rproc *rproc;
0766 const struct imx_rproc_dcfg *dcfg;
0767 int ret;
0768
0769
0770 rproc = rproc_alloc(dev, "imx-rproc", &imx_rproc_ops,
0771 NULL, sizeof(*priv));
0772 if (!rproc)
0773 return -ENOMEM;
0774
0775 dcfg = of_device_get_match_data(dev);
0776 if (!dcfg) {
0777 ret = -EINVAL;
0778 goto err_put_rproc;
0779 }
0780
0781 priv = rproc->priv;
0782 priv->rproc = rproc;
0783 priv->dcfg = dcfg;
0784 priv->dev = dev;
0785
0786 dev_set_drvdata(dev, rproc);
0787 priv->workqueue = create_workqueue(dev_name(dev));
0788 if (!priv->workqueue) {
0789 dev_err(dev, "cannot create workqueue\n");
0790 ret = -ENOMEM;
0791 goto err_put_rproc;
0792 }
0793
0794 ret = imx_rproc_xtr_mbox_init(rproc);
0795 if (ret)
0796 goto err_put_wkq;
0797
0798 ret = imx_rproc_addr_init(priv, pdev);
0799 if (ret) {
0800 dev_err(dev, "failed on imx_rproc_addr_init\n");
0801 goto err_put_mbox;
0802 }
0803
0804 ret = imx_rproc_detect_mode(priv);
0805 if (ret)
0806 goto err_put_mbox;
0807
0808 ret = imx_rproc_clk_enable(priv);
0809 if (ret)
0810 goto err_put_mbox;
0811
0812 INIT_WORK(&priv->rproc_work, imx_rproc_vq_work);
0813
0814 if (rproc->state != RPROC_DETACHED)
0815 rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot");
0816
0817 ret = rproc_add(rproc);
0818 if (ret) {
0819 dev_err(dev, "rproc_add failed\n");
0820 goto err_put_clk;
0821 }
0822
0823 return 0;
0824
0825 err_put_clk:
0826 clk_disable_unprepare(priv->clk);
0827 err_put_mbox:
0828 imx_rproc_free_mbox(rproc);
0829 err_put_wkq:
0830 destroy_workqueue(priv->workqueue);
0831 err_put_rproc:
0832 rproc_free(rproc);
0833
0834 return ret;
0835 }
0836
0837 static int imx_rproc_remove(struct platform_device *pdev)
0838 {
0839 struct rproc *rproc = platform_get_drvdata(pdev);
0840 struct imx_rproc *priv = rproc->priv;
0841
0842 clk_disable_unprepare(priv->clk);
0843 rproc_del(rproc);
0844 imx_rproc_free_mbox(rproc);
0845 destroy_workqueue(priv->workqueue);
0846 rproc_free(rproc);
0847
0848 return 0;
0849 }
0850
0851 static const struct of_device_id imx_rproc_of_match[] = {
0852 { .compatible = "fsl,imx7ulp-cm4", .data = &imx_rproc_cfg_imx7ulp },
0853 { .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d },
0854 { .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx },
0855 { .compatible = "fsl,imx8mq-cm4", .data = &imx_rproc_cfg_imx8mq },
0856 { .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq },
0857 { .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn },
0858 { .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn },
0859 { .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },
0860 { .compatible = "fsl,imx93-cm33", .data = &imx_rproc_cfg_imx93 },
0861 {},
0862 };
0863 MODULE_DEVICE_TABLE(of, imx_rproc_of_match);
0864
0865 static struct platform_driver imx_rproc_driver = {
0866 .probe = imx_rproc_probe,
0867 .remove = imx_rproc_remove,
0868 .driver = {
0869 .name = "imx-rproc",
0870 .of_match_table = imx_rproc_of_match,
0871 },
0872 };
0873
0874 module_platform_driver(imx_rproc_driver);
0875
0876 MODULE_LICENSE("GPL v2");
0877 MODULE_DESCRIPTION("i.MX remote processor control driver");
0878 MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");