media: rk1608: add lock for spi2apb

Change-Id: Ie841f4a496250ee86da7e5a0ae2bcef1c623e43c
Signed-off-by: Shengqin Zhang <zsq@rock-chips.com>
This commit is contained in:
Shengqin Zhang
2019-07-09 18:13:11 +08:00
committed by Tao Huang
parent eaa7df72ab
commit 075e034f16
3 changed files with 71 additions and 50 deletions

View File

@@ -178,17 +178,19 @@ int rk1608_write(struct spi_device *spi,
*
* It returns zero on success, else a negative error code.
*/
static int _rk1608_safe_write(struct spi_device *spi, s32 addr,
const s32 *data, size_t data_len)
static int _rk1608_safe_write(struct rk1608_state *rk1608, struct spi_device *spi,
s32 addr, const s32 *data, size_t data_len)
{
int ret = 0;
s32 state = 0;
s32 try = 0;
do {
mutex_lock(&rk1608->spi2apb_lock);
ret = rk1608_write(spi, addr, data, data_len);
if (ret == 0)
ret = rk1608_operation_query(spi, &state);
mutex_unlock(&rk1608->spi2apb_lock);
if (ret != 0)
return ret;
@@ -203,7 +205,7 @@ static int _rk1608_safe_write(struct spi_device *spi, s32 addr,
return (state & RK1608_STATE_MASK);
}
int rk1608_safe_write(struct spi_device *spi,
int rk1608_safe_write(struct rk1608_state *rk1608, struct spi_device *spi,
s32 addr, const s32 *data, size_t data_len)
{
int ret = 0;
@@ -212,7 +214,7 @@ int rk1608_safe_write(struct spi_device *spi,
while (data_len > 0) {
size_t slen = ALIGN(MIN(data_len, max_op_size), 4);
ret = _rk1608_safe_write(spi, addr, data, slen);
ret = _rk1608_safe_write(rk1608, spi, addr, data, slen);
if (ret == -ENOMEM) {
max_op_size = slen / 2;
continue;
@@ -228,18 +230,18 @@ int rk1608_safe_write(struct spi_device *spi,
return ret;
}
static void rk1608_hw_init(struct spi_device *spi)
static void rk1608_hw_init(struct rk1608_state *rk1608, struct spi_device *spi)
{
s32 write_data = SPI0_PLL_SEL_APLL;
/* modify rk1608 spi slave clk to 300M */
rk1608_safe_write(spi, CRUPMU_CLKSEL14_CON, &write_data, 4);
rk1608_safe_write(rk1608, spi, CRUPMU_CLKSEL14_CON, &write_data, 4);
/* modify rk1608 spi io driver strength to 8mA */
write_data = BIT7_6_SEL_8MA;
rk1608_safe_write(spi, PMUGRF_GPIO1A_E, &write_data, 4);
rk1608_safe_write(rk1608, spi, PMUGRF_GPIO1A_E, &write_data, 4);
write_data = BIT1_0_SEL_8MA;
rk1608_safe_write(spi, PMUGRF_GPIO1B_E, &write_data, 4);
rk1608_safe_write(rk1608, spi, PMUGRF_GPIO1B_E, &write_data, 4);
}
/**
@@ -325,16 +327,20 @@ int rk1608_read(struct spi_device *spi,
*
* It returns zero on success, else a negative error code.
*/
int rk1608_safe_read(struct spi_device *spi,
int rk1608_safe_read(struct rk1608_state *rk1608, struct spi_device *spi,
s32 addr, s32 *data, size_t data_len)
{
s32 state = 0;
s32 retry = 0;
do {
mutex_lock(&rk1608->spi2apb_lock);
rk1608_read(spi, addr, data, data_len);
if (rk1608_operation_query(spi, &state) != 0)
if (rk1608_operation_query(spi, &state) != 0) {
mutex_unlock(&rk1608->spi2apb_lock);
return -EPERM;
}
mutex_unlock(&rk1608->spi2apb_lock);
if ((state & RK1608_STATE_MASK) == 0)
break;
udelay(RK1608_OP_TRY_DELAY);
@@ -343,7 +349,7 @@ int rk1608_safe_read(struct spi_device *spi,
return -(state & RK1608_STATE_MASK);
}
static int rk1608_read_wait(struct spi_device *spi,
static int rk1608_read_wait(struct rk1608_state *rk1608, struct spi_device *spi,
const struct rk1608_section *sec)
{
s32 value = 0;
@@ -351,7 +357,7 @@ static int rk1608_read_wait(struct spi_device *spi,
int ret = 0;
do {
ret = rk1608_safe_read(spi, sec->wait_addr, &value, 4);
ret = rk1608_safe_read(rk1608, spi, sec->wait_addr, &value, 4);
if (!ret && value == sec->wait_value)
break;
@@ -367,7 +373,8 @@ static int rk1608_read_wait(struct spi_device *spi,
return ret;
}
static int rk1608_boot_request(struct spi_device *spi,
static int rk1608_boot_request(struct rk1608_state *rk1608,
struct spi_device *spi,
const struct rk1608_section *sec)
{
struct rk1608_boot_req boot_req;
@@ -381,7 +388,7 @@ static int rk1608_boot_request(struct spi_device *spi,
boot_req.status = 1;
boot_req.cmd = 2;
ret = rk1608_safe_write(spi, BOOT_REQUEST_ADDR,
ret = rk1608_safe_write(rk1608, spi, BOOT_REQUEST_ADDR,
(s32 *)&boot_req, sizeof(boot_req));
if (ret)
return ret;
@@ -389,7 +396,7 @@ static int rk1608_boot_request(struct spi_device *spi,
if (sec->flag & BOOT_FLAG_READ_WAIT) {
/* Waitting for rk1608 init ddr done */
do {
ret = rk1608_safe_read(spi, BOOT_REQUEST_ADDR,
ret = rk1608_safe_read(rk1608, spi, BOOT_REQUEST_ADDR,
(s32 *)&boot_req,
sizeof(boot_req));
@@ -408,7 +415,8 @@ static int rk1608_boot_request(struct spi_device *spi,
return ret;
}
static int rk1608_download_section(struct spi_device *spi, const u8 *data,
static int rk1608_download_section(struct rk1608_state *rk1608,
struct spi_device *spi, const u8 *data,
const struct rk1608_section *sec)
{
int ret = 0;
@@ -420,7 +428,7 @@ static int rk1608_download_section(struct spi_device *spi, const u8 *data,
sec->timeout, sec->crc_16, sec->flag, sec->type);
if (sec->size > 0) {
ret = rk1608_safe_write(spi, sec->load_addr,
ret = rk1608_safe_write(rk1608, spi, sec->load_addr,
(s32 *)(data + sec->offset),
sec->size);
if (ret) {
@@ -430,9 +438,9 @@ static int rk1608_download_section(struct spi_device *spi, const u8 *data,
}
if (sec->flag & BOOT_FLAG_BOOT_REQUEST)
ret = rk1608_boot_request(spi, sec);
ret = rk1608_boot_request(rk1608, spi, sec);
else if (sec->flag & BOOT_FLAG_READ_WAIT)
ret = rk1608_read_wait(spi, sec);
ret = rk1608_read_wait(rk1608, spi, sec);
return ret;
}
@@ -446,7 +454,8 @@ static int rk1608_download_section(struct spi_device *spi, const u8 *data,
*
* It returns zero on success, else a negative error code.
*/
int rk1608_download_fw(struct spi_device *spi, const char *fw_name)
int rk1608_download_fw(struct rk1608_state *rk1608, struct spi_device *spi,
const char *fw_name)
{
const struct rk1608_header *head;
const struct firmware *fw;
@@ -469,7 +478,7 @@ int rk1608_download_fw(struct spi_device *spi, const char *fw_name)
fw_name, head->version);
for (i = 0; i < head->section_count; i++) {
ret = rk1608_download_section(spi, fw->data,
ret = rk1608_download_section(rk1608, spi, fw->data,
&head->sections[i]);
if (ret)
break;
@@ -823,11 +832,11 @@ static int rk1608_power_on(struct rk1608_state *pdata)
rk1608_lsb_w32(spi, SPI_ENR, 0);
rk1608_lsb_w32(spi, SPI_CTRL0,
OPM_SLAVE_MODE | RSD_SEL_2CYC | DFS_SEL_16BIT);
rk1608_hw_init(pdata->spi);
rk1608_hw_init(pdata, pdata->spi);
rk1608_set_spi_speed(pdata, pdata->max_speed_hz);
/* Download system firmware */
ret = rk1608_download_fw(pdata->spi, pdata->firm_name);
ret = rk1608_download_fw(pdata, pdata->spi, pdata->firm_name);
if (ret)
dev_err(pdata->dev, "Download firmware failed!");
else
@@ -1202,19 +1211,20 @@ static const struct v4l2_subdev_ops rk1608_subdev_ops = {
*
* It returns zero on success, else a negative error code.
*/
static int rk1608_msq_read_head(struct spi_device *spi,
static int rk1608_msq_read_head(struct rk1608_state *rk1608,
struct spi_device *spi,
u32 addr, struct rk1608_msg_queue *q)
{
int err = 0;
s32 reg;
err = rk1608_safe_read(spi, RK1608_PMU_SYS_REG0, &reg, 4);
err = rk1608_safe_read(rk1608, spi, RK1608_PMU_SYS_REG0, &reg, 4);
if (err || ((reg & RK1608_MSG_QUEUE_OK_MASK) !=
RK1608_MSG_QUEUE_OK_TAG))
return -EINVAL;
err = rk1608_safe_read(spi, addr, (s32 *)q, sizeof(*q));
err = rk1608_safe_read(rk1608, spi, addr, (s32 *)q, sizeof(*q));
return err;
}
@@ -1229,7 +1239,8 @@ static int rk1608_msq_read_head(struct spi_device *spi,
*
* It returns zero on success, else a negative error code.
*/
int rk1608_msq_recv_msg(struct spi_device *spi, struct msg **m)
int rk1608_msq_recv_msg(struct rk1608_state *rk1608, struct spi_device *spi,
struct msg **m)
{
struct rk1608_msg_queue queue;
struct rk1608_msg_queue *q = &queue;
@@ -1239,18 +1250,19 @@ int rk1608_msq_recv_msg(struct spi_device *spi, struct msg **m)
int err = 0;
*m = NULL;
err = rk1608_msq_read_head(spi, RK1608_S_MSG_QUEUE_ADDR, q);
err = rk1608_msq_read_head(rk1608, spi, RK1608_S_MSG_QUEUE_ADDR, q);
if (err)
return err;
if (q->cur_send == q->cur_recv)
return -EINVAL;
/* Skip to head when size is 0 */
err = rk1608_safe_read(spi, (s32)q->cur_recv, (s32 *)&size, 4);
err = rk1608_safe_read(rk1608, spi, (s32)q->cur_recv, (s32 *)&size, 4);
if (err)
return err;
if (size == 0) {
err = rk1608_safe_read(spi, (s32)q->buf_head, (s32 *)&size, 4);
err = rk1608_safe_read(rk1608, spi, (s32)q->buf_head,
(s32 *)&size, 4);
if (err)
return err;
@@ -1271,9 +1283,9 @@ int rk1608_msq_recv_msg(struct spi_device *spi, struct msg **m)
*m = kmalloc(msg_size, GFP_KERNEL);
if (!*m)
return -ENOMEM;
err = rk1608_safe_read(spi, recv_addr, (s32 *)*m, msg_size);
err = rk1608_safe_read(rk1608, spi, recv_addr, (s32 *)*m, msg_size);
if (err == 0) {
err = rk1608_safe_write(spi, RK1608_S_MSG_QUEUE_ADDR +
err = rk1608_safe_write(rk1608, spi, RK1608_S_MSG_QUEUE_ADDR +
(u8 *)&q->cur_recv - (u8 *)q,
&next_recv_addr, 4);
}
@@ -1352,7 +1364,8 @@ static u32 rk1608_msq_head_free_size(const struct rk1608_msg_queue *q)
*
* It returns zero on success, else a negative error code.
*/
int rk1608_msq_send_msg(struct spi_device *spi, struct msg *m)
int rk1608_msq_send_msg(struct rk1608_state *rk1608, struct spi_device *spi,
struct msg *m)
{
int err = 0;
s32 tmp = 0;
@@ -1360,24 +1373,26 @@ int rk1608_msq_send_msg(struct spi_device *spi, struct msg *m)
struct rk1608_msg_queue *q = &queue;
u32 msg_size = m->size * sizeof(u32);
err = rk1608_msq_read_head(spi, RK1608_R_MSG_QUEUE_ADDR, q);
err = rk1608_msq_read_head(rk1608, spi, RK1608_R_MSG_QUEUE_ADDR, q);
if (err)
return err;
if (rk1608_msq_tail_free_size(q) > msg_size) {
u32 next_send;
err = rk1608_safe_write(spi, q->cur_send, (s32 *)m, msg_size);
err = rk1608_safe_write(rk1608, spi, q->cur_send,
(s32 *)m, msg_size);
next_send = q->cur_send + msg_size;
if (next_send == q->buf_tail)
next_send = q->buf_head;
q->cur_send = next_send;
} else if (rk1608_msq_head_free_size(q) > msg_size) {
/* Set size to 0 for skip to head mark */
err = rk1608_safe_write(spi, q->cur_send, &tmp, 4);
err = rk1608_safe_write(rk1608, spi, q->cur_send, &tmp, 4);
if (err)
return err;
err = rk1608_safe_write(spi, q->buf_head, (s32 *)m, msg_size);
err = rk1608_safe_write(rk1608, spi, q->buf_head, (s32 *)m,
msg_size);
q->cur_send = q->buf_head + msg_size;
} else {
return -EPERM;
@@ -1386,7 +1401,7 @@ int rk1608_msq_send_msg(struct spi_device *spi, struct msg *m)
if (err)
return err;
err = rk1608_safe_write(spi, RK1608_R_MSG_QUEUE_ADDR +
err = rk1608_safe_write(rk1608, spi, RK1608_R_MSG_QUEUE_ADDR +
(u8 *)&q->cur_send - (u8 *)q, &q->cur_send, 4);
rk1608_interrupt_request(spi, RK1608_IRQ_TYPE_MSG);
@@ -1409,7 +1424,7 @@ int rk1608_send_msg_to_dsp(struct rk1608_state *pdata, struct msg *m)
}
mutex_lock(&pdata->send_msg_lock);
ret = rk1608_msq_send_msg(pdata->spi, m);
ret = rk1608_msq_send_msg(pdata, pdata->spi, m);
mutex_unlock(&pdata->send_msg_lock);
/* For msg sync */
@@ -1460,7 +1475,7 @@ static irqreturn_t rk1608_threaded_isr(int irq, void *ctx)
struct rk1608_state *pdata = ctx;
struct msg *msg;
while (!rk1608_msq_recv_msg(pdata->spi, &msg) && NULL != msg) {
while (!rk1608_msq_recv_msg(pdata, pdata->spi, &msg) && NULL != msg) {
rk1608_dispatch_received_msg(pdata, msg);
/* For kernel msg sync */
if (msg->type >= id_msg_init_sensor_ret_t &&
@@ -1644,6 +1659,7 @@ static int rk1608_probe(struct spi_device *spi)
mutex_init(&rk1608->sensor_lock);
mutex_init(&rk1608->send_msg_lock);
mutex_init(&rk1608->lock);
mutex_init(&rk1608->spi2apb_lock);
spin_lock_init(&rk1608->hdrae_lock);
sd = &rk1608->sd;
@@ -1682,6 +1698,7 @@ static int rk1608_remove(struct spi_device *spi)
mutex_destroy(&rk1608->lock);
mutex_destroy(&rk1608->send_msg_lock);
mutex_destroy(&rk1608->sensor_lock);
mutex_destroy(&rk1608->spi2apb_lock);
rk1608_dev_unregister(rk1608);
return 0;

View File

@@ -95,6 +95,7 @@ struct rk1608_state {
struct mutex lock; /* protect resource */
struct mutex sensor_lock; /* protect sensor */
struct mutex send_msg_lock; /* protect msg */
struct mutex spi2apb_lock; /* protect spi2apb write/read */
spinlock_t hdrae_lock; /* protect hdrae parameter */
struct gpio_desc *reset_gpio;
struct gpio_desc *irq_gpio;
@@ -404,7 +405,7 @@ int rk1608_write(struct spi_device *spi, s32 addr,
*
* It returns zero on success, else operation state code.
*/
int rk1608_safe_write(struct spi_device *spi,
int rk1608_safe_write(struct rk1608_state *rk1608, struct spi_device *spi,
s32 addr, const s32 *data, size_t data_len);
/**
@@ -432,7 +433,7 @@ int rk1608_read(struct spi_device *spi, s32 addr,
*
* It returns zero on success, else operation state code.
*/
int rk1608_safe_read(struct spi_device *spi,
int rk1608_safe_read(struct rk1608_state *rk1608, struct spi_device *spi,
s32 addr, s32 *data, size_t data_len);
/**
@@ -477,7 +478,8 @@ int rk1608_interrupt_request(struct spi_device *spi, s32 interrupt_num);
*
* It returns zero on success, else a negative error code.
**/
int rk1608_download_fw(struct spi_device *spi, const char *fw_name);
int rk1608_download_fw(struct rk1608_state *rk1608, struct spi_device *spi,
const char *fw_name);
/**
* rk1608_msq_recv_msg - receive a msg from RK1608 -> AP msg queue
@@ -489,7 +491,8 @@ int rk1608_download_fw(struct spi_device *spi, const char *fw_name);
*
* It returns zero on success, else a negative error code.
*/
int rk1608_msq_recv_msg(struct spi_device *spi, struct msg **m);
int rk1608_msq_recv_msg(struct rk1608_state *rk1608, struct spi_device *spi,
struct msg **m);
/*
* rk1608_msq_send_msg - send a msg from AP -> RK1608 msg queue
@@ -499,7 +502,8 @@ int rk1608_msq_recv_msg(struct spi_device *spi, struct msg **m);
*
* It returns zero on success, else a negative error code.
*/
int rk1608_msq_send_msg(struct spi_device *spi, struct msg *m);
int rk1608_msq_send_msg(struct rk1608_state *rk1608, struct spi_device *spi,
struct msg *m);
int rk1608_set_power(struct rk1608_state *pdata, int on);

View File

@@ -479,7 +479,7 @@ static int do_cmd_download_fw(struct rk1608_state *pdata,
if (args->argc == 2 && args->argv[1].type == AUTO_ARG_TYPE_STR)
fw_name = args->argv[1].m_str;
ret = rk1608_download_fw(pdata->spi, fw_name);
ret = rk1608_download_fw(pdata, pdata->spi, fw_name);
if (ret)
dev_err(pdata->dev, "download firmware failed!\n");
else
@@ -564,7 +564,7 @@ static int do_cmd_recv_msg(struct rk1608_state *pdata,
char buf[256] = "";
int ret = 0;
ret = rk1608_msq_recv_msg(pdata->spi, &m);
ret = rk1608_msq_recv_msg(pdata, pdata->spi, &m);
if (ret || !m)
return 0;
@@ -787,7 +787,7 @@ static long rk1608_dev_ioctl(struct file *file, unsigned int cmd,
break;
}
dev_info(pdata->dev, "download fw:%s\n", fw_name);
ret = rk1608_download_fw(pdata->spi, fw_name);
ret = rk1608_download_fw(pdata, pdata->spi, fw_name);
break;
}
case PREISP_WRITE: {
@@ -805,7 +805,7 @@ static long rk1608_dev_ioctl(struct file *file, unsigned int cmd,
break;
}
ret = rk1608_safe_write(pdata->spi, pkt.addr, data, pkt.data_len);
ret = rk1608_safe_write(pdata, pdata->spi, pkt.addr, data, pkt.data_len);
kfree(data);
break;
}
@@ -824,7 +824,7 @@ static long rk1608_dev_ioctl(struct file *file, unsigned int cmd,
break;
}
ret = rk1608_safe_read(pdata->spi, pkt.addr, data, pkt.data_len);
ret = rk1608_safe_read(pdata, pdata->spi, pkt.addr, data, pkt.data_len);
if (ret) {
kfree(data);
break;