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