Lines Matching +full:on +full:- +full:chip

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2021-2022 NVIDIA Corporation
32 * struct hte_ts_info - Information related to requested timestamp.
71 * struct hte_device - HTE abstract device
77 * @chip: HTE chip providing this HTE device.
87 struct hte_chip *chip; member
107 const struct hte_chip *chip = gdev->chip; in hte_chip_dbgfs_init() local
108 const char *name = chip->name ? chip->name : dev_name(chip->dev); in hte_chip_dbgfs_init()
110 gdev->dbg_root = debugfs_create_dir(name, hte_root); in hte_chip_dbgfs_init()
112 debugfs_create_atomic_t("ts_requested", 0444, gdev->dbg_root, in hte_chip_dbgfs_init()
113 &gdev->ts_req); in hte_chip_dbgfs_init()
114 debugfs_create_u32("total_ts", 0444, gdev->dbg_root, in hte_chip_dbgfs_init()
115 &gdev->nlines); in hte_chip_dbgfs_init()
120 if (!ei->gdev->dbg_root || !name) in hte_ts_dbgfs_init()
123 ei->ts_dbg_root = debugfs_create_dir(name, ei->gdev->dbg_root); in hte_ts_dbgfs_init()
125 debugfs_create_atomic_t("dropped_timestamps", 0444, ei->ts_dbg_root, in hte_ts_dbgfs_init()
126 &ei->dropped_ts); in hte_ts_dbgfs_init()
142 * hte_ts_put() - Release and disable timestamp for the given desc.
148 * Returns: 0 on success or a negative error code on failure.
158 return -EINVAL; in hte_ts_put()
160 ei = desc->hte_data; in hte_ts_put()
162 if (!ei || !ei->gdev) in hte_ts_put()
163 return -EINVAL; in hte_ts_put()
165 gdev = ei->gdev; in hte_ts_put()
167 mutex_lock(&ei->req_mlock); in hte_ts_put()
169 if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) && in hte_ts_put()
170 !test_bit(HTE_TS_REGISTERED, &ei->flags))) { in hte_ts_put()
171 dev_info(gdev->sdev, "id:%d is not requested\n", in hte_ts_put()
172 desc->attr.line_id); in hte_ts_put()
173 ret = -EINVAL; in hte_ts_put()
177 if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) && in hte_ts_put()
178 test_bit(HTE_TS_REGISTERED, &ei->flags))) { in hte_ts_put()
179 dev_info(gdev->sdev, "id:%d is registered but not requested\n", in hte_ts_put()
180 desc->attr.line_id); in hte_ts_put()
181 ret = -EINVAL; in hte_ts_put()
185 if (test_bit(HTE_TS_REQ, &ei->flags) && in hte_ts_put()
186 !test_bit(HTE_TS_REGISTERED, &ei->flags)) { in hte_ts_put()
187 clear_bit(HTE_TS_REQ, &ei->flags); in hte_ts_put()
188 desc->hte_data = NULL; in hte_ts_put()
193 ret = gdev->chip->ops->release(gdev->chip, desc, ei->xlated_id); in hte_ts_put()
195 dev_err(gdev->sdev, "id: %d free failed\n", in hte_ts_put()
196 desc->attr.line_id); in hte_ts_put()
200 kfree(ei->line_name); in hte_ts_put()
201 if (ei->free_attr_name) in hte_ts_put()
202 kfree_const(desc->attr.name); in hte_ts_put()
204 debugfs_remove_recursive(ei->ts_dbg_root); in hte_ts_put()
206 spin_lock_irqsave(&ei->slock, flag); in hte_ts_put()
208 if (test_bit(HTE_TS_QUEUE_WK, &ei->flags)) { in hte_ts_put()
209 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_put()
210 flush_work(&ei->cb_work); in hte_ts_put()
211 spin_lock_irqsave(&ei->slock, flag); in hte_ts_put()
214 atomic_dec(&gdev->ts_req); in hte_ts_put()
215 atomic_set(&ei->dropped_ts, 0); in hte_ts_put()
217 ei->seq = 1; in hte_ts_put()
218 ei->flags = 0; in hte_ts_put()
219 desc->hte_data = NULL; in hte_ts_put()
221 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_put()
223 ei->cb = NULL; in hte_ts_put()
224 ei->tcb = NULL; in hte_ts_put()
225 ei->cl_data = NULL; in hte_ts_put()
228 module_put(gdev->owner); in hte_ts_put()
230 mutex_unlock(&ei->req_mlock); in hte_ts_put()
231 dev_dbg(gdev->sdev, "release id: %d\n", desc->attr.line_id); in hte_ts_put()
246 return -EINVAL; in hte_ts_dis_en_common()
248 ei = desc->hte_data; in hte_ts_dis_en_common()
250 if (!ei || !ei->gdev) in hte_ts_dis_en_common()
251 return -EINVAL; in hte_ts_dis_en_common()
253 gdev = ei->gdev; in hte_ts_dis_en_common()
254 ts_id = desc->attr.line_id; in hte_ts_dis_en_common()
256 mutex_lock(&ei->req_mlock); in hte_ts_dis_en_common()
258 if (!test_bit(HTE_TS_REGISTERED, &ei->flags)) { in hte_ts_dis_en_common()
259 dev_dbg(gdev->sdev, "id:%d is not registered", ts_id); in hte_ts_dis_en_common()
260 ret = -EUSERS; in hte_ts_dis_en_common()
264 spin_lock_irqsave(&ei->slock, flag); in hte_ts_dis_en_common()
267 if (!test_bit(HTE_TS_DISABLE, &ei->flags)) { in hte_ts_dis_en_common()
272 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_dis_en_common()
273 ret = gdev->chip->ops->enable(gdev->chip, ei->xlated_id); in hte_ts_dis_en_common()
275 dev_warn(gdev->sdev, "id: %d enable failed\n", in hte_ts_dis_en_common()
280 spin_lock_irqsave(&ei->slock, flag); in hte_ts_dis_en_common()
281 clear_bit(HTE_TS_DISABLE, &ei->flags); in hte_ts_dis_en_common()
283 if (test_bit(HTE_TS_DISABLE, &ei->flags)) { in hte_ts_dis_en_common()
288 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_dis_en_common()
289 ret = gdev->chip->ops->disable(gdev->chip, ei->xlated_id); in hte_ts_dis_en_common()
291 dev_warn(gdev->sdev, "id: %d disable failed\n", in hte_ts_dis_en_common()
296 spin_lock_irqsave(&ei->slock, flag); in hte_ts_dis_en_common()
297 set_bit(HTE_TS_DISABLE, &ei->flags); in hte_ts_dis_en_common()
301 spin_unlock_irqrestore(&ei->slock, flag); in hte_ts_dis_en_common()
303 mutex_unlock(&ei->req_mlock); in hte_ts_dis_en_common()
308 * hte_disable_ts() - Disable timestamp on given descriptor.
315 * Returns: 0 on success or a negative error code on failure.
324 * hte_enable_ts() - Enable timestamp on given descriptor.
329 * Returns: 0 on success or a negative error code on failure.
342 if (unlikely(!ei->tcb)) in hte_do_cb_work()
345 ei->tcb(ei->cl_data); in hte_do_cb_work()
347 spin_lock_irqsave(&ei->slock, flag); in hte_do_cb_work()
348 clear_bit(HTE_TS_QUEUE_WK, &ei->flags); in hte_do_cb_work()
349 spin_unlock_irqrestore(&ei->slock, flag); in hte_do_cb_work()
357 struct hte_ts_info *ei = desc->hte_data; in __hte_req_ts()
359 gdev = ei->gdev; in __hte_req_ts()
364 mutex_lock(&ei->req_mlock); in __hte_req_ts()
366 if (test_bit(HTE_TS_REGISTERED, &ei->flags) || in __hte_req_ts()
367 !test_bit(HTE_TS_REQ, &ei->flags)) { in __hte_req_ts()
368 dev_dbg(gdev->chip->dev, "id:%u req failed\n", in __hte_req_ts()
369 desc->attr.line_id); in __hte_req_ts()
370 ret = -EUSERS; in __hte_req_ts()
374 ei->cb = cb; in __hte_req_ts()
375 ei->tcb = tcb; in __hte_req_ts()
377 INIT_WORK(&ei->cb_work, hte_do_cb_work); in __hte_req_ts()
379 ret = gdev->chip->ops->request(gdev->chip, desc, ei->xlated_id); in __hte_req_ts()
381 dev_err(gdev->chip->dev, "ts request failed\n"); in __hte_req_ts()
385 ei->cl_data = data; in __hte_req_ts()
386 ei->seq = 1; in __hte_req_ts()
388 atomic_inc(&gdev->ts_req); in __hte_req_ts()
390 if (desc->attr.name) in __hte_req_ts()
391 ei->line_name = NULL; in __hte_req_ts()
393 ei->line_name = kasprintf(GFP_KERNEL, "ts_%u", desc->attr.line_id); in __hte_req_ts()
395 hte_ts_dbgfs_init(desc->attr.name == NULL ? in __hte_req_ts()
396 ei->line_name : desc->attr.name, ei); in __hte_req_ts()
397 set_bit(HTE_TS_REGISTERED, &ei->flags); in __hte_req_ts()
399 dev_dbg(gdev->chip->dev, "id: %u, xlated id:%u", in __hte_req_ts()
400 desc->attr.line_id, ei->xlated_id); in __hte_req_ts()
405 mutex_unlock(&ei->req_mlock); in __hte_req_ts()
415 mutex_lock(&ei->req_mlock); in hte_bind_ts_info_locked()
417 if (test_bit(HTE_TS_REQ, &ei->flags)) { in hte_bind_ts_info_locked()
418 dev_dbg(ei->gdev->chip->dev, "id:%u is already requested\n", in hte_bind_ts_info_locked()
419 desc->attr.line_id); in hte_bind_ts_info_locked()
420 ret = -EUSERS; in hte_bind_ts_info_locked()
424 set_bit(HTE_TS_REQ, &ei->flags); in hte_bind_ts_info_locked()
425 desc->hte_data = ei; in hte_bind_ts_info_locked()
426 ei->xlated_id = x_id; in hte_bind_ts_info_locked()
429 mutex_unlock(&ei->req_mlock); in hte_bind_ts_info_locked()
441 if (gdev->chip && gdev->chip->dev && in of_node_to_htedevice()
442 device_match_of_node(gdev->chip->dev, np)) { in of_node_to_htedevice()
449 return ERR_PTR(-ENODEV); in of_node_to_htedevice()
459 if (gdev->chip && gdev->chip->match_from_linedata) { in hte_find_dev_from_linedata()
460 if (!gdev->chip->match_from_linedata(gdev->chip, desc)) in hte_find_dev_from_linedata()
468 return ERR_PTR(-ENODEV); in hte_find_dev_from_linedata()
472 * of_hte_req_count - Return the number of entities to timestamp.
479 * Returns: Positive number on success, -ENOENT if no entries,
480 * -EINVAL for other errors.
486 if (!dev || !dev->of_node) in of_hte_req_count()
487 return -EINVAL; in of_hte_req_count()
489 count = of_count_phandle_with_args(dev->of_node, "timestamps", in of_hte_req_count()
490 "#timestamp-cells"); in of_hte_req_count()
492 return count ? count : -ENOENT; in of_hte_req_count()
511 if (!dev->of_node) in hte_of_get_dev()
512 return ERR_PTR(-EINVAL); in hte_of_get_dev()
514 np = dev->of_node; in hte_of_get_dev()
516 if (!of_property_present(np, "timestamp-names")) { in hte_of_get_dev()
518 desc->attr.name = NULL; in hte_of_get_dev()
520 ret = of_property_read_string_index(np, "timestamp-names", in hte_of_get_dev()
521 index, &desc->attr.name); in hte_of_get_dev()
523 pr_err("can't parse \"timestamp-names\" property\n"); in hte_of_get_dev()
527 if (desc->attr.name) { in hte_of_get_dev()
528 temp = skip_spaces(desc->attr.name); in hte_of_get_dev()
530 desc->attr.name = NULL; in hte_of_get_dev()
534 ret = of_parse_phandle_with_args(np, "timestamps", "#timestamp-cells", in hte_of_get_dev()
542 of_node_put(args->np); in hte_of_get_dev()
544 return of_node_to_htedevice(args->np); in hte_of_get_dev()
548 * hte_ts_get() - The function to initialize and obtain HTE desc.
555 * @desc: Pre-allocated timestamp descriptor.
560 * Returns: Returns 0 on success or negative error code on failure.
573 return -EINVAL; in hte_ts_get()
587 if (!try_module_get(gdev->owner)) in hte_ts_get()
588 return -ENODEV; in hte_ts_get()
590 if (!gdev->chip) { in hte_ts_get()
593 ret = -ENODEV; in hte_ts_get()
598 if (!gdev->chip->xlate_of) in hte_ts_get()
599 ret = -EINVAL; in hte_ts_get()
601 ret = gdev->chip->xlate_of(gdev->chip, &args, in hte_ts_get()
604 if (!gdev->chip->xlate_plat) in hte_ts_get()
605 ret = -EINVAL; in hte_ts_get()
607 ret = gdev->chip->xlate_plat(gdev->chip, desc, in hte_ts_get()
614 ei = &gdev->ei[xlated_id]; in hte_ts_get()
620 ei->free_attr_name = free_name; in hte_ts_get()
625 module_put(gdev->owner); in hte_ts_get()
636 * hte_request_ts_ns() - The API to request and enable hardware timestamp in
642 * @desc: Pre-allocated and initialized timestamp descriptor.
649 * Returns: Returns 0 on success or negative error code on failure.
657 if (!desc || !desc->hte_data || !cb) in hte_request_ts_ns()
658 return -EINVAL; in hte_request_ts_ns()
660 ei = desc->hte_data; in hte_request_ts_ns()
661 if (!ei || !ei->gdev) in hte_request_ts_ns()
662 return -EINVAL; in hte_request_ts_ns()
666 dev_err(ei->gdev->chip->dev, in hte_request_ts_ns()
667 "failed to request id: %d\n", desc->attr.line_id); in hte_request_ts_ns()
676 * devm_hte_request_ts_ns() - Resource managed API to request and enable
684 * @desc: Pre-allocated and initialized timestamp descriptor.
691 * Returns: Returns 0 on success or negative error code on failure.
700 return -EINVAL; in devm_hte_request_ts_ns()
715 * hte_init_line_attr() - Initialize line attributes.
721 * @desc: Pre-allocated timestamp descriptor.
728 * Returns: 0 on success or negative error code for the failure.
734 return -EINVAL; in hte_init_line_attr()
736 memset(&desc->attr, 0, sizeof(desc->attr)); in hte_init_line_attr()
738 desc->attr.edge_flags = edge_flags; in hte_init_line_attr()
739 desc->attr.line_id = line_id; in hte_init_line_attr()
740 desc->attr.line_data = data; in hte_init_line_attr()
744 return -ENOMEM; in hte_init_line_attr()
747 desc->attr.name = name; in hte_init_line_attr()
754 * hte_get_clk_src_info() - Get the clock source information for a ts
761 * Returns: 0 on success else negative error code on failure.
766 struct hte_chip *chip; in hte_get_clk_src_info() local
769 if (!desc || !desc->hte_data || !ci) { in hte_get_clk_src_info()
771 return -EINVAL; in hte_get_clk_src_info()
774 ei = desc->hte_data; in hte_get_clk_src_info()
775 if (!ei->gdev || !ei->gdev->chip) in hte_get_clk_src_info()
776 return -EINVAL; in hte_get_clk_src_info()
778 chip = ei->gdev->chip; in hte_get_clk_src_info()
779 if (!chip->ops->get_clk_src_info) in hte_get_clk_src_info()
780 return -EOPNOTSUPP; in hte_get_clk_src_info()
782 return chip->ops->get_clk_src_info(chip, ci); in hte_get_clk_src_info()
787 * hte_push_ts_ns() - Push timestamp data in nanoseconds.
791 * @chip: The HTE chip, used during the registration.
796 * Returns: 0 on success or a negative error code on failure.
798 int hte_push_ts_ns(const struct hte_chip *chip, u32 xlated_id, in hte_push_ts_ns() argument
806 if (!chip || !data || !chip->gdev) in hte_push_ts_ns()
807 return -EINVAL; in hte_push_ts_ns()
809 if (xlated_id >= chip->nlines) in hte_push_ts_ns()
810 return -EINVAL; in hte_push_ts_ns()
812 ei = &chip->gdev->ei[xlated_id]; in hte_push_ts_ns()
814 spin_lock_irqsave(&ei->slock, flag); in hte_push_ts_ns()
817 data->seq = ei->seq++; in hte_push_ts_ns()
819 if (!test_bit(HTE_TS_REGISTERED, &ei->flags) || in hte_push_ts_ns()
820 test_bit(HTE_TS_DISABLE, &ei->flags)) { in hte_push_ts_ns()
821 dev_dbg(chip->dev, "Unknown timestamp push\n"); in hte_push_ts_ns()
822 atomic_inc(&ei->dropped_ts); in hte_push_ts_ns()
823 st = -EINVAL; in hte_push_ts_ns()
827 ret = ei->cb(data, ei->cl_data); in hte_push_ts_ns()
828 if (ret == HTE_RUN_SECOND_CB && ei->tcb) { in hte_push_ts_ns()
829 queue_work(system_unbound_wq, &ei->cb_work); in hte_push_ts_ns()
830 set_bit(HTE_TS_QUEUE_WK, &ei->flags); in hte_push_ts_ns()
834 spin_unlock_irqrestore(&ei->slock, flag); in hte_push_ts_ns()
840 static int hte_register_chip(struct hte_chip *chip) in hte_register_chip() argument
845 if (!chip || !chip->dev || !chip->dev->of_node) in hte_register_chip()
846 return -EINVAL; in hte_register_chip()
848 if (!chip->ops || !chip->ops->request || !chip->ops->release) { in hte_register_chip()
849 dev_err(chip->dev, "Driver needs to provide ops\n"); in hte_register_chip()
850 return -EINVAL; in hte_register_chip()
853 gdev = kzalloc(struct_size(gdev, ei, chip->nlines), GFP_KERNEL); in hte_register_chip()
855 return -ENOMEM; in hte_register_chip()
857 gdev->chip = chip; in hte_register_chip()
858 chip->gdev = gdev; in hte_register_chip()
859 gdev->nlines = chip->nlines; in hte_register_chip()
860 gdev->sdev = chip->dev; in hte_register_chip()
862 for (i = 0; i < chip->nlines; i++) { in hte_register_chip()
863 gdev->ei[i].gdev = gdev; in hte_register_chip()
864 mutex_init(&gdev->ei[i].req_mlock); in hte_register_chip()
865 spin_lock_init(&gdev->ei[i].slock); in hte_register_chip()
868 if (chip->dev->driver) in hte_register_chip()
869 gdev->owner = chip->dev->driver->owner; in hte_register_chip()
871 gdev->owner = THIS_MODULE; in hte_register_chip()
873 of_node_get(chip->dev->of_node); in hte_register_chip()
875 INIT_LIST_HEAD(&gdev->list); in hte_register_chip()
878 list_add_tail(&gdev->list, &hte_devices); in hte_register_chip()
883 dev_dbg(chip->dev, "Added hte chip\n"); in hte_register_chip()
888 static int hte_unregister_chip(struct hte_chip *chip) in hte_unregister_chip() argument
892 if (!chip) in hte_unregister_chip()
893 return -EINVAL; in hte_unregister_chip()
895 gdev = chip->gdev; in hte_unregister_chip()
898 list_del(&gdev->list); in hte_unregister_chip()
901 gdev->chip = NULL; in hte_unregister_chip()
903 of_node_put(chip->dev->of_node); in hte_unregister_chip()
904 debugfs_remove_recursive(gdev->dbg_root); in hte_unregister_chip()
907 dev_dbg(chip->dev, "Removed hte chip\n"); in hte_unregister_chip()
912 static void _hte_devm_unregister_chip(void *chip) in _hte_devm_unregister_chip() argument
914 hte_unregister_chip(chip); in _hte_devm_unregister_chip()
918 * devm_hte_register_chip() - Resource managed API to register HTE chip.
923 * @chip: the HTE chip to add to subsystem.
925 * Returns: 0 on success or a negative error code on failure.
927 int devm_hte_register_chip(struct hte_chip *chip) in devm_hte_register_chip() argument
931 err = hte_register_chip(chip); in devm_hte_register_chip()
935 err = devm_add_action_or_reset(chip->dev, _hte_devm_unregister_chip, in devm_hte_register_chip()
936 chip); in devm_hte_register_chip()