0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/arm-cci.h>
0018 #include <linux/io.h>
0019 #include <linux/module.h>
0020 #include <linux/of_address.h>
0021 #include <linux/of_platform.h>
0022 #include <linux/platform_device.h>
0023 #include <linux/slab.h>
0024
0025 #include <asm/cacheflush.h>
0026 #include <asm/smp_plat.h>
0027
0028 static void __iomem *cci_ctrl_base __ro_after_init;
0029 static unsigned long cci_ctrl_phys __ro_after_init;
0030
0031 #ifdef CONFIG_ARM_CCI400_PORT_CTRL
0032 struct cci_nb_ports {
0033 unsigned int nb_ace;
0034 unsigned int nb_ace_lite;
0035 };
0036
0037 static const struct cci_nb_ports cci400_ports = {
0038 .nb_ace = 2,
0039 .nb_ace_lite = 3
0040 };
0041
0042 #define CCI400_PORTS_DATA (&cci400_ports)
0043 #else
0044 #define CCI400_PORTS_DATA (NULL)
0045 #endif
0046
0047 static const struct of_device_id arm_cci_matches[] = {
0048 #ifdef CONFIG_ARM_CCI400_COMMON
0049 {.compatible = "arm,cci-400", .data = CCI400_PORTS_DATA },
0050 #endif
0051 #ifdef CONFIG_ARM_CCI5xx_PMU
0052 { .compatible = "arm,cci-500", },
0053 { .compatible = "arm,cci-550", },
0054 #endif
0055 {},
0056 };
0057
0058 static const struct of_dev_auxdata arm_cci_auxdata[] = {
0059 OF_DEV_AUXDATA("arm,cci-400-pmu", 0, NULL, &cci_ctrl_base),
0060 OF_DEV_AUXDATA("arm,cci-400-pmu,r0", 0, NULL, &cci_ctrl_base),
0061 OF_DEV_AUXDATA("arm,cci-400-pmu,r1", 0, NULL, &cci_ctrl_base),
0062 OF_DEV_AUXDATA("arm,cci-500-pmu,r0", 0, NULL, &cci_ctrl_base),
0063 OF_DEV_AUXDATA("arm,cci-550-pmu,r0", 0, NULL, &cci_ctrl_base),
0064 {}
0065 };
0066
0067 #define DRIVER_NAME "ARM-CCI"
0068
0069 static int cci_platform_probe(struct platform_device *pdev)
0070 {
0071 if (!cci_probed())
0072 return -ENODEV;
0073
0074 return of_platform_populate(pdev->dev.of_node, NULL,
0075 arm_cci_auxdata, &pdev->dev);
0076 }
0077
0078 static struct platform_driver cci_platform_driver = {
0079 .driver = {
0080 .name = DRIVER_NAME,
0081 .of_match_table = arm_cci_matches,
0082 },
0083 .probe = cci_platform_probe,
0084 };
0085
0086 static int __init cci_platform_init(void)
0087 {
0088 return platform_driver_register(&cci_platform_driver);
0089 }
0090
0091 #ifdef CONFIG_ARM_CCI400_PORT_CTRL
0092
0093 #define CCI_PORT_CTRL 0x0
0094 #define CCI_CTRL_STATUS 0xc
0095
0096 #define CCI_ENABLE_SNOOP_REQ 0x1
0097 #define CCI_ENABLE_DVM_REQ 0x2
0098 #define CCI_ENABLE_REQ (CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ)
0099
0100 enum cci_ace_port_type {
0101 ACE_INVALID_PORT = 0x0,
0102 ACE_PORT,
0103 ACE_LITE_PORT,
0104 };
0105
0106 struct cci_ace_port {
0107 void __iomem *base;
0108 unsigned long phys;
0109 enum cci_ace_port_type type;
0110 struct device_node *dn;
0111 };
0112
0113 static struct cci_ace_port *ports;
0114 static unsigned int nb_cci_ports;
0115
0116 struct cpu_port {
0117 u64 mpidr;
0118 u32 port;
0119 };
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 #define PORT_VALID_SHIFT 31
0130 #define PORT_VALID (0x1 << PORT_VALID_SHIFT)
0131
0132 static inline void init_cpu_port(struct cpu_port *port, u32 index, u64 mpidr)
0133 {
0134 port->port = PORT_VALID | index;
0135 port->mpidr = mpidr;
0136 }
0137
0138 static inline bool cpu_port_is_valid(struct cpu_port *port)
0139 {
0140 return !!(port->port & PORT_VALID);
0141 }
0142
0143 static inline bool cpu_port_match(struct cpu_port *port, u64 mpidr)
0144 {
0145 return port->mpidr == (mpidr & MPIDR_HWID_BITMASK);
0146 }
0147
0148 static struct cpu_port cpu_port[NR_CPUS];
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 static int __cci_ace_get_port(struct device_node *dn, int type)
0162 {
0163 int i;
0164 bool ace_match;
0165 struct device_node *cci_portn;
0166
0167 cci_portn = of_parse_phandle(dn, "cci-control-port", 0);
0168 for (i = 0; i < nb_cci_ports; i++) {
0169 ace_match = ports[i].type == type;
0170 if (ace_match && cci_portn == ports[i].dn)
0171 return i;
0172 }
0173 return -ENODEV;
0174 }
0175
0176 int cci_ace_get_port(struct device_node *dn)
0177 {
0178 return __cci_ace_get_port(dn, ACE_LITE_PORT);
0179 }
0180 EXPORT_SYMBOL_GPL(cci_ace_get_port);
0181
0182 static void cci_ace_init_ports(void)
0183 {
0184 int port, cpu;
0185 struct device_node *cpun;
0186
0187
0188
0189
0190
0191
0192
0193
0194 for_each_possible_cpu(cpu) {
0195
0196 cpun = of_get_cpu_node(cpu, NULL);
0197
0198 if (WARN(!cpun, "Missing cpu device node\n"))
0199 continue;
0200
0201 port = __cci_ace_get_port(cpun, ACE_PORT);
0202 if (port < 0)
0203 continue;
0204
0205 init_cpu_port(&cpu_port[cpu], port, cpu_logical_map(cpu));
0206 }
0207
0208 for_each_possible_cpu(cpu) {
0209 WARN(!cpu_port_is_valid(&cpu_port[cpu]),
0210 "CPU %u does not have an associated CCI port\n",
0211 cpu);
0212 }
0213 }
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233 static void notrace cci_port_control(unsigned int port, bool enable)
0234 {
0235 void __iomem *base = ports[port].base;
0236
0237 writel_relaxed(enable ? CCI_ENABLE_REQ : 0, base + CCI_PORT_CTRL);
0238
0239
0240
0241
0242
0243
0244
0245
0246 while (readl_relaxed(cci_ctrl_base + CCI_CTRL_STATUS) & 0x1)
0247 ;
0248 }
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 int notrace cci_disable_port_by_cpu(u64 mpidr)
0266 {
0267 int cpu;
0268 bool is_valid;
0269 for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
0270 is_valid = cpu_port_is_valid(&cpu_port[cpu]);
0271 if (is_valid && cpu_port_match(&cpu_port[cpu], mpidr)) {
0272 cci_port_control(cpu_port[cpu].port, false);
0273 return 0;
0274 }
0275 }
0276 return -ENODEV;
0277 }
0278 EXPORT_SYMBOL_GPL(cci_disable_port_by_cpu);
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 asmlinkage void __naked cci_enable_port_for_self(void)
0299 {
0300 asm volatile ("\n"
0301 " .arch armv7-a\n"
0302 " mrc p15, 0, r0, c0, c0, 5 @ get MPIDR value \n"
0303 " and r0, r0, #"__stringify(MPIDR_HWID_BITMASK)" \n"
0304 " adr r1, 5f \n"
0305 " ldr r2, [r1] \n"
0306 " add r1, r1, r2 @ &cpu_port \n"
0307 " add ip, r1, %[sizeof_cpu_port] \n"
0308
0309
0310 "1: ldr r2, [r1, %[offsetof_cpu_port_mpidr_lsb]] \n"
0311 " cmp r2, r0 @ compare MPIDR \n"
0312 " bne 2f \n"
0313
0314
0315 " ldr r3, [r1, %[offsetof_cpu_port_port]] \n"
0316 " tst r3, #"__stringify(PORT_VALID)" \n"
0317 " bne 3f \n"
0318
0319
0320 "2: add r1, r1, %[sizeof_struct_cpu_port] \n"
0321 " cmp r1, ip @ done? \n"
0322 " blo 1b \n"
0323
0324
0325 "cci_port_not_found: \n"
0326 " wfi \n"
0327 " wfe \n"
0328 " b cci_port_not_found \n"
0329
0330
0331 "3: bic r3, r3, #"__stringify(PORT_VALID)" \n"
0332 " adr r0, 6f \n"
0333 " ldmia r0, {r1, r2} \n"
0334 " sub r1, r1, r0 @ virt - phys \n"
0335 " ldr r0, [r0, r2] @ *(&ports) \n"
0336 " mov r2, %[sizeof_struct_ace_port] \n"
0337 " mla r0, r2, r3, r0 @ &ports[index] \n"
0338 " sub r0, r0, r1 @ virt_to_phys() \n"
0339
0340
0341 " ldr r0, [r0, %[offsetof_port_phys]] \n"
0342 " mov r3, %[cci_enable_req]\n"
0343 " str r3, [r0, #"__stringify(CCI_PORT_CTRL)"] \n"
0344
0345
0346 " adr r1, 7f \n"
0347 " ldr r0, [r1] \n"
0348 " ldr r0, [r0, r1] @ cci_ctrl_base \n"
0349 "4: ldr r1, [r0, #"__stringify(CCI_CTRL_STATUS)"] \n"
0350 " tst r1, %[cci_control_status_bits] \n"
0351 " bne 4b \n"
0352
0353 " mov r0, #0 \n"
0354 " bx lr \n"
0355
0356 " .align 2 \n"
0357 "5: .word cpu_port - . \n"
0358 "6: .word . \n"
0359 " .word ports - 6b \n"
0360 "7: .word cci_ctrl_phys - . \n"
0361 : :
0362 [sizeof_cpu_port] "i" (sizeof(cpu_port)),
0363 [cci_enable_req] "i" cpu_to_le32(CCI_ENABLE_REQ),
0364 [cci_control_status_bits] "i" cpu_to_le32(1),
0365 #ifndef __ARMEB__
0366 [offsetof_cpu_port_mpidr_lsb] "i" (offsetof(struct cpu_port, mpidr)),
0367 #else
0368 [offsetof_cpu_port_mpidr_lsb] "i" (offsetof(struct cpu_port, mpidr)+4),
0369 #endif
0370 [offsetof_cpu_port_port] "i" (offsetof(struct cpu_port, port)),
0371 [sizeof_struct_cpu_port] "i" (sizeof(struct cpu_port)),
0372 [sizeof_struct_ace_port] "i" (sizeof(struct cci_ace_port)),
0373 [offsetof_port_phys] "i" (offsetof(struct cci_ace_port, phys)) );
0374 }
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388 int notrace __cci_control_port_by_device(struct device_node *dn, bool enable)
0389 {
0390 int port;
0391
0392 if (!dn)
0393 return -ENODEV;
0394
0395 port = __cci_ace_get_port(dn, ACE_LITE_PORT);
0396 if (WARN_ONCE(port < 0, "node %pOF ACE lite port look-up failure\n",
0397 dn))
0398 return -ENODEV;
0399 cci_port_control(port, enable);
0400 return 0;
0401 }
0402 EXPORT_SYMBOL_GPL(__cci_control_port_by_device);
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415 int notrace __cci_control_port_by_index(u32 port, bool enable)
0416 {
0417 if (port >= nb_cci_ports || ports[port].type == ACE_INVALID_PORT)
0418 return -ENODEV;
0419
0420
0421
0422
0423
0424
0425 if (ports[port].type == ACE_PORT)
0426 return -EPERM;
0427
0428 cci_port_control(port, enable);
0429 return 0;
0430 }
0431 EXPORT_SYMBOL_GPL(__cci_control_port_by_index);
0432
0433 static const struct of_device_id arm_cci_ctrl_if_matches[] = {
0434 {.compatible = "arm,cci-400-ctrl-if", },
0435 {},
0436 };
0437
0438 static int cci_probe_ports(struct device_node *np)
0439 {
0440 struct cci_nb_ports const *cci_config;
0441 int ret, i, nb_ace = 0, nb_ace_lite = 0;
0442 struct device_node *cp;
0443 struct resource res;
0444 const char *match_str;
0445 bool is_ace;
0446
0447
0448 cci_config = of_match_node(arm_cci_matches, np)->data;
0449 if (!cci_config)
0450 return -ENODEV;
0451
0452 nb_cci_ports = cci_config->nb_ace + cci_config->nb_ace_lite;
0453
0454 ports = kcalloc(nb_cci_ports, sizeof(*ports), GFP_KERNEL);
0455 if (!ports)
0456 return -ENOMEM;
0457
0458 for_each_available_child_of_node(np, cp) {
0459 if (!of_match_node(arm_cci_ctrl_if_matches, cp))
0460 continue;
0461
0462 i = nb_ace + nb_ace_lite;
0463
0464 if (i >= nb_cci_ports)
0465 break;
0466
0467 if (of_property_read_string(cp, "interface-type",
0468 &match_str)) {
0469 WARN(1, "node %pOF missing interface-type property\n",
0470 cp);
0471 continue;
0472 }
0473 is_ace = strcmp(match_str, "ace") == 0;
0474 if (!is_ace && strcmp(match_str, "ace-lite")) {
0475 WARN(1, "node %pOF containing invalid interface-type property, skipping it\n",
0476 cp);
0477 continue;
0478 }
0479
0480 ret = of_address_to_resource(cp, 0, &res);
0481 if (!ret) {
0482 ports[i].base = ioremap(res.start, resource_size(&res));
0483 ports[i].phys = res.start;
0484 }
0485 if (ret || !ports[i].base) {
0486 WARN(1, "unable to ioremap CCI port %d\n", i);
0487 continue;
0488 }
0489
0490 if (is_ace) {
0491 if (WARN_ON(nb_ace >= cci_config->nb_ace))
0492 continue;
0493 ports[i].type = ACE_PORT;
0494 ++nb_ace;
0495 } else {
0496 if (WARN_ON(nb_ace_lite >= cci_config->nb_ace_lite))
0497 continue;
0498 ports[i].type = ACE_LITE_PORT;
0499 ++nb_ace_lite;
0500 }
0501 ports[i].dn = cp;
0502 }
0503
0504
0505
0506
0507
0508 if (!nb_ace && !nb_ace_lite)
0509 return -ENODEV;
0510
0511
0512 cci_ace_init_ports();
0513
0514
0515
0516
0517
0518 sync_cache_w(&cci_ctrl_base);
0519 sync_cache_w(&cci_ctrl_phys);
0520 sync_cache_w(&ports);
0521 sync_cache_w(&cpu_port);
0522 __sync_cache_range_w(ports, sizeof(*ports) * nb_cci_ports);
0523 pr_info("ARM CCI driver probed\n");
0524
0525 return 0;
0526 }
0527 #else
0528 static inline int cci_probe_ports(struct device_node *np)
0529 {
0530 return 0;
0531 }
0532 #endif
0533
0534 static int cci_probe(void)
0535 {
0536 int ret;
0537 struct device_node *np;
0538 struct resource res;
0539
0540 np = of_find_matching_node(NULL, arm_cci_matches);
0541 if (!of_device_is_available(np))
0542 return -ENODEV;
0543
0544 ret = of_address_to_resource(np, 0, &res);
0545 if (!ret) {
0546 cci_ctrl_base = ioremap(res.start, resource_size(&res));
0547 cci_ctrl_phys = res.start;
0548 }
0549 if (ret || !cci_ctrl_base) {
0550 WARN(1, "unable to ioremap CCI ctrl\n");
0551 return -ENXIO;
0552 }
0553
0554 return cci_probe_ports(np);
0555 }
0556
0557 static int cci_init_status = -EAGAIN;
0558 static DEFINE_MUTEX(cci_probing);
0559
0560 static int cci_init(void)
0561 {
0562 if (cci_init_status != -EAGAIN)
0563 return cci_init_status;
0564
0565 mutex_lock(&cci_probing);
0566 if (cci_init_status == -EAGAIN)
0567 cci_init_status = cci_probe();
0568 mutex_unlock(&cci_probing);
0569 return cci_init_status;
0570 }
0571
0572
0573
0574
0575
0576
0577
0578 bool cci_probed(void)
0579 {
0580 return cci_init() == 0;
0581 }
0582 EXPORT_SYMBOL_GPL(cci_probed);
0583
0584 early_initcall(cci_init);
0585 core_initcall(cci_platform_init);
0586 MODULE_LICENSE("GPL");
0587 MODULE_DESCRIPTION("ARM CCI support");