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 { 4075471687STerje Bergstrom 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