Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  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);