Lines Matching +full:on +full:- +full:chip
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2021-2022 NVIDIA Corporation
34 * struct hte_ts_info - Information related to requested timestamp.
73 * struct hte_device - HTE abstract device
79 * @chip: HTE chip providing this HTE device.
89 struct hte_chip *chip; member
109 const struct hte_chip *chip = gdev->chip; in hte_chip_dbgfs_init() local
110 const char *name = chip->name ? chip->name : dev_name(chip->dev); in hte_chip_dbgfs_init()
112 gdev->dbg_root = debugfs_create_dir(name, hte_root); in hte_chip_dbgfs_init()
114 debugfs_create_atomic_t("ts_requested", 0444, gdev->dbg_root, in hte_chip_dbgfs_init()
115 &gdev->ts_req); in hte_chip_dbgfs_init()
116 debugfs_create_u32("total_ts", 0444, gdev->dbg_root, in hte_chip_dbgfs_init()
117 &gdev->nlines); in hte_chip_dbgfs_init()
122 if (!ei->gdev->dbg_root || !name) in hte_ts_dbgfs_init()
125 ei->ts_dbg_root = debugfs_create_dir(name, ei->gdev->dbg_root); in hte_ts_dbgfs_init()
127 debugfs_create_atomic_t("dropped_timestamps", 0444, ei->ts_dbg_root, in hte_ts_dbgfs_init()
128 &ei->dropped_ts); in hte_ts_dbgfs_init()
144 * hte_ts_put() - Release and disable timestamp for the given desc.
150 * Returns: 0 on success or a negative error code on failure.
160 return -EINVAL; in hte_ts_put()
162 ei = desc->hte_data; in hte_ts_put()
164 if (!ei || !ei->gdev) in hte_ts_put()
165 return -EINVAL; in hte_ts_put()
167 gdev = ei->gdev; in hte_ts_put()
169 mutex_lock(&ei->req_mlock); in hte_ts_put()
171 if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) && in hte_ts_put()
172 !test_bit(HTE_TS_REGISTERED, &ei->flags))) { in hte_ts_put()
173 dev_info(gdev->sdev, "id:%d is not requested\n", in hte_ts_put()
174 desc->attr.line_id); in hte_ts_put()
175 ret = -EINVAL; in hte_ts_put()
179 if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) && in hte_ts_put()
180 test_bit(HTE_TS_REGISTERED, &ei->flags))) { in hte_ts_put()
181 dev_info(gdev->sdev, "id:%d is registered but not requested\n", in hte_ts_put()
182 desc->attr.line_id); in hte_ts_put()
183 ret = -EINVAL; in hte_ts_put()
187 if (test_bit(HTE_TS_REQ, &ei->flags) && in hte_ts_put()
188 !test_bit(HTE_TS_REGISTERED, &ei->flags)) { in hte_ts_put()
189 clear_bit(HTE_TS_REQ, &ei->flags); in hte_ts_put()
190 desc->hte_data = NULL; in hte_ts_put()
195 ret = gdev->chip->ops->release(gdev->chip, desc, ei->xlated_id); in hte_ts_put()
197 dev_err(gdev->sdev, "id: %d free failed\n", in hte_ts_put()
198 desc->attr.line_id); in hte_ts_put()
202 kfree(ei->line_name); in hte_ts_put()
203 if (ei->free_attr_name) in hte_ts_put()
204 kfree_const(desc->attr.name); in hte_ts_put()
206 debugfs_remove_recursive(ei->ts_dbg_root); in hte_ts_put()
208 spin_lock_irqsave(&ei->slock, flag); in hte_ts_put()
210 if (test_bit(HTE_TS_QUEUE_WK, &ei->flags)) { in hte_ts_put()
211 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_put()
212 flush_work(&ei->cb_work); in hte_ts_put()
213 spin_lock_irqsave(&ei->slock, flag); in hte_ts_put()
216 atomic_dec(&gdev->ts_req); in hte_ts_put()
217 atomic_set(&ei->dropped_ts, 0); in hte_ts_put()
219 ei->seq = 1; in hte_ts_put()
220 ei->flags = 0; in hte_ts_put()
221 desc->hte_data = NULL; in hte_ts_put()
223 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_put()
225 ei->cb = NULL; in hte_ts_put()
226 ei->tcb = NULL; in hte_ts_put()
227 ei->cl_data = NULL; in hte_ts_put()
230 module_put(gdev->owner); in hte_ts_put()
232 mutex_unlock(&ei->req_mlock); in hte_ts_put()
233 dev_dbg(gdev->sdev, "release id: %d\n", desc->attr.line_id); in hte_ts_put()
248 return -EINVAL; in hte_ts_dis_en_common()
250 ei = desc->hte_data; in hte_ts_dis_en_common()
252 if (!ei || !ei->gdev) in hte_ts_dis_en_common()
253 return -EINVAL; in hte_ts_dis_en_common()
255 gdev = ei->gdev; in hte_ts_dis_en_common()
256 ts_id = desc->attr.line_id; in hte_ts_dis_en_common()
258 mutex_lock(&ei->req_mlock); in hte_ts_dis_en_common()
260 if (!test_bit(HTE_TS_REGISTERED, &ei->flags)) { in hte_ts_dis_en_common()
261 dev_dbg(gdev->sdev, "id:%d is not registered", ts_id); in hte_ts_dis_en_common()
262 ret = -EUSERS; in hte_ts_dis_en_common()
266 spin_lock_irqsave(&ei->slock, flag); in hte_ts_dis_en_common()
269 if (!test_bit(HTE_TS_DISABLE, &ei->flags)) { in hte_ts_dis_en_common()
274 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_dis_en_common()
275 ret = gdev->chip->ops->enable(gdev->chip, ei->xlated_id); in hte_ts_dis_en_common()
277 dev_warn(gdev->sdev, "id: %d enable failed\n", in hte_ts_dis_en_common()
282 spin_lock_irqsave(&ei->slock, flag); in hte_ts_dis_en_common()
283 clear_bit(HTE_TS_DISABLE, &ei->flags); in hte_ts_dis_en_common()
285 if (test_bit(HTE_TS_DISABLE, &ei->flags)) { in hte_ts_dis_en_common()
290 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_dis_en_common()
291 ret = gdev->chip->ops->disable(gdev->chip, ei->xlated_id); in hte_ts_dis_en_common()
293 dev_warn(gdev->sdev, "id: %d disable failed\n", in hte_ts_dis_en_common()
298 spin_lock_irqsave(&ei->slock, flag); in hte_ts_dis_en_common()
299 set_bit(HTE_TS_DISABLE, &ei->flags); in hte_ts_dis_en_common()
303 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_dis_en_common()
305 mutex_unlock(&ei->req_mlock); in hte_ts_dis_en_common()
310 * hte_disable_ts() - Disable timestamp on given descriptor.
317 * Returns: 0 on success or a negative error code on failure.
326 * hte_enable_ts() - Enable timestamp on given descriptor.
331 * Returns: 0 on success or a negative error code on failure.
344 if (unlikely(!ei->tcb)) in hte_do_cb_work()
347 ei->tcb(ei->cl_data); in hte_do_cb_work()
349 spin_lock_irqsave(&ei->slock, flag); in hte_do_cb_work()
350 clear_bit(HTE_TS_QUEUE_WK, &ei->flags); in hte_do_cb_work()
351 spin_unlock_irqrestore(&ei->slock, flag); in hte_do_cb_work()
359 struct hte_ts_info *ei = desc->hte_data; in __hte_req_ts()
361 gdev = ei->gdev; in __hte_req_ts()
366 mutex_lock(&ei->req_mlock); in __hte_req_ts()
368 if (test_bit(HTE_TS_REGISTERED, &ei->flags) || in __hte_req_ts()
369 !test_bit(HTE_TS_REQ, &ei->flags)) { in __hte_req_ts()
370 dev_dbg(gdev->chip->dev, "id:%u req failed\n", in __hte_req_ts()
371 desc->attr.line_id); in __hte_req_ts()
372 ret = -EUSERS; in __hte_req_ts()
376 ei->cb = cb; in __hte_req_ts()
377 ei->tcb = tcb; in __hte_req_ts()
379 INIT_WORK(&ei->cb_work, hte_do_cb_work); in __hte_req_ts()
381 ret = gdev->chip->ops->request(gdev->chip, desc, ei->xlated_id); in __hte_req_ts()
383 dev_err(gdev->chip->dev, "ts request failed\n"); in __hte_req_ts()
387 ei->cl_data = data; in __hte_req_ts()
388 ei->seq = 1; in __hte_req_ts()
390 atomic_inc(&gdev->ts_req); in __hte_req_ts()
392 ei->line_name = NULL; in __hte_req_ts()
393 if (!desc->attr.name) { in __hte_req_ts()
394 ei->line_name = kzalloc(HTE_TS_NAME_LEN, GFP_KERNEL); in __hte_req_ts()
395 if (ei->line_name) in __hte_req_ts()
396 scnprintf(ei->line_name, HTE_TS_NAME_LEN, "ts_%u", in __hte_req_ts()
397 desc->attr.line_id); in __hte_req_ts()
400 hte_ts_dbgfs_init(desc->attr.name == NULL ? in __hte_req_ts()
401 ei->line_name : desc->attr.name, ei); in __hte_req_ts()
402 set_bit(HTE_TS_REGISTERED, &ei->flags); in __hte_req_ts()
404 dev_dbg(gdev->chip->dev, "id: %u, xlated id:%u", in __hte_req_ts()
405 desc->attr.line_id, ei->xlated_id); in __hte_req_ts()
410 mutex_unlock(&ei->req_mlock); in __hte_req_ts()
420 mutex_lock(&ei->req_mlock); in hte_bind_ts_info_locked()
422 if (test_bit(HTE_TS_REQ, &ei->flags)) { in hte_bind_ts_info_locked()
423 dev_dbg(ei->gdev->chip->dev, "id:%u is already requested\n", in hte_bind_ts_info_locked()
424 desc->attr.line_id); in hte_bind_ts_info_locked()
425 ret = -EUSERS; in hte_bind_ts_info_locked()
429 set_bit(HTE_TS_REQ, &ei->flags); in hte_bind_ts_info_locked()
430 desc->hte_data = ei; in hte_bind_ts_info_locked()
431 ei->xlated_id = x_id; in hte_bind_ts_info_locked()
434 mutex_unlock(&ei->req_mlock); in hte_bind_ts_info_locked()
446 if (gdev->chip && gdev->chip->dev && in of_node_to_htedevice()
447 device_match_of_node(gdev->chip->dev, np)) { in of_node_to_htedevice()
454 return ERR_PTR(-ENODEV); in of_node_to_htedevice()
464 if (gdev->chip && gdev->chip->match_from_linedata) { in hte_find_dev_from_linedata()
465 if (!gdev->chip->match_from_linedata(gdev->chip, desc)) in hte_find_dev_from_linedata()
473 return ERR_PTR(-ENODEV); in hte_find_dev_from_linedata()
477 * of_hte_req_count - Return the number of entities to timestamp.
484 * Returns: Positive number on success, -ENOENT if no entries,
485 * -EINVAL for other errors.
491 if (!dev || !dev->of_node) in of_hte_req_count()
492 return -EINVAL; in of_hte_req_count()
494 count = of_count_phandle_with_args(dev->of_node, "timestamps", in of_hte_req_count()
495 "#timestamp-cells"); in of_hte_req_count()
497 return count ? count : -ENOENT; in of_hte_req_count()
516 if (!dev->of_node) in hte_of_get_dev()
517 return ERR_PTR(-EINVAL); in hte_of_get_dev()
519 np = dev->of_node; in hte_of_get_dev()
521 if (!of_property_present(np, "timestamp-names")) { in hte_of_get_dev()
523 desc->attr.name = NULL; in hte_of_get_dev()
525 ret = of_property_read_string_index(np, "timestamp-names", in hte_of_get_dev()
526 index, &desc->attr.name); in hte_of_get_dev()
528 pr_err("can't parse \"timestamp-names\" property\n"); in hte_of_get_dev()
532 if (desc->attr.name) { in hte_of_get_dev()
533 temp = skip_spaces(desc->attr.name); in hte_of_get_dev()
535 desc->attr.name = NULL; in hte_of_get_dev()
539 ret = of_parse_phandle_with_args(np, "timestamps", "#timestamp-cells", in hte_of_get_dev()
547 of_node_put(args->np); in hte_of_get_dev()
549 return of_node_to_htedevice(args->np); in hte_of_get_dev()
553 * hte_ts_get() - The function to initialize and obtain HTE desc.
560 * @desc: Pre-allocated timestamp descriptor.
565 * Returns: Returns 0 on success or negative error code on failure.
578 return -EINVAL; in hte_ts_get()
592 if (!try_module_get(gdev->owner)) in hte_ts_get()
593 return -ENODEV; in hte_ts_get()
595 if (!gdev->chip) { in hte_ts_get()
598 ret = -ENODEV; in hte_ts_get()
603 if (!gdev->chip->xlate_of) in hte_ts_get()
604 ret = -EINVAL; in hte_ts_get()
606 ret = gdev->chip->xlate_of(gdev->chip, &args, in hte_ts_get()
609 if (!gdev->chip->xlate_plat) in hte_ts_get()
610 ret = -EINVAL; in hte_ts_get()
612 ret = gdev->chip->xlate_plat(gdev->chip, desc, in hte_ts_get()
619 ei = &gdev->ei[xlated_id]; in hte_ts_get()
625 ei->free_attr_name = free_name; in hte_ts_get()
630 module_put(gdev->owner); in hte_ts_get()
641 * hte_request_ts_ns() - The API to request and enable hardware timestamp in
647 * @desc: Pre-allocated and initialized timestamp descriptor.
654 * Returns: Returns 0 on success or negative error code on failure.
662 if (!desc || !desc->hte_data || !cb) in hte_request_ts_ns()
663 return -EINVAL; in hte_request_ts_ns()
665 ei = desc->hte_data; in hte_request_ts_ns()
666 if (!ei || !ei->gdev) in hte_request_ts_ns()
667 return -EINVAL; in hte_request_ts_ns()
671 dev_err(ei->gdev->chip->dev, in hte_request_ts_ns()
672 "failed to request id: %d\n", desc->attr.line_id); in hte_request_ts_ns()
681 * devm_hte_request_ts_ns() - Resource managed API to request and enable
689 * @desc: Pre-allocated and initialized timestamp descriptor.
696 * Returns: Returns 0 on success or negative error code on failure.
705 return -EINVAL; in devm_hte_request_ts_ns()
720 * hte_init_line_attr() - Initialize line attributes.
726 * @desc: Pre-allocated timestamp descriptor.
733 * Returns: 0 on success or negative error code for the failure.
739 return -EINVAL; in hte_init_line_attr()
741 memset(&desc->attr, 0, sizeof(desc->attr)); in hte_init_line_attr()
743 desc->attr.edge_flags = edge_flags; in hte_init_line_attr()
744 desc->attr.line_id = line_id; in hte_init_line_attr()
745 desc->attr.line_data = data; in hte_init_line_attr()
749 return -ENOMEM; in hte_init_line_attr()
752 desc->attr.name = name; in hte_init_line_attr()
759 * hte_get_clk_src_info() - Get the clock source information for a ts
766 * Returns: 0 on success else negative error code on failure.
771 struct hte_chip *chip; in hte_get_clk_src_info() local
774 if (!desc || !desc->hte_data || !ci) { in hte_get_clk_src_info()
776 return -EINVAL; in hte_get_clk_src_info()
779 ei = desc->hte_data; in hte_get_clk_src_info()
780 if (!ei->gdev || !ei->gdev->chip) in hte_get_clk_src_info()
781 return -EINVAL; in hte_get_clk_src_info()
783 chip = ei->gdev->chip; in hte_get_clk_src_info()
784 if (!chip->ops->get_clk_src_info) in hte_get_clk_src_info()
785 return -EOPNOTSUPP; in hte_get_clk_src_info()
787 return chip->ops->get_clk_src_info(chip, ci); in hte_get_clk_src_info()
792 * hte_push_ts_ns() - Push timestamp data in nanoseconds.
796 * @chip: The HTE chip, used during the registration.
801 * Returns: 0 on success or a negative error code on failure.
803 int hte_push_ts_ns(const struct hte_chip *chip, u32 xlated_id, in hte_push_ts_ns() argument
811 if (!chip || !data || !chip->gdev) in hte_push_ts_ns()
812 return -EINVAL; in hte_push_ts_ns()
814 if (xlated_id >= chip->nlines) in hte_push_ts_ns()
815 return -EINVAL; in hte_push_ts_ns()
817 ei = &chip->gdev->ei[xlated_id]; in hte_push_ts_ns()
819 spin_lock_irqsave(&ei->slock, flag); in hte_push_ts_ns()
822 data->seq = ei->seq++; in hte_push_ts_ns()
824 if (!test_bit(HTE_TS_REGISTERED, &ei->flags) || in hte_push_ts_ns()
825 test_bit(HTE_TS_DISABLE, &ei->flags)) { in hte_push_ts_ns()
826 dev_dbg(chip->dev, "Unknown timestamp push\n"); in hte_push_ts_ns()
827 atomic_inc(&ei->dropped_ts); in hte_push_ts_ns()
828 st = -EINVAL; in hte_push_ts_ns()
832 ret = ei->cb(data, ei->cl_data); in hte_push_ts_ns()
833 if (ret == HTE_RUN_SECOND_CB && ei->tcb) { in hte_push_ts_ns()
834 queue_work(system_unbound_wq, &ei->cb_work); in hte_push_ts_ns()
835 set_bit(HTE_TS_QUEUE_WK, &ei->flags); in hte_push_ts_ns()
839 spin_unlock_irqrestore(&ei->slock, flag); in hte_push_ts_ns()
845 static int hte_register_chip(struct hte_chip *chip) in hte_register_chip() argument
850 if (!chip || !chip->dev || !chip->dev->of_node) in hte_register_chip()
851 return -EINVAL; in hte_register_chip()
853 if (!chip->ops || !chip->ops->request || !chip->ops->release) { in hte_register_chip()
854 dev_err(chip->dev, "Driver needs to provide ops\n"); in hte_register_chip()
855 return -EINVAL; in hte_register_chip()
858 gdev = kzalloc(struct_size(gdev, ei, chip->nlines), GFP_KERNEL); in hte_register_chip()
860 return -ENOMEM; in hte_register_chip()
862 gdev->chip = chip; in hte_register_chip()
863 chip->gdev = gdev; in hte_register_chip()
864 gdev->nlines = chip->nlines; in hte_register_chip()
865 gdev->sdev = chip->dev; in hte_register_chip()
867 for (i = 0; i < chip->nlines; i++) { in hte_register_chip()
868 gdev->ei[i].gdev = gdev; in hte_register_chip()
869 mutex_init(&gdev->ei[i].req_mlock); in hte_register_chip()
870 spin_lock_init(&gdev->ei[i].slock); in hte_register_chip()
873 if (chip->dev->driver) in hte_register_chip()
874 gdev->owner = chip->dev->driver->owner; in hte_register_chip()
876 gdev->owner = THIS_MODULE; in hte_register_chip()
878 of_node_get(chip->dev->of_node); in hte_register_chip()
880 INIT_LIST_HEAD(&gdev->list); in hte_register_chip()
883 list_add_tail(&gdev->list, &hte_devices); in hte_register_chip()
888 dev_dbg(chip->dev, "Added hte chip\n"); in hte_register_chip()
893 static int hte_unregister_chip(struct hte_chip *chip) in hte_unregister_chip() argument
897 if (!chip) in hte_unregister_chip()
898 return -EINVAL; in hte_unregister_chip()
900 gdev = chip->gdev; in hte_unregister_chip()
903 list_del(&gdev->list); in hte_unregister_chip()
906 gdev->chip = NULL; in hte_unregister_chip()
908 of_node_put(chip->dev->of_node); in hte_unregister_chip()
909 debugfs_remove_recursive(gdev->dbg_root); in hte_unregister_chip()
912 dev_dbg(chip->dev, "Removed hte chip\n"); in hte_unregister_chip()
917 static void _hte_devm_unregister_chip(void *chip) in _hte_devm_unregister_chip() argument
919 hte_unregister_chip(chip); in _hte_devm_unregister_chip()
923 * devm_hte_register_chip() - Resource managed API to register HTE chip.
928 * @chip: the HTE chip to add to subsystem.
930 * Returns: 0 on success or a negative error code on failure.
932 int devm_hte_register_chip(struct hte_chip *chip) in devm_hte_register_chip() argument
936 err = hte_register_chip(chip); in devm_hte_register_chip()
940 err = devm_add_action_or_reset(chip->dev, _hte_devm_unregister_chip, in devm_hte_register_chip()
941 chip); in devm_hte_register_chip()