1 /* 2 * Tegra host1x Syncpoints 3 * 4 * Copyright (c) 2010-2013, NVIDIA Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #ifndef __HOST1X_SYNCPT_H 20 #define __HOST1X_SYNCPT_H 21 22 #include <linux/atomic.h> 23 #include <linux/kernel.h> 24 #include <linux/sched.h> 25 26 #include "intr.h" 27 28 struct host1x; 29 30 /* Reserved for replacing an expired wait with a NOP */ 31 #define HOST1X_SYNCPT_RESERVED 0 32 33 struct host1x_syncpt { 34 int id; 35 atomic_t min_val; 36 atomic_t max_val; 37 u32 base_val; 38 const char *name; 39 int client_managed; 40 struct host1x *host; 41 struct device *dev; 42 43 /* interrupt data */ 44 struct host1x_syncpt_intr intr; 45 }; 46 47 /* Initialize sync point array */ 48 int host1x_syncpt_init(struct host1x *host); 49 50 /* Free sync point array */ 51 void host1x_syncpt_deinit(struct host1x *host); 52 53 /* 54 * Read max. It indicates how many operations there are in queue, either in 55 * channel or in a software thread. 56 * */ 57 static inline u32 host1x_syncpt_read_max(struct host1x_syncpt *sp) 58 { 59 smp_rmb(); 60 return (u32)atomic_read(&sp->max_val); 61 } 62 63 /* 64 * Read min, which is a shadow of the current sync point value in hardware. 65 */ 66 static inline u32 host1x_syncpt_read_min(struct host1x_syncpt *sp) 67 { 68 smp_rmb(); 69 return (u32)atomic_read(&sp->min_val); 70 } 71 72 /* Return number of sync point supported. */ 73 int host1x_syncpt_nb_pts(struct host1x *host); 74 75 /* Return number of wait bases supported. */ 76 int host1x_syncpt_nb_bases(struct host1x *host); 77 78 /* Return number of mlocks supported. */ 79 int host1x_syncpt_nb_mlocks(struct host1x *host); 80 81 /* 82 * Check sync point sanity. If max is larger than min, there have too many 83 * sync point increments. 84 * 85 * Client managed sync point are not tracked. 86 * */ 87 static inline bool host1x_syncpt_check_max(struct host1x_syncpt *sp, u32 real) 88 { 89 u32 max; 90 if (sp->client_managed) 91 return true; 92 max = host1x_syncpt_read_max(sp); 93 return (s32)(max - real) >= 0; 94 } 95 96 /* Return true if sync point is client managed. */ 97 static inline int host1x_syncpt_client_managed(struct host1x_syncpt *sp) 98 { 99 return sp->client_managed; 100 } 101 102 /* 103 * Returns true if syncpoint min == max, which means that there are no 104 * outstanding operations. 105 */ 106 static inline bool host1x_syncpt_idle(struct host1x_syncpt *sp) 107 { 108 int min, max; 109 smp_rmb(); 110 min = atomic_read(&sp->min_val); 111 max = atomic_read(&sp->max_val); 112 return (min == max); 113 } 114 115 /* Return pointer to struct denoting sync point id. */ 116 struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id); 117 118 /* Request incrementing a sync point. */ 119 void host1x_syncpt_cpu_incr(struct host1x_syncpt *sp); 120 121 /* Load current value from hardware to the shadow register. */ 122 u32 host1x_syncpt_load(struct host1x_syncpt *sp); 123 124 /* Check if the given syncpoint value has already passed */ 125 bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh); 126 127 /* Save host1x sync point state into shadow registers. */ 128 void host1x_syncpt_save(struct host1x *host); 129 130 /* Reset host1x sync point state from shadow registers. */ 131 void host1x_syncpt_restore(struct host1x *host); 132 133 /* Read current wait base value into shadow register and return it. */ 134 u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp); 135 136 /* Increment sync point and its max. */ 137 void host1x_syncpt_incr(struct host1x_syncpt *sp); 138 139 /* Indicate future operations by incrementing the sync point max. */ 140 u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs); 141 142 /* Wait until sync point reaches a threshold value, or a timeout. */ 143 int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, 144 long timeout, u32 *value); 145 146 /* Check if sync point id is valid. */ 147 static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp) 148 { 149 return sp->id < host1x_syncpt_nb_pts(sp->host); 150 } 151 152 /* Patch a wait by replacing it with a wait for syncpt 0 value 0 */ 153 int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr); 154 155 /* Return id of the sync point */ 156 u32 host1x_syncpt_id(struct host1x_syncpt *sp); 157 158 /* Allocate a sync point for a device. */ 159 struct host1x_syncpt *host1x_syncpt_request(struct device *dev, 160 int client_managed); 161 162 /* Free a sync point. */ 163 void host1x_syncpt_free(struct host1x_syncpt *sp); 164 165 #endif 166