Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.19-rc2 717 lines 16 kB view raw
1/* Copyright (c) 2012, The Linux Foundation. All rights reserved. 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License version 2 and 5 * only version 2 as published by the Free Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 */ 12 13#include <linux/kernel.h> 14#include <linux/module.h> 15#include <linux/init.h> 16#include <linux/types.h> 17#include <linux/device.h> 18#include <linux/io.h> 19#include <linux/err.h> 20#include <linux/export.h> 21#include <linux/slab.h> 22#include <linux/mutex.h> 23#include <linux/clk.h> 24#include <linux/coresight.h> 25#include <linux/of_platform.h> 26#include <linux/delay.h> 27 28#include "coresight-priv.h" 29 30static DEFINE_MUTEX(coresight_mutex); 31 32static int coresight_id_match(struct device *dev, void *data) 33{ 34 int trace_id, i_trace_id; 35 struct coresight_device *csdev, *i_csdev; 36 37 csdev = data; 38 i_csdev = to_coresight_device(dev); 39 40 /* 41 * No need to care about oneself and components that are not 42 * sources or not enabled 43 */ 44 if (i_csdev == csdev || !i_csdev->enable || 45 i_csdev->type != CORESIGHT_DEV_TYPE_SOURCE) 46 return 0; 47 48 /* Get the source ID for both compoment */ 49 trace_id = source_ops(csdev)->trace_id(csdev); 50 i_trace_id = source_ops(i_csdev)->trace_id(i_csdev); 51 52 /* All you need is one */ 53 if (trace_id == i_trace_id) 54 return 1; 55 56 return 0; 57} 58 59static int coresight_source_is_unique(struct coresight_device *csdev) 60{ 61 int trace_id = source_ops(csdev)->trace_id(csdev); 62 63 /* this shouldn't happen */ 64 if (trace_id < 0) 65 return 0; 66 67 return !bus_for_each_dev(&coresight_bustype, NULL, 68 csdev, coresight_id_match); 69} 70 71static int coresight_find_link_inport(struct coresight_device *csdev) 72{ 73 int i; 74 struct coresight_device *parent; 75 struct coresight_connection *conn; 76 77 parent = container_of(csdev->path_link.next, 78 struct coresight_device, path_link); 79 80 for (i = 0; i < parent->nr_outport; i++) { 81 conn = &parent->conns[i]; 82 if (conn->child_dev == csdev) 83 return conn->child_port; 84 } 85 86 dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n", 87 dev_name(&parent->dev), dev_name(&csdev->dev)); 88 89 return 0; 90} 91 92static int coresight_find_link_outport(struct coresight_device *csdev) 93{ 94 int i; 95 struct coresight_device *child; 96 struct coresight_connection *conn; 97 98 child = container_of(csdev->path_link.prev, 99 struct coresight_device, path_link); 100 101 for (i = 0; i < csdev->nr_outport; i++) { 102 conn = &csdev->conns[i]; 103 if (conn->child_dev == child) 104 return conn->outport; 105 } 106 107 dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n", 108 dev_name(&csdev->dev), dev_name(&child->dev)); 109 110 return 0; 111} 112 113static int coresight_enable_sink(struct coresight_device *csdev) 114{ 115 int ret; 116 117 if (!csdev->enable) { 118 if (sink_ops(csdev)->enable) { 119 ret = sink_ops(csdev)->enable(csdev); 120 if (ret) 121 return ret; 122 } 123 csdev->enable = true; 124 } 125 126 atomic_inc(csdev->refcnt); 127 128 return 0; 129} 130 131static void coresight_disable_sink(struct coresight_device *csdev) 132{ 133 if (atomic_dec_return(csdev->refcnt) == 0) { 134 if (sink_ops(csdev)->disable) { 135 sink_ops(csdev)->disable(csdev); 136 csdev->enable = false; 137 } 138 } 139} 140 141static int coresight_enable_link(struct coresight_device *csdev) 142{ 143 int ret; 144 int link_subtype; 145 int refport, inport, outport; 146 147 inport = coresight_find_link_inport(csdev); 148 outport = coresight_find_link_outport(csdev); 149 link_subtype = csdev->subtype.link_subtype; 150 151 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) 152 refport = inport; 153 else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) 154 refport = outport; 155 else 156 refport = 0; 157 158 if (atomic_inc_return(&csdev->refcnt[refport]) == 1) { 159 if (link_ops(csdev)->enable) { 160 ret = link_ops(csdev)->enable(csdev, inport, outport); 161 if (ret) 162 return ret; 163 } 164 } 165 166 csdev->enable = true; 167 168 return 0; 169} 170 171static void coresight_disable_link(struct coresight_device *csdev) 172{ 173 int i, nr_conns; 174 int link_subtype; 175 int refport, inport, outport; 176 177 inport = coresight_find_link_inport(csdev); 178 outport = coresight_find_link_outport(csdev); 179 link_subtype = csdev->subtype.link_subtype; 180 181 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { 182 refport = inport; 183 nr_conns = csdev->nr_inport; 184 } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) { 185 refport = outport; 186 nr_conns = csdev->nr_outport; 187 } else { 188 refport = 0; 189 nr_conns = 1; 190 } 191 192 if (atomic_dec_return(&csdev->refcnt[refport]) == 0) { 193 if (link_ops(csdev)->disable) 194 link_ops(csdev)->disable(csdev, inport, outport); 195 } 196 197 for (i = 0; i < nr_conns; i++) 198 if (atomic_read(&csdev->refcnt[i]) != 0) 199 return; 200 201 csdev->enable = false; 202} 203 204static int coresight_enable_source(struct coresight_device *csdev) 205{ 206 int ret; 207 208 if (!coresight_source_is_unique(csdev)) { 209 dev_warn(&csdev->dev, "traceID %d not unique\n", 210 source_ops(csdev)->trace_id(csdev)); 211 return -EINVAL; 212 } 213 214 if (!csdev->enable) { 215 if (source_ops(csdev)->enable) { 216 ret = source_ops(csdev)->enable(csdev); 217 if (ret) 218 return ret; 219 } 220 csdev->enable = true; 221 } 222 223 atomic_inc(csdev->refcnt); 224 225 return 0; 226} 227 228static void coresight_disable_source(struct coresight_device *csdev) 229{ 230 if (atomic_dec_return(csdev->refcnt) == 0) { 231 if (source_ops(csdev)->disable) { 232 source_ops(csdev)->disable(csdev); 233 csdev->enable = false; 234 } 235 } 236} 237 238static int coresight_enable_path(struct list_head *path) 239{ 240 int ret = 0; 241 struct coresight_device *cd; 242 243 list_for_each_entry(cd, path, path_link) { 244 if (cd == list_first_entry(path, struct coresight_device, 245 path_link)) { 246 ret = coresight_enable_sink(cd); 247 } else if (list_is_last(&cd->path_link, path)) { 248 /* 249 * Don't enable the source just yet - this needs to 250 * happen at the very end when all links and sink 251 * along the path have been configured properly. 252 */ 253 ; 254 } else { 255 ret = coresight_enable_link(cd); 256 } 257 if (ret) 258 goto err; 259 } 260 261 return 0; 262err: 263 list_for_each_entry_continue_reverse(cd, path, path_link) { 264 if (cd == list_first_entry(path, struct coresight_device, 265 path_link)) { 266 coresight_disable_sink(cd); 267 } else if (list_is_last(&cd->path_link, path)) { 268 ; 269 } else { 270 coresight_disable_link(cd); 271 } 272 } 273 274 return ret; 275} 276 277static int coresight_disable_path(struct list_head *path) 278{ 279 struct coresight_device *cd; 280 281 list_for_each_entry_reverse(cd, path, path_link) { 282 if (cd == list_first_entry(path, struct coresight_device, 283 path_link)) { 284 coresight_disable_sink(cd); 285 } else if (list_is_last(&cd->path_link, path)) { 286 /* 287 * The source has already been stopped, no need 288 * to do it again here. 289 */ 290 ; 291 } else { 292 coresight_disable_link(cd); 293 } 294 } 295 296 return 0; 297} 298 299static int coresight_build_paths(struct coresight_device *csdev, 300 struct list_head *path, 301 bool enable) 302{ 303 int i, ret = -EINVAL; 304 struct coresight_connection *conn; 305 306 list_add(&csdev->path_link, path); 307 308 if (csdev->type == CORESIGHT_DEV_TYPE_SINK && csdev->activated) { 309 if (enable) 310 ret = coresight_enable_path(path); 311 else 312 ret = coresight_disable_path(path); 313 } else { 314 for (i = 0; i < csdev->nr_outport; i++) { 315 conn = &csdev->conns[i]; 316 if (coresight_build_paths(conn->child_dev, 317 path, enable) == 0) 318 ret = 0; 319 } 320 } 321 322 if (list_first_entry(path, struct coresight_device, path_link) != csdev) 323 dev_err(&csdev->dev, "wrong device in %s\n", __func__); 324 325 list_del(&csdev->path_link); 326 327 return ret; 328} 329 330int coresight_enable(struct coresight_device *csdev) 331{ 332 int ret = 0; 333 LIST_HEAD(path); 334 335 mutex_lock(&coresight_mutex); 336 if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) { 337 ret = -EINVAL; 338 dev_err(&csdev->dev, "wrong device type in %s\n", __func__); 339 goto out; 340 } 341 if (csdev->enable) 342 goto out; 343 344 if (coresight_build_paths(csdev, &path, true)) { 345 dev_err(&csdev->dev, "building path(s) failed\n"); 346 goto out; 347 } 348 349 if (coresight_enable_source(csdev)) 350 dev_err(&csdev->dev, "source enable failed\n"); 351out: 352 mutex_unlock(&coresight_mutex); 353 return ret; 354} 355EXPORT_SYMBOL_GPL(coresight_enable); 356 357void coresight_disable(struct coresight_device *csdev) 358{ 359 LIST_HEAD(path); 360 361 mutex_lock(&coresight_mutex); 362 if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) { 363 dev_err(&csdev->dev, "wrong device type in %s\n", __func__); 364 goto out; 365 } 366 if (!csdev->enable) 367 goto out; 368 369 coresight_disable_source(csdev); 370 if (coresight_build_paths(csdev, &path, false)) 371 dev_err(&csdev->dev, "releasing path(s) failed\n"); 372 373out: 374 mutex_unlock(&coresight_mutex); 375} 376EXPORT_SYMBOL_GPL(coresight_disable); 377 378static ssize_t enable_sink_show(struct device *dev, 379 struct device_attribute *attr, char *buf) 380{ 381 struct coresight_device *csdev = to_coresight_device(dev); 382 383 return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->activated); 384} 385 386static ssize_t enable_sink_store(struct device *dev, 387 struct device_attribute *attr, 388 const char *buf, size_t size) 389{ 390 int ret; 391 unsigned long val; 392 struct coresight_device *csdev = to_coresight_device(dev); 393 394 ret = kstrtoul(buf, 10, &val); 395 if (ret) 396 return ret; 397 398 if (val) 399 csdev->activated = true; 400 else 401 csdev->activated = false; 402 403 return size; 404 405} 406static DEVICE_ATTR_RW(enable_sink); 407 408static ssize_t enable_source_show(struct device *dev, 409 struct device_attribute *attr, char *buf) 410{ 411 struct coresight_device *csdev = to_coresight_device(dev); 412 413 return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable); 414} 415 416static ssize_t enable_source_store(struct device *dev, 417 struct device_attribute *attr, 418 const char *buf, size_t size) 419{ 420 int ret = 0; 421 unsigned long val; 422 struct coresight_device *csdev = to_coresight_device(dev); 423 424 ret = kstrtoul(buf, 10, &val); 425 if (ret) 426 return ret; 427 428 if (val) { 429 ret = coresight_enable(csdev); 430 if (ret) 431 return ret; 432 } else { 433 coresight_disable(csdev); 434 } 435 436 return size; 437} 438static DEVICE_ATTR_RW(enable_source); 439 440static struct attribute *coresight_sink_attrs[] = { 441 &dev_attr_enable_sink.attr, 442 NULL, 443}; 444ATTRIBUTE_GROUPS(coresight_sink); 445 446static struct attribute *coresight_source_attrs[] = { 447 &dev_attr_enable_source.attr, 448 NULL, 449}; 450ATTRIBUTE_GROUPS(coresight_source); 451 452static struct device_type coresight_dev_type[] = { 453 { 454 .name = "none", 455 }, 456 { 457 .name = "sink", 458 .groups = coresight_sink_groups, 459 }, 460 { 461 .name = "link", 462 }, 463 { 464 .name = "linksink", 465 .groups = coresight_sink_groups, 466 }, 467 { 468 .name = "source", 469 .groups = coresight_source_groups, 470 }, 471}; 472 473static void coresight_device_release(struct device *dev) 474{ 475 struct coresight_device *csdev = to_coresight_device(dev); 476 477 kfree(csdev); 478} 479 480static int coresight_orphan_match(struct device *dev, void *data) 481{ 482 int i; 483 bool still_orphan = false; 484 struct coresight_device *csdev, *i_csdev; 485 struct coresight_connection *conn; 486 487 csdev = data; 488 i_csdev = to_coresight_device(dev); 489 490 /* No need to check oneself */ 491 if (csdev == i_csdev) 492 return 0; 493 494 /* Move on to another component if no connection is orphan */ 495 if (!i_csdev->orphan) 496 return 0; 497 /* 498 * Circle throuch all the connection of that component. If we find 499 * an orphan connection whose name matches @csdev, link it. 500 */ 501 for (i = 0; i < i_csdev->nr_outport; i++) { 502 conn = &i_csdev->conns[i]; 503 504 /* We have found at least one orphan connection */ 505 if (conn->child_dev == NULL) { 506 /* Does it match this newly added device? */ 507 if (!strcmp(dev_name(&csdev->dev), conn->child_name)) 508 conn->child_dev = csdev; 509 } else { 510 /* Too bad, this component still has an orphan */ 511 still_orphan = true; 512 } 513 } 514 515 i_csdev->orphan = still_orphan; 516 517 /* 518 * Returning '0' ensures that all known component on the 519 * bus will be checked. 520 */ 521 return 0; 522} 523 524static void coresight_fixup_orphan_conns(struct coresight_device *csdev) 525{ 526 /* 527 * No need to check for a return value as orphan connection(s) 528 * are hooked-up with each newly added component. 529 */ 530 bus_for_each_dev(&coresight_bustype, NULL, 531 csdev, coresight_orphan_match); 532} 533 534 535static int coresight_name_match(struct device *dev, void *data) 536{ 537 char *to_match; 538 struct coresight_device *i_csdev; 539 540 to_match = data; 541 i_csdev = to_coresight_device(dev); 542 543 if (!strcmp(to_match, dev_name(&i_csdev->dev))) 544 return 1; 545 546 return 0; 547} 548 549static void coresight_fixup_device_conns(struct coresight_device *csdev) 550{ 551 int i; 552 struct device *dev = NULL; 553 struct coresight_connection *conn; 554 555 for (i = 0; i < csdev->nr_outport; i++) { 556 conn = &csdev->conns[i]; 557 dev = bus_find_device(&coresight_bustype, NULL, 558 (void *)conn->child_name, 559 coresight_name_match); 560 561 if (dev) { 562 conn->child_dev = to_coresight_device(dev); 563 } else { 564 csdev->orphan = true; 565 conn->child_dev = NULL; 566 } 567 } 568} 569 570/** 571 * coresight_timeout - loop until a bit has changed to a specific state. 572 * @addr: base address of the area of interest. 573 * @offset: address of a register, starting from @addr. 574 * @position: the position of the bit of interest. 575 * @value: the value the bit should have. 576 * 577 * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if 578 * TIMEOUT_US has elapsed, which ever happens first. 579 */ 580 581int coresight_timeout(void __iomem *addr, u32 offset, int position, int value) 582{ 583 int i; 584 u32 val; 585 586 for (i = TIMEOUT_US; i > 0; i--) { 587 val = __raw_readl(addr + offset); 588 /* waiting on the bit to go from 0 to 1 */ 589 if (value) { 590 if (val & BIT(position)) 591 return 0; 592 /* waiting on the bit to go from 1 to 0 */ 593 } else { 594 if (!(val & BIT(position))) 595 return 0; 596 } 597 598 /* 599 * Delay is arbitrary - the specification doesn't say how long 600 * we are expected to wait. Extra check required to make sure 601 * we don't wait needlessly on the last iteration. 602 */ 603 if (i - 1) 604 udelay(1); 605 } 606 607 return -EAGAIN; 608} 609 610struct bus_type coresight_bustype = { 611 .name = "coresight", 612}; 613 614static int __init coresight_init(void) 615{ 616 return bus_register(&coresight_bustype); 617} 618postcore_initcall(coresight_init); 619 620struct coresight_device *coresight_register(struct coresight_desc *desc) 621{ 622 int i; 623 int ret; 624 int link_subtype; 625 int nr_refcnts = 1; 626 atomic_t *refcnts = NULL; 627 struct coresight_device *csdev; 628 struct coresight_connection *conns; 629 630 csdev = kzalloc(sizeof(*csdev), GFP_KERNEL); 631 if (!csdev) { 632 ret = -ENOMEM; 633 goto err_kzalloc_csdev; 634 } 635 636 if (desc->type == CORESIGHT_DEV_TYPE_LINK || 637 desc->type == CORESIGHT_DEV_TYPE_LINKSINK) { 638 link_subtype = desc->subtype.link_subtype; 639 640 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) 641 nr_refcnts = desc->pdata->nr_inport; 642 else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) 643 nr_refcnts = desc->pdata->nr_outport; 644 } 645 646 refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL); 647 if (!refcnts) { 648 ret = -ENOMEM; 649 goto err_kzalloc_refcnts; 650 } 651 652 csdev->refcnt = refcnts; 653 654 csdev->nr_inport = desc->pdata->nr_inport; 655 csdev->nr_outport = desc->pdata->nr_outport; 656 conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL); 657 if (!conns) { 658 ret = -ENOMEM; 659 goto err_kzalloc_conns; 660 } 661 662 for (i = 0; i < csdev->nr_outport; i++) { 663 conns[i].outport = desc->pdata->outports[i]; 664 conns[i].child_name = desc->pdata->child_names[i]; 665 conns[i].child_port = desc->pdata->child_ports[i]; 666 } 667 668 csdev->conns = conns; 669 670 csdev->type = desc->type; 671 csdev->subtype = desc->subtype; 672 csdev->ops = desc->ops; 673 csdev->orphan = false; 674 675 csdev->dev.type = &coresight_dev_type[desc->type]; 676 csdev->dev.groups = desc->groups; 677 csdev->dev.parent = desc->dev; 678 csdev->dev.release = coresight_device_release; 679 csdev->dev.bus = &coresight_bustype; 680 dev_set_name(&csdev->dev, "%s", desc->pdata->name); 681 682 ret = device_register(&csdev->dev); 683 if (ret) 684 goto err_device_register; 685 686 mutex_lock(&coresight_mutex); 687 688 coresight_fixup_device_conns(csdev); 689 coresight_fixup_orphan_conns(csdev); 690 691 mutex_unlock(&coresight_mutex); 692 693 return csdev; 694 695err_device_register: 696 kfree(conns); 697err_kzalloc_conns: 698 kfree(refcnts); 699err_kzalloc_refcnts: 700 kfree(csdev); 701err_kzalloc_csdev: 702 return ERR_PTR(ret); 703} 704EXPORT_SYMBOL_GPL(coresight_register); 705 706void coresight_unregister(struct coresight_device *csdev) 707{ 708 mutex_lock(&coresight_mutex); 709 710 kfree(csdev->conns); 711 device_unregister(&csdev->dev); 712 713 mutex_unlock(&coresight_mutex); 714} 715EXPORT_SYMBOL_GPL(coresight_unregister); 716 717MODULE_LICENSE("GPL v2");