580 lines
13 KiB
C
580 lines
13 KiB
C
|
/*
|
||
|
* linux-3.10/drivers/media/platform/sunxi-vin/vin-cci/bsp_cci.c
|
||
|
*
|
||
|
* Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
|
||
|
*
|
||
|
* This software is licensed under the terms of the GNU General Public
|
||
|
* License version 2, as published by the Free Software Foundation, and
|
||
|
* may be copied, distributed, and modified under those terms.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*
|
||
|
******************************************************************************
|
||
|
*
|
||
|
* bsp_cci.c
|
||
|
*
|
||
|
* Hawkview ISP - bsp_cci.c module
|
||
|
*
|
||
|
* Copyright (c) 2014 by Allwinnertech Co., Ltd. http://www.allwinnertech.com
|
||
|
*
|
||
|
* Version Author Date Description
|
||
|
*
|
||
|
* 2.0 Yang Feng 2014/04/23 Second Version
|
||
|
*
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
|
||
|
#include "bsp_cci.h"
|
||
|
#include "../platform/platform_cfg.h"
|
||
|
#include <linux/delay.h>
|
||
|
#include <linux/sched.h>
|
||
|
#include <linux/mutex.h>
|
||
|
#include <linux/semaphore.h>
|
||
|
|
||
|
wait_queue_head_t wait[MAX_CSIC_CCI_NUM];
|
||
|
static int status_err_flag[MAX_CSIC_CCI_NUM] = { 0 };
|
||
|
struct mutex cci_mutex[MAX_CSIC_CCI_NUM];
|
||
|
struct semaphore cci_sema[MAX_CSIC_CCI_NUM];
|
||
|
|
||
|
int bsp_csi_cci_set_base_addr(unsigned int sel, unsigned long addr)
|
||
|
{
|
||
|
init_waitqueue_head(&wait[sel]);
|
||
|
mutex_init(&cci_mutex[sel]);
|
||
|
sema_init(&cci_sema[sel], 1);
|
||
|
return csi_cci_set_base_addr(sel, addr);
|
||
|
}
|
||
|
|
||
|
static void cci_cal_div(unsigned int clk, unsigned char *div_coef)
|
||
|
{
|
||
|
unsigned char clk_m = 0;
|
||
|
unsigned char clk_n = 0;
|
||
|
unsigned int src_clk = CCI_HCLK / 10;
|
||
|
unsigned int sclk_req = clk;
|
||
|
unsigned char _2_pow_clk_n = 1;
|
||
|
unsigned int sclk_real = 0;
|
||
|
unsigned int divider = src_clk / sclk_req;
|
||
|
|
||
|
if (divider == 0) {
|
||
|
clk_m = 1;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
while (clk_n < 8) {
|
||
|
clk_m = (divider / _2_pow_clk_n) - 1;
|
||
|
while (clk_m < 16) {
|
||
|
sclk_real = src_clk / (clk_m + 1) / _2_pow_clk_n;
|
||
|
if (sclk_real <= sclk_req)
|
||
|
goto out;
|
||
|
else
|
||
|
clk_m++;
|
||
|
}
|
||
|
|
||
|
clk_n++;
|
||
|
_2_pow_clk_n *= 2;
|
||
|
}
|
||
|
|
||
|
out:
|
||
|
|
||
|
div_coef[0] = clk_m;
|
||
|
div_coef[1] = clk_n;
|
||
|
}
|
||
|
|
||
|
void bsp_csi_cci_init(unsigned int sel)
|
||
|
{
|
||
|
unsigned char div_coef[2];
|
||
|
|
||
|
csi_cci_reset(sel);
|
||
|
csi_cci_enable(sel);
|
||
|
cci_cal_div(400 * 1000, div_coef);
|
||
|
csi_cci_set_clk_div(sel, div_coef);
|
||
|
csi_cci_set_pkt_interval(sel, 16);
|
||
|
csi_cci_set_ack_timeout(sel, 16);
|
||
|
csi_cci_set_trig_dly(sel, 0);
|
||
|
cci_pad_en(sel);
|
||
|
}
|
||
|
|
||
|
void bsp_csi_cci_exit(unsigned int sel)
|
||
|
{
|
||
|
bsp_cci_int_disable(sel, CCI_INT_ALL);
|
||
|
csi_cci_reset(sel);
|
||
|
csi_cci_disable(sel);
|
||
|
}
|
||
|
|
||
|
void bsp_cci_set_tx_mode(unsigned int sel, struct cci_tx_mode *tx_mode)
|
||
|
{
|
||
|
csi_cci_set_tx_buf_mode(sel, &tx_mode->tx_buf_mode);
|
||
|
csi_cci_set_trig_mode(sel, &tx_mode->tx_trig_mode);
|
||
|
csi_cci_set_trig_line_cnt(sel, tx_mode->tx_trig_line_cnt);
|
||
|
}
|
||
|
|
||
|
void bsp_cci_tx_start(unsigned int sel, struct cci_msg *msg)
|
||
|
{
|
||
|
unsigned int i, j, pkt_len, max_pkt_num, pkt_num;
|
||
|
unsigned char *buf;
|
||
|
|
||
|
csi_cci_set_bus_fmt(sel, &msg->bus_fmt);
|
||
|
|
||
|
buf = msg->pkt_buf;
|
||
|
pkt_num = msg->pkt_num;
|
||
|
pkt_len = msg->bus_fmt.addr_len + msg->bus_fmt.data_len;
|
||
|
max_pkt_num = FIFO_DEPTH / pkt_len;
|
||
|
|
||
|
while (pkt_num != 0) {
|
||
|
if (pkt_num < max_pkt_num) {
|
||
|
j = pkt_num;
|
||
|
pkt_num = 0;
|
||
|
} else {
|
||
|
j = max_pkt_num;
|
||
|
pkt_num = pkt_num - max_pkt_num;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < j; i++) {
|
||
|
csi_cci_wr_tx_buf(sel, buf, pkt_len);
|
||
|
buf += pkt_len;
|
||
|
}
|
||
|
csi_cci_trans_start(sel, SINGLE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void bsp_cci_tx_data_rb(unsigned int sel, struct cci_msg *msg)
|
||
|
{
|
||
|
unsigned int i, j, pkt_len, max_pkt_num, pkt_num;
|
||
|
unsigned char *buf;
|
||
|
csi_cci_set_bus_fmt(sel, &msg->bus_fmt);
|
||
|
buf = msg->pkt_buf;
|
||
|
pkt_num = msg->pkt_num;
|
||
|
pkt_len = msg->bus_fmt.addr_len + msg->bus_fmt.data_len;
|
||
|
max_pkt_num = FIFO_DEPTH / pkt_len;
|
||
|
|
||
|
while (pkt_num != 0) {
|
||
|
if (pkt_num < max_pkt_num) {
|
||
|
j = pkt_num;
|
||
|
pkt_num = 0;
|
||
|
} else {
|
||
|
j = max_pkt_num;
|
||
|
pkt_num = pkt_num - max_pkt_num;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < j; i++) {
|
||
|
csi_cci_fifo_pt_add(sel, msg->bus_fmt.addr_len);
|
||
|
csi_cci_rd_tx_buf(sel, buf + msg->bus_fmt.addr_len,
|
||
|
msg->bus_fmt.data_len);
|
||
|
buf += pkt_len;
|
||
|
}
|
||
|
}
|
||
|
csi_cci_fifo_pt_reset(sel);
|
||
|
}
|
||
|
static void bsp_cci_error_process(unsigned int sel)
|
||
|
{
|
||
|
cci_int_clear_status(sel, CCI_INT_ERROR);
|
||
|
bsp_cci_bus_error_process(sel);
|
||
|
bsp_csi_cci_exit(sel);
|
||
|
bsp_csi_cci_init_helper(sel);
|
||
|
}
|
||
|
static int bsp_cci_tx_start_wait_done_unlocked(unsigned int sel,
|
||
|
struct cci_msg *msg)
|
||
|
{
|
||
|
#ifdef CCI_IRQ
|
||
|
int ret = 0;
|
||
|
unsigned long timeout = 0;
|
||
|
bsp_cci_tx_start(sel, msg);
|
||
|
#ifdef FPGA_VER
|
||
|
timeout =
|
||
|
wait_event_timeout(wait[sel], csi_cci_get_trans_done(sel) == 0,
|
||
|
HZ / 50);
|
||
|
#else
|
||
|
timeout =
|
||
|
wait_event_timeout(wait[sel], csi_cci_get_trans_done(sel) == 0, HZ);
|
||
|
if (timeout == 0) {
|
||
|
printk("[VIN CCI_%d ERR] timeout error at "
|
||
|
"addr_8bit = %x, wr_flag = %d, val = %x\n",
|
||
|
sel, msg->bus_fmt.saddr_7bit << 1, msg->bus_fmt.wr_flag,
|
||
|
*(int *)msg->pkt_buf);
|
||
|
ret = -1;
|
||
|
}
|
||
|
#endif
|
||
|
if (1 == status_err_flag[sel]) {
|
||
|
printk("[VIN CCI_%d ERR] Status error at "
|
||
|
"addr_8bit = %x, wr_flag = %d, val = %x\n",
|
||
|
sel, msg->bus_fmt.saddr_7bit << 1, msg->bus_fmt.wr_flag,
|
||
|
*(int *)msg->pkt_buf);
|
||
|
ret = -1;
|
||
|
}
|
||
|
if (msg->bus_fmt.wr_flag == 1)
|
||
|
bsp_cci_tx_data_rb(sel, msg);
|
||
|
return ret;
|
||
|
#else
|
||
|
struct cci_int_status status;
|
||
|
int ret = 0;
|
||
|
bsp_cci_tx_start(sel, msg);
|
||
|
usleep_range(100, 120);
|
||
|
while (1) {
|
||
|
if (csi_cci_get_trans_done(sel) == 0) {
|
||
|
break;
|
||
|
} else {
|
||
|
usleep_range(80, 100);
|
||
|
}
|
||
|
};
|
||
|
cci_int_get_status(sel, &status);
|
||
|
if (status.error) {
|
||
|
cci_int_clear_status(sel, CCI_INT_ERROR);
|
||
|
printk("[VIN CCI_%d ERR] Status error at "
|
||
|
"addr_8bit = %x, wr_flag = %d\n",
|
||
|
sel, msg->bus_fmt.saddr_7bit << 1, msg->bus_fmt.wr_flag);
|
||
|
bsp_cci_bus_error_process(sel);
|
||
|
bsp_csi_cci_exit(sel);
|
||
|
bsp_csi_cci_init_helper(sel);
|
||
|
ret = -1;
|
||
|
}
|
||
|
if (status.complete)
|
||
|
cci_int_clear_status(sel, CCI_INT_FINISH);
|
||
|
if (msg->bus_fmt.wr_flag == 1)
|
||
|
bsp_cci_tx_data_rb(sel, msg);
|
||
|
return ret;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int bsp_cci_tx_start_wait_done(unsigned int sel, struct cci_msg *msg)
|
||
|
{
|
||
|
int ret = -1;
|
||
|
mutex_lock(&cci_mutex[sel]);
|
||
|
if (down_trylock(&cci_sema[sel])) {
|
||
|
printk("down_trylock fail!\n");
|
||
|
return -1;
|
||
|
}
|
||
|
ret = bsp_cci_tx_start_wait_done_unlocked(sel, msg);
|
||
|
up(&cci_sema[sel]);
|
||
|
mutex_unlock(&cci_mutex[sel]);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void bsp_cci_int_enable(unsigned int sel, enum cci_int_sel interrupt)
|
||
|
{
|
||
|
cci_int_enable(sel, interrupt);
|
||
|
}
|
||
|
|
||
|
void bsp_cci_int_disable(unsigned int sel, enum cci_int_sel interrupt)
|
||
|
{
|
||
|
cci_int_disable(sel, interrupt);
|
||
|
}
|
||
|
|
||
|
void CCI_INLINE bsp_cci_int_get_status(unsigned int sel,
|
||
|
struct cci_int_status *status)
|
||
|
{
|
||
|
cci_int_get_status(sel, status);
|
||
|
}
|
||
|
|
||
|
void CCI_INLINE bsp_cci_int_clear_status(unsigned int sel,
|
||
|
enum cci_int_sel interrupt)
|
||
|
{
|
||
|
cci_int_clear_status(sel, interrupt);
|
||
|
}
|
||
|
|
||
|
enum cci_bus_status CCI_INLINE bsp_cci_get_bus_status(unsigned int sel)
|
||
|
{
|
||
|
return cci_get_bus_status(sel);
|
||
|
}
|
||
|
|
||
|
int bsp_cci_irq_process(unsigned int sel)
|
||
|
{
|
||
|
struct cci_int_status status;
|
||
|
unsigned int ret = 0;
|
||
|
cci_int_get_status(sel, &status);
|
||
|
if (status.error) {
|
||
|
bsp_cci_error_process(sel);
|
||
|
status_err_flag[sel] = 1;
|
||
|
ret = -1;
|
||
|
}
|
||
|
if (status.complete) {
|
||
|
status_err_flag[sel] = 0;
|
||
|
cci_int_clear_status(sel, CCI_INT_FINISH);
|
||
|
}
|
||
|
wake_up(&wait[sel]);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void bsp_cci_bus_error_process(unsigned int sel)
|
||
|
{
|
||
|
cci_stop(sel);
|
||
|
cci_sck_cycles(sel, 16);
|
||
|
}
|
||
|
|
||
|
void bsp_csi_cci_init_helper(unsigned int sel)
|
||
|
{
|
||
|
struct cci_tx_mode tx_mode;
|
||
|
bsp_csi_cci_init(sel);
|
||
|
tx_mode.tx_buf_mode.buf_src = FIFO;
|
||
|
tx_mode.tx_buf_mode.pkt_mode = COMPACT;
|
||
|
tx_mode.tx_buf_mode.pkt_cnt = 1;
|
||
|
tx_mode.tx_trig_mode.trig_src = NO_TRIG;
|
||
|
tx_mode.tx_trig_mode.trig_con = TRIG_DEFAULT;
|
||
|
tx_mode.tx_trig_line_cnt = 0;
|
||
|
bsp_cci_set_tx_mode(sel, &tx_mode);
|
||
|
bsp_cci_int_clear_status(sel, CCI_INT_ALL);
|
||
|
bsp_cci_int_enable(sel, CCI_INT_ALL);
|
||
|
}
|
||
|
|
||
|
int cci_wr_8_8(unsigned int sel, unsigned char reg, unsigned char data,
|
||
|
unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[2];
|
||
|
|
||
|
buf[0] = reg;
|
||
|
buf[1] = data;
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 0;
|
||
|
msg.bus_fmt.rs_start = START_WITH_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 1;
|
||
|
msg.bus_fmt.data_len = 1;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
return bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
}
|
||
|
|
||
|
int cci_wr_16_8(unsigned int sel, unsigned short reg, unsigned char data,
|
||
|
unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[3];
|
||
|
|
||
|
buf[0] = (reg & 0xff00) >> 8;
|
||
|
buf[1] = (reg & 0x00ff);
|
||
|
buf[2] = data;
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 0;
|
||
|
msg.bus_fmt.rs_start = START_WITH_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 2;
|
||
|
msg.bus_fmt.data_len = 1;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
return bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
}
|
||
|
|
||
|
int cci_wr_16_16(unsigned int sel, unsigned short reg, unsigned short data,
|
||
|
unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[4];
|
||
|
|
||
|
buf[0] = (reg & 0xff00) >> 8;
|
||
|
buf[1] = (reg & 0x00ff);
|
||
|
buf[2] = (data & 0xff00) >> 8;
|
||
|
buf[3] = (data & 0x00ff);
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 0;
|
||
|
msg.bus_fmt.rs_start = START_WITH_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 2;
|
||
|
msg.bus_fmt.data_len = 2;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
return bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
}
|
||
|
|
||
|
int cci_wr_8_16(unsigned int sel, unsigned char reg, unsigned short data,
|
||
|
unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[3];
|
||
|
|
||
|
buf[0] = reg;
|
||
|
buf[1] = (data & 0xff00) >> 8;
|
||
|
buf[2] = (data & 0x00ff);
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 0;
|
||
|
msg.bus_fmt.rs_start = START_WITH_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 1;
|
||
|
msg.bus_fmt.data_len = 2;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
return bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
}
|
||
|
|
||
|
int cci_wr_0_16(unsigned int sel, unsigned short data, unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[2];
|
||
|
|
||
|
buf[0] = (data & 0xff00) >> 8;
|
||
|
buf[1] = (data & 0x00ff);
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 0;
|
||
|
msg.bus_fmt.rs_start = START_WITHOUT_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 0;
|
||
|
msg.bus_fmt.data_len = 2;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
return bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
}
|
||
|
|
||
|
int cci_rd_8_8(unsigned int sel, unsigned char reg, unsigned char *data,
|
||
|
unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[2];
|
||
|
int ret;
|
||
|
buf[0] = reg;
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 1;
|
||
|
msg.bus_fmt.rs_start = START_WITH_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 1;
|
||
|
msg.bus_fmt.data_len = 1;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
ret = bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
*data = buf[1];
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int cci_rd_16_8(unsigned int sel, unsigned short reg, unsigned char *data,
|
||
|
unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[3];
|
||
|
int ret;
|
||
|
|
||
|
buf[0] = (reg & 0xff00) >> 8;
|
||
|
buf[1] = (reg & 0x00ff);
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 1;
|
||
|
msg.bus_fmt.rs_start = START_WITH_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 2;
|
||
|
msg.bus_fmt.data_len = 1;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
ret = bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
*data = buf[2];
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int cci_rd_16_16(unsigned int sel, unsigned short reg, unsigned short *data,
|
||
|
unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[4];
|
||
|
int ret;
|
||
|
|
||
|
buf[0] = (reg & 0xff00) >> 8;
|
||
|
buf[1] = (reg & 0x00ff);
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 1;
|
||
|
msg.bus_fmt.rs_start = START_WITH_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 2;
|
||
|
msg.bus_fmt.data_len = 2;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
ret = bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
*data = buf[2] * 256 + buf[3];
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int cci_rd_8_16(unsigned int sel, unsigned char reg, unsigned short *data,
|
||
|
unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[3];
|
||
|
int ret;
|
||
|
|
||
|
buf[0] = reg;
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 1;
|
||
|
msg.bus_fmt.rs_start = START_WITH_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 1;
|
||
|
msg.bus_fmt.data_len = 2;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
ret = bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
*data = buf[1] * 256 + buf[2];
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int cci_rd_0_16(unsigned int sel, unsigned short *data, unsigned char slv)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[2];
|
||
|
int ret;
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 1;
|
||
|
msg.bus_fmt.rs_start = START_WITHOUT_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 0;
|
||
|
msg.bus_fmt.data_len = 2;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
|
||
|
ret = bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
*data = buf[0] * 256 + buf[1];
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#define CCI_MAX_MSG_LEN 12
|
||
|
|
||
|
int cci_wr_a16_d8_continuous(unsigned int sel, unsigned short reg,
|
||
|
unsigned char *data, unsigned char slv, int size)
|
||
|
{
|
||
|
struct cci_msg msg;
|
||
|
unsigned char buf[2 + CCI_MAX_MSG_LEN];
|
||
|
int ret = 0, i;
|
||
|
while (size > 0) {
|
||
|
int len = size > CCI_MAX_MSG_LEN ? CCI_MAX_MSG_LEN : size;
|
||
|
buf[0] = (reg & 0xff00) >> 8;
|
||
|
buf[1] = (reg & 0x00ff);
|
||
|
for (i = 2; i < 2 + len; i++)
|
||
|
buf[i] = *data++;
|
||
|
|
||
|
msg.bus_fmt.saddr_7bit = slv;
|
||
|
msg.bus_fmt.wr_flag = 0;
|
||
|
msg.bus_fmt.rs_start = START_WITH_ID_W;
|
||
|
msg.bus_fmt.rs_mode = STOP_START;
|
||
|
msg.bus_fmt.addr_len = 2;
|
||
|
msg.bus_fmt.data_len = len;
|
||
|
msg.pkt_buf = buf;
|
||
|
msg.pkt_num = 1;
|
||
|
ret = bsp_cci_tx_start_wait_done(sel, &msg);
|
||
|
if (ret >= 0) {
|
||
|
ret = 0;
|
||
|
} else if (ret < 0) {
|
||
|
printk("[CCI] sensor_write error!\n");
|
||
|
break;
|
||
|
}
|
||
|
reg += len;
|
||
|
size -= len;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|