Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
duo-buildroot-sdk
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
duo-buildroot-sdk
Commits
1bca5068
Commit
1bca5068
authored
Nov 30, 2023
by
carbon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add mailbox based inter-processor communication
parent
56595260
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1035 additions
and
27 deletions
+1035
-27
build/boards/cv180x/cv1800b_milkv_duo_sd/linux/cvitek_cv1800b_milkv_duo_sd_defconfig
..._milkv_duo_sd/linux/cvitek_cv1800b_milkv_duo_sd_defconfig
+1
-0
freertos/cvitek/driver/rtos_cmdqu/include/rtos_cmdqu.h
freertos/cvitek/driver/rtos_cmdqu/include/rtos_cmdqu.h
+3
-16
freertos/cvitek/task/comm/src/riscv64/comm_main.c
freertos/cvitek/task/comm/src/riscv64/comm_main.c
+198
-10
freertos/cvitek/task/main/src/main.c
freertos/cvitek/task/main/src/main.c
+12
-0
linux_5.10/drivers/soc/cvitek/Kconfig
linux_5.10/drivers/soc/cvitek/Kconfig
+1
-0
linux_5.10/drivers/soc/cvitek/Makefile
linux_5.10/drivers/soc/cvitek/Makefile
+2
-1
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/Kconfig
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/Kconfig
+4
-0
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/Makefile
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/Makefile
+5
-0
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/cvi_mailbox.h
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/cvi_mailbox.h
+77
-0
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/cvi_spinlock.c
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/cvi_spinlock.c
+108
-0
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/cvi_spinlock.h
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/cvi_spinlock.h
+43
-0
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/rtos_cmdqu.c
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/rtos_cmdqu.c
+530
-0
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/rtos_cmdqu.h
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/rtos_cmdqu.h
+51
-0
No files found.
build/boards/cv180x/cv1800b_milkv_duo_sd/linux/cvitek_cv1800b_milkv_duo_sd_defconfig
View file @
1bca5068
...
@@ -270,6 +270,7 @@ CONFIG_ION_CARVEOUT_HEAP=y
...
@@ -270,6 +270,7 @@ CONFIG_ION_CARVEOUT_HEAP=y
CONFIG_ION_CMA_HEAP=y
CONFIG_ION_CMA_HEAP=y
# CONFIG_IOMMU_SUPPORT is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_CV1835_SYSDMA_REMAP=y
CONFIG_CV1835_SYSDMA_REMAP=y
CONFIG_CVI_MAILBOX=y
CONFIG_PWM=y
CONFIG_PWM=y
CONFIG_SIFIVE_PLIC=y
CONFIG_SIFIVE_PLIC=y
CONFIG_ANDROID=y
CONFIG_ANDROID=y
...
...
freertos/cvitek/driver/rtos_cmdqu/include/rtos_cmdqu.h
View file @
1bca5068
...
@@ -11,22 +11,9 @@
...
@@ -11,22 +11,9 @@
enum
SYS_CMD_ID
{
enum
SYS_CMD_ID
{
SYS_CMD_INFO_TRANS
=
0x50
,
CMD_TEST_A
=
0x10
,
SYS_CMD_INFO_LINUX_INIT_DONE
,
CMD_TEST_B
,
SYS_CMD_INFO_RTOS_INIT_DONE
,
CMD_TEST_C
,
SYS_CMD_INFO_STOP_ISR
,
SYS_CMD_INFO_STOP_ISR_DONE
,
SYS_CMD_INFO_LINUX
,
SYS_CMD_INFO_RTOS
,
SYS_CMD_SYNC_TIME
,
SYS_CMD_INFO_DUMP_MSG
,
SYS_CMD_INFO_DUMP_EN
,
SYS_CMD_INFO_DUMP_DIS
,
SYS_CMD_INFO_DUMP_JPG
,
SYS_CMD_INFO_TRACE_SNAPSHOT_START
,
SYS_CMD_INFO_TRACE_SNAPSHOT_STOP
,
SYS_CMD_INFO_TRACE_STREAM_START
,
SYS_CMD_INFO_TRACE_STREAM_STOP
,
SYS_CMD_INFO_LIMIT
,
SYS_CMD_INFO_LIMIT
,
};
};
...
...
freertos/cvitek/task/comm/src/riscv64/comm_main.c
View file @
1bca5068
...
@@ -19,49 +19,80 @@
...
@@ -19,49 +19,80 @@
#include "cvi_spinlock.h"
#include "cvi_spinlock.h"
//#define __DEBUG__
// #define __DEBUG__
#ifdef __DEBUG__
#ifdef __DEBUG__
#define debug_printf printf
#define debug_printf printf
#else
#else
#define debug_printf(...)
#define debug_printf(...)
#endif
#endif
typedef
struct
_TASK_CTX_S
{
char
name
[
32
];
u16
stack_size
;
UBaseType_t
priority
;
void
(
*
runTask
)(
void
*
pvParameters
);
u8
queLength
;
QueueHandle_t
queHandle
;
}
TASK_CTX_S
;
/****************************************************************************
/****************************************************************************
* Function prototypes
* Function prototypes
****************************************************************************/
****************************************************************************/
void
prvQueueISR
(
void
);
void
prvCmdQuRunTask
(
void
*
pvParameters
);
/****************************************************************************
/****************************************************************************
* Global parameters
* Global parameters
****************************************************************************/
****************************************************************************/
TASK_CTX_S
gTaskCtx
[
1
]
=
{
{
.
name
=
"CMDQU"
,
.
stack_size
=
configMINIMAL_STACK_SIZE
,
.
priority
=
tskIDLE_PRIORITY
+
5
,
.
runTask
=
prvCmdQuRunTask
,
.
queLength
=
30
,
.
queHandle
=
NULL
,
},
};
/* mailbox parameters */
/* mailbox parameters */
volatile
struct
mailbox_set_register
*
mbox_reg
;
volatile
struct
mailbox_set_register
*
mbox_reg
;
volatile
struct
mailbox_done_register
*
mbox_done_reg
;
volatile
struct
mailbox_done_register
*
mbox_done_reg
;
volatile
unsigned
long
*
mailbox_context
;
// mailbox buffer context is 64 Bytess
volatile
unsigned
long
*
mailbox_context
;
// mailbox buffer context is 64 Bytess
/****************************************************************************
/****************************************************************************
* Function definitions
* Function definitions
****************************************************************************/
****************************************************************************/
DEFINE_CVI_SPINLOCK
(
mailbox_lock
,
SPIN_MBOX
);
void
main_create_tasks
(
void
)
{
u8
i
=
0
;
#define TASK_INIT(_idx) \
do { \
gTaskCtx[_idx].queHandle = xQueueCreate(gTaskCtx[_idx].queLength, sizeof(cmdqu_t)); \
if (gTaskCtx[_idx].queHandle != NULL && gTaskCtx[_idx].runTask != NULL) { \
xTaskCreate(gTaskCtx[_idx].runTask, gTaskCtx[_idx].name, gTaskCtx[_idx].stack_size, \
NULL, gTaskCtx[_idx].priority, NULL); \
} \
} while(0)
for
(;
i
<
ARRAY_SIZE
(
gTaskCtx
);
i
++
)
{
DEFINE_CVI_SPINLOCK
(
mailbox_lock
,
SPIN_MBOX
);
TASK_INIT
(
i
);
}
}
void
main_cvirtos
(
void
)
void
main_cvirtos
(
void
)
{
{
printf
(
"create cvi task
\n
"
);
printf
(
"create cvi task
\n
"
);
/* Start the tasks and timer running. */
/* Start the tasks and timer running. */
request_irq
(
MBOX_INT_C906_2ND
,
prvQueueISR
,
0
,
"mailbox"
,
(
void
*
)
0
);
main_create_tasks
();
/* Start the tasks and timer running. */
vTaskStartScheduler
();
/* If all is well, the scheduler will now be running, and the following
/* If all is well, the scheduler will now be running, and the following
...
@@ -77,3 +108,160 @@ void main_cvirtos(void)
...
@@ -77,3 +108,160 @@ void main_cvirtos(void)
for
(;;)
for
(;;)
;
;
}
}
void
prvCmdQuRunTask
(
void
*
pvParameters
)
{
/* Remove compiler warning about unused parameter. */
(
void
)
pvParameters
;
cmdqu_t
rtos_cmdq
;
cmdqu_t
*
cmdq
;
cmdqu_t
*
rtos_cmdqu_t
;
static
int
stop_ip
=
0
;
int
ret
=
0
;
int
flags
;
int
valid
;
int
send_to_cpu
=
SEND_TO_CPU1
;
unsigned
int
reg_base
=
MAILBOX_REG_BASE
;
/* to compatible code with linux side */
cmdq
=
&
rtos_cmdq
;
mbox_reg
=
(
struct
mailbox_set_register
*
)
reg_base
;
mbox_done_reg
=
(
struct
mailbox_done_register
*
)
(
reg_base
+
2
);
mailbox_context
=
(
unsigned
long
*
)
(
MAILBOX_REG_BUFF
);
cvi_spinlock_init
();
printf
(
"prvCmdQuRunTask run
\n
"
);
for
(;;)
{
xQueueReceive
(
gTaskCtx
[
0
].
queHandle
,
&
rtos_cmdq
,
portMAX_DELAY
);
switch
(
rtos_cmdq
.
cmd_id
)
{
case
CMD_TEST_A
:
//do something
//send to C906B
rtos_cmdq
.
cmd_id
=
CMD_TEST_A
;
rtos_cmdq
.
param_ptr
=
0x12345678
;
rtos_cmdq
.
resv
.
valid
.
rtos_valid
=
1
;
rtos_cmdq
.
resv
.
valid
.
linux_valid
=
0
;
printf
(
"recv cmd(%d) from C906B...send [0x%x] to C906B
\n
"
,
rtos_cmdq
.
cmd_id
,
rtos_cmdq
.
param_ptr
);
goto
send_label
;
case
CMD_TEST_B
:
//nothing to do
printf
(
"nothing to do...
\n
"
);
break
;
case
CMD_TEST_C
:
rtos_cmdq
.
cmd_id
=
CMD_TEST_C
;
rtos_cmdq
.
param_ptr
=
0x55aa
;
rtos_cmdq
.
resv
.
valid
.
rtos_valid
=
1
;
rtos_cmdq
.
resv
.
valid
.
linux_valid
=
0
;
printf
(
"recv cmd(%d) from C906B...send [0x%x] to C906B
\n
"
,
rtos_cmdq
.
cmd_id
,
rtos_cmdq
.
param_ptr
);
goto
send_label
;
default:
send_label:
/* used to send command to linux*/
rtos_cmdqu_t
=
(
cmdqu_t
*
)
mailbox_context
;
debug_printf
(
"RTOS_CMDQU_SEND %d
\n
"
,
send_to_cpu
);
debug_printf
(
"ip_id=%d cmd_id=%d param_ptr=%x
\n
"
,
cmdq
->
ip_id
,
cmdq
->
cmd_id
,
(
unsigned
int
)
cmdq
->
param_ptr
);
debug_printf
(
"mailbox_context = %x
\n
"
,
mailbox_context
);
debug_printf
(
"linux_cmdqu_t = %x
\n
"
,
rtos_cmdqu_t
);
debug_printf
(
"cmdq->ip_id = %d
\n
"
,
cmdq
->
ip_id
);
debug_printf
(
"cmdq->cmd_id = %d
\n
"
,
cmdq
->
cmd_id
);
debug_printf
(
"cmdq->block = %d
\n
"
,
cmdq
->
block
);
debug_printf
(
"cmdq->para_ptr = %x
\n
"
,
cmdq
->
param_ptr
);
drv_spin_lock_irqsave
(
&
mailbox_lock
,
flags
);
if
(
flags
==
MAILBOX_LOCK_FAILED
)
{
printf
(
"[%s][%d] drv_spin_lock_irqsave failed! ip_id = %d , cmd_id = %d
\n
"
,
cmdq
->
ip_id
,
cmdq
->
cmd_id
);
break
;
}
for
(
valid
=
0
;
valid
<
MAILBOX_MAX_NUM
;
valid
++
)
{
if
(
rtos_cmdqu_t
->
resv
.
valid
.
linux_valid
==
0
&&
rtos_cmdqu_t
->
resv
.
valid
.
rtos_valid
==
0
)
{
// mailbox buffer context is 4 bytes write access
int
*
ptr
=
(
int
*
)
rtos_cmdqu_t
;
cmdq
->
resv
.
valid
.
rtos_valid
=
1
;
*
ptr
=
((
cmdq
->
ip_id
<<
0
)
|
(
cmdq
->
cmd_id
<<
8
)
|
(
cmdq
->
block
<<
15
)
|
(
cmdq
->
resv
.
valid
.
linux_valid
<<
16
)
|
(
cmdq
->
resv
.
valid
.
rtos_valid
<<
24
));
rtos_cmdqu_t
->
param_ptr
=
cmdq
->
param_ptr
;
debug_printf
(
"rtos_cmdqu_t->linux_valid = %d
\n
"
,
rtos_cmdqu_t
->
resv
.
valid
.
linux_valid
);
debug_printf
(
"rtos_cmdqu_t->rtos_valid = %d
\n
"
,
rtos_cmdqu_t
->
resv
.
valid
.
rtos_valid
);
debug_printf
(
"rtos_cmdqu_t->ip_id =%x %d
\n
"
,
&
rtos_cmdqu_t
->
ip_id
,
rtos_cmdqu_t
->
ip_id
);
debug_printf
(
"rtos_cmdqu_t->cmd_id = %d
\n
"
,
rtos_cmdqu_t
->
cmd_id
);
debug_printf
(
"rtos_cmdqu_t->block = %d
\n
"
,
rtos_cmdqu_t
->
block
);
debug_printf
(
"rtos_cmdqu_t->param_ptr addr=%x %x
\n
"
,
&
rtos_cmdqu_t
->
param_ptr
,
rtos_cmdqu_t
->
param_ptr
);
debug_printf
(
"*ptr = %x
\n
"
,
*
ptr
);
// clear mailbox
mbox_reg
->
cpu_mbox_set
[
send_to_cpu
].
cpu_mbox_int_clr
.
mbox_int_clr
=
(
1
<<
valid
);
// trigger mailbox valid to rtos
mbox_reg
->
cpu_mbox_en
[
send_to_cpu
].
mbox_info
|=
(
1
<<
valid
);
mbox_reg
->
mbox_set
.
mbox_set
=
(
1
<<
valid
);
break
;
}
rtos_cmdqu_t
++
;
}
drv_spin_unlock_irqrestore
(
&
mailbox_lock
,
flags
);
if
(
valid
>=
MAILBOX_MAX_NUM
)
{
printf
(
"No valid mailbox is available
\n
"
);
return
-
1
;
}
break
;
}
}
}
void
prvQueueISR
(
void
)
{
printf
(
"prvQueueISR
\n
"
);
unsigned
char
set_val
;
unsigned
char
valid_val
;
int
i
;
cmdqu_t
*
cmdq
;
BaseType_t
YieldRequired
=
pdFALSE
;
set_val
=
mbox_reg
->
cpu_mbox_set
[
RECEIVE_CPU
].
cpu_mbox_int_int
.
mbox_int
;
if
(
set_val
)
{
for
(
i
=
0
;
i
<
MAILBOX_MAX_NUM
;
i
++
)
{
valid_val
=
set_val
&
(
1
<<
i
);
if
(
valid_val
)
{
cmdqu_t
rtos_cmdq
;
cmdq
=
(
cmdqu_t
*
)(
mailbox_context
)
+
i
;
debug_printf
(
"mailbox_context =%x
\n
"
,
mailbox_context
);
debug_printf
(
"sizeof mailbox_context =%x
\n
"
,
sizeof
(
cmdqu_t
));
/* mailbox buffer context is send from linux, clear mailbox interrupt */
mbox_reg
->
cpu_mbox_set
[
RECEIVE_CPU
].
cpu_mbox_int_clr
.
mbox_int_clr
=
valid_val
;
// need to disable enable bit
mbox_reg
->
cpu_mbox_en
[
RECEIVE_CPU
].
mbox_info
&=
~
valid_val
;
// copy cmdq context (8 bytes) to buffer ASAP
*
((
unsigned
long
*
)
&
rtos_cmdq
)
=
*
((
unsigned
long
*
)
cmdq
);
/* need to clear mailbox interrupt before clear mailbox buffer */
*
((
unsigned
long
*
)
cmdq
)
=
0
;
/* mailbox buffer context is send from linux*/
if
(
rtos_cmdq
.
resv
.
valid
.
linux_valid
==
1
)
{
debug_printf
(
"cmdq=%x
\n
"
,
cmdq
);
debug_printf
(
"cmdq->ip_id =%d
\n
"
,
rtos_cmdq
.
ip_id
);
debug_printf
(
"cmdq->cmd_id =%d
\n
"
,
rtos_cmdq
.
cmd_id
);
debug_printf
(
"cmdq->param_ptr =%x
\n
"
,
rtos_cmdq
.
param_ptr
);
debug_printf
(
"cmdq->block =%x
\n
"
,
rtos_cmdq
.
block
);
debug_printf
(
"cmdq->linux_valid =%d
\n
"
,
rtos_cmdq
.
resv
.
valid
.
linux_valid
);
debug_printf
(
"cmdq->rtos_valid =%x
\n
"
,
rtos_cmdq
.
resv
.
valid
.
rtos_valid
);
xQueueSendFromISR
(
gTaskCtx
[
0
].
queHandle
,
&
rtos_cmdq
,
&
YieldRequired
);
portYIELD_FROM_ISR
(
YieldRequired
);
}
else
printf
(
"rtos cmdq is not valid %d, ip=%d , cmd=%d
\n
"
,
rtos_cmdq
.
resv
.
valid
.
rtos_valid
,
rtos_cmdq
.
ip_id
,
rtos_cmdq
.
cmd_id
);
}
}
}
}
freertos/cvitek/task/main/src/main.c
View file @
1bca5068
...
@@ -103,6 +103,7 @@ within this file. */
...
@@ -103,6 +103,7 @@ within this file. */
void
vApplicationMallocFailedHook
(
void
);
void
vApplicationMallocFailedHook
(
void
);
void
vApplicationIdleHook
(
void
);
void
vApplicationIdleHook
(
void
);
void
vApplicationStackOverflowHook
(
TaskHandle_t
pxTask
,
char
*
pcTaskName
);
void
vApplicationStackOverflowHook
(
TaskHandle_t
pxTask
,
char
*
pcTaskName
);
void
vApplicationTickHook
(
void
);
/* configAPPLICATION_ALLOCATED_HEAP is set to 1 in FreeRTOSConfig.h so the
/* configAPPLICATION_ALLOCATED_HEAP is set to 1 in FreeRTOSConfig.h so the
application can define the array used as the FreeRTOS heap. This is done so the
application can define the array used as the FreeRTOS heap. This is done so the
...
@@ -220,6 +221,17 @@ void vApplicationIdleHook(void)
...
@@ -220,6 +221,17 @@ void vApplicationIdleHook(void)
}
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
void
vApplicationTickHook
(
void
)
{
#ifdef FULL_DEMO
{
/* Only the comprehensive demo actually uses the tick hook. */
extern
void
vFullDemoTickHook
(
void
);
vFullDemoTickHook
();
}
#endif
}
/*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
...
...
linux_5.10/drivers/soc/cvitek/Kconfig
View file @
1bca5068
...
@@ -30,4 +30,5 @@ config CVI_BT_PIN
...
@@ -30,4 +30,5 @@ config CVI_BT_PIN
GPIO number to do certain action, ex. power on
GPIO number to do certain action, ex. power on
or wakeup pin.
or wakeup pin.
source "drivers/soc/cvitek/rtos_cmdqu/Kconfig"
endmenu
endmenu
linux_5.10/drivers/soc/cvitek/Makefile
View file @
1bca5068
obj-$(CONFIG_CV1835_SYSDMA_REMAP)
+=
sysdma/cv1835_dma_remap.o
obj-$(CONFIG_CV1835_SYSDMA_REMAP)
+=
sysdma/cv1835_dma_remap.o
obj-$(CONFIG_CVI_WIFI_PIN)
+=
wifi_pin/cvi_wifi_pin.o
obj-$(CONFIG_CVI_WIFI_PIN)
+=
wifi_pin/cvi_wifi_pin.o
obj-$(CONFIG_CVI_BT_PIN)
+=
bt_pin/cvi_bt_pin.o
obj-$(CONFIG_CVI_BT_PIN)
+=
bt_pin/cvi_bt_pin.o
\ No newline at end of file
obj-$(CONFIG_CVI_MAILBOX)
+=
rtos_cmdqu/
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/Kconfig
0 → 100644
View file @
1bca5068
config CVI_MAILBOX
tristate "cv180x/cv181x mailbox dirver"
help
"cv180x/cv181x mailbox driver"
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/Makefile
0 → 100644
View file @
1bca5068
obj-$(CONFIG_CVI_MAILBOX)
:=
cvi_mbox.o
cvi_mbox-y
:=
rtos_cmdqu.o
\
cvi_spinlock.o
ccflags-y
+=
-I
$(srctree)
/
$(src)
/
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/cvi_mailbox.h
0 → 100644
View file @
1bca5068
#ifndef __CVI_MAILBOX_H__
#define __CVI_MAILBOX_H__
union
cpu_mailbox_info_offset
{
char
mbox_info
;
int
reserved
;
};
union
cpu_mailbox_int_clr_offset
{
char
mbox_int_clr
;
int
reserved
;
};
union
cpu_mailbox_int_mask_offset
{
char
mbox_int_mask
;
int
reserved
;
};
union
cpu_mailbox_int_offset
{
char
mbox_int
;
int
reserved
;
};
union
cpu_mailbox_int_raw_offset
{
char
mbox_int_raw
;
int
reserved
;
};
union
mailbox_set
{
char
mbox_set
;
int
reserved
;
};
union
mailbox_status
{
char
mbox_status
;
int
reserved
;
};
union
cpu_mailbox_status
{
char
mbox_status
;
int
reserved
;
};
/* register mapping refers to mailbox user guide*/
struct
cpu_mbox_int
{
union
cpu_mailbox_int_clr_offset
cpu_mbox_int_clr
;
union
cpu_mailbox_int_mask_offset
cpu_mbox_int_mask
;
union
cpu_mailbox_int_offset
cpu_mbox_int_int
;
union
cpu_mailbox_int_raw_offset
cpu_mbox_int_raw
;
};
struct
mailbox_set_register
{
union
cpu_mailbox_info_offset
cpu_mbox_en
[
4
];
//0x00, 0x04, 0x08, 0x0c
struct
cpu_mbox_int
cpu_mbox_set
[
4
];
//0x10~0x1C, 0x20~0x2C, 0x30~0x3C, 0x40~0x4C
int
reserved
[
4
];
//0x50~0x5C
union
mailbox_set
mbox_set
;
//0x60
union
mailbox_status
mbox_status
;
//0x64
int
reserved2
[
2
];
//0x68~0x6C
union
cpu_mailbox_status
cpu_mbox_status
[
4
];
//0x70
};
struct
mailbox_done_register
{
union
cpu_mailbox_info_offset
cpu_mbox_done_en
[
4
];
struct
cpu_mbox_int
cpu_mbox_done
[
4
];
};
volatile
struct
mailbox_set_register
*
mbox_reg
;
volatile
struct
mailbox_done_register
*
mbox_done_reg
;
volatile
unsigned
long
*
mailbox_context
;
// mailbox buffer context is 64 Bytess
#define MAILBOX_MAX_NUM 0x0008
#define MAILBOX_DONE_OFFSET 0x0002
#define MAILBOX_CONTEXT_OFFSET 0x0400
// C906B
#define RECEIVE_CPU 1
// C906L
#define SEND_TO_CPU 2
#endif // end of__CVI_MAILBOX_H__
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/cvi_spinlock.c
0 → 100644
View file @
1bca5068
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Cvitek Co., Ltd. 2019-2022. All rights reserved.
*
* File Name: cvi_spinlock.c
* Description:
*/
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of_reserved_mem.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/uaccess.h>
#include <linux/version.h>
#include "cvi_spinlock.h"
static
unsigned
long
reg_base
;
spinlock_t
reg_write_lock
;
static
unsigned
char
lockCount
[
SPIN_MAX
+
1
]
=
{
0
};
static
void
*
__iomem
c906l_pc_reg
;
void
cvi_spinlock_init
(
void
)
{
spin_lock_init
(
&
reg_write_lock
);
c906l_pc_reg
=
ioremap
(
0x1901070
,
4
);
if
(
c906l_pc_reg
==
NULL
)
{
pr_err
(
"c906l_pc_reg ioremap failed!
\n
"
);
}
pr_info
(
"[%s] success
\n
"
,
__func__
);
}
void
cvi_spinlock_uninit
(
void
)
{
iounmap
(
c906l_pc_reg
);
}
void
spinlock_base
(
unsigned
long
mb_base
)
{
reg_base
=
mb_base
;
}
static
inline
int
hw_spin_trylock
(
hw_raw_spinlock_t
*
lock
)
{
writew
(
lock
->
locks
,
(
void
*
)(
reg_base
+
sizeof
(
int
)
*
lock
->
hw_field
));
if
(
readw
((
void
*
)(
reg_base
+
sizeof
(
int
)
*
lock
->
hw_field
))
==
lock
->
locks
)
return
MAILBOX_LOCK_SUCCESS
;
return
MAILBOX_LOCK_FAILED
;
}
int
hw_spin_lock
(
hw_raw_spinlock_t
*
lock
)
{
u64
i
;
u64
loops
=
1000000
;
hw_raw_spinlock_t
_lock
=
{.
hw_field
=
lock
->
hw_field
,
.
locks
=
lock
->
locks
};
if
(
lock
->
hw_field
>=
SPIN_LINUX_RTOS
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
reg_write_lock
,
flags
);
if
(
lockCount
[
lock
->
hw_field
]
==
0
)
{
lockCount
[
lock
->
hw_field
]
++
;
}
_lock
.
locks
=
lockCount
[
lock
->
hw_field
];
lockCount
[
lock
->
hw_field
]
++
;
spin_unlock_irqrestore
(
&
reg_write_lock
,
flags
);
}
else
{
//....
}
for
(
i
=
0
;
i
<
loops
;
i
++
)
{
if
(
hw_spin_trylock
(
&
_lock
)
==
MAILBOX_LOCK_SUCCESS
)
{
lock
->
locks
=
_lock
.
locks
;
return
MAILBOX_LOCK_SUCCESS
;
}
udelay
(
1
);
}
pr_err
(
"__spin_lock_debug fail! loops = %lld
\n
"
,
loops
);
return
MAILBOX_LOCK_FAILED
;
}
int
_hw_raw_spin_lock_irqsave
(
hw_raw_spinlock_t
*
lock
)
{
int
flag
=
MAILBOX_LOCK_SUCCESS
;
// lock
if
(
hw_spin_lock
(
lock
)
==
MAILBOX_LOCK_FAILED
)
{
pr_err
(
"spin lock fail! C906L pc = 0x%x,reg_val=0x%x, lock->locks=0x%x
\n
"
,
ioread32
(
c906l_pc_reg
),
readw
((
void
*
)(
reg_base
+
sizeof
(
int
)
*
lock
->
hw_field
)),
lock
->
locks
);
return
MAILBOX_LOCK_FAILED
;
}
return
flag
;
}
void
_hw_raw_spin_unlock_irqrestore
(
hw_raw_spinlock_t
*
lock
,
int
flag
)
{
// unlock
if
(
readw
((
void
*
)(
reg_base
+
sizeof
(
int
)
*
lock
->
hw_field
))
==
lock
->
locks
)
{
writew
(
lock
->
locks
,
(
void
*
)(
reg_base
+
sizeof
(
int
)
*
lock
->
hw_field
));
}
else
{
pr_err
(
"spin unlock fail! C906L pc=0x%x,reg_val=0x%x, lock->locks=0x%x
\n
"
,
ioread32
(
c906l_pc_reg
),
readw
((
void
*
)(
reg_base
+
sizeof
(
int
)
*
lock
->
hw_field
)),
lock
->
locks
);
}
}
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/cvi_spinlock.h
0 → 100644
View file @
1bca5068
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __DRV_SPINLOCK_H__
#define __DRV_SPINLOCK_H__
enum
SPINLOCK_FIELD
{
SPIN_UART
,
SPIN_LINUX_RTOS
=
4
,
// this spinlock field is used for linux & rtos
SPIN_MBOX
=
SPIN_LINUX_RTOS
,
SPIN_MAX
=
7
,
};
typedef
struct
hw_raw_spinlock
{
unsigned
short
locks
;
unsigned
short
hw_field
;
}
hw_raw_spinlock_t
;
#define MAILBOX_LOCK_SUCCESS 1
#define MAILBOX_LOCK_FAILED (-1)
#define __CVI_ARCH_SPIN_LOCK_UNLOCKED \
(0)
#define __CVI_RAW_SPIN_LOCK_INITIALIZER(spinlock_hw_field) \
{ .locks = __CVI_ARCH_SPIN_LOCK_UNLOCKED, .hw_field = spinlock_hw_field, }
#define DEFINE_CVI_SPINLOCK(x, y) \
hw_raw_spinlock_t x = __CVI_RAW_SPIN_LOCK_INITIALIZER(y)
int
_hw_raw_spin_lock_irqsave
(
hw_raw_spinlock_t
*
lock
);
void
_hw_raw_spin_unlock_irqrestore
(
hw_raw_spinlock_t
*
lock
,
int
flag
);
#define drv_spin_lock_irqsave(lock, flags) \
{ flags = _hw_raw_spin_lock_irqsave(lock); }
#define drv_spin_unlock_irqrestore(lock, flags) \
_hw_raw_spin_unlock_irqrestore(lock, flags)
void
spinlock_base
(
unsigned
long
mb_base
);
void
cvi_spinlock_init
(
void
);
void
cvi_spinlock_uninit
(
void
);
#endif // end of __DRV_SPINLOCK_H__
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/rtos_cmdqu.c
0 → 100644
View file @
1bca5068
#include <linux/init.h>
#include <linux/module.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/list.h>
#include <linux/time.h>
#include <linux/uaccess.h>
#include <linux/version.h>
#include <linux/of_reserved_mem.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include "rtos_cmdqu.h"
#include "cvi_mailbox.h"
#include "cvi_spinlock.h"
struct
cvi_rtos_cmdqu_device
{
struct
device
*
dev
;
struct
miscdevice
miscdev
;
};
spinlock_t
mailbox_queue_lock
;
spinlock_t
send_queue_lock
;
static
__u64
reg_base
;
static
int
mailbox_irq
;
static
int
cvi_rtos_cmdqu_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
0
;
}
static
int
cvi_rtos_cmdqu_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
0
;
}
struct
rtos_cmdqu_wait_list_t
{
struct
list_head
list
;
cmdqu_t
cmdq
;
wait_queue_head_t
wq
;
int
condition
;
};
static
struct
rtos_cmdqu_wait_list_t
rtos_cmdqu_wait_head
;
/* used for callback test*/
static
void
callback_rtos_irq_handler
(
int
cmd_id
,
unsigned
int
ptr
,
void
*
dev_id
)
{
pr_info
(
"callback_rtos_hander cmd_id = %x ptr=%x dev_id=%p
\n
"
,
cmd_id
,
ptr
,
dev_id
);
}
DEFINE_CVI_SPINLOCK
(
mailbox_lock
,
SPIN_MBOX
);
irqreturn_t
rtos_irq_handler
(
int
irq
,
void
*
dev_id
)
{
char
set_val
,
done_val
;
int
i
;
int
flags
;
cmdqu_t
*
cmdq
;
struct
rtos_cmdqu_wait_list_t
*
wait_list
;
struct
list_head
*
pos
;
drv_spin_lock_irqsave
(
&
mailbox_lock
,
flags
);
if
(
flags
==
MAILBOX_LOCK_FAILED
)
{
pr_err
(
"drv_spin_lock_irqsave failed!
\n
"
);
//must clear irq?
return
IRQ_HANDLED
;
}
pr_info
(
"rtos_irq_handler irq=%d
\n
"
,
irq
);
set_val
=
mbox_reg
->
cpu_mbox_set
[
RECEIVE_CPU
].
cpu_mbox_int_int
.
mbox_int
;
done_val
=
mbox_done_reg
->
cpu_mbox_done
[
RECEIVE_CPU
].
cpu_mbox_int_int
.
mbox_int
;
pr_debug
(
"set_val=%x
\n
"
,
set_val
);
pr_debug
(
"done_val=%x
\n
"
,
done_val
);
for
(
i
=
0
;
i
<
MAILBOX_MAX_NUM
&&
set_val
>
0
;
i
++
)
{
/* valid_val uses unsigned char because of mailbox register table
* ~valid_val will be 0xFF
*/
unsigned
char
valid_val
=
set_val
&
(
1
<<
i
);
pr_debug
(
"MAILBOX_MAX_NUM = %d
\n
"
,
MAILBOX_MAX_NUM
);
pr_debug
(
"valid_val = %d set_val=%d i = %d
\n
"
,
valid_val
,
set_val
,
i
);
if
(
valid_val
)
{
cmdqu_t
linux_cmdq
;
cmdq
=
(
cmdqu_t
*
)(
mailbox_context
)
+
i
;
/* mailbox buffer context is send from rtos, clear mailbox interrupt */
mbox_reg
->
cpu_mbox_set
[
RECEIVE_CPU
].
cpu_mbox_int_clr
.
mbox_int_clr
=
valid_val
;
// need to disable enable bit
mbox_reg
->
cpu_mbox_en
[
RECEIVE_CPU
].
mbox_info
&=
~
valid_val
;
// copy cmdq context (8 bytes) to buffer ASAP ??
*
((
unsigned
long
long
*
)
&
linux_cmdq
)
=
*
((
unsigned
long
long
*
)
cmdq
);
/* need to clear mailbox interrupt before clear mailbox buffer ??*/
*
((
unsigned
long
long
*
)
cmdq
)
=
0
;
/* mailbox buffer context is send from rtos */
pr_debug
(
"cmdq=%p
\n
"
,
cmdq
);
pr_debug
(
"cmdq->ip_id =%d
\n
"
,
linux_cmdq
.
ip_id
);
pr_debug
(
"cmdq->cmd_id =%d
\n
"
,
linux_cmdq
.
cmd_id
);
pr_debug
(
"cmdq->param_ptr =%x
\n
"
,
linux_cmdq
.
param_ptr
);
pr_debug
(
"cmdq->block =%d
\n
"
,
linux_cmdq
.
block
);
pr_debug
(
"cmdq->linux_valid =%d
\n
"
,
linux_cmdq
.
resv
.
valid
.
linux_valid
);
pr_debug
(
"cmdq->rtos_valid =%x"
,
linux_cmdq
.
resv
.
valid
.
rtos_valid
);
if
(
linux_cmdq
.
resv
.
valid
.
rtos_valid
==
1
&&
linux_cmdq
.
block
==
1
)
{
// dewait
list_for_each
(
pos
,
&
rtos_cmdqu_wait_head
.
list
)
{
wait_list
=
list_entry
(
pos
,
struct
rtos_cmdqu_wait_list_t
,
list
);
pr_debug
(
"s wait_list->cmdq.ip_id=%d
\n
"
,
wait_list
->
cmdq
.
ip_id
);
pr_debug
(
"s wait_list->cmdq.cmd_id=%d
\n
"
,
wait_list
->
cmdq
.
cmd_id
);
if
(
wait_list
->
cmdq
.
ip_id
==
linux_cmdq
.
ip_id
&&
wait_list
->
cmdq
.
cmd_id
==
linux_cmdq
.
cmd_id
)
{
/* copy data to wait_list and return to user space */
*
((
unsigned
long
long
*
)
&
wait_list
->
cmdq
)
=
*
((
unsigned
long
long
*
)
&
linux_cmdq
);
pr_debug
(
"wait_list->cmdq.ip_id=%d
\n
"
,
wait_list
->
cmdq
.
ip_id
);
pr_debug
(
"wait_list->cmdq.cmd_id=%d
\n
"
,
wait_list
->
cmdq
.
cmd_id
);
pr_debug
(
"wait_list->cmdq.param_ptr=%x
\n
"
,
wait_list
->
cmdq
.
param_ptr
);
wait_list
->
condition
=
1
;
wake_up_interruptible
(
&
wait_list
->
wq
);
break
;
}
}
}
else
pr_err
(
"error ip=%d , cmd=%d
\n
"
,
linux_cmdq
.
ip_id
,
linux_cmdq
.
cmd_id
);
}
}
drv_spin_unlock_irqrestore
(
&
mailbox_lock
,
flags
);
return
IRQ_HANDLED
;
}
long
rtos_cmdqu_init
(
void
)
{
long
ret
=
0
;
int
i
;
pr_debug
(
"RTOS_CMDQU_INIT
\n
"
);
spin_lock_init
(
&
mailbox_queue_lock
);
spin_lock_init
(
&
send_queue_lock
);
mbox_reg
=
(
struct
mailbox_set_register
*
)
reg_base
;
mbox_done_reg
=
(
struct
mailbox_done_register
*
)
(
reg_base
+
MAILBOX_DONE_OFFSET
);
mailbox_context
=
(
unsigned
long
*
)
(
reg_base
+
MAILBOX_CONTEXT_OFFSET
);
//MAILBOX_CONTEXT;
pr_debug
(
"mbox_reg=%p
\n
"
,
mbox_reg
);
pr_debug
(
"mbox_done_reg=%p
\n
"
,
mbox_done_reg
);
pr_debug
(
"mailbox_context=%p
\n
"
,
mailbox_context
);
// init mailbox_context
for
(
i
=
0
;
i
<
MAILBOX_MAX_NUM
;
i
++
)
mailbox_context
[
i
]
=
0
;
/* init sqirq parameters*/
return
ret
;
}
long
rtos_cmdqu_deinit
(
void
)
{
long
ret
=
0
;
pr_debug
(
"RTOS_CMDQU_DEINIT
\n
"
);
//mailbox deinit
return
ret
;
}
int
rtos_cmdqu_send
(
cmdqu_t
*
cmdq
)
{
int
ret
=
0
;
int
valid
;
unsigned
long
flags
;
int
mb_flags
;
cmdqu_t
*
linux_cmdqu_t
;
pr_debug
(
"RTOS_CMDQU_SEND
\n
"
);
pr_debug
(
"ip_id=%d cmd_id=%d param_ptr=%x
\n
"
,
cmdq
->
ip_id
,
cmdq
->
cmd_id
,
(
unsigned
int
)
cmdq
->
param_ptr
);
spin_lock_irqsave
(
&
mailbox_queue_lock
,
flags
);
// when linux and rtos send command at the same time, it might cause a problem.
// might need to spinlock with rtos, do it later
drv_spin_lock_irqsave
(
&
mailbox_lock
,
mb_flags
);
if
(
mb_flags
==
MAILBOX_LOCK_FAILED
)
{
pr_err
(
"ip_id=%d cmd_id=%d param_ptr=%x
\n
"
,
cmdq
->
ip_id
,
cmdq
->
cmd_id
,
(
unsigned
int
)
cmdq
->
param_ptr
);
spin_unlock_irqrestore
(
&
mailbox_queue_lock
,
flags
);
return
-
ENOBUFS
;
}
linux_cmdqu_t
=
(
cmdqu_t
*
)
mailbox_context
;
pr_debug
(
"mailbox_context = %p
\n
"
,
mailbox_context
);
pr_debug
(
"linux_cmdqu_t = %p
\n
"
,
linux_cmdqu_t
);
pr_debug
(
"cmdq->ip_id = %d
\n
"
,
cmdq
->
ip_id
);
pr_debug
(
"cmdq->cmd_id = %d
\n
"
,
cmdq
->
cmd_id
);
pr_debug
(
"cmdq->block = %d
\n
"
,
cmdq
->
block
);
pr_debug
(
"cmdq->para_ptr = %d
\n
"
,
cmdq
->
param_ptr
);
for
(
valid
=
0
;
valid
<
MAILBOX_MAX_NUM
;
valid
++
)
{
if
(
linux_cmdqu_t
->
resv
.
valid
.
linux_valid
==
0
&&
linux_cmdqu_t
->
resv
.
valid
.
rtos_valid
==
0
)
{
// mailbox buffer context is int (4 bytes) access
int
*
ptr
=
(
int
*
)
linux_cmdqu_t
;
linux_cmdqu_t
->
resv
.
valid
.
linux_valid
=
1
;
*
ptr
=
((
cmdq
->
ip_id
<<
0
)
|
(
cmdq
->
cmd_id
<<
8
)
|
(
cmdq
->
block
<<
15
)
|
(
linux_cmdqu_t
->
resv
.
valid
.
linux_valid
<<
16
)
|
(
linux_cmdqu_t
->
resv
.
valid
.
rtos_valid
<<
24
));
linux_cmdqu_t
->
param_ptr
=
cmdq
->
param_ptr
;
pr_debug
(
"linux_valid = %d
\n
"
,
linux_cmdqu_t
->
resv
.
valid
.
linux_valid
);
pr_debug
(
"rtos_valid = %d
\n
"
,
linux_cmdqu_t
->
resv
.
valid
.
rtos_valid
);
pr_debug
(
"ip_id = %d
\n
"
,
linux_cmdqu_t
->
ip_id
);
pr_debug
(
"cmd_id = %d
\n
"
,
linux_cmdqu_t
->
cmd_id
);
pr_debug
(
"block = %d
\n
"
,
linux_cmdqu_t
->
block
);
pr_debug
(
"param_ptr = %x
\n
"
,
linux_cmdqu_t
->
param_ptr
);
pr_debug
(
"*ptr = %x
\n
"
,
*
ptr
);
// clear mailbox
mbox_reg
->
cpu_mbox_set
[
SEND_TO_CPU
].
cpu_mbox_int_clr
.
mbox_int_clr
=
(
1
<<
valid
);
// trigger mailbox valid to rtos
mbox_reg
->
cpu_mbox_en
[
SEND_TO_CPU
].
mbox_info
|=
(
1
<<
valid
);
mbox_reg
->
mbox_set
.
mbox_set
=
(
1
<<
valid
);
break
;
}
linux_cmdqu_t
++
;
}
if
(
valid
>=
MAILBOX_MAX_NUM
)
{
pr_err
(
"No valid mailbox is available
\n
"
);
drv_spin_unlock_irqrestore
(
&
mailbox_lock
,
mb_flags
);
spin_unlock_irqrestore
(
&
mailbox_queue_lock
,
flags
);
return
-
ENOBUFS
;
}
drv_spin_unlock_irqrestore
(
&
mailbox_lock
,
mb_flags
);
spin_unlock_irqrestore
(
&
mailbox_queue_lock
,
flags
);
return
ret
;
}
EXPORT_SYMBOL
(
rtos_cmdqu_send
);
int
rtos_cmdqu_send_wait
(
cmdqu_t
*
cmdq
,
int
wait_cmd_id
)
{
unsigned
long
flags
;
struct
rtos_cmdqu_wait_list_t
*
wait_list
;
struct
list_head
*
pos
;
int
delaytime
;
int
ret
=
0
;
pr_debug
(
"%s %d
\n
"
,
__func__
,
__LINE__
);
spin_lock_irqsave
(
&
send_queue_lock
,
flags
);
/* check list with same commands? if yes, ignore it */
list_for_each
(
pos
,
&
rtos_cmdqu_wait_head
.
list
)
{
wait_list
=
list_entry
(
pos
,
struct
rtos_cmdqu_wait_list_t
,
list
);
pr_debug
(
"list->cmdq.ip_id=%d
\n
"
,
wait_list
->
cmdq
.
ip_id
);
pr_debug
(
"list->cmdq.cmd_id=%d
\n
"
,
wait_list
->
cmdq
.
cmd_id
);
if
(
cmdq
->
ip_id
==
wait_list
->
cmdq
.
ip_id
&&
wait_cmd_id
==
wait_list
->
cmdq
.
cmd_id
)
{
pr_debug
(
"exist : wait_list->cmdq.ip_id=%d
\n
"
,
wait_list
->
cmdq
.
ip_id
);
pr_debug
(
"exist : wait_list->cmdq.cmd_id=%d
\n
"
,
wait_list
->
cmdq
.
cmd_id
);
pr_debug
(
"exist : wait_list->cmdq.param_ptr=%d
\n
"
,
wait_list
->
cmdq
.
param_ptr
);
spin_unlock_irqrestore
(
&
send_queue_lock
,
flags
);
return
-
EEXIST
;
}
}
cmdq
->
block
=
1
;
wait_list
=
kzalloc
(
sizeof
(
struct
rtos_cmdqu_wait_list_t
),
GFP_KERNEL
);
if
(
!
wait_list
)
{
spin_unlock_irqrestore
(
&
send_queue_lock
,
flags
);
return
-
ENOMEM
;
}
*
((
unsigned
long
long
*
)
&
wait_list
->
cmdq
)
=
*
((
unsigned
long
long
*
)
cmdq
);
wait_list
->
cmdq
.
cmd_id
=
wait_cmd_id
;
init_waitqueue_head
(
&
wait_list
->
wq
);
list_add_tail
(
&
wait_list
->
list
,
&
rtos_cmdqu_wait_head
.
list
);
spin_unlock_irqrestore
(
&
send_queue_lock
,
flags
);
/* check the delay ms
* if mstime is 65535 (-1), it will be blocked infinite (MAX_JIFFY_OFFSET)
*/
delaytime
=
wait_list
->
cmdq
.
resv
.
mstime
;
if
(
delaytime
==
0xFFFF
)
delaytime
=
-
1
;
ret
=
rtos_cmdqu_send
(
cmdq
);
ret
=
wait_event_interruptible_timeout
(
wait_list
->
wq
,
wait_list
->
condition
!=
0
,
msecs_to_jiffies
(
delaytime
));
spin_lock_irqsave
(
&
send_queue_lock
,
flags
);
list_del_init
(
&
wait_list
->
list
);
spin_unlock_irqrestore
(
&
send_queue_lock
,
flags
);
if
(
!
ret
)
{
ret
=
-
ETIME
;
kfree
(
wait_list
);
pr_err
(
"RTOS_CMDQU_SEND_WAIT timeout
\n
"
);
return
ret
;
}
pr_debug
(
"RTOS_CMDQU_SEND_WAIT done
\n
"
);
pr_debug
(
"list wait_list->cmdq.ip_id=%d wait_list->cmdq.cmd_id=%d wait_list->cmdq.param_ptr=%x
\n
"
,
wait_list
->
cmdq
.
ip_id
,
wait_list
->
cmdq
.
cmd_id
,
wait_list
->
cmdq
.
param_ptr
);
/* get context from interrupt and return to userspace */
*
((
unsigned
long
long
*
)
cmdq
)
=
*
((
unsigned
long
long
*
)
&
wait_list
->
cmdq
);
kfree
(
wait_list
);
return
0
;
}
EXPORT_SYMBOL
(
rtos_cmdqu_send_wait
);
static
long
cvi_rtos_cmdqu_ioctl
(
struct
file
*
filp
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
cvi_rtos_cmdqu_device
*
dev
=
filp
->
private_data
;
struct
rtos_cmdqu_wait_list_t
*
wait_list
;
struct
list_head
*
pos
;
long
ret
=
0
;
unsigned
long
flags
;
cmdqu_t
cmdq
;
pr_debug
(
"%s dev=%p
\n
"
,
__func__
,
dev
);
switch
(
cmd
)
{
case
RTOS_CMDQU_SEND
:
pr_debug
(
"RTOS_CMDQU_SEND
\n
"
);
copy_from_user
(
&
cmdq
,
(
struct
cmdqu_t
__user
*
)
arg
,
sizeof
(
struct
cmdqu_t
));
ret
=
rtos_cmdqu_send
(
&
cmdq
);
break
;
case
RTOS_CMDQU_SEND_WAKEUP
:
pr_debug
(
"RTOS_CMDQU_SEND_WAKEUP
\n
"
);
copy_from_user
(
&
cmdq
,
(
struct
cmdqu_t
__user
*
)
arg
,
sizeof
(
struct
cmdqu_t
));
pr_debug
(
"cmdq.ip_id=%d cmdq.cmd_id=%d
\n
"
,
cmdq
.
ip_id
,
cmdq
.
cmd_id
);
spin_lock_irqsave
(
&
send_queue_lock
,
flags
);
list_for_each
(
pos
,
&
rtos_cmdqu_wait_head
.
list
)
{
wait_list
=
list_entry
(
pos
,
struct
rtos_cmdqu_wait_list_t
,
list
);
pr_debug
(
"list->cmdq.ip_id=%d
\n
"
,
wait_list
->
cmdq
.
ip_id
);
pr_debug
(
"list->cmdq.cmd_id=%d
\n
"
,
wait_list
->
cmdq
.
cmd_id
);
if
(
cmdq
.
ip_id
==
wait_list
->
cmdq
.
ip_id
&&
cmdq
.
cmd_id
==
wait_list
->
cmdq
.
cmd_id
&&
wait_list
->
cmdq
.
block
==
1
)
{
/* copy data to wait_list and return to user space */
*
((
unsigned
long
long
*
)
&
wait_list
->
cmdq
)
=
*
((
unsigned
long
long
*
)
&
cmdq
);
pr_debug
(
"wait_list->cmdq.ip_id=%d
\n
"
,
wait_list
->
cmdq
.
ip_id
);
pr_debug
(
"wait_list->cmdq.cmd_id=%d
\n
"
,
wait_list
->
cmdq
.
cmd_id
);
pr_debug
(
"wait_list->cmdq.param_ptr=%d
\n
"
,
wait_list
->
cmdq
.
param_ptr
);
wait_list
->
condition
=
1
;
wake_up_interruptible
(
&
wait_list
->
wq
);
break
;
}
}
spin_unlock_irqrestore
(
&
send_queue_lock
,
flags
);
pr_debug
(
"RTOS_CMDQU_SEND_WAKEUP done
\n
"
);
break
;
case
RTOS_CMDQU_SEND_WAIT
:
pr_debug
(
"RTOS_CMDQU_SEND_WAIT
\n
"
);
ret
=
copy_from_user
(
&
cmdq
,
(
struct
cmdqu_t
__user
*
)
arg
,
sizeof
(
struct
cmdqu_t
));
if
(
ret
)
{
return
-
EFAULT
;
}
rtos_cmdqu_send_wait
(
&
cmdq
,
cmdq
.
cmd_id
);
ret
=
copy_to_user
((
struct
cmdqu_t
__user
*
)
arg
,
&
cmdq
,
sizeof
(
struct
cmdqu_t
));
break
;
default:
ret
=
-
EFAULT
;
break
;
}
return
ret
;
}
static
const
struct
file_operations
rtos_cmdqu_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
cvi_rtos_cmdqu_open
,
.
release
=
cvi_rtos_cmdqu_release
,
.
unlocked_ioctl
=
cvi_rtos_cmdqu_ioctl
,
};
static
int
_register_dev
(
struct
cvi_rtos_cmdqu_device
*
ndev
)
{
int
rc
;
ndev
->
miscdev
.
minor
=
MISC_DYNAMIC_MINOR
;
ndev
->
miscdev
.
name
=
RTOS_CMDQU_DEV_NAME
;
ndev
->
miscdev
.
fops
=
&
rtos_cmdqu_fops
;
rc
=
misc_register
(
&
ndev
->
miscdev
);
if
(
rc
)
{
dev_err
(
ndev
->
dev
,
"cvi_rtos_cmdqu: failed to register misc device.
\n
"
);
return
rc
;
}
return
0
;
}
static
int
cvi_rtos_cmdqu_probe
(
struct
platform_device
*
pdev
)
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
cvi_rtos_cmdqu_device
*
ndev
;
struct
resource
*
res
;
int
ret
=
0
;
int
err
=
-
1
;
pr_info
(
"%s start ---
\n
"
,
__func__
);
pr_info
(
"name=%s
\n
"
,
pdev
->
name
);
ndev
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
ndev
),
GFP_KERNEL
);
if
(
!
ndev
)
return
-
ENOMEM
;
ndev
->
dev
=
dev
;
ret
=
_register_dev
(
ndev
);
if
(
ret
<
0
)
{
pr_err
(
"regsiter cvi_rtos_cmdqu chrdev error
\n
"
);
return
ret
;
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
// void __iomem *regs;
// regs = devm_ioremap_resource(dev, res);
// if (IS_ERR(regs)) {
// ret = PTR_ERR(regs);
// goto ERROR_PROVE_DEVICE;
// }
// printk("regs=%x\n", regs);
reg_base
=
(
__u64
)
devm_ioremap
(
&
pdev
->
dev
,
res
->
start
,
res
->
end
-
res
->
start
);
pr_info
(
"res-reg: start: 0x%llx, end: 0x%llx, virt-addr(%llx).
\n
"
,
res
->
start
,
res
->
end
,
le64_to_cpu
(
reg_base
));
// spinlock ip offset address (0xc0)
spinlock_base
(
reg_base
+
0xc0
);
mailbox_irq
=
platform_get_irq_byname
(
pdev
,
"mailbox"
);
INIT_LIST_HEAD
(
&
rtos_cmdqu_wait_head
.
list
);
/* init cmdqu*/
rtos_cmdqu_init
();
platform_set_drvdata
(
pdev
,
ndev
);
err
=
request_irq
(
mailbox_irq
,
rtos_irq_handler
,
0
,
"mailbox"
,
(
void
*
)
ndev
);
if
(
err
)
{
pr_err
(
"fail to register interrupt handler
\n
"
);
return
-
1
;
}
pr_info
(
"%s DONE
\n
"
,
__func__
);
return
0
;
//ERROR_PROVE_DEVICE:
// return err;
}
static
int
cvi_rtos_cmdqu_remove
(
struct
platform_device
*
pdev
)
{
struct
cvi_rtos_cmdqu_device
*
ndev
=
platform_get_drvdata
(
pdev
);
misc_deregister
(
&
ndev
->
miscdev
);
platform_set_drvdata
(
pdev
,
NULL
);
/* remove irq handler*/
free_irq
(
mailbox_irq
,
ndev
);
rtos_cmdqu_deinit
();
pr_debug
(
"%s DONE
\n
"
,
__func__
);
return
0
;
}
static
const
struct
of_device_id
cvi_rtos_cmdqu_match
[]
=
{
{
.
compatible
=
"cvitek,rtos_cmdqu"
},
{},
};
static
struct
platform_driver
cvi_rtos_cmdqu_driver
=
{
.
probe
=
cvi_rtos_cmdqu_probe
,
.
remove
=
cvi_rtos_cmdqu_remove
,
.
driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
RTOS_CMDQU_DEV_NAME
,
.
of_match_table
=
cvi_rtos_cmdqu_match
,
},
};
struct
class
*
pbase_class
;
static
void
cvi_rtos_cmdqu_exit
(
void
)
{
platform_driver_unregister
(
&
cvi_rtos_cmdqu_driver
);
class_destroy
(
pbase_class
);
cvi_spinlock_uninit
();
pr_debug
(
"%s DONE
\n
"
,
__func__
);
}
static
int
cvi_rtos_cmdqu_init
(
void
)
{
int
rc
;
pr_info
(
"cvi_rtos_cmdqu_init
\n
"
);
pbase_class
=
class_create
(
THIS_MODULE
,
RTOS_CMDQU_DEV_NAME
);
if
(
IS_ERR
(
pbase_class
))
{
pr_err
(
"create class failed
\n
"
);
rc
=
PTR_ERR
(
pbase_class
);
goto
cleanup
;
}
platform_driver_register
(
&
cvi_rtos_cmdqu_driver
);
pr_debug
(
"%s done
\n
"
,
__func__
);
cvi_spinlock_init
();
return
0
;
cleanup:
cvi_rtos_cmdqu_exit
();
return
rc
;
}
MODULE_DESCRIPTION
(
"RTOS_CMD_QUEUE"
);
MODULE_LICENSE
(
"GPL"
);
module_init
(
cvi_rtos_cmdqu_init
);
module_exit
(
cvi_rtos_cmdqu_exit
);
linux_5.10/drivers/soc/cvitek/rtos_cmdqu/rtos_cmdqu.h
0 → 100644
View file @
1bca5068
#ifndef __RTOS_COMMAND_QUEUE__
#define __RTOS_COMMAND_QUEUE__
#include <linux/kernel.h>
#define NR_SYSTEM_CMD 20
struct
valid_t
{
unsigned
char
linux_valid
;
unsigned
char
rtos_valid
;
}
__attribute__
((
packed
));
typedef
union
resv_t
{
struct
valid_t
valid
;
unsigned
short
mstime
;
// 0 : noblock, -1 : block infinite
}
resv_t
;
typedef
struct
cmdqu_t
cmdqu_t
;
/* cmdqu size should be 8 bytes because of mailbox buffer size */
struct
cmdqu_t
{
unsigned
char
ip_id
;
unsigned
char
cmd_id
:
7
;
unsigned
char
block
:
1
;
union
resv_t
resv
;
unsigned
int
param_ptr
;
}
__attribute__
((
packed
))
__attribute__
((
aligned
(
0x8
)));
/* keep those commands for ioctl system used */
enum
SYSTEM_CMD_TYPE
{
CMDQU_SEND
=
1
,
CMDQU_SEND_WAIT
,
CMDQU_SEND_WAKEUP
,
CMDQU_SYSTEM_LIMIT
=
NR_SYSTEM_CMD
,
};
enum
SYS_CMD_ID
{
CMD_TEST_A
=
0x10
,
CMD_TEST_B
,
CMD_TEST_C
,
SYS_CMD_INFO_LIMIT
,
};
#define RTOS_CMDQU_DEV_NAME "cvi-rtos-cmdqu"
#define RTOS_CMDQU_SEND _IOW('r', CMDQU_SEND, unsigned long)
#define RTOS_CMDQU_SEND_WAIT _IOW('r', CMDQU_SEND_WAIT, unsigned long)
#define RTOS_CMDQU_SEND_WAKEUP _IOW('r', CMDQU_SEND_WAKEUP, unsigned long)
int
rtos_cmdqu_send
(
cmdqu_t
*
cmdq
);
int
rtos_cmdqu_send_wait
(
cmdqu_t
*
cmdq
,
int
wait_cmd_id
);
#endif // end of __RTOS_COMMAND_QUEUE__
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