Skip to content

Commit 9c26abe

Browse files
committed
Merge branch 'v5.5-next/cmdq-stable' into v5.5-next/soc
2 parents 56f6737 + d412f18 commit 9c26abe

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,10 +9,52 @@
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

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

111-
static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code,
112-
u32 arg_a, u32 arg_b)
153+
static int cmdq_pkt_append_command(struct cmdq_pkt *pkt,
154+
struct cmdq_instruction inst)
113155
{
114-
u64 *cmd_ptr;
156+
struct cmdq_instruction *cmd_ptr;
115157

116158
if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) {
117159
/*
@@ -127,77 +169,130 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code,
127169
__func__, (u32)pkt->buf_size);
128170
return -ENOMEM;
129171
}
172+
130173
cmd_ptr = pkt->va_base + pkt->cmd_buf_size;
131-
(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
174+
*cmd_ptr = inst;
132175
pkt->cmd_buf_size += CMDQ_INST_SIZE;
133176

134177
return 0;
135178
}
136179

137180
int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value)
138181
{
139-
u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) |
140-
(subsys << CMDQ_SUBSYS_SHIFT);
182+
struct cmdq_instruction inst;
141183

142-
return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value);
184+
inst.op = CMDQ_CODE_WRITE;
185+
inst.value = value;
186+
inst.offset = offset;
187+
inst.subsys = subsys;
188+
189+
return cmdq_pkt_append_command(pkt, inst);
143190
}
144191
EXPORT_SYMBOL(cmdq_pkt_write);
145192

146193
int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
147194
u16 offset, u32 value, u32 mask)
148195
{
149-
u32 offset_mask = offset;
150-
int err = 0;
196+
struct cmdq_instruction inst = { {0} };
197+
u16 offset_mask = offset;
198+
int err;
151199

152200
if (mask != 0xffffffff) {
153-
err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask);
201+
inst.op = CMDQ_CODE_MASK;
202+
inst.mask = ~mask;
203+
err = cmdq_pkt_append_command(pkt, inst);
204+
if (err < 0)
205+
return err;
206+
154207
offset_mask |= CMDQ_WRITE_ENABLE_MASK;
155208
}
156-
err |= cmdq_pkt_write(pkt, subsys, offset_mask, value);
209+
err = cmdq_pkt_write(pkt, subsys, offset_mask, value);
157210

158211
return err;
159212
}
160213
EXPORT_SYMBOL(cmdq_pkt_write_mask);
161214

162215
int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event)
163216
{
164-
u32 arg_b;
217+
struct cmdq_instruction inst = { {0} };
165218

166219
if (event >= CMDQ_MAX_EVENT)
167220
return -EINVAL;
168221

169-
/*
170-
* WFE arg_b
171-
* bit 0-11: wait value
172-
* bit 15: 1 - wait, 0 - no wait
173-
* bit 16-27: update value
174-
* bit 31: 1 - update, 0 - no update
175-
*/
176-
arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
222+
inst.op = CMDQ_CODE_WFE;
223+
inst.value = CMDQ_WFE_OPTION;
224+
inst.event = event;
177225

178-
return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event, arg_b);
226+
return cmdq_pkt_append_command(pkt, inst);
179227
}
180228
EXPORT_SYMBOL(cmdq_pkt_wfe);
181229

182230
int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event)
183231
{
232+
struct cmdq_instruction inst = { {0} };
233+
184234
if (event >= CMDQ_MAX_EVENT)
185235
return -EINVAL;
186236

187-
return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event,
188-
CMDQ_WFE_UPDATE);
237+
inst.op = CMDQ_CODE_WFE;
238+
inst.value = CMDQ_WFE_UPDATE;
239+
inst.event = event;
240+
241+
return cmdq_pkt_append_command(pkt, inst);
189242
}
190243
EXPORT_SYMBOL(cmdq_pkt_clear_event);
191244

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

196285
/* insert EOC and generate IRQ for each command iteration */
197-
err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
286+
inst.op = CMDQ_CODE_EOC;
287+
inst.value = CMDQ_EOC_IRQ_EN;
288+
err = cmdq_pkt_append_command(pkt, inst);
289+
if (err < 0)
290+
return err;
198291

199292
/* JUMP to end */
200-
err |= cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
293+
inst.op = CMDQ_CODE_JUMP;
294+
inst.value = CMDQ_JUMP_PASS;
295+
err = cmdq_pkt_append_command(pkt, inst);
201296

202297
return err;
203298
}

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)