Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
9c26abeb
Commit
9c26abeb
authored
Jan 10, 2020
by
Matthias Brugger
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'v5.5-next/cmdq-stable' into v5.5-next/soc
parents
56f67371
d412f18c
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
185 additions
and
26 deletions
+185
-26
drivers/soc/mediatek/mtk-cmdq-helper.c
drivers/soc/mediatek/mtk-cmdq-helper.c
+121
-26
include/linux/mailbox/mtk-cmdq-mailbox.h
include/linux/mailbox/mtk-cmdq-mailbox.h
+11
-0
include/linux/soc/mediatek/mtk-cmdq.h
include/linux/soc/mediatek/mtk-cmdq.h
+53
-0
No files found.
drivers/soc/mediatek/mtk-cmdq-helper.c
View file @
9c26abeb
...
...
@@ -9,10 +9,52 @@
#include <linux/mailbox_controller.h>
#include <linux/soc/mediatek/mtk-cmdq.h>
#define CMDQ_ARG_A_WRITE_MASK 0xffff
#define CMDQ_WRITE_ENABLE_MASK BIT(0)
#define CMDQ_POLL_ENABLE_MASK BIT(0)
#define CMDQ_EOC_IRQ_EN BIT(0)
struct
cmdq_instruction
{
union
{
u32
value
;
u32
mask
;
};
union
{
u16
offset
;
u16
event
;
};
u8
subsys
;
u8
op
;
};
int
cmdq_dev_get_client_reg
(
struct
device
*
dev
,
struct
cmdq_client_reg
*
client_reg
,
int
idx
)
{
struct
of_phandle_args
spec
;
int
err
;
if
(
!
client_reg
)
return
-
ENOENT
;
err
=
of_parse_phandle_with_fixed_args
(
dev
->
of_node
,
"mediatek,gce-client-reg"
,
3
,
idx
,
&
spec
);
if
(
err
<
0
)
{
dev_err
(
dev
,
"error %d can't parse gce-client-reg property (%d)"
,
err
,
idx
);
return
err
;
}
client_reg
->
subsys
=
(
u8
)
spec
.
args
[
0
];
client_reg
->
offset
=
(
u16
)
spec
.
args
[
1
];
client_reg
->
size
=
(
u16
)
spec
.
args
[
2
];
of_node_put
(
spec
.
np
);
return
0
;
}
EXPORT_SYMBOL
(
cmdq_dev_get_client_reg
);
static
void
cmdq_client_timeout
(
struct
timer_list
*
t
)
{
struct
cmdq_client
*
client
=
from_timer
(
client
,
t
,
timer
);
...
...
@@ -108,10 +150,10 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt)
}
EXPORT_SYMBOL
(
cmdq_pkt_destroy
);
static
int
cmdq_pkt_append_command
(
struct
cmdq_pkt
*
pkt
,
enum
cmdq_code
code
,
u32
arg_a
,
u32
arg_b
)
static
int
cmdq_pkt_append_command
(
struct
cmdq_pkt
*
pkt
,
struct
cmdq_instruction
inst
)
{
u64
*
cmd_ptr
;
struct
cmdq_instruction
*
cmd_ptr
;
if
(
unlikely
(
pkt
->
cmd_buf_size
+
CMDQ_INST_SIZE
>
pkt
->
buf_size
))
{
/*
...
...
@@ -127,8 +169,9 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code,
__func__
,
(
u32
)
pkt
->
buf_size
);
return
-
ENOMEM
;
}
cmd_ptr
=
pkt
->
va_base
+
pkt
->
cmd_buf_size
;
(
*
cmd_ptr
)
=
(
u64
)((
code
<<
CMDQ_OP_CODE_SHIFT
)
|
arg_a
)
<<
32
|
arg_b
;
*
cmd_ptr
=
inst
;
pkt
->
cmd_buf_size
+=
CMDQ_INST_SIZE
;
return
0
;
...
...
@@ -136,24 +179,34 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code,
int
cmdq_pkt_write
(
struct
cmdq_pkt
*
pkt
,
u8
subsys
,
u16
offset
,
u32
value
)
{
u32
arg_a
=
(
offset
&
CMDQ_ARG_A_WRITE_MASK
)
|
(
subsys
<<
CMDQ_SUBSYS_SHIFT
);
struct
cmdq_instruction
inst
;
inst
.
op
=
CMDQ_CODE_WRITE
;
inst
.
value
=
value
;
inst
.
offset
=
offset
;
inst
.
subsys
=
subsys
;
return
cmdq_pkt_append_command
(
pkt
,
CMDQ_CODE_WRITE
,
arg_a
,
value
);
return
cmdq_pkt_append_command
(
pkt
,
inst
);
}
EXPORT_SYMBOL
(
cmdq_pkt_write
);
int
cmdq_pkt_write_mask
(
struct
cmdq_pkt
*
pkt
,
u8
subsys
,
u16
offset
,
u32
value
,
u32
mask
)
{
u32
offset_mask
=
offset
;
int
err
=
0
;
struct
cmdq_instruction
inst
=
{
{
0
}
};
u16
offset_mask
=
offset
;
int
err
;
if
(
mask
!=
0xffffffff
)
{
err
=
cmdq_pkt_append_command
(
pkt
,
CMDQ_CODE_MASK
,
0
,
~
mask
);
inst
.
op
=
CMDQ_CODE_MASK
;
inst
.
mask
=
~
mask
;
err
=
cmdq_pkt_append_command
(
pkt
,
inst
);
if
(
err
<
0
)
return
err
;
offset_mask
|=
CMDQ_WRITE_ENABLE_MASK
;
}
err
|
=
cmdq_pkt_write
(
pkt
,
subsys
,
offset_mask
,
value
);
err
=
cmdq_pkt_write
(
pkt
,
subsys
,
offset_mask
,
value
);
return
err
;
}
...
...
@@ -161,43 +214,85 @@ EXPORT_SYMBOL(cmdq_pkt_write_mask);
int
cmdq_pkt_wfe
(
struct
cmdq_pkt
*
pkt
,
u16
event
)
{
u32
arg_b
;
struct
cmdq_instruction
inst
=
{
{
0
}
}
;
if
(
event
>=
CMDQ_MAX_EVENT
)
return
-
EINVAL
;
/*
* WFE arg_b
* bit 0-11: wait value
* bit 15: 1 - wait, 0 - no wait
* bit 16-27: update value
* bit 31: 1 - update, 0 - no update
*/
arg_b
=
CMDQ_WFE_UPDATE
|
CMDQ_WFE_WAIT
|
CMDQ_WFE_WAIT_VALUE
;
inst
.
op
=
CMDQ_CODE_WFE
;
inst
.
value
=
CMDQ_WFE_OPTION
;
inst
.
event
=
event
;
return
cmdq_pkt_append_command
(
pkt
,
CMDQ_CODE_WFE
,
event
,
arg_b
);
return
cmdq_pkt_append_command
(
pkt
,
inst
);
}
EXPORT_SYMBOL
(
cmdq_pkt_wfe
);
int
cmdq_pkt_clear_event
(
struct
cmdq_pkt
*
pkt
,
u16
event
)
{
struct
cmdq_instruction
inst
=
{
{
0
}
};
if
(
event
>=
CMDQ_MAX_EVENT
)
return
-
EINVAL
;
return
cmdq_pkt_append_command
(
pkt
,
CMDQ_CODE_WFE
,
event
,
CMDQ_WFE_UPDATE
);
inst
.
op
=
CMDQ_CODE_WFE
;
inst
.
value
=
CMDQ_WFE_UPDATE
;
inst
.
event
=
event
;
return
cmdq_pkt_append_command
(
pkt
,
inst
);
}
EXPORT_SYMBOL
(
cmdq_pkt_clear_event
);
int
cmdq_pkt_poll
(
struct
cmdq_pkt
*
pkt
,
u8
subsys
,
u16
offset
,
u32
value
)
{
struct
cmdq_instruction
inst
=
{
{
0
}
};
int
err
;
inst
.
op
=
CMDQ_CODE_POLL
;
inst
.
value
=
value
;
inst
.
offset
=
offset
;
inst
.
subsys
=
subsys
;
err
=
cmdq_pkt_append_command
(
pkt
,
inst
);
return
err
;
}
EXPORT_SYMBOL
(
cmdq_pkt_poll
);
int
cmdq_pkt_poll_mask
(
struct
cmdq_pkt
*
pkt
,
u8
subsys
,
u16
offset
,
u32
value
,
u32
mask
)
{
struct
cmdq_instruction
inst
=
{
{
0
}
};
int
err
;
inst
.
op
=
CMDQ_CODE_MASK
;
inst
.
mask
=
~
mask
;
err
=
cmdq_pkt_append_command
(
pkt
,
inst
);
if
(
err
<
0
)
return
err
;
offset
=
offset
|
CMDQ_POLL_ENABLE_MASK
;
err
=
cmdq_pkt_poll
(
pkt
,
subsys
,
offset
,
value
);
return
err
;
}
EXPORT_SYMBOL
(
cmdq_pkt_poll_mask
);
static
int
cmdq_pkt_finalize
(
struct
cmdq_pkt
*
pkt
)
{
struct
cmdq_instruction
inst
=
{
{
0
}
};
int
err
;
/* insert EOC and generate IRQ for each command iteration */
err
=
cmdq_pkt_append_command
(
pkt
,
CMDQ_CODE_EOC
,
0
,
CMDQ_EOC_IRQ_EN
);
inst
.
op
=
CMDQ_CODE_EOC
;
inst
.
value
=
CMDQ_EOC_IRQ_EN
;
err
=
cmdq_pkt_append_command
(
pkt
,
inst
);
if
(
err
<
0
)
return
err
;
/* JUMP to end */
err
|=
cmdq_pkt_append_command
(
pkt
,
CMDQ_CODE_JUMP
,
0
,
CMDQ_JUMP_PASS
);
inst
.
op
=
CMDQ_CODE_JUMP
;
inst
.
value
=
CMDQ_JUMP_PASS
;
err
=
cmdq_pkt_append_command
(
pkt
,
inst
);
return
err
;
}
...
...
include/linux/mailbox/mtk-cmdq-mailbox.h
View file @
9c26abeb
...
...
@@ -20,6 +20,16 @@
#define CMDQ_WFE_WAIT BIT(15)
#define CMDQ_WFE_WAIT_VALUE 0x1
/*
* WFE arg_b
* bit 0-11: wait value
* bit 15: 1 - wait, 0 - no wait
* bit 16-27: update value
* bit 31: 1 - update, 0 - no update
*/
#define CMDQ_WFE_OPTION (CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | \
CMDQ_WFE_WAIT_VALUE)
/** cmdq event maximum */
#define CMDQ_MAX_EVENT 0x3ff
...
...
@@ -45,6 +55,7 @@
enum
cmdq_code
{
CMDQ_CODE_MASK
=
0x02
,
CMDQ_CODE_WRITE
=
0x04
,
CMDQ_CODE_POLL
=
0x08
,
CMDQ_CODE_JUMP
=
0x10
,
CMDQ_CODE_WFE
=
0x20
,
CMDQ_CODE_EOC
=
0x40
,
...
...
include/linux/soc/mediatek/mtk-cmdq.h
View file @
9c26abeb
...
...
@@ -15,6 +15,12 @@
struct
cmdq_pkt
;
struct
cmdq_client_reg
{
u8
subsys
;
u16
offset
;
u16
size
;
};
struct
cmdq_client
{
spinlock_t
lock
;
u32
pkt_cnt
;
...
...
@@ -24,6 +30,21 @@ struct cmdq_client {
u32
timeout_ms
;
/* in unit of microsecond */
};
/**
* cmdq_dev_get_client_reg() - parse cmdq client reg from the device
* node of CMDQ client
* @dev: device of CMDQ mailbox client
* @client_reg: CMDQ client reg pointer
* @idx: the index of desired reg
*
* Return: 0 for success; else the error code is returned
*
* Help CMDQ client parsing the cmdq client reg
* from the device node of CMDQ client.
*/
int
cmdq_dev_get_client_reg
(
struct
device
*
dev
,
struct
cmdq_client_reg
*
client_reg
,
int
idx
);
/**
* cmdq_mbox_create() - create CMDQ mailbox client and channel
* @dev: device of CMDQ mailbox client
...
...
@@ -99,6 +120,38 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event);
*/
int
cmdq_pkt_clear_event
(
struct
cmdq_pkt
*
pkt
,
u16
event
);
/**
* cmdq_pkt_poll() - Append polling command to the CMDQ packet, ask GCE to
* execute an instruction that wait for a specified
* hardware register to check for the value w/o mask.
* All GCE hardware threads will be blocked by this
* instruction.
* @pkt: the CMDQ packet
* @subsys: the CMDQ sub system code
* @offset: register offset from CMDQ sub system
* @value: the specified target register value
*
* Return: 0 for success; else the error code is returned
*/
int
cmdq_pkt_poll
(
struct
cmdq_pkt
*
pkt
,
u8
subsys
,
u16
offset
,
u32
value
);
/**
* cmdq_pkt_poll_mask() - Append polling command to the CMDQ packet, ask GCE to
* execute an instruction that wait for a specified
* hardware register to check for the value w/ mask.
* All GCE hardware threads will be blocked by this
* instruction.
* @pkt: the CMDQ packet
* @subsys: the CMDQ sub system code
* @offset: register offset from CMDQ sub system
* @value: the specified target register value
* @mask: the specified target register mask
*
* Return: 0 for success; else the error code is returned
*/
int
cmdq_pkt_poll_mask
(
struct
cmdq_pkt
*
pkt
,
u8
subsys
,
u16
offset
,
u32
value
,
u32
mask
);
/**
* cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ
* packet and call back at the end of done packet
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment