bdk: i2c: refactor
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2022 CTCaer
|
* Copyright (c) 2018-2026 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -49,6 +49,9 @@
|
|||||||
#define I2C_TX_FIFO (0x50 / 4)
|
#define I2C_TX_FIFO (0x50 / 4)
|
||||||
#define I2C_RX_FIFO (0x54 / 4)
|
#define I2C_RX_FIFO (0x54 / 4)
|
||||||
|
|
||||||
|
#define I2C_PACKET_TRANSFER_STATUS (0x58 / 4)
|
||||||
|
#define PKT_TRANSFER_COMPLETE BIT(24)
|
||||||
|
|
||||||
#define I2C_FIFO_CONTROL (0x5C / 4)
|
#define I2C_FIFO_CONTROL (0x5C / 4)
|
||||||
#define RX_FIFO_FLUSH BIT(0)
|
#define RX_FIFO_FLUSH BIT(0)
|
||||||
#define TX_FIFO_FLUSH BIT(1)
|
#define TX_FIFO_FLUSH BIT(1)
|
||||||
@@ -96,7 +99,7 @@ static void _i2c_load_cfg_wait(vu32 *base)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, const u8 *buf, u32 size)
|
static int _i2c_send_normal(u32 i2c_idx, u32 dev_addr, const u8 *buf, u32 size)
|
||||||
{
|
{
|
||||||
if (size > 8)
|
if (size > 8)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -129,12 +132,12 @@ static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, const u8 *buf, u32 size)
|
|||||||
_i2c_load_cfg_wait(base);
|
_i2c_load_cfg_wait(base);
|
||||||
|
|
||||||
// Initiate transaction on normal mode.
|
// Initiate transaction on normal mode.
|
||||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
|
base[I2C_CNFG] = (base[I2C_CNFG] & ~NORMAL_MODE_GO) | NORMAL_MODE_GO;
|
||||||
|
|
||||||
u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
|
u32 timeout = get_tmr_ms() + 100; // Actual for max 8 bytes at 100KHz is 0.74ms.
|
||||||
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
|
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
|
||||||
{
|
{
|
||||||
if (get_tmr_us() > timeout)
|
if (get_tmr_ms() > timeout)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +147,7 @@ static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, const u8 *buf, u32 size)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
static int _i2c_recv_normal(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
||||||
{
|
{
|
||||||
if (size > 8)
|
if (size > 8)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -161,12 +164,12 @@ static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
|||||||
_i2c_load_cfg_wait(base);
|
_i2c_load_cfg_wait(base);
|
||||||
|
|
||||||
// Initiate transaction on normal mode.
|
// Initiate transaction on normal mode.
|
||||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
|
base[I2C_CNFG] = (base[I2C_CNFG] & ~NORMAL_MODE_GO) | NORMAL_MODE_GO;
|
||||||
|
|
||||||
u32 timeout = get_tmr_us() + 200000; // Actual for max 8 bytes at 100KHz is 0.74ms.
|
u32 timeout = get_tmr_ms() + 100; // Actual for max 8 bytes at 100KHz is 0.74ms.
|
||||||
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
|
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
|
||||||
{
|
{
|
||||||
if (get_tmr_us() > timeout)
|
if (get_tmr_ms() > timeout)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,12 +189,12 @@ static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
static int _i2c_send_packet(u32 i2c_idx, const u8 *buf, u32 size, u32 dev_addr)
|
||||||
{
|
{
|
||||||
if (size > 32)
|
if (size > 32)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int res = 0;
|
int res = 1;
|
||||||
|
|
||||||
vu32 *base = (vu32 *)(I2C_BASE + (u32)_i2c_base_offsets[i2c_idx]);
|
vu32 *base = (vu32 *)(I2C_BASE + (u32)_i2c_base_offsets[i2c_idx]);
|
||||||
|
|
||||||
@@ -213,7 +216,7 @@ static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
|||||||
_i2c_load_cfg_wait(base);
|
_i2c_load_cfg_wait(base);
|
||||||
|
|
||||||
// Initiate transaction on packet mode.
|
// Initiate transaction on packet mode.
|
||||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | PACKET_MODE_GO;
|
base[I2C_CNFG] = (base[I2C_CNFG] & ~NORMAL_MODE_GO) | PACKET_MODE_GO;
|
||||||
|
|
||||||
u32 hdr[3];
|
u32 hdr[3];
|
||||||
hdr[0] = I2C_PACKET_PROT_I2C;
|
hdr[0] = I2C_PACKET_PROT_I2C;
|
||||||
@@ -225,7 +228,7 @@ static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
|||||||
base[I2C_TX_FIFO] = hdr[1];
|
base[I2C_TX_FIFO] = hdr[1];
|
||||||
base[I2C_TX_FIFO] = hdr[2];
|
base[I2C_TX_FIFO] = hdr[2];
|
||||||
|
|
||||||
u32 timeout = get_tmr_ms() + 400;
|
u32 timeout = get_tmr_ms() + 200;
|
||||||
while (size)
|
while (size)
|
||||||
{
|
{
|
||||||
if (base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT)
|
if (base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT)
|
||||||
@@ -240,17 +243,17 @@ static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
|||||||
|
|
||||||
if (get_tmr_ms() > timeout)
|
if (get_tmr_ms() > timeout)
|
||||||
{
|
{
|
||||||
res = 1;
|
res = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK)
|
if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK)
|
||||||
res = 1;
|
res = 0;
|
||||||
|
|
||||||
// Disable packet mode.
|
// Wait for STOP and disable packet mode.
|
||||||
usleep(20);
|
usleep(20);
|
||||||
base[I2C_CNFG] &= 0xFFFFF9FF;
|
base[I2C_CNFG] &= ~(PACKET_MODE_GO | NORMAL_MODE_GO);
|
||||||
|
|
||||||
// Disable interrupts.
|
// Disable interrupts.
|
||||||
base[I2C_INT_EN] = 0;
|
base[I2C_INT_EN] = 0;
|
||||||
@@ -258,12 +261,12 @@ static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _i2c_recv_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg)
|
int i2c_xfer_packet(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg)
|
||||||
{
|
{
|
||||||
if (size > 32)
|
if (size > 32)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int res = 0;
|
int res = 1;
|
||||||
|
|
||||||
vu32 *base = (vu32 *)(I2C_BASE + (u32)_i2c_base_offsets[i2c_idx]);
|
vu32 *base = (vu32 *)(I2C_BASE + (u32)_i2c_base_offsets[i2c_idx]);
|
||||||
|
|
||||||
@@ -285,7 +288,7 @@ static int _i2c_recv_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg)
|
|||||||
_i2c_load_cfg_wait(base);
|
_i2c_load_cfg_wait(base);
|
||||||
|
|
||||||
// Initiate transaction on packet mode.
|
// Initiate transaction on packet mode.
|
||||||
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | PACKET_MODE_GO;
|
base[I2C_CNFG] = (base[I2C_CNFG] & ~NORMAL_MODE_GO) | PACKET_MODE_GO;
|
||||||
|
|
||||||
// Send reg request.
|
// Send reg request.
|
||||||
u32 hdr[3];
|
u32 hdr[3];
|
||||||
@@ -299,7 +302,7 @@ static int _i2c_recv_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg)
|
|||||||
base[I2C_TX_FIFO] = hdr[2];
|
base[I2C_TX_FIFO] = hdr[2];
|
||||||
base[I2C_TX_FIFO] = reg;
|
base[I2C_TX_FIFO] = reg;
|
||||||
|
|
||||||
u32 timeout = get_tmr_ms() + 400;
|
u32 timeout = get_tmr_ms() + 200;
|
||||||
while (!(base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT))
|
while (!(base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT))
|
||||||
if (get_tmr_ms() > timeout)
|
if (get_tmr_ms() > timeout)
|
||||||
break;
|
break;
|
||||||
@@ -313,7 +316,7 @@ static int _i2c_recv_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg)
|
|||||||
base[I2C_TX_FIFO] = hdr[1];
|
base[I2C_TX_FIFO] = hdr[1];
|
||||||
base[I2C_TX_FIFO] = hdr[2];
|
base[I2C_TX_FIFO] = hdr[2];
|
||||||
|
|
||||||
timeout = get_tmr_ms() + 400;
|
timeout = get_tmr_ms() + 200;
|
||||||
while (size)
|
while (size)
|
||||||
{
|
{
|
||||||
if (base[I2C_FIFO_STATUS] & RX_FIFO_FULL_CNT)
|
if (base[I2C_FIFO_STATUS] & RX_FIFO_FULL_CNT)
|
||||||
@@ -327,17 +330,17 @@ static int _i2c_recv_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg)
|
|||||||
|
|
||||||
if (get_tmr_ms() > timeout)
|
if (get_tmr_ms() > timeout)
|
||||||
{
|
{
|
||||||
res = 1;
|
res = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK)
|
if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK)
|
||||||
res = 1;
|
res = 0;
|
||||||
|
|
||||||
// Disable packet mode.
|
// Wait for STOP and disable packet mode.
|
||||||
usleep(20);
|
usleep(20);
|
||||||
base[I2C_CNFG] &= 0xFFFFF9FF;
|
base[I2C_CNFG] &= ~(PACKET_MODE_GO | NORMAL_MODE_GO);
|
||||||
|
|
||||||
// Disable interrupts.
|
// Disable interrupts.
|
||||||
base[I2C_INT_EN] = 0;
|
base[I2C_INT_EN] = 0;
|
||||||
@@ -366,42 +369,33 @@ void i2c_init(u32 i2c_idx)
|
|||||||
base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
|
base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr)
|
int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, const u8 *buf, u32 size)
|
||||||
{
|
{
|
||||||
return _i2c_recv_single(i2c_idx, buf, size, dev_addr);
|
return _i2c_send_packet(i2c_idx, buf, size, dev_addr);
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
|
|
||||||
{
|
|
||||||
if (size > 32)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return _i2c_send_pkt(i2c_idx, buf, size, dev_addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
|
int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
|
||||||
{
|
{
|
||||||
return _i2c_recv_pkt(i2c_idx, buf, size, dev_addr, reg);
|
return i2c_xfer_packet(i2c_idx, buf, size, dev_addr, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size)
|
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size)
|
||||||
{
|
{
|
||||||
u8 tmp[8];
|
|
||||||
|
|
||||||
if (size > 7)
|
if (size > 7)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
u8 tmp[8];
|
||||||
tmp[0] = reg;
|
tmp[0] = reg;
|
||||||
memcpy(tmp + 1, buf, size);
|
memcpy(tmp + 1, buf, size);
|
||||||
|
|
||||||
return _i2c_send_single(i2c_idx, dev_addr, tmp, size + 1);
|
return _i2c_send_normal(i2c_idx, dev_addr, tmp, size + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
|
int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
|
||||||
{
|
{
|
||||||
int res = _i2c_send_single(i2c_idx, dev_addr, (u8 *)®, 1);
|
int res = _i2c_send_normal(i2c_idx, dev_addr, (u8 *)®, 1);
|
||||||
if (res)
|
if (res)
|
||||||
res = _i2c_recv_single(i2c_idx, buf, size, dev_addr);
|
res = _i2c_recv_normal(i2c_idx, buf, size, dev_addr);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2020 CTCaer
|
* Copyright (c) 2020-2026 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
#define I2C_6 5
|
#define I2C_6 5
|
||||||
|
|
||||||
void i2c_init(u32 i2c_idx);
|
void i2c_init(u32 i2c_idx);
|
||||||
int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr);
|
int i2c_xfer_packet(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg);
|
||||||
int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size);
|
int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, const u8 *buf, u32 size);
|
||||||
int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
|
int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
|
||||||
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size);
|
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size);
|
||||||
int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
|
int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
|
||||||
|
|||||||
Reference in New Issue
Block a user