1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include "iris_core.h" 7 #include "iris_hfi_queue.h" 8 9 static void iris_hfi_queue_set_header(struct iris_core *core, u32 queue_id, 10 struct iris_iface_q_info *iface_q) 11 { 12 iface_q->qhdr->status = 0x1; 13 iface_q->qhdr->start_addr = iface_q->device_addr; 14 iface_q->qhdr->header_type = IFACEQ_DFLT_QHDR; 15 iface_q->qhdr->queue_type = queue_id; 16 iface_q->qhdr->q_size = IFACEQ_QUEUE_SIZE / sizeof(u32); 17 iface_q->qhdr->pkt_size = 0; /* variable packet size */ 18 iface_q->qhdr->rx_wm = 0x1; 19 iface_q->qhdr->tx_wm = 0x1; 20 iface_q->qhdr->rx_req = 0x1; 21 iface_q->qhdr->tx_req = 0x0; 22 iface_q->qhdr->rx_irq_status = 0x0; 23 iface_q->qhdr->tx_irq_status = 0x0; 24 iface_q->qhdr->read_idx = 0x0; 25 iface_q->qhdr->write_idx = 0x0; 26 27 /* 28 * Set receive request to zero on debug queue as there is no 29 * need of interrupt from video hardware for debug messages 30 */ 31 if (queue_id == IFACEQ_DBGQ_ID) 32 iface_q->qhdr->rx_req = 0; 33 } 34 35 static void 36 iris_hfi_queue_init(struct iris_core *core, u32 queue_id, struct iris_iface_q_info *iface_q) 37 { 38 struct iris_hfi_queue_table_header *q_tbl_hdr = core->iface_q_table_vaddr; 39 u32 offset = sizeof(*q_tbl_hdr) + (queue_id * IFACEQ_QUEUE_SIZE); 40 41 iface_q->device_addr = core->iface_q_table_daddr + offset; 42 iface_q->kernel_vaddr = 43 (void *)((char *)core->iface_q_table_vaddr + offset); 44 iface_q->qhdr = &q_tbl_hdr->q_hdr[queue_id]; 45 46 iris_hfi_queue_set_header(core, queue_id, iface_q); 47 } 48 49 static void iris_hfi_queue_deinit(struct iris_iface_q_info *iface_q) 50 { 51 iface_q->qhdr = NULL; 52 iface_q->kernel_vaddr = NULL; 53 iface_q->device_addr = 0; 54 } 55 56 int iris_hfi_queues_init(struct iris_core *core) 57 { 58 struct iris_hfi_queue_table_header *q_tbl_hdr; 59 u32 queue_size; 60 61 /* Iris hardware requires 4K queue alignment */ 62 queue_size = ALIGN((sizeof(*q_tbl_hdr) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ)), SZ_4K); 63 core->iface_q_table_vaddr = dma_alloc_attrs(core->dev, queue_size, 64 &core->iface_q_table_daddr, 65 GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); 66 if (!core->iface_q_table_vaddr) { 67 dev_err(core->dev, "queues alloc and map failed\n"); 68 return -ENOMEM; 69 } 70 71 core->sfr_vaddr = dma_alloc_attrs(core->dev, SFR_SIZE, 72 &core->sfr_daddr, 73 GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); 74 if (!core->sfr_vaddr) { 75 dev_err(core->dev, "sfr alloc and map failed\n"); 76 dma_free_attrs(core->dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr, 77 core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); 78 return -ENOMEM; 79 } 80 81 iris_hfi_queue_init(core, IFACEQ_CMDQ_ID, &core->command_queue); 82 iris_hfi_queue_init(core, IFACEQ_MSGQ_ID, &core->message_queue); 83 iris_hfi_queue_init(core, IFACEQ_DBGQ_ID, &core->debug_queue); 84 85 q_tbl_hdr = (struct iris_hfi_queue_table_header *)core->iface_q_table_vaddr; 86 q_tbl_hdr->version = 0; 87 q_tbl_hdr->device_addr = (void *)core; 88 strscpy(q_tbl_hdr->name, "iris-hfi-queues", sizeof(q_tbl_hdr->name)); 89 q_tbl_hdr->size = sizeof(*q_tbl_hdr); 90 q_tbl_hdr->qhdr0_offset = sizeof(*q_tbl_hdr) - 91 (IFACEQ_NUMQ * sizeof(struct iris_hfi_queue_header)); 92 q_tbl_hdr->qhdr_size = sizeof(q_tbl_hdr->q_hdr[0]); 93 q_tbl_hdr->num_q = IFACEQ_NUMQ; 94 q_tbl_hdr->num_active_q = IFACEQ_NUMQ; 95 96 /* Write sfr size in first word to be used by firmware */ 97 *((u32 *)core->sfr_vaddr) = SFR_SIZE; 98 99 return 0; 100 } 101 102 void iris_hfi_queues_deinit(struct iris_core *core) 103 { 104 u32 queue_size; 105 106 if (!core->iface_q_table_vaddr) 107 return; 108 109 iris_hfi_queue_deinit(&core->debug_queue); 110 iris_hfi_queue_deinit(&core->message_queue); 111 iris_hfi_queue_deinit(&core->command_queue); 112 113 dma_free_attrs(core->dev, SFR_SIZE, core->sfr_vaddr, 114 core->sfr_daddr, DMA_ATTR_WRITE_COMBINE); 115 116 core->sfr_vaddr = NULL; 117 core->sfr_daddr = 0; 118 119 queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + 120 (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ), SZ_4K); 121 122 dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, 123 core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); 124 125 core->iface_q_table_vaddr = NULL; 126 core->iface_q_table_daddr = 0; 127 } 128