Skip to content

Commit 17aab65

Browse files
committed
cmdq patches needed by drm driver to use cmdq interface
2 parents e0e4706 + d412f18 commit 17aab65

File tree

3 files changed

+185
-26
lines changed

3 files changed

+185
-26
lines changed

drivers/soc/mediatek/mtk-cmdq-helper.c

Lines changed: 121 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,54 @@
99
#include <linux/mailbox_controller.h>
1010
#include <linux/soc/mediatek/mtk-cmdq.h>
1111

12-
#define CMDQ_ARG_A_WRITE_MASK 0xffff
1312
#define CMDQ_WRITE_ENABLE_MASK BIT(0)
13+
#define CMDQ_POLL_ENABLE_MASK BIT(0)
1414
#define CMDQ_EOC_IRQ_EN BIT(0)
1515
#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \
1616
<< 32 | CMDQ_EOC_IRQ_EN)
1717

18+
struct cmdq_instruction {
19+
union {
20+
u32 value;
21+
u32 mask;
22+
};
23+
union {
24+
u16 offset;
25+
u16 event;
26+
};
27+
u8 subsys;
28+
u8 op;
29+
};
30+
31+
int cmdq_dev_get_client_reg(struct device *dev,
32+
struct cmdq_client_reg *client_reg, int idx)
33+
{
34+
struct of_phandle_args spec;
35+
int err;
36+
37+
if (!client_reg)
38+
return -ENOENT;
39+
40+
err = of_parse_phandle_with_fixed_args(dev->of_node,
41+
"mediatek,gce-client-reg",
42+
3, idx, &spec);
43+
if (err < 0) {
44+
dev_err(dev,
45+
"error %d can't parse gce-client-reg property (%d)",
46+
err, idx);
47+
48+
return err;
49+
}
50+
51+
client_reg->subsys = (u8)spec.args[0];
52+
client_reg->offset = (u16)spec.args[1];
53+
client_reg->size = (u16)spec.args[2];
54+
of_node_put(spec.np);
55+
56+
return 0;
57+
}
58+
EXPORT_SYMBOL(cmdq_dev_get_client_reg);
59+
1860
static void cmdq_client_timeout(struct timer_list *t)
1961
{
2062
struct cmdq_client *client = from_timer(client, t, timer);
@@ -110,10 +152,10 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt)
110152
}
111153
EXPORT_SYMBOL(cmdq_pkt_destroy);
112154

