xref: /openbmc/linux/drivers/gpu/host1x/syncpt.h (revision 6579324a)
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>
2375471687STerje Bergstrom #include <linux/kernel.h>
2475471687STerje Bergstrom #include <linux/sched.h>
2575471687STerje Bergstrom 
267ede0b0bSTerje Bergstrom #include "intr.h"
277ede0b0bSTerje Bergstrom 
2875471687STerje Bergstrom struct host1x;
2975471687STerje Bergstrom 
306579324aSTerje Bergstrom /* Reserved for replacing an expired wait with a NOP */
316579324aSTerje Bergstrom #define HOST1X_SYNCPT_RESERVED			0
326579324aSTerje Bergstrom 
3375471687STerje Bergstrom struct host1x_syncpt {
3475471687STerje Bergstrom 	int id;
3575471687STerje Bergstrom 	atomic_t min_val;
3675471687STerje Bergstrom 	atomic_t max_val;
3775471687STerje Bergstrom 	u32 base_val;
3875471687STerje Bergstrom 	const char *name;
3975471687STerje Bergstrom 	int client_managed;
4075471687STerje Bergstrom 	struct host1x *host;
4175471687STerje Bergstrom 	struct device *dev;
427ede0b0bSTerje Bergstrom 
437ede0b0bSTerje Bergstrom 	/* interrupt data */
447ede0b0bSTerje Bergstrom 	struct host1x_syncpt_intr intr;
4575471687STerje Bergstrom };
4675471687STerje Bergstrom 
4775471687STerje Bergstrom /* Initialize sync point array  */
4875471687STerje Bergstrom int host1x_syncpt_init(struct host1x *host);
4975471687STerje Bergstrom 
5075471687STerje Bergstrom /*  Free sync point array */
5175471687STerje Bergstrom void host1x_syncpt_deinit(struct host1x *host);
5275471687STerje Bergstrom 
5375471687STerje Bergstrom /*
5475471687STerje Bergstrom  * Read max. It indicates how many operations there are in queue, either in
5575471687STerje Bergstrom  * channel or in a software thread.
5675471687STerje Bergstrom  * */
5775471687STerje Bergstrom static inline u32 host1x_syncpt_read_max(struct host1x_syncpt *sp)
5875471687STerje Bergstrom {
5975471687STerje Bergstrom 	smp_rmb();
6075471687STerje Bergstrom 	return (u32)atomic_read(&sp->max_val);
6175471687STerje Bergstrom }
6275471687STerje Bergstrom 
6375471687STerje Bergstrom /*
6475471687STerje Bergstrom  * Read min, which is a shadow of the current sync point value in hardware.
6575471687STerje Bergstrom  */
6675471687STerje Bergstrom static inline u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
6775471687STerje Bergstrom {
6875471687STerje Bergstrom 	smp_rmb();
6975471687STerje Bergstrom 	return (u32)atomic_read(&sp->min_val);
7075471687STerje Bergstrom }
7175471687STerje Bergstrom 
7275471687STerje Bergstrom /* Return number of sync point supported. */
7375471687STerje Bergstrom int host1x_syncpt_nb_pts(struct host1x *host);
7475471687STerje Bergstrom 
7575471687STerje Bergstrom /* Return number of wait bases supported. */
7675471687STerje Bergstrom int host1x_syncpt_nb_bases(struct host1x *host);
7775471687STerje Bergstrom 
7875471687STerje Bergstrom /* Return number of mlocks supported. */
7975471687STerje Bergstrom int host1x_syncpt_nb_mlocks(struct host1x *host);
8075471687STerje Bergstrom 
8175471687STerje Bergstrom /*
8275471687STerje Bergstrom  * Check sync point sanity. If max is larger than min, there have too many
8375471687STerje Bergstrom  * sync point increments.
8475471687STerje Bergstrom  *
8575471687STerje Bergstrom  * Client managed sync point are not tracked.
8675471687STerje Bergstrom  * */
8775471687STerje Bergstrom static inline bool host1x_syncpt_check_max(struct host1x_syncpt *sp, u32 real)
8875471687STerje Bergstrom {
8975471687STerje Bergstrom 	u32 max;
9075471687STerje Bergstrom 	if (sp->client_managed)
9175471687STerje Bergstrom 		return true;
9275471687STerje Bergstrom 	max = host1x_syncpt_read_max(sp);
9375471687STerje Bergstrom 	return (s32)(max - real) >= 0;
9475471687STerje Bergstrom }
9575471687STerje Bergstrom 
9675471687STerje Bergstrom /* Return true if sync point is client managed. */
9775471687STerje Bergstrom static inline int host1x_syncpt_client_managed(struct host1x_syncpt *sp)
9875471687STerje Bergstrom {
9975471687STerje Bergstrom 	return sp->client_managed;
10075471687STerje Bergstrom }
10175471687STerje Bergstrom 
10275471687STerje Bergstrom /*
10375471687STerje Bergstrom  * Returns true if syncpoint min == max, which means that there are no
10475471687STerje Bergstrom  * outstanding operations.
10575471687STerje Bergstrom  */
10675471687STerje Bergstrom static inline bool host1x_syncpt_idle(struct host1x_syncpt *sp)
10775471687STerje Bergstrom {
10875471687STerje Bergstrom 	int min, max;
10975471687STerje Bergstrom 	smp_rmb();
11075471687STerje Bergstrom 	min = atomic_read(&sp->min_val);
11175471687STerje Bergstrom 	max = atomic_read(&sp->max_val);
11275471687STerje Bergstrom 	return (min == max);
11375471687STerje Bergstrom }
11475471687STerje Bergstrom 
11575471687STerje Bergstrom /* Return pointer to struct denoting sync point id. */
11675471687STerje Bergstrom struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id);
11775471687STerje Bergstrom 
11875471687STerje Bergstrom /* Request incrementing a sync point. */
11975471687STerje Bergstrom void host1x_syncpt_cpu_incr(struct host1x_syncpt *sp);
12075471687STerje Bergstrom 
12175471687STerje Bergstrom /* Load current value from hardware to the shadow register. */
12275471687STerje Bergstrom u32 host1x_syncpt_load(struct host1x_syncpt *sp);
12375471687STerje Bergstrom 
1247ede0b0bSTerje Bergstrom /* Check if the given syncpoint value has already passed */
1257ede0b0bSTerje Bergstrom bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh);
1267ede0b0bSTerje Bergstrom 
12775471687STerje Bergstrom /* Save host1x sync point state into shadow registers. */
12875471687STerje Bergstrom void host1x_syncpt_save(struct host1x *host);
12975471687STerje Bergstrom 
13075471687STerje Bergstrom /* Reset host1x sync point state from shadow registers. */
13175471687STerje Bergstrom void host1x_syncpt_restore(struct host1x *host);
13275471687STerje Bergstrom 
13375471687STerje Bergstrom /* Read current wait base value into shadow register and return it. */
13475471687STerje Bergstrom u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp);
13575471687STerje Bergstrom 
13675471687STerje Bergstrom /* Increment sync point and its max. */
13775471687STerje Bergstrom void host1x_syncpt_incr(struct host1x_syncpt *sp);
13875471687STerje Bergstrom 
13975471687STerje Bergstrom /* Indicate future operations by incrementing the sync point max. */
14075471687STerje Bergstrom u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
14175471687STerje Bergstrom 
1427ede0b0bSTerje Bergstrom /* Wait until sync point reaches a threshold value, or a timeout. */
1437ede0b0bSTerje Bergstrom int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh,
1447ede0b0bSTerje Bergstrom 			long timeout, u32 *value);
1457ede0b0bSTerje Bergstrom 
14675471687STerje Bergstrom /* Check if sync point id is valid. */
14775471687STerje Bergstrom static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
14875471687STerje Bergstrom {
14975471687STerje Bergstrom 	return sp->id < host1x_syncpt_nb_pts(sp->host);
15075471687STerje Bergstrom }
15175471687STerje Bergstrom 
1526579324aSTerje Bergstrom /* Patch a wait by replacing it with a wait for syncpt 0 value 0 */
1536579324aSTerje Bergstrom int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr);
1546579324aSTerje Bergstrom 
15575471687STerje Bergstrom /* Return id of the sync point */
15675471687STerje Bergstrom u32 host1x_syncpt_id(struct host1x_syncpt *sp);
15775471687STerje Bergstrom 
15875471687STerje Bergstrom /* Allocate a sync point for a device. */
15975471687STerje Bergstrom struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
16075471687STerje Bergstrom 		int client_managed);
16175471687STerje Bergstrom 
16275471687STerje Bergstrom /* Free a sync point. */
16375471687STerje Bergstrom void host1x_syncpt_free(struct host1x_syncpt *sp);
16475471687STerje Bergstrom 
16575471687STerje Bergstrom #endif
166