hte.c (21958B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2021-2022 NVIDIA Corporation 4 * 5 * Author: Dipen Patel <dipenp@nvidia.com> 6 */ 7 8#include <linux/kernel.h> 9#include <linux/module.h> 10#include <linux/err.h> 11#include <linux/slab.h> 12#include <linux/of.h> 13#include <linux/of_device.h> 14#include <linux/mutex.h> 15#include <linux/uaccess.h> 16#include <linux/hte.h> 17#include <linux/delay.h> 18#include <linux/debugfs.h> 19 20#define HTE_TS_NAME_LEN 10 21 22/* Global list of the HTE devices */ 23static DEFINE_SPINLOCK(hte_lock); 24static LIST_HEAD(hte_devices); 25 26enum { 27 HTE_TS_REGISTERED, 28 HTE_TS_REQ, 29 HTE_TS_DISABLE, 30 HTE_TS_QUEUE_WK, 31}; 32 33/** 34 * struct hte_ts_info - Information related to requested timestamp. 35 * 36 * @xlated_id: Timestamp ID as understood between HTE subsys and HTE provider, 37 * See xlate callback API. 38 * @flags: Flags holding state information. 39 * @hte_cb_flags: Callback related flags. 40 * @seq: Timestamp sequence counter. 41 * @line_name: HTE allocated line name. 42 * @free_attr_name: If set, free the attr name. 43 * @cb: A nonsleeping callback function provided by clients. 44 * @tcb: A secondary sleeping callback function provided by clients. 45 * @dropped_ts: Dropped timestamps. 46 * @slock: Spin lock to synchronize between disable/enable, 47 * request/release APIs. 48 * @cb_work: callback workqueue, used when tcb is specified. 49 * @req_mlock: Lock during timestamp request/release APIs. 50 * @ts_dbg_root: Root for the debug fs. 51 * @gdev: HTE abstract device that this timestamp information belongs to. 52 * @cl_data: Client specific data. 53 */ 54struct hte_ts_info { 55 u32 xlated_id; 56 unsigned long flags; 57 unsigned long hte_cb_flags; 58 u64 seq; 59 char *line_name; 60 bool free_attr_name; 61 hte_ts_cb_t cb; 62 hte_ts_sec_cb_t tcb; 63 atomic_t dropped_ts; 64 spinlock_t slock; 65 struct work_struct cb_work; 66 struct mutex req_mlock; 67 struct dentry *ts_dbg_root; 68 struct hte_device *gdev; 69 void *cl_data; 70}; 71 72/** 73 * struct hte_device - HTE abstract device 74 * @nlines: Number of entities this device supports. 75 * @ts_req: Total number of entities requested. 76 * @sdev: Device used at various debug prints. 77 * @dbg_root: Root directory for debug fs. 78 * @list: List node to store hte_device for each provider. 79 * @chip: HTE chip providing this HTE device. 80 * @owner: helps prevent removal of modules when in use. 81 * @ei: Timestamp information. 82 */ 83struct hte_device { 84 u32 nlines; 85 atomic_t ts_req; 86 struct device *sdev; 87 struct dentry *dbg_root; 88 struct list_head list; 89 struct hte_chip *chip; 90 struct module *owner; 91 struct hte_ts_info ei[]; 92}; 93 94#ifdef CONFIG_DEBUG_FS 95 96static struct dentry *hte_root; 97 98static int __init hte_subsys_dbgfs_init(void) 99{ 100 /* creates /sys/kernel/debug/hte/ */ 101 hte_root = debugfs_create_dir("hte", NULL); 102 103 return 0; 104} 105subsys_initcall(hte_subsys_dbgfs_init); 106 107static void hte_chip_dbgfs_init(struct hte_device *gdev) 108{ 109 const struct hte_chip *chip = gdev->chip; 110 const char *name = chip->name ? chip->name : dev_name(chip->dev); 111 112 gdev->dbg_root = debugfs_create_dir(name, hte_root); 113 114 debugfs_create_atomic_t("ts_requested", 0444, gdev->dbg_root, 115 &gdev->ts_req); 116 debugfs_create_u32("total_ts", 0444, gdev->dbg_root, 117 &gdev->nlines); 118} 119 120static void hte_ts_dbgfs_init(const char *name, struct hte_ts_info *ei) 121{ 122 if (!ei->gdev->dbg_root || !name) 123 return; 124 125 ei->ts_dbg_root = debugfs_create_dir(name, ei->gdev->dbg_root); 126 127 debugfs_create_atomic_t("dropped_timestamps", 0444, ei->ts_dbg_root, 128 &ei->dropped_ts); 129} 130 131#else 132 133static void hte_chip_dbgfs_init(struct hte_device *gdev) 134{ 135} 136 137static void hte_ts_dbgfs_init(const char *name, struct hte_ts_info *ei) 138{ 139} 140 141#endif 142 143/** 144 * hte_ts_put() - Release and disable timestamp for the given desc. 145 * 146 * @desc: timestamp descriptor. 147 * 148 * Context: debugfs_remove_recursive() function call may use sleeping locks, 149 * not suitable from atomic context. 150 * Returns: 0 on success or a negative error code on failure. 151 */ 152int hte_ts_put(struct hte_ts_desc *desc) 153{ 154 int ret = 0; 155 unsigned long flag; 156 struct hte_device *gdev; 157 struct hte_ts_info *ei; 158 159 if (!desc) 160 return -EINVAL; 161 162 ei = desc->hte_data; 163 164 if (!ei || !ei->gdev) 165 return -EINVAL; 166 167 gdev = ei->gdev; 168 169 mutex_lock(&ei->req_mlock); 170 171 if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) && 172 !test_bit(HTE_TS_REGISTERED, &ei->flags))) { 173 dev_info(gdev->sdev, "id:%d is not requested\n", 174 desc->attr.line_id); 175 ret = -EINVAL; 176 goto unlock; 177 } 178 179 if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) && 180 test_bit(HTE_TS_REGISTERED, &ei->flags))) { 181 dev_info(gdev->sdev, "id:%d is registered but not requested\n", 182 desc->attr.line_id); 183 ret = -EINVAL; 184 goto unlock; 185 } 186 187 if (test_bit(HTE_TS_REQ, &ei->flags) && 188 !test_bit(HTE_TS_REGISTERED, &ei->flags)) { 189 clear_bit(HTE_TS_REQ, &ei->flags); 190 desc->hte_data = NULL; 191 ret = 0; 192 goto mod_put; 193 } 194 195 ret = gdev->chip->ops->release(gdev->chip, desc, ei->xlated_id); 196 if (ret) { 197 dev_err(gdev->sdev, "id: %d free failed\n", 198 desc->attr.line_id); 199 goto unlock; 200 } 201 202 kfree(ei->line_name); 203 if (ei->free_attr_name) 204 kfree_const(desc->attr.name); 205 206 debugfs_remove_recursive(ei->ts_dbg_root); 207 208 spin_lock_irqsave(&ei->slock, flag); 209 210 if (test_bit(HTE_TS_QUEUE_WK, &ei->flags)) { 211 spin_unlock_irqrestore(&ei->slock, flag); 212 flush_work(&ei->cb_work); 213 spin_lock_irqsave(&ei->slock, flag); 214 } 215 216 atomic_dec(&gdev->ts_req); 217 atomic_set(&ei->dropped_ts, 0); 218 219 ei->seq = 1; 220 ei->flags = 0; 221 desc->hte_data = NULL; 222 223 spin_unlock_irqrestore(&ei->slock, flag); 224 225 ei->cb = NULL; 226 ei->tcb = NULL; 227 ei->cl_data = NULL; 228 229mod_put: 230 module_put(gdev->owner); 231unlock: 232 mutex_unlock(&ei->req_mlock); 233 dev_dbg(gdev->sdev, "release id: %d\n", desc->attr.line_id); 234 235 return ret; 236} 237EXPORT_SYMBOL_GPL(hte_ts_put); 238 239static int hte_ts_dis_en_common(struct hte_ts_desc *desc, bool en) 240{ 241 u32 ts_id; 242 struct hte_device *gdev; 243 struct hte_ts_info *ei; 244 int ret; 245 unsigned long flag; 246 247 if (!desc) 248 return -EINVAL; 249 250 ei = desc->hte_data; 251 252 if (!ei || !ei->gdev) 253 return -EINVAL; 254 255 gdev = ei->gdev; 256 ts_id = desc->attr.line_id; 257 258 mutex_lock(&ei->req_mlock); 259 260 if (!test_bit(HTE_TS_REGISTERED, &ei->flags)) { 261 dev_dbg(gdev->sdev, "id:%d is not registered", ts_id); 262 ret = -EUSERS; 263 goto out; 264 } 265 266 spin_lock_irqsave(&ei->slock, flag); 267 268 if (en) { 269 if (!test_bit(HTE_TS_DISABLE, &ei->flags)) { 270 ret = 0; 271 goto out_unlock; 272 } 273 274 spin_unlock_irqrestore(&ei->slock, flag); 275 ret = gdev->chip->ops->enable(gdev->chip, ei->xlated_id); 276 if (ret) { 277 dev_warn(gdev->sdev, "id: %d enable failed\n", 278 ts_id); 279 goto out; 280 } 281 282 spin_lock_irqsave(&ei->slock, flag); 283 clear_bit(HTE_TS_DISABLE, &ei->flags); 284 } else { 285 if (test_bit(HTE_TS_DISABLE, &ei->flags)) { 286 ret = 0; 287 goto out_unlock; 288 } 289 290 spin_unlock_irqrestore(&ei->slock, flag); 291 ret = gdev->chip->ops->disable(gdev->chip, ei->xlated_id); 292 if (ret) { 293 dev_warn(gdev->sdev, "id: %d disable failed\n", 294 ts_id); 295 goto out; 296 } 297 298 spin_lock_irqsave(&ei->slock, flag); 299 set_bit(HTE_TS_DISABLE, &ei->flags); 300 } 301 302out_unlock: 303 spin_unlock_irqrestore(&ei->slock, flag); 304out: 305 mutex_unlock(&ei->req_mlock); 306 return ret; 307} 308 309/** 310 * hte_disable_ts() - Disable timestamp on given descriptor. 311 * 312 * The API does not release any resources associated with desc. 313 * 314 * @desc: ts descriptor, this is the same as returned by the request API. 315 * 316 * Context: Holds mutex lock, not suitable from atomic context. 317 * Returns: 0 on success or a negative error code on failure. 318 */ 319int hte_disable_ts(struct hte_ts_desc *desc) 320{ 321 return hte_ts_dis_en_common(desc, false); 322} 323EXPORT_SYMBOL_GPL(hte_disable_ts); 324 325/** 326 * hte_enable_ts() - Enable timestamp on given descriptor. 327 * 328 * @desc: ts descriptor, this is the same as returned by the request API. 329 * 330 * Context: Holds mutex lock, not suitable from atomic context. 331 * Returns: 0 on success or a negative error code on failure. 332 */ 333int hte_enable_ts(struct hte_ts_desc *desc) 334{ 335 return hte_ts_dis_en_common(desc, true); 336} 337EXPORT_SYMBOL_GPL(hte_enable_ts); 338 339static void hte_do_cb_work(struct work_struct *w) 340{ 341 unsigned long flag; 342 struct hte_ts_info *ei = container_of(w, struct hte_ts_info, cb_work); 343 344 if (unlikely(!ei->tcb)) 345 return; 346 347 ei->tcb(ei->cl_data); 348 349 spin_lock_irqsave(&ei->slock, flag); 350 clear_bit(HTE_TS_QUEUE_WK, &ei->flags); 351 spin_unlock_irqrestore(&ei->slock, flag); 352} 353 354static int __hte_req_ts(struct hte_ts_desc *desc, hte_ts_cb_t cb, 355 hte_ts_sec_cb_t tcb, void *data) 356{ 357 int ret; 358 struct hte_device *gdev; 359 struct hte_ts_info *ei = desc->hte_data; 360 361 gdev = ei->gdev; 362 /* 363 * There is a chance that multiple consumers requesting same entity, 364 * lock here. 365 */ 366 mutex_lock(&ei->req_mlock); 367 368 if (test_bit(HTE_TS_REGISTERED, &ei->flags) || 369 !test_bit(HTE_TS_REQ, &ei->flags)) { 370 dev_dbg(gdev->chip->dev, "id:%u req failed\n", 371 desc->attr.line_id); 372 ret = -EUSERS; 373 goto unlock; 374 } 375 376 ei->cb = cb; 377 ei->tcb = tcb; 378 if (tcb) 379 INIT_WORK(&ei->cb_work, hte_do_cb_work); 380 381 ret = gdev->chip->ops->request(gdev->chip, desc, ei->xlated_id); 382 if (ret < 0) { 383 dev_err(gdev->chip->dev, "ts request failed\n"); 384 goto unlock; 385 } 386 387 ei->cl_data = data; 388 ei->seq = 1; 389 390 atomic_inc(&gdev->ts_req); 391 392 ei->line_name = NULL; 393 if (!desc->attr.name) { 394 ei->line_name = kzalloc(HTE_TS_NAME_LEN, GFP_KERNEL); 395 if (ei->line_name) 396 scnprintf(ei->line_name, HTE_TS_NAME_LEN, "ts_%u", 397 desc->attr.line_id); 398 } 399 400 hte_ts_dbgfs_init(desc->attr.name == NULL ? 401 ei->line_name : desc->attr.name, ei); 402 set_bit(HTE_TS_REGISTERED, &ei->flags); 403 404 dev_dbg(gdev->chip->dev, "id: %u, xlated id:%u", 405 desc->attr.line_id, ei->xlated_id); 406 407 ret = 0; 408 409unlock: 410 mutex_unlock(&ei->req_mlock); 411 412 return ret; 413} 414 415static int hte_bind_ts_info_locked(struct hte_ts_info *ei, 416 struct hte_ts_desc *desc, u32 x_id) 417{ 418 int ret = 0; 419 420 mutex_lock(&ei->req_mlock); 421 422 if (test_bit(HTE_TS_REQ, &ei->flags)) { 423 dev_dbg(ei->gdev->chip->dev, "id:%u is already requested\n", 424 desc->attr.line_id); 425 ret = -EUSERS; 426 goto out; 427 } 428 429 set_bit(HTE_TS_REQ, &ei->flags); 430 desc->hte_data = ei; 431 ei->xlated_id = x_id; 432 433out: 434 mutex_unlock(&ei->req_mlock); 435 436 return ret; 437} 438 439static struct hte_device *of_node_to_htedevice(struct device_node *np) 440{ 441 struct hte_device *gdev; 442 443 spin_lock(&hte_lock); 444 445 list_for_each_entry(gdev, &hte_devices, list) 446 if (gdev->chip && gdev->chip->dev && 447 gdev->chip->dev->of_node == np) { 448 spin_unlock(&hte_lock); 449 return gdev; 450 } 451 452 spin_unlock(&hte_lock); 453 454 return ERR_PTR(-ENODEV); 455} 456 457static struct hte_device *hte_find_dev_from_linedata(struct hte_ts_desc *desc) 458{ 459 struct hte_device *gdev; 460 461 spin_lock(&hte_lock); 462 463 list_for_each_entry(gdev, &hte_devices, list) 464 if (gdev->chip && gdev->chip->match_from_linedata) { 465 if (!gdev->chip->match_from_linedata(gdev->chip, desc)) 466 continue; 467 spin_unlock(&hte_lock); 468 return gdev; 469 } 470 471 spin_unlock(&hte_lock); 472 473 return ERR_PTR(-ENODEV); 474} 475 476/** 477 * of_hte_req_count - Return the number of entities to timestamp. 478 * 479 * The function returns the total count of the requested entities to timestamp 480 * by parsing device tree. 481 * 482 * @dev: The HTE consumer. 483 * 484 * Returns: Positive number on success, -ENOENT if no entries, 485 * -EINVAL for other errors. 486 */ 487int of_hte_req_count(struct device *dev) 488{ 489 int count; 490 491 if (!dev || !dev->of_node) 492 return -EINVAL; 493 494 count = of_count_phandle_with_args(dev->of_node, "timestamps", 495 "#timestamp-cells"); 496 497 return count ? count : -ENOENT; 498} 499EXPORT_SYMBOL_GPL(of_hte_req_count); 500 501static inline struct hte_device *hte_get_dev(struct hte_ts_desc *desc) 502{ 503 return hte_find_dev_from_linedata(desc); 504} 505 506static struct hte_device *hte_of_get_dev(struct device *dev, 507 struct hte_ts_desc *desc, 508 int index, 509 struct of_phandle_args *args, 510 bool *free_name) 511{ 512 int ret; 513 struct device_node *np; 514 char *temp; 515 516 if (!dev->of_node) 517 return ERR_PTR(-EINVAL); 518 519 np = dev->of_node; 520 521 if (!of_find_property(np, "timestamp-names", NULL)) { 522 /* Let hte core construct it during request time */ 523 desc->attr.name = NULL; 524 } else { 525 ret = of_property_read_string_index(np, "timestamp-names", 526 index, &desc->attr.name); 527 if (ret) { 528 pr_err("can't parse \"timestamp-names\" property\n"); 529 return ERR_PTR(ret); 530 } 531 *free_name = false; 532 if (desc->attr.name) { 533 temp = skip_spaces(desc->attr.name); 534 if (!*temp) 535 desc->attr.name = NULL; 536 } 537 } 538 539 ret = of_parse_phandle_with_args(np, "timestamps", "#timestamp-cells", 540 index, args); 541 if (ret) { 542 pr_err("%s(): can't parse \"timestamps\" property\n", 543 __func__); 544 return ERR_PTR(ret); 545 } 546 547 of_node_put(args->np); 548 549 return of_node_to_htedevice(args->np); 550} 551 552/** 553 * hte_ts_get() - The function to initialize and obtain HTE desc. 554 * 555 * The function initializes the consumer provided HTE descriptor. If consumer 556 * has device tree node, index is used to parse the line id and other details. 557 * The function needs to be called before using any request APIs. 558 * 559 * @dev: HTE consumer/client device, used in case of parsing device tree node. 560 * @desc: Pre-allocated timestamp descriptor. 561 * @index: The index will be used as an index to parse line_id from the 562 * device tree node if node is present. 563 * 564 * Context: Holds mutex lock. 565 * Returns: Returns 0 on success or negative error code on failure. 566 */ 567int hte_ts_get(struct device *dev, struct hte_ts_desc *desc, int index) 568{ 569 struct hte_device *gdev; 570 struct hte_ts_info *ei; 571 const struct fwnode_handle *fwnode; 572 struct of_phandle_args args; 573 u32 xlated_id; 574 int ret; 575 bool free_name = false; 576 577 if (!desc) 578 return -EINVAL; 579 580 fwnode = dev ? dev_fwnode(dev) : NULL; 581 582 if (is_of_node(fwnode)) 583 gdev = hte_of_get_dev(dev, desc, index, &args, &free_name); 584 else 585 gdev = hte_get_dev(desc); 586 587 if (IS_ERR(gdev)) { 588 pr_err("%s() no hte dev found\n", __func__); 589 return PTR_ERR(gdev); 590 } 591 592 if (!try_module_get(gdev->owner)) 593 return -ENODEV; 594 595 if (!gdev->chip) { 596 pr_err("%s(): requested id does not have provider\n", 597 __func__); 598 ret = -ENODEV; 599 goto put; 600 } 601 602 if (is_of_node(fwnode)) { 603 if (!gdev->chip->xlate_of) 604 ret = -EINVAL; 605 else 606 ret = gdev->chip->xlate_of(gdev->chip, &args, 607 desc, &xlated_id); 608 } else { 609 if (!gdev->chip->xlate_plat) 610 ret = -EINVAL; 611 else 612 ret = gdev->chip->xlate_plat(gdev->chip, desc, 613 &xlated_id); 614 } 615 616 if (ret < 0) 617 goto put; 618 619 ei = &gdev->ei[xlated_id]; 620 621 ret = hte_bind_ts_info_locked(ei, desc, xlated_id); 622 if (ret) 623 goto put; 624 625 ei->free_attr_name = free_name; 626 627 return 0; 628 629put: 630 module_put(gdev->owner); 631 return ret; 632} 633EXPORT_SYMBOL_GPL(hte_ts_get); 634 635static void __devm_hte_release_ts(void *res) 636{ 637 hte_ts_put(res); 638} 639 640/** 641 * hte_request_ts_ns() - The API to request and enable hardware timestamp in 642 * nanoseconds. 643 * 644 * The entity is provider specific for example, GPIO lines, signals, buses 645 * etc...The API allocates necessary resources and enables the timestamp. 646 * 647 * @desc: Pre-allocated and initialized timestamp descriptor. 648 * @cb: Callback to push the timestamp data to consumer. 649 * @tcb: Optional callback. If its provided, subsystem initializes 650 * workqueue. It is called when cb returns HTE_RUN_SECOND_CB. 651 * @data: Client data, used during cb and tcb callbacks. 652 * 653 * Context: Holds mutex lock. 654 * Returns: Returns 0 on success or negative error code on failure. 655 */ 656int hte_request_ts_ns(struct hte_ts_desc *desc, hte_ts_cb_t cb, 657 hte_ts_sec_cb_t tcb, void *data) 658{ 659 int ret; 660 struct hte_ts_info *ei; 661 662 if (!desc || !desc->hte_data || !cb) 663 return -EINVAL; 664 665 ei = desc->hte_data; 666 if (!ei || !ei->gdev) 667 return -EINVAL; 668 669 ret = __hte_req_ts(desc, cb, tcb, data); 670 if (ret < 0) { 671 dev_err(ei->gdev->chip->dev, 672 "failed to request id: %d\n", desc->attr.line_id); 673 return ret; 674 } 675 676 return 0; 677} 678EXPORT_SYMBOL_GPL(hte_request_ts_ns); 679 680/** 681 * devm_hte_request_ts_ns() - Resource managed API to request and enable 682 * hardware timestamp in nanoseconds. 683 * 684 * The entity is provider specific for example, GPIO lines, signals, buses 685 * etc...The API allocates necessary resources and enables the timestamp. It 686 * deallocates and disables automatically when the consumer exits. 687 * 688 * @dev: HTE consumer/client device. 689 * @desc: Pre-allocated and initialized timestamp descriptor. 690 * @cb: Callback to push the timestamp data to consumer. 691 * @tcb: Optional callback. If its provided, subsystem initializes 692 * workqueue. It is called when cb returns HTE_RUN_SECOND_CB. 693 * @data: Client data, used during cb and tcb callbacks. 694 * 695 * Context: Holds mutex lock. 696 * Returns: Returns 0 on success or negative error code on failure. 697 */ 698int devm_hte_request_ts_ns(struct device *dev, struct hte_ts_desc *desc, 699 hte_ts_cb_t cb, hte_ts_sec_cb_t tcb, 700 void *data) 701{ 702 int err; 703 704 if (!dev) 705 return -EINVAL; 706 707 err = hte_request_ts_ns(desc, cb, tcb, data); 708 if (err) 709 return err; 710 711 err = devm_add_action_or_reset(dev, __devm_hte_release_ts, desc); 712 if (err) 713 return err; 714 715 return 0; 716} 717EXPORT_SYMBOL_GPL(devm_hte_request_ts_ns); 718 719/** 720 * hte_init_line_attr() - Initialize line attributes. 721 * 722 * Zeroes out line attributes and initializes with provided arguments. 723 * The function needs to be called before calling any consumer facing 724 * functions. 725 * 726 * @desc: Pre-allocated timestamp descriptor. 727 * @line_id: line id. 728 * @edge_flags: edge flags related to line_id. 729 * @name: name of the line. 730 * @data: line data related to line_id. 731 * 732 * Context: Any. 733 * Returns: 0 on success or negative error code for the failure. 734 */ 735int hte_init_line_attr(struct hte_ts_desc *desc, u32 line_id, 736 unsigned long edge_flags, const char *name, void *data) 737{ 738 if (!desc) 739 return -EINVAL; 740 741 memset(&desc->attr, 0, sizeof(desc->attr)); 742 743 desc->attr.edge_flags = edge_flags; 744 desc->attr.line_id = line_id; 745 desc->attr.line_data = data; 746 if (name) { 747 name = kstrdup_const(name, GFP_KERNEL); 748 if (!name) 749 return -ENOMEM; 750 } 751 752 desc->attr.name = name; 753 754 return 0; 755} 756EXPORT_SYMBOL_GPL(hte_init_line_attr); 757 758/** 759 * hte_get_clk_src_info() - Get the clock source information for a ts 760 * descriptor. 761 * 762 * @desc: ts descriptor, same as returned from request API. 763 * @ci: The API fills this structure with the clock information data. 764 * 765 * Context: Any context. 766 * Returns: 0 on success else negative error code on failure. 767 */ 768int hte_get_clk_src_info(const struct hte_ts_desc *desc, 769 struct hte_clk_info *ci) 770{ 771 struct hte_chip *chip; 772 struct hte_ts_info *ei; 773 774 if (!desc || !desc->hte_data || !ci) { 775 pr_debug("%s:%d\n", __func__, __LINE__); 776 return -EINVAL; 777 } 778 779 ei = desc->hte_data; 780 if (!ei->gdev || !ei->gdev->chip) 781 return -EINVAL; 782 783 chip = ei->gdev->chip; 784 if (!chip->ops->get_clk_src_info) 785 return -EOPNOTSUPP; 786 787 return chip->ops->get_clk_src_info(chip, ci); 788} 789EXPORT_SYMBOL_GPL(hte_get_clk_src_info); 790 791/** 792 * hte_push_ts_ns() - Push timestamp data in nanoseconds. 793 * 794 * It is used by the provider to push timestamp data. 795 * 796 * @chip: The HTE chip, used during the registration. 797 * @xlated_id: entity id understood by both subsystem and provider, this is 798 * obtained from xlate callback during request API. 799 * @data: timestamp data. 800 * 801 * Returns: 0 on success or a negative error code on failure. 802 */ 803int hte_push_ts_ns(const struct hte_chip *chip, u32 xlated_id, 804 struct hte_ts_data *data) 805{ 806 enum hte_return ret; 807 int st = 0; 808 struct hte_ts_info *ei; 809 unsigned long flag; 810 811 if (!chip || !data || !chip->gdev) 812 return -EINVAL; 813 814 if (xlated_id >= chip->nlines) 815 return -EINVAL; 816 817 ei = &chip->gdev->ei[xlated_id]; 818 819 spin_lock_irqsave(&ei->slock, flag); 820 821 /* timestamp sequence counter */ 822 data->seq = ei->seq++; 823 824 if (!test_bit(HTE_TS_REGISTERED, &ei->flags) || 825 test_bit(HTE_TS_DISABLE, &ei->flags)) { 826 dev_dbg(chip->dev, "Unknown timestamp push\n"); 827 atomic_inc(&ei->dropped_ts); 828 st = -EINVAL; 829 goto unlock; 830 } 831 832 ret = ei->cb(data, ei->cl_data); 833 if (ret == HTE_RUN_SECOND_CB && ei->tcb) { 834 queue_work(system_unbound_wq, &ei->cb_work); 835 set_bit(HTE_TS_QUEUE_WK, &ei->flags); 836 } 837 838unlock: 839 spin_unlock_irqrestore(&ei->slock, flag); 840 841 return st; 842} 843EXPORT_SYMBOL_GPL(hte_push_ts_ns); 844 845static int hte_register_chip(struct hte_chip *chip) 846{ 847 struct hte_device *gdev; 848 u32 i; 849 850 if (!chip || !chip->dev || !chip->dev->of_node) 851 return -EINVAL; 852 853 if (!chip->ops || !chip->ops->request || !chip->ops->release) { 854 dev_err(chip->dev, "Driver needs to provide ops\n"); 855 return -EINVAL; 856 } 857 858 gdev = kzalloc(struct_size(gdev, ei, chip->nlines), GFP_KERNEL); 859 if (!gdev) 860 return -ENOMEM; 861 862 gdev->chip = chip; 863 chip->gdev = gdev; 864 gdev->nlines = chip->nlines; 865 gdev->sdev = chip->dev; 866 867 for (i = 0; i < chip->nlines; i++) { 868 gdev->ei[i].gdev = gdev; 869 mutex_init(&gdev->ei[i].req_mlock); 870 spin_lock_init(&gdev->ei[i].slock); 871 } 872 873 if (chip->dev->driver) 874 gdev->owner = chip->dev->driver->owner; 875 else 876 gdev->owner = THIS_MODULE; 877 878 of_node_get(chip->dev->of_node); 879 880 INIT_LIST_HEAD(&gdev->list); 881 882 spin_lock(&hte_lock); 883 list_add_tail(&gdev->list, &hte_devices); 884 spin_unlock(&hte_lock); 885 886 hte_chip_dbgfs_init(gdev); 887 888 dev_dbg(chip->dev, "Added hte chip\n"); 889 890 return 0; 891} 892 893static int hte_unregister_chip(struct hte_chip *chip) 894{ 895 struct hte_device *gdev; 896 897 if (!chip) 898 return -EINVAL; 899 900 gdev = chip->gdev; 901 902 spin_lock(&hte_lock); 903 list_del(&gdev->list); 904 spin_unlock(&hte_lock); 905 906 gdev->chip = NULL; 907 908 of_node_put(chip->dev->of_node); 909 debugfs_remove_recursive(gdev->dbg_root); 910 kfree(gdev); 911 912 dev_dbg(chip->dev, "Removed hte chip\n"); 913 914 return 0; 915} 916 917static void _hte_devm_unregister_chip(void *chip) 918{ 919 hte_unregister_chip(chip); 920} 921 922/** 923 * devm_hte_register_chip() - Resource managed API to register HTE chip. 924 * 925 * It is used by the provider to register itself with the HTE subsystem. 926 * The unregistration is done automatically when the provider exits. 927 * 928 * @chip: the HTE chip to add to subsystem. 929 * 930 * Returns: 0 on success or a negative error code on failure. 931 */ 932int devm_hte_register_chip(struct hte_chip *chip) 933{ 934 int err; 935 936 err = hte_register_chip(chip); 937 if (err) 938 return err; 939 940 err = devm_add_action_or_reset(chip->dev, _hte_devm_unregister_chip, 941 chip); 942 if (err) 943 return err; 944 945 return 0; 946} 947EXPORT_SYMBOL_GPL(devm_hte_register_chip);