1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (c) 2018 MediaTek Inc. 4 * 5 */ 6 7 #ifndef __MTK_CMDQ_H__ 8 #define __MTK_CMDQ_H__ 9 10 #include <linux/mailbox_client.h> 11 #include <linux/mailbox/mtk-cmdq-mailbox.h> 12 #include <linux/timer.h> 13 14 #define CMDQ_ADDR_HIGH(addr) ((u32)(((addr) >> 16) & GENMASK(31, 0))) 15 #define CMDQ_ADDR_LOW(addr) ((u16)(addr) | BIT(1)) 16 17 struct cmdq_pkt; 18 19 struct cmdq_client_reg { 20 u8 subsys; 21 u16 offset; 22 u16 size; 23 }; 24 25 struct cmdq_client { 26 struct mbox_client client; 27 struct mbox_chan *chan; 28 }; 29 30 #if IS_ENABLED(CONFIG_MTK_CMDQ) 31 32 /** 33 * cmdq_dev_get_client_reg() - parse cmdq client reg from the device 34 * node of CMDQ client 35 * @dev: device of CMDQ mailbox client 36 * @client_reg: CMDQ client reg pointer 37 * @idx: the index of desired reg 38 * 39 * Return: 0 for success; else the error code is returned 40 * 41 * Help CMDQ client parsing the cmdq client reg 42 * from the device node of CMDQ client. 43 */ 44 int cmdq_dev_get_client_reg(struct device *dev, 45 struct cmdq_client_reg *client_reg, int idx); 46 47 /** 48 * cmdq_mbox_create() - create CMDQ mailbox client and channel 49 * @dev: device of CMDQ mailbox client 50 * @index: index of CMDQ mailbox channel 51 * 52 * Return: CMDQ mailbox client pointer 53 */ 54 struct cmdq_client *cmdq_mbox_create(struct device *dev, int index); 55 56 /** 57 * cmdq_mbox_destroy() - destroy CMDQ mailbox client and channel 58 * @client: the CMDQ mailbox client 59 */ 60 void cmdq_mbox_destroy(struct cmdq_client *client); 61 62 /** 63 * cmdq_pkt_create() - create a CMDQ packet 64 * @client: the CMDQ mailbox client 65 * @size: required CMDQ buffer size 66 * 67 * Return: CMDQ packet pointer 68 */ 69 struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size); 70 71 /** 72 * cmdq_pkt_destroy() - destroy the CMDQ packet 73 * @pkt: the CMDQ packet 74 */ 75 void cmdq_pkt_destroy(struct cmdq_pkt *pkt); 76 77 /** 78 * cmdq_pkt_write() - append write command to the CMDQ packet 79 * @pkt: the CMDQ packet 80 * @subsys: the CMDQ sub system code 81 * @offset: register offset from CMDQ sub system 82 * @value: the specified target register value 83 * 84 * Return: 0 for success; else the error code is returned 85 */ 86 int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value); 87 88 /** 89 * cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet 90 * @pkt: the CMDQ packet 91 * @subsys: the CMDQ sub system code 92 * @offset: register offset from CMDQ sub system 93 * @value: the specified target register value 94 * @mask: the specified target register mask 95 * 96 * Return: 0 for success; else the error code is returned 97 */ 98 int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, 99 u16 offset, u32 value, u32 mask); 100 101 /* 102 * cmdq_pkt_read_s() - append read_s command to the CMDQ packet 103 * @pkt: the CMDQ packet 104 * @high_addr_reg_idx: internal register ID which contains high address of pa 105 * @addr_low: low address of pa 106 * @reg_idx: the CMDQ internal register ID to cache read data 107 * 108 * Return: 0 for success; else the error code is returned 109 */ 110 int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, 111 u16 reg_idx); 112 113 /** 114 * cmdq_pkt_write_s() - append write_s command to the CMDQ packet 115 * @pkt: the CMDQ packet 116 * @high_addr_reg_idx: internal register ID which contains high address of pa 117 * @addr_low: low address of pa 118 * @src_reg_idx: the CMDQ internal register ID which cache source value 119 * 120 * Return: 0 for success; else the error code is returned 121 * 122 * Support write value to physical address without subsys. Use CMDQ_ADDR_HIGH() 123 * to get high address and call cmdq_pkt_assign() to assign value into internal 124 * reg. Also use CMDQ_ADDR_LOW() to get low address for addr_low parameter when 125 * call to this function. 126 */ 127 int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 128 u16 addr_low, u16 src_reg_idx); 129 130 /** 131 * cmdq_pkt_write_s_mask() - append write_s with mask command to the CMDQ packet 132 * @pkt: the CMDQ packet 133 * @high_addr_reg_idx: internal register ID which contains high address of pa 134 * @addr_low: low address of pa 135 * @src_reg_idx: the CMDQ internal register ID which cache source value 136 * @mask: the specified target address mask, use U32_MAX if no need 137 * 138 * Return: 0 for success; else the error code is returned 139 * 140 * Support write value to physical address without subsys. Use CMDQ_ADDR_HIGH() 141 * to get high address and call cmdq_pkt_assign() to assign value into internal 142 * reg. Also use CMDQ_ADDR_LOW() to get low address for addr_low parameter when 143 * call to this function. 144 */ 145 int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 146 u16 addr_low, u16 src_reg_idx, u32 mask); 147 148 /** 149 * cmdq_pkt_write_s_value() - append write_s command to the CMDQ packet which 150 * write value to a physical address 151 * @pkt: the CMDQ packet 152 * @high_addr_reg_idx: internal register ID which contains high address of pa 153 * @addr_low: low address of pa 154 * @value: the specified target value 155 * 156 * Return: 0 for success; else the error code is returned 157 */ 158 int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, 159 u16 addr_low, u32 value); 160 161 /** 162 * cmdq_pkt_write_s_mask_value() - append write_s command with mask to the CMDQ 163 * packet which write value to a physical 164 * address 165 * @pkt: the CMDQ packet 166 * @high_addr_reg_idx: internal register ID which contains high address of pa 167 * @addr_low: low address of pa 168 * @value: the specified target value 169 * @mask: the specified target mask 170 * 171 * Return: 0 for success; else the error code is returned 172 */ 173 int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, 174 u16 addr_low, u32 value, u32 mask); 175 176 /** 177 * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet 178 * @pkt: the CMDQ packet 179 * @event: the desired event type to wait 180 * @clear: clear event or not after event arrive 181 * 182 * Return: 0 for success; else the error code is returned 183 */ 184 int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear); 185 186 /** 187 * cmdq_pkt_clear_event() - append clear event command to the CMDQ packet 188 * @pkt: the CMDQ packet 189 * @event: the desired event to be cleared 190 * 191 * Return: 0 for success; else the error code is returned 192 */ 193 int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event); 194 195 /** 196 * cmdq_pkt_set_event() - append set event command to the CMDQ packet 197 * @pkt: the CMDQ packet 198 * @event: the desired event to be set 199 * 200 * Return: 0 for success; else the error code is returned 201 */ 202 int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event); 203 204 /** 205 * cmdq_pkt_poll() - Append polling command to the CMDQ packet, ask GCE to 206 * execute an instruction that wait for a specified 207 * hardware register to check for the value w/o mask. 208 * All GCE hardware threads will be blocked by this 209 * instruction. 210 * @pkt: the CMDQ packet 211 * @subsys: the CMDQ sub system code 212 * @offset: register offset from CMDQ sub system 213 * @value: the specified target register value 214 * 215 * Return: 0 for success; else the error code is returned 216 */ 217 int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, 218 u16 offset, u32 value); 219 220 /** 221 * cmdq_pkt_poll_mask() - Append polling command to the CMDQ packet, ask GCE to 222 * execute an instruction that wait for a specified 223 * hardware register to check for the value w/ mask. 224 * All GCE hardware threads will be blocked by this 225 * instruction. 226 * @pkt: the CMDQ packet 227 * @subsys: the CMDQ sub system code 228 * @offset: register offset from CMDQ sub system 229 * @value: the specified target register value 230 * @mask: the specified target register mask 231 * 232 * Return: 0 for success; else the error code is returned 233 */ 234 int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, 235 u16 offset, u32 value, u32 mask); 236 237 /** 238 * cmdq_pkt_assign() - Append logic assign command to the CMDQ packet, ask GCE 239 * to execute an instruction that set a constant value into 240 * internal register and use as value, mask or address in 241 * read/write instruction. 242 * @pkt: the CMDQ packet 243 * @reg_idx: the CMDQ internal register ID 244 * @value: the specified value 245 * 246 * Return: 0 for success; else the error code is returned 247 */ 248 int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value); 249 250 /** 251 * cmdq_pkt_jump() - Append jump command to the CMDQ packet, ask GCE 252 * to execute an instruction that change current thread PC to 253 * a physical address which should contains more instruction. 254 * @pkt: the CMDQ packet 255 * @addr: physical address of target instruction buffer 256 * 257 * Return: 0 for success; else the error code is returned 258 */ 259 int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr); 260 261 /** 262 * cmdq_pkt_finalize() - Append EOC and jump command to pkt. 263 * @pkt: the CMDQ packet 264 * 265 * Return: 0 for success; else the error code is returned 266 */ 267 int cmdq_pkt_finalize(struct cmdq_pkt *pkt); 268 269 /** 270 * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ 271 * packet and call back at the end of done packet 272 * @pkt: the CMDQ packet 273 * 274 * Return: 0 for success; else the error code is returned 275 * 276 * Trigger CMDQ to asynchronously execute the CMDQ packet and call back 277 * at the end of done packet. Note that this is an ASYNC function. When the 278 * function returned, it may or may not be finished. 279 */ 280 int cmdq_pkt_flush_async(struct cmdq_pkt *pkt); 281 282 #else /* IS_ENABLED(CONFIG_MTK_CMDQ) */ 283 284 static inline int cmdq_dev_get_client_reg(struct device *dev, 285 struct cmdq_client_reg *client_reg, int idx) 286 { 287 return -ENODEV; 288 } 289 290 static inline struct cmdq_client *cmdq_mbox_create(struct device *dev, int index) 291 { 292 return ERR_PTR(-EINVAL); 293 } 294 295 static inline void cmdq_mbox_destroy(struct cmdq_client *client) { } 296 297 static inline struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) 298 { 299 return ERR_PTR(-EINVAL); 300 } 301 302 static inline void cmdq_pkt_destroy(struct cmdq_pkt *pkt) { } 303 304 static inline int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) 305 { 306 return -ENOENT; 307 } 308 309 static inline int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, 310 u16 offset, u32 value, u32 mask) 311 { 312 return -ENOENT; 313 } 314 315 static inline int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 316 u16 addr_low, u16 reg_idx) 317 { 318 return -ENOENT; 319 } 320 321 static inline int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 322 u16 addr_low, u16 src_reg_idx) 323 { 324 return -ENOENT; 325 } 326 327 static inline int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 328 u16 addr_low, u16 src_reg_idx, u32 mask) 329 { 330 return -ENOENT; 331 } 332 333 static inline int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, 334 u16 addr_low, u32 value) 335 { 336 return -ENOENT; 337 } 338 339 static inline int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, 340 u16 addr_low, u32 value, u32 mask) 341 { 342 return -ENOENT; 343 } 344 345 static inline int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear) 346 { 347 return -EINVAL; 348 } 349 350 static inline int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) 351 { 352 return -EINVAL; 353 } 354 355 static inline int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event) 356 { 357 return -EINVAL; 358 } 359 360 static inline int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, 361 u16 offset, u32 value) 362 { 363 return -EINVAL; 364 } 365 366 static inline int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, 367 u16 offset, u32 value, u32 mask) 368 { 369 return -EINVAL; 370 } 371 372 static inline int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) 373 { 374 return -EINVAL; 375 } 376 377 static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr) 378 { 379 return -EINVAL; 380 } 381 382 static inline int cmdq_pkt_finalize(struct cmdq_pkt *pkt) 383 { 384 return -EINVAL; 385 } 386 387 static inline int cmdq_pkt_flush_async(struct cmdq_pkt *pkt) 388 { 389 return -EINVAL; 390 } 391 392 #endif /* IS_ENABLED(CONFIG_MTK_CMDQ) */ 393 394 #endif /* __MTK_CMDQ_H__ */ 395