xref: /openbmc/linux/drivers/gpu/host1x/syncpt.h (revision 5c0d8d38)
175471687STerje Bergstrom /*
275471687STerje Bergstrom  * Tegra host1x Syncpoints
375471687STerje Bergstrom  *
475471687STerje Bergstrom  * Copyright (c) 2010-2013, NVIDIA Corporation.
575471687STerje Bergstrom  *
675471687STerje Bergstrom  * This program is free software; you can redistribute it and/or modify it
775471687STerje Bergstrom  * under the terms and conditions of the GNU General Public License,
875471687STerje Bergstrom  * version 2, as published by the Free Software Foundation.
975471687STerje Bergstrom  *
1075471687STerje Bergstrom  * This program is distributed in the hope it will be useful, but WITHOUT
1175471687STerje Bergstrom  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1275471687STerje Bergstrom  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1375471687STerje Bergstrom  * more details.
1475471687STerje Bergstrom  *
1575471687STerje Bergstrom  * You should have received a copy of the GNU General Public License
1675471687STerje Bergstrom  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1775471687STerje Bergstrom  */
1875471687STerje Bergstrom 
1975471687STerje Bergstrom #ifndef __HOST1X_SYNCPT_H
2075471687STerje Bergstrom #define __HOST1X_SYNCPT_H
2175471687STerje Bergstrom 
2275471687STerje Bergstrom #include <linux/atomic.h>
2335d747a8SThierry Reding #include <linux/host1x.h>
2475471687STerje Bergstrom #include <linux/kernel.h>
2575471687STerje Bergstrom #include <linux/sched.h>
2675471687STerje Bergstrom 
277ede0b0bSTerje Bergstrom #include "intr.h"
287ede0b0bSTerje Bergstrom 
2975471687STerje Bergstrom struct host1x;
3075471687STerje Bergstrom 
316579324aSTerje Bergstrom /* Reserved for replacing an expired wait with a NOP */
326579324aSTerje Bergstrom #define HOST1X_SYNCPT_RESERVED			0
336579324aSTerje Bergstrom 
34f5a954feSArto Merilainen struct host1x_syncpt_base {
35f5a954feSArto Merilainen 	unsigned int id;
36f5a954feSArto Merilainen 	bool requested;
37f5a954feSArto Merilainen };
38f5a954feSArto Merilainen 
3975471687STerje Bergstrom struct host1x_syncpt {
405c0d8d38SThierry Reding 	unsigned int id;
4175471687STerje Bergstrom 	atomic_t min_val;
4275471687STerje Bergstrom 	atomic_t max_val;
4375471687STerje Bergstrom 	u32 base_val;
4475471687STerje Bergstrom 	const char *name;
45ece66891SArto Merilainen 	bool client_managed;
4675471687STerje Bergstrom 	struct host1x *host;
4775471687STerje Bergstrom 	struct device *dev;
48f5a954feSArto Merilainen 	struct host1x_syncpt_base *base;
497ede0b0bSTerje Bergstrom 
507ede0b0bSTerje Bergstrom 	/* interrupt data */
517ede0b0bSTerje Bergstrom 	struct host1x_syncpt_intr intr;
5275471687STerje Bergstrom };
5375471687STerje Bergstrom 
5475471687STerje Bergstrom /* Initialize sync point array  */
5575471687STerje Bergstrom int host1x_syncpt_init(struct host1x *host);
5675471687STerje Bergstrom 
5775471687STerje Bergstrom /*  Free sync point array */
5875471687STerje Bergstrom void host1x_syncpt_deinit(struct host1x *host);
5975471687STerje Bergstrom 
6075471687STerje Bergstrom /* Return number of sync point supported. */
6114c95fc8SThierry Reding unsigned int host1x_syncpt_nb_pts(struct host1x *host);
6275471687STerje Bergstrom 
6375471687STerje Bergstrom /* Return number of wait bases supported. */
6414c95fc8SThierry Reding unsigned int host1x_syncpt_nb_bases(struct host1x *host);
6575471687STerje Bergstrom 
6675471687STerje Bergstrom /* Return number of mlocks supported. */
6714c95fc8SThierry Reding unsigned int host1x_syncpt_nb_mlocks(struct host1x *host);
6875471687STerje Bergstrom 
6975471687STerje Bergstrom /*
7075471687STerje Bergstrom  * Check sync point sanity. If max is larger than min, there have too many
7175471687STerje Bergstrom  * sync point increments.
7275471687STerje Bergstrom  *
7375471687STerje Bergstrom  * Client managed sync point are not tracked.
7475471687STerje Bergstrom  * */
7575471687STerje Bergstrom static inline bool host1x_syncpt_check_max(struct host1x_syncpt *sp, u32 real)
7675471687STerje Bergstrom {
7775471687STerje Bergstrom 	u32 max;
7875471687STerje Bergstrom 	if (sp->client_managed)
7975471687STerje Bergstrom 		return true;
8075471687STerje Bergstrom 	max = host1x_syncpt_read_max(sp);
8175471687STerje Bergstrom 	return (s32)(max - real) >= 0;
8275471687STerje Bergstrom }
8375471687STerje Bergstrom 
8475471687STerje Bergstrom /* Return true if sync point is client managed. */
85ece66891SArto Merilainen static inline bool host1x_syncpt_client_managed(struct host1x_syncpt *sp)
8675471687STerje Bergstrom {
8775471687STerje Bergstrom 	return sp->client_managed;
8875471687STerje Bergstrom }
8975471687STerje Bergstrom 
9075471687STerje Bergstrom /*
9175471687STerje Bergstrom  * Returns true if syncpoint min == max, which means that there are no
9275471687STerje Bergstrom  * outstanding operations.
9375471687STerje Bergstrom  */
9475471687STerje Bergstrom static inline bool host1x_syncpt_idle(struct host1x_syncpt *sp)
9575471687STerje Bergstrom {
9675471687STerje Bergstrom 	int min, max;
9775471687STerje Bergstrom 	smp_rmb();
9875471687STerje Bergstrom 	min = atomic_read(&sp->min_val);
9975471687STerje Bergstrom 	max = atomic_read(&sp->max_val);
10075471687STerje Bergstrom 	return (min == max);
10175471687STerje Bergstrom }
10275471687STerje Bergstrom 
10375471687STerje Bergstrom /* Load current value from hardware to the shadow register. */
10475471687STerje Bergstrom u32 host1x_syncpt_load(struct host1x_syncpt *sp);
10575471687STerje Bergstrom 
1067ede0b0bSTerje Bergstrom /* Check if the given syncpoint value has already passed */
1077ede0b0bSTerje Bergstrom bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh);
1087ede0b0bSTerje Bergstrom 
10975471687STerje Bergstrom /* Save host1x sync point state into shadow registers. */
11075471687STerje Bergstrom void host1x_syncpt_save(struct host1x *host);
11175471687STerje Bergstrom 
11275471687STerje Bergstrom /* Reset host1x sync point state from shadow registers. */
11375471687STerje Bergstrom void host1x_syncpt_restore(struct host1x *host);
11475471687STerje Bergstrom 
11575471687STerje Bergstrom /* Read current wait base value into shadow register and return it. */
11675471687STerje Bergstrom u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp);
11775471687STerje Bergstrom 
11875471687STerje Bergstrom /* Indicate future operations by incrementing the sync point max. */
11975471687STerje Bergstrom u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
12075471687STerje Bergstrom 
12175471687STerje Bergstrom /* Check if sync point id is valid. */
12275471687STerje Bergstrom static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
12375471687STerje Bergstrom {
12475471687STerje Bergstrom 	return sp->id < host1x_syncpt_nb_pts(sp->host);
12575471687STerje Bergstrom }
12675471687STerje Bergstrom 
1276579324aSTerje Bergstrom /* Patch a wait by replacing it with a wait for syncpt 0 value 0 */
1286579324aSTerje Bergstrom int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr);
1296579324aSTerje Bergstrom 
13075471687STerje Bergstrom #endif
131