113-
static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code,
114-
u32 arg_a, u32 arg_b)
155+
static int cmdq_pkt_append_command(struct cmdq_pkt *pkt,
156+
struct cmdq_instruction inst)
115157
{
116-
u64 *cmd_ptr;
158+
struct cmdq_instruction *cmd_ptr;
117159

118160
if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) {
119161
/*
@@ -129,77 +171,130 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code,
129171
__func__, (u32)pkt->buf_size);
130172
return -ENOMEM;
131173
}
174+
132175
cmd_ptr = pkt->va_base + pkt->cmd_buf_size;
133-
(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
176+
*cmd_ptr = inst;
134177
pkt->cmd_buf_size += CMDQ_INST_SIZE;
135178

136179
return 0;
137180
}
138181

139182
int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value)
140183
{
141-
u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) |
142-
(subsys << CMDQ_SUBSYS_SHIFT);
184+
struct cmdq_instruction inst;
143185

144-
return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value);
186+
inst.op = CMDQ_CODE_WRITE;
187+
inst.value = value;
188+
inst.offset = offset;
189+
inst.subsys = subsys;
190+
191+
return cmdq_pkt_append_command(pkt, inst);
145192
}
146193
EXPORT_SYMBOL(cmdq_pkt_write);
147194

148195
int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
149196
u16 offset, u32 value, u32 mask)
150197
{
151-
u32 offset_mask = offset;
152-
int err = 0;
198+
struct cmdq_instruction inst = { {0} };
199+
u16 offset_mask = offset;
200+
int err;
153201

154202
if (mask != 0xffffffff) {
155-
err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask);
203+
inst.op = CMDQ_CODE_MASK;
204+
inst.mask = ~mask;
205+
err = cmdq_pkt_append_command(pkt, inst);
206+
if (err < 0)
207+
return err;
208+
156209
offset_mask |= CMDQ_WRITE_ENABLE_MASK;
157210
}
158-
err |= cmdq_pkt_write(pkt, subsys, offset_mask, value);
211+
err = cmdq_pkt_write(pkt, subsys, offset_mask, value);
159212

160213
return err;
161214
}
162215
EXPORT_SYMBOL(cmdq_pkt_write_mask);
163216

164217
int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event)
165218
{
166-
u32 arg_b;
219+
struct cmdq_instruction inst = { {0} };
167220

168221
if (event >= CMDQ_MAX_EVENT)
169222
return -EINVAL;
170223

171-
/*
172-
* WFE arg_b
173-
* bit 0-11: wait value
174-
* bit 15: 1 - wait, 0 - no wait
175-
* bit 16-27: update value
176-
* bit 31: 1 - update, 0 - no update
177-
*/
178-
arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
224+
inst.op = CMDQ_CODE_WFE;
225+
inst.value = CMDQ_WFE_OPTION;
226+
inst.event = event;
179227

180-
return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event, arg_b);
228+
return cmdq_pkt_append_command(pkt, inst);
181229
}
182230
EXPORT_SYMBOL(cmdq_pkt_wfe);
183231

184232
int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event)
185233
{
234+
struct cmdq_instruction inst = { {0} };
235+
186236
if (event >= CMDQ_MAX_EVENT)
187237
return -EINVAL;
188238

189-
return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event,
190-
CMDQ_WFE_UPDATE);
239+
inst.op = CMDQ_CODE_WFE;
240+
inst.value = CMDQ_WFE_UPDATE;
241+
inst.event = event;
242+
243+
return cmdq_pkt_append_command(pkt, inst);
191244
}
192245
EXPORT_SYMBOL(cmdq_pkt_clear_event);
193246

247+
int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys,
248+
u16 offset, u32 value)
249+
{
250+
struct cmdq_instruction inst = { {0} };
251+
int err;
252+
253+
inst.op = CMDQ_CODE_POLL;
254+
inst.value = value;
255+
inst.offset = offset;
256+
inst.subsys = subsys;
257+
err = cmdq_pkt_append_command(pkt, inst);
258+
259+
return err;
260+
}
261+
EXPORT_SYMBOL(cmdq_pkt_poll);
262+
263+
int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys,
264+
u16 offset, u32 value, u32 mask)
265+
{
266+
struct cmdq_instruction inst = { {0} };
267+
int err;
268+
269+
inst.op = CMDQ_CODE_MASK;
270+
inst.mask = ~mask;
271+
err = cmdq_pkt_append_command(pkt, inst);
272+
if (err < 0)
273+
return err;
274+
275+
offset = offset | CMDQ_POLL_ENABLE_MASK;
276+
err = cmdq_pkt_poll(pkt, subsys, offset, value);
277+
278+
return err;
279+
}
280+
EXPORT_SYMBOL(cmdq_pkt_poll_mask);
281+
194282
static int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
195283
{
284+
struct cmdq_instruction inst = { {0} };
196285
int err;
197286

198287
/* insert EOC and generate IRQ for each command iteration */
199-
err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
288+
inst.op = CMDQ_CODE_EOC;
289+
inst.value = CMDQ_EOC_IRQ_EN;
290+
err = cmdq_pkt_append_command(pkt, inst);
291+
if (err < 0)
292+
return err;
200293

201294
/* JUMP to end */
202-
err |= cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
295+
inst.op = CMDQ_CODE_JUMP;
296+
inst.value = CMDQ_JUMP_PASS;
297+
err = cmdq_pkt_append_command(pkt, inst);
203298

204299
return err;
205300
}

