162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Tegra host1x Syncpoints
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2010-2013, NVIDIA Corporation.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef __HOST1X_SYNCPT_H
962306a36Sopenharmony_ci#define __HOST1X_SYNCPT_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/atomic.h>
1262306a36Sopenharmony_ci#include <linux/host1x.h>
1362306a36Sopenharmony_ci#include <linux/kernel.h>
1462306a36Sopenharmony_ci#include <linux/kref.h>
1562306a36Sopenharmony_ci#include <linux/sched.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "fence.h"
1862306a36Sopenharmony_ci#include "intr.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct host1x;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/* Reserved for replacing an expired wait with a NOP */
2362306a36Sopenharmony_ci#define HOST1X_SYNCPT_RESERVED			0
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistruct host1x_syncpt_base {
2662306a36Sopenharmony_ci	unsigned int id;
2762306a36Sopenharmony_ci	bool requested;
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistruct host1x_syncpt {
3162306a36Sopenharmony_ci	struct kref ref;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	unsigned int id;
3462306a36Sopenharmony_ci	atomic_t min_val;
3562306a36Sopenharmony_ci	atomic_t max_val;
3662306a36Sopenharmony_ci	u32 base_val;
3762306a36Sopenharmony_ci	const char *name;
3862306a36Sopenharmony_ci	bool client_managed;
3962306a36Sopenharmony_ci	struct host1x *host;
4062306a36Sopenharmony_ci	struct host1x_syncpt_base *base;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	/* interrupt data */
4362306a36Sopenharmony_ci	struct host1x_fence_list fences;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	/*
4662306a36Sopenharmony_ci	 * If a submission incrementing this syncpoint fails, lock it so that
4762306a36Sopenharmony_ci	 * further submission cannot be made until application has handled the
4862306a36Sopenharmony_ci	 * failure.
4962306a36Sopenharmony_ci	 */
5062306a36Sopenharmony_ci	bool locked;
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/* Initialize sync point array  */
5462306a36Sopenharmony_ciint host1x_syncpt_init(struct host1x *host);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/*  Free sync point array */
5762306a36Sopenharmony_civoid host1x_syncpt_deinit(struct host1x *host);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/* Return number of sync point supported. */
6062306a36Sopenharmony_ciunsigned int host1x_syncpt_nb_pts(struct host1x *host);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/* Return number of wait bases supported. */
6362306a36Sopenharmony_ciunsigned int host1x_syncpt_nb_bases(struct host1x *host);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/* Return number of mlocks supported. */
6662306a36Sopenharmony_ciunsigned int host1x_syncpt_nb_mlocks(struct host1x *host);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * Check sync point sanity. If max is larger than min, there have too many
7062306a36Sopenharmony_ci * sync point increments.
7162306a36Sopenharmony_ci *
7262306a36Sopenharmony_ci * Client managed sync point are not tracked.
7362306a36Sopenharmony_ci * */
7462306a36Sopenharmony_cistatic inline bool host1x_syncpt_check_max(struct host1x_syncpt *sp, u32 real)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	u32 max;
7762306a36Sopenharmony_ci	if (sp->client_managed)
7862306a36Sopenharmony_ci		return true;
7962306a36Sopenharmony_ci	max = host1x_syncpt_read_max(sp);
8062306a36Sopenharmony_ci	return (s32)(max - real) >= 0;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/* Return true if sync point is client managed. */
8462306a36Sopenharmony_cistatic inline bool host1x_syncpt_client_managed(struct host1x_syncpt *sp)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	return sp->client_managed;
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/*
9062306a36Sopenharmony_ci * Returns true if syncpoint min == max, which means that there are no
9162306a36Sopenharmony_ci * outstanding operations.
9262306a36Sopenharmony_ci */
9362306a36Sopenharmony_cistatic inline bool host1x_syncpt_idle(struct host1x_syncpt *sp)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	int min, max;
9662306a36Sopenharmony_ci	smp_rmb();
9762306a36Sopenharmony_ci	min = atomic_read(&sp->min_val);
9862306a36Sopenharmony_ci	max = atomic_read(&sp->max_val);
9962306a36Sopenharmony_ci	return (min == max);
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/* Load current value from hardware to the shadow register. */
10362306a36Sopenharmony_ciu32 host1x_syncpt_load(struct host1x_syncpt *sp);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/* Check if the given syncpoint value has already passed */
10662306a36Sopenharmony_cibool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci/* Save host1x sync point state into shadow registers. */
10962306a36Sopenharmony_civoid host1x_syncpt_save(struct host1x *host);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/* Reset host1x sync point state from shadow registers. */
11262306a36Sopenharmony_civoid host1x_syncpt_restore(struct host1x *host);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/* Read current wait base value into shadow register and return it. */
11562306a36Sopenharmony_ciu32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/* Indicate future operations by incrementing the sync point max. */
11862306a36Sopenharmony_ciu32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/* Check if sync point id is valid. */
12162306a36Sopenharmony_cistatic inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	return sp->id < host1x_syncpt_nb_pts(sp->host);
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic inline void host1x_syncpt_set_locked(struct host1x_syncpt *sp)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	sp->locked = true;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci#endif
132