18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Tegra host1x Syncpoints
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2010-2013, NVIDIA Corporation.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef __HOST1X_SYNCPT_H
98c2ecf20Sopenharmony_ci#define __HOST1X_SYNCPT_H
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/atomic.h>
128c2ecf20Sopenharmony_ci#include <linux/host1x.h>
138c2ecf20Sopenharmony_ci#include <linux/kernel.h>
148c2ecf20Sopenharmony_ci#include <linux/sched.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "intr.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistruct host1x;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci/* Reserved for replacing an expired wait with a NOP */
218c2ecf20Sopenharmony_ci#define HOST1X_SYNCPT_RESERVED			0
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistruct host1x_syncpt_base {
248c2ecf20Sopenharmony_ci	unsigned int id;
258c2ecf20Sopenharmony_ci	bool requested;
268c2ecf20Sopenharmony_ci};
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistruct host1x_syncpt {
298c2ecf20Sopenharmony_ci	unsigned int id;
308c2ecf20Sopenharmony_ci	atomic_t min_val;
318c2ecf20Sopenharmony_ci	atomic_t max_val;
328c2ecf20Sopenharmony_ci	u32 base_val;
338c2ecf20Sopenharmony_ci	const char *name;
348c2ecf20Sopenharmony_ci	bool client_managed;
358c2ecf20Sopenharmony_ci	struct host1x *host;
368c2ecf20Sopenharmony_ci	struct host1x_client *client;
378c2ecf20Sopenharmony_ci	struct host1x_syncpt_base *base;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	/* interrupt data */
408c2ecf20Sopenharmony_ci	struct host1x_syncpt_intr intr;
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/* Initialize sync point array  */
448c2ecf20Sopenharmony_ciint host1x_syncpt_init(struct host1x *host);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/*  Free sync point array */
478c2ecf20Sopenharmony_civoid host1x_syncpt_deinit(struct host1x *host);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/* Return number of sync point supported. */
508c2ecf20Sopenharmony_ciunsigned int host1x_syncpt_nb_pts(struct host1x *host);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* Return number of wait bases supported. */
538c2ecf20Sopenharmony_ciunsigned int host1x_syncpt_nb_bases(struct host1x *host);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/* Return number of mlocks supported. */
568c2ecf20Sopenharmony_ciunsigned int host1x_syncpt_nb_mlocks(struct host1x *host);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/*
598c2ecf20Sopenharmony_ci * Check sync point sanity. If max is larger than min, there have too many
608c2ecf20Sopenharmony_ci * sync point increments.
618c2ecf20Sopenharmony_ci *
628c2ecf20Sopenharmony_ci * Client managed sync point are not tracked.
638c2ecf20Sopenharmony_ci * */
648c2ecf20Sopenharmony_cistatic inline bool host1x_syncpt_check_max(struct host1x_syncpt *sp, u32 real)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	u32 max;
678c2ecf20Sopenharmony_ci	if (sp->client_managed)
688c2ecf20Sopenharmony_ci		return true;
698c2ecf20Sopenharmony_ci	max = host1x_syncpt_read_max(sp);
708c2ecf20Sopenharmony_ci	return (s32)(max - real) >= 0;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* Return true if sync point is client managed. */
748c2ecf20Sopenharmony_cistatic inline bool host1x_syncpt_client_managed(struct host1x_syncpt *sp)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	return sp->client_managed;
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/*
808c2ecf20Sopenharmony_ci * Returns true if syncpoint min == max, which means that there are no
818c2ecf20Sopenharmony_ci * outstanding operations.
828c2ecf20Sopenharmony_ci */
838c2ecf20Sopenharmony_cistatic inline bool host1x_syncpt_idle(struct host1x_syncpt *sp)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	int min, max;
868c2ecf20Sopenharmony_ci	smp_rmb();
878c2ecf20Sopenharmony_ci	min = atomic_read(&sp->min_val);
888c2ecf20Sopenharmony_ci	max = atomic_read(&sp->max_val);
898c2ecf20Sopenharmony_ci	return (min == max);
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci/* Load current value from hardware to the shadow register. */
938c2ecf20Sopenharmony_ciu32 host1x_syncpt_load(struct host1x_syncpt *sp);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/* Check if the given syncpoint value has already passed */
968c2ecf20Sopenharmony_cibool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci/* Save host1x sync point state into shadow registers. */
998c2ecf20Sopenharmony_civoid host1x_syncpt_save(struct host1x *host);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci/* Reset host1x sync point state from shadow registers. */
1028c2ecf20Sopenharmony_civoid host1x_syncpt_restore(struct host1x *host);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci/* Read current wait base value into shadow register and return it. */
1058c2ecf20Sopenharmony_ciu32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/* Indicate future operations by incrementing the sync point max. */
1088c2ecf20Sopenharmony_ciu32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/* Check if sync point id is valid. */
1118c2ecf20Sopenharmony_cistatic inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	return sp->id < host1x_syncpt_nb_pts(sp->host);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci#endif
117