include/linux/mailbox/mtk-cmdq-mailbox.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@
2020
#define CMDQ_WFE_WAIT BIT(15)
2121
#define CMDQ_WFE_WAIT_VALUE 0x1
2222

23+
/*
24+
* WFE arg_b
25+
* bit 0-11: wait value
26+
* bit 15: 1 - wait, 0 - no wait
27+
* bit 16-27: update value
28+
* bit 31: 1 - update, 0 - no update
29+
*/
30+
#define CMDQ_WFE_OPTION (CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | \
31+
CMDQ_WFE_WAIT_VALUE)
32+
2333
/** cmdq event maximum */
2434
#define CMDQ_MAX_EVENT 0x3ff
2535

@@ -45,6 +55,7 @@
4555
enum cmdq_code {
4656
CMDQ_CODE_MASK = 0x02,
4757
CMDQ_CODE_WRITE = 0x04,
58+
CMDQ_CODE_POLL = 0x08,
4859
CMDQ_CODE_JUMP = 0x10,
4960
CMDQ_CODE_WFE = 0x20,
5061
CMDQ_CODE_EOC = 0x40,

include/linux/soc/mediatek/mtk-cmdq.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515

1616
struct cmdq_pkt;
1717

18+
struct cmdq_client_reg {
19+
u8 subsys;
20+
u16 offset;
21+
u16 size;
22+
};
23+
1824
struct cmdq_client {
1925
spinlock_t lock;
2026
u32 pkt_cnt;
@@ -24,6 +30,21 @@ struct cmdq_client {
2430
u32 timeout_ms; /* in unit of microsecond */
2531
};
2632

33+
/**
34+
* cmdq_dev_get_client_reg() - parse cmdq client reg from the device
35+
* node of CMDQ client
36+
* @dev: device of CMDQ mailbox client
37+
* @client_reg: CMDQ client reg pointer
38+
* @idx: the index of desired reg
39+
*
40+
* Return: 0 for success; else the error code is returned
41+
*
42+
* Help CMDQ client parsing the cmdq client reg
43+
* from the device node of CMDQ client.
44+
*/
45+
int cmdq_dev_get_client_reg(struct device *dev,
46+
struct cmdq_client_reg *client_reg, int idx);
47+
2748
/**
2849
* cmdq_mbox_create() - create CMDQ mailbox client and channel
2950
* @dev: device of CMDQ mailbox client
@@ -99,6 +120,38 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event);
99120
*/
100121
int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event);
101122

123+
/**
124+
* cmdq_pkt_poll() - Append polling command to the CMDQ packet, ask GCE to
125+
* execute an instruction that wait for a specified
126+
* hardware register to check for the value w/o mask.
127+
* All GCE hardware threads will be blocked by this
128+
* instruction.
129+
* @pkt: the CMDQ packet
130+
* @subsys: the CMDQ sub system code
131+
* @offset: register offset from CMDQ sub system
132+
* @value: the specified target register value
133+
*
134+
* Return: 0 for success; else the error code is returned
135+
*/
136+
int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys,
137+
u16 offset, u32 value);
138+
139+
/**
140+
* cmdq_pkt_poll_mask() - Append polling command to the CMDQ packet, ask GCE to
141+
* execute an instruction that wait for a specified
142+
* hardware register to check for the value w/ mask.
143+
* All GCE hardware threads will be blocked by this
144+
* instruction.
145+
* @pkt: the CMDQ packet
146+
* @subsys: the CMDQ sub system code
147+
* @offset: register offset from CMDQ sub system
148+
* @value: the specified target register value
149+
* @mask: the specified target register mask
150+
*
151+
* Return: 0 for success; else the error code is returned
152+
*/
153+
int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys,
154+
u16 offset, u32 value, u32 mask);
102155
/**
103156
* cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ
104157
* packet and call back at the end of done packet

0 commit comments

Comments
 (0)