1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Support for Intel Camera Imaging ISP subsystem.
4  * Copyright (c) 2010 - 2015, Intel Corporation.
5  */
6 
7 #include "hmm.h"
8 
9 #include "type_support.h"
10 #include "queue_access.h"
11 #include "ia_css_circbuf.h"
12 #include "sp.h"
13 #include "assert_support.h"
14 
ia_css_queue_load(struct ia_css_queue * rdesc,ia_css_circbuf_desc_t * cb_desc,uint32_t ignore_desc_flags)15 int ia_css_queue_load(
16     struct ia_css_queue *rdesc,
17     ia_css_circbuf_desc_t *cb_desc,
18     uint32_t ignore_desc_flags)
19 {
20 	if (!rdesc || !cb_desc)
21 		return -EINVAL;
22 
23 	if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
24 		assert(ignore_desc_flags <= QUEUE_IGNORE_DESC_FLAGS_MAX);
25 
26 		if (0 == (ignore_desc_flags & QUEUE_IGNORE_SIZE_FLAG)) {
27 			cb_desc->size = sp_dmem_load_uint8(rdesc->proc_id,
28 							   rdesc->desc.remote.cb_desc_addr
29 							   + offsetof(ia_css_circbuf_desc_t, size));
30 
31 			if (cb_desc->size == 0) {
32 				/* Adding back the workaround which was removed
33 				   while refactoring queues. When reading size
34 				   through sp_dmem_load_*, sometimes we get back
35 				   the value as zero. This causes division by 0
36 				   exception as the size is used in a modular
37 				   division operation. */
38 				return -EDOM;
39 			}
40 		}
41 
42 		if (0 == (ignore_desc_flags & QUEUE_IGNORE_START_FLAG))
43 			cb_desc->start = sp_dmem_load_uint8(rdesc->proc_id,
44 							    rdesc->desc.remote.cb_desc_addr
45 							    + offsetof(ia_css_circbuf_desc_t, start));
46 
47 		if (0 == (ignore_desc_flags & QUEUE_IGNORE_END_FLAG))
48 			cb_desc->end = sp_dmem_load_uint8(rdesc->proc_id,
49 							  rdesc->desc.remote.cb_desc_addr
50 							  + offsetof(ia_css_circbuf_desc_t, end));
51 
52 		if (0 == (ignore_desc_flags & QUEUE_IGNORE_STEP_FLAG))
53 			cb_desc->step = sp_dmem_load_uint8(rdesc->proc_id,
54 							   rdesc->desc.remote.cb_desc_addr
55 							   + offsetof(ia_css_circbuf_desc_t, step));
56 
57 	} else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
58 		/* doing DMA transfer of entire structure */
59 		hmm_load(rdesc->desc.remote.cb_desc_addr,
60 			  (void *)cb_desc,
61 			  sizeof(ia_css_circbuf_desc_t));
62 	} else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
63 		/* Not supported yet */
64 		return -ENOTSUPP;
65 	}
66 
67 	return 0;
68 }
69 
ia_css_queue_store(struct ia_css_queue * rdesc,ia_css_circbuf_desc_t * cb_desc,uint32_t ignore_desc_flags)70 int ia_css_queue_store(
71     struct ia_css_queue *rdesc,
72     ia_css_circbuf_desc_t *cb_desc,
73     uint32_t ignore_desc_flags)
74 {
75 	if (!rdesc || !cb_desc)
76 		return -EINVAL;
77 
78 	if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
79 		assert(ignore_desc_flags <= QUEUE_IGNORE_DESC_FLAGS_MAX);
80 
81 		if (0 == (ignore_desc_flags & QUEUE_IGNORE_SIZE_FLAG))
82 			sp_dmem_store_uint8(rdesc->proc_id,
83 					    rdesc->desc.remote.cb_desc_addr
84 					    + offsetof(ia_css_circbuf_desc_t, size),
85 					    cb_desc->size);
86 
87 		if (0 == (ignore_desc_flags & QUEUE_IGNORE_START_FLAG))
88 			sp_dmem_store_uint8(rdesc->proc_id,
89 					    rdesc->desc.remote.cb_desc_addr
90 					    + offsetof(ia_css_circbuf_desc_t, start),
91 					    cb_desc->start);
92 
93 		if (0 == (ignore_desc_flags & QUEUE_IGNORE_END_FLAG))
94 			sp_dmem_store_uint8(rdesc->proc_id,
95 					    rdesc->desc.remote.cb_desc_addr
96 					    + offsetof(ia_css_circbuf_desc_t, end),
97 					    cb_desc->end);
98 
99 		if (0 == (ignore_desc_flags & QUEUE_IGNORE_STEP_FLAG))
100 			sp_dmem_store_uint8(rdesc->proc_id,
101 					    rdesc->desc.remote.cb_desc_addr
102 					    + offsetof(ia_css_circbuf_desc_t, step),
103 					    cb_desc->step);
104 	} else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
105 		/* doing DMA transfer of entire structure */
106 		hmm_store(rdesc->desc.remote.cb_desc_addr,
107 			   (void *)cb_desc,
108 			   sizeof(ia_css_circbuf_desc_t));
109 	} else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
110 		/* Not supported yet */
111 		return -ENOTSUPP;
112 	}
113 
114 	return 0;
115 }
116 
ia_css_queue_item_load(struct ia_css_queue * rdesc,u8 position,ia_css_circbuf_elem_t * item)117 int ia_css_queue_item_load(
118     struct ia_css_queue *rdesc,
119     u8 position,
120     ia_css_circbuf_elem_t *item)
121 {
122 	if (!rdesc || !item)
123 		return -EINVAL;
124 
125 	if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
126 		sp_dmem_load(rdesc->proc_id,
127 			     rdesc->desc.remote.cb_elems_addr
128 			     + position * sizeof(ia_css_circbuf_elem_t),
129 			     item,
130 			     sizeof(ia_css_circbuf_elem_t));
131 	} else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
132 		hmm_load(rdesc->desc.remote.cb_elems_addr
133 			  + position * sizeof(ia_css_circbuf_elem_t),
134 			  (void *)item,
135 			  sizeof(ia_css_circbuf_elem_t));
136 	} else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
137 		/* Not supported yet */
138 		return -ENOTSUPP;
139 	}
140 
141 	return 0;
142 }
143 
ia_css_queue_item_store(struct ia_css_queue * rdesc,u8 position,ia_css_circbuf_elem_t * item)144 int ia_css_queue_item_store(
145     struct ia_css_queue *rdesc,
146     u8 position,
147     ia_css_circbuf_elem_t *item)
148 {
149 	if (!rdesc || !item)
150 		return -EINVAL;
151 
152 	if (rdesc->location == IA_CSS_QUEUE_LOC_SP) {
153 		sp_dmem_store(rdesc->proc_id,
154 			      rdesc->desc.remote.cb_elems_addr
155 			      + position * sizeof(ia_css_circbuf_elem_t),
156 			      item,
157 			      sizeof(ia_css_circbuf_elem_t));
158 	} else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) {
159 		hmm_store(rdesc->desc.remote.cb_elems_addr
160 			   + position * sizeof(ia_css_circbuf_elem_t),
161 			   (void *)item,
162 			   sizeof(ia_css_circbuf_elem_t));
163 	} else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) {
164 		/* Not supported yet */
165 		return -ENOTSUPP;
166 	}
167 
168 	return 0;
169 }
170