1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Tegra host1x Syncpoints
4 *
5 * Copyright (c) 2010-2013, NVIDIA Corporation.
6 */
7
8#ifndef __HOST1X_SYNCPT_H
9#define __HOST1X_SYNCPT_H
10
11#include <linux/atomic.h>
12#include <linux/host1x.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15
16#include "intr.h"
17
18struct host1x;
19
20/* Reserved for replacing an expired wait with a NOP */
21#define HOST1X_SYNCPT_RESERVED			0
22
23struct host1x_syncpt_base {
24	unsigned int id;
25	bool requested;
26};
27
28struct host1x_syncpt {
29	unsigned int id;
30	atomic_t min_val;
31	atomic_t max_val;
32	u32 base_val;
33	const char *name;
34	bool client_managed;
35	struct host1x *host;
36	struct host1x_client *client;
37	struct host1x_syncpt_base *base;
38
39	/* interrupt data */
40	struct host1x_syncpt_intr intr;
41};
42
43/* Initialize sync point array  */
44int host1x_syncpt_init(struct host1x *host);
45
46/*  Free sync point array */
47void host1x_syncpt_deinit(struct host1x *host);
48
49/* Return number of sync point supported. */
50unsigned int host1x_syncpt_nb_pts(struct host1x *host);
51
52/* Return number of wait bases supported. */
53unsigned int host1x_syncpt_nb_bases(struct host1x *host);
54
55/* Return number of mlocks supported. */
56unsigned int host1x_syncpt_nb_mlocks(struct host1x *host);
57
58/*
59 * Check sync point sanity. If max is larger than min, there have too many
60 * sync point increments.
61 *
62 * Client managed sync point are not tracked.
63 * */
64static inline bool host1x_syncpt_check_max(struct host1x_syncpt *sp, u32 real)
65{
66	u32 max;
67	if (sp->client_managed)
68		return true;
69	max = host1x_syncpt_read_max(sp);
70	return (s32)(max - real) >= 0;
71}
72
73/* Return true if sync point is client managed. */
74static inline bool host1x_syncpt_client_managed(struct host1x_syncpt *sp)
75{
76	return sp->client_managed;
77}
78
79/*
80 * Returns true if syncpoint min == max, which means that there are no
81 * outstanding operations.
82 */
83static inline bool host1x_syncpt_idle(struct host1x_syncpt *sp)
84{
85	int min, max;
86	smp_rmb();
87	min = atomic_read(&sp->min_val);
88	max = atomic_read(&sp->max_val);
89	return (min == max);
90}
91
92/* Load current value from hardware to the shadow register. */
93u32 host1x_syncpt_load(struct host1x_syncpt *sp);
94
95/* Check if the given syncpoint value has already passed */
96bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh);
97
98/* Save host1x sync point state into shadow registers. */
99void host1x_syncpt_save(struct host1x *host);
100
101/* Reset host1x sync point state from shadow registers. */
102void host1x_syncpt_restore(struct host1x *host);
103
104/* Read current wait base value into shadow register and return it. */
105u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp);
106
107/* Indicate future operations by incrementing the sync point max. */
108u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
109
110/* Check if sync point id is valid. */
111static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
112{
113	return sp->id < host1x_syncpt_nb_pts(sp->host);
114}
115
116#endif
117