400 lines
9.6 KiB
C
400 lines
9.6 KiB
C
#include "include.h"
|
|
|
|
#define TRACE_EN 0
|
|
|
|
#if TRACE_EN
|
|
#define TRACE(...) printf(__VA_ARGS__)
|
|
#define TRACE_K(...) printk(__VA_ARGS__)
|
|
#else
|
|
#define TRACE(...)
|
|
#define TRACE_K(...)
|
|
#endif
|
|
|
|
#if I2C_SW_EN
|
|
//AT(.text.bsp.i2c)
|
|
//static void bsp_i2c_delay(void)
|
|
//{
|
|
// u8 delay = 60;
|
|
// while (delay--) {
|
|
// asm("nop");
|
|
// }
|
|
//}
|
|
#define bsp_i2c_delay() delay_us(5)
|
|
|
|
//ACK: The transmitter releases the SDA line (HIGH->LOW) during the acknowledge clock pulse
|
|
AT(.text.bsp.i2c)
|
|
void bsp_i2c_tx_ack(void)
|
|
{
|
|
I2C_SDA_OUT();
|
|
I2C_SDA_L();
|
|
bsp_i2c_delay();
|
|
I2C_SCL_H();
|
|
bsp_i2c_delay();
|
|
I2C_SCL_L();
|
|
}
|
|
|
|
AT(.text.bsp.i2c)
|
|
bool bsp_i2c_rx_ack(void)
|
|
{
|
|
bool ret = false;
|
|
I2C_SDA_IN();
|
|
bsp_i2c_delay();
|
|
I2C_SCL_H();
|
|
bsp_i2c_delay();
|
|
if (!I2C_SDA_IS_H()) {
|
|
ret = true;
|
|
}
|
|
I2C_SCL_L();
|
|
return ret;
|
|
}
|
|
|
|
//NACK: The transmitter holds the SDA line (keep HIGH) during the acknowledge clock pulse
|
|
AT(.text.bsp.i2c)
|
|
void bsp_i2c_tx_nack(void)
|
|
{
|
|
I2C_SDA_OUT();
|
|
I2C_SDA_H();
|
|
bsp_i2c_delay();
|
|
I2C_SCL_H();
|
|
bsp_i2c_delay();
|
|
I2C_SCL_L();
|
|
}
|
|
|
|
//START: A HIGH to LOW transition on the SDA line while SCL is HIGH is one such unique case.
|
|
AT(.text.bsp.i2c)
|
|
void bsp_i2c_start(void)
|
|
{
|
|
I2C_SDA_SCL_OUT();
|
|
I2C_SDA_SCL_H();
|
|
bsp_i2c_delay();
|
|
I2C_SDA_L();
|
|
bsp_i2c_delay();
|
|
I2C_SCL_L();
|
|
}
|
|
|
|
//STOP: A LOW to HIGH transition on the SDA line while SCL is HIGH
|
|
AT(.text.bsp.i2c)
|
|
void bsp_i2c_stop(void)
|
|
{
|
|
I2C_SDA_OUT();
|
|
I2C_SDA_L();
|
|
bsp_i2c_delay();
|
|
I2C_SCL_H();
|
|
bsp_i2c_delay();
|
|
I2C_SDA_H();
|
|
}
|
|
|
|
//tx 1byte
|
|
AT(.text.bsp.i2c)
|
|
void bsp_i2c_tx_byte(uint8_t dat)
|
|
{
|
|
u8 i;
|
|
I2C_SDA_OUT();
|
|
for (i=0; i<8; i++) {
|
|
if (dat & BIT(7)) {
|
|
I2C_SDA_H();
|
|
} else {
|
|
I2C_SDA_L();
|
|
}
|
|
bsp_i2c_delay();
|
|
I2C_SCL_H();
|
|
bsp_i2c_delay();
|
|
I2C_SCL_L();
|
|
dat <<= 1;
|
|
}
|
|
}
|
|
|
|
//rx 1byte
|
|
AT(.text.bsp.i2c)
|
|
uint8_t bsp_i2c_rx_byte(void)
|
|
{
|
|
u8 i, dat = 0;
|
|
I2C_SDA_IN();
|
|
for (i=0; i<8; i++) {
|
|
bsp_i2c_delay();
|
|
I2C_SCL_H();
|
|
bsp_i2c_delay();
|
|
dat <<= 1;
|
|
if (I2C_SDA_IS_H()) {
|
|
dat |= BIT(0);
|
|
}
|
|
I2C_SCL_L();
|
|
}
|
|
return dat;
|
|
}
|
|
#endif //I2C_SW_EN
|
|
|
|
#if I2C_HW_EN
|
|
|
|
#if CHIP_PACKAGE_QFN40
|
|
static i2c_t __IIC0 = {
|
|
.sfr = (i2c_sfr_t *)&IIC0CON0,
|
|
.map = (i2c_map_t *)&FUNCMCON2,
|
|
};
|
|
i2c_t *HW_IIC = &__IIC0;
|
|
#else
|
|
#if (CHIP_PACKAGE_SELECT == CHIP_5682C)
|
|
static i2c_t __IIC0 = {
|
|
.sfr = (i2c_sfr_t *)&IIC0CON0,
|
|
.map = (i2c_map_t *)&FUNCMCON2,
|
|
};
|
|
i2c_t *HW_IIC = &__IIC0;
|
|
#else
|
|
static i2c_t __IIC1 = {
|
|
.sfr = (i2c_sfr_t *)&IIC1CON0,
|
|
.map = (i2c_map_t *)&FUNCMCON2,
|
|
};
|
|
i2c_t *HW_IIC = &__IIC1;
|
|
#endif
|
|
#endif
|
|
|
|
void bsp_i2c0_lock(void)
|
|
{
|
|
os_i2c0_lock(100);
|
|
}
|
|
|
|
void bsp_i2c0_unlock(void)
|
|
{
|
|
os_i2c0_unlock();
|
|
}
|
|
|
|
AT(.com_text.str)
|
|
char str_tmp[] = ">>>bsp_i2c_isr\n";
|
|
|
|
AT(.com_text.isr.i2c)
|
|
void bsp_i2c_isr(void)
|
|
{
|
|
if (HW_IIC->sfr->IICxCON0 & BIT(31)) {
|
|
HW_IIC->sfr->IICxCON0 |= BIT(29); // clear pending
|
|
HW_IIC->sfr->IICxCON0 &= ~BIT(1); // disable irq
|
|
|
|
HW_IIC->sfr->IICxDMACNT = 0; // Disable DMA
|
|
// printf(str_tmp);
|
|
}
|
|
}
|
|
|
|
static u32 bsp_hw_i2c_config(u32 i2c_cfg, u16 dev_addr, u16 reg_addr, u32 dat)
|
|
{
|
|
TRACE("%s: cfg=%X dev=%X reg=%X\n", __FUNCTION__, i2c_cfg, dev_addr, reg_addr);
|
|
|
|
HW_IIC->sfr->IICxCMDA = (u8)dev_addr | ((u32)(dev_addr >> 8)) << 24 |
|
|
(u32)((u8)reg_addr) << 8 | (u32)((u8)(reg_addr >> 8)) << 16;
|
|
|
|
HW_IIC->sfr->IICxCON1 = i2c_cfg;
|
|
HW_IIC->sfr->IICxDATA = dat;
|
|
HW_IIC->sfr->IICxCON0 |= BIT(28); // kick
|
|
|
|
u32 ticks = tick_get();
|
|
while ((!(HW_IIC->sfr->IICxCON0 & BIT(31)))) {
|
|
if (tick_check_expire(ticks, 20)) {
|
|
TRACE("IIC ERROR[%x %x %x %x]\n", i2c_cfg, dev_addr, reg_addr, dat);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
HW_IIC->sfr->IICxCON0 |= BIT(29);
|
|
|
|
if (i2c_cfg & RDATA) {
|
|
return HW_IIC->sfr->IICxDATA;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void bsp_hw_i2c_tx_byte(u32 i2c_cfg, u16 dev_addr, u16 reg_addr, u32 data)
|
|
{
|
|
bsp_i2c0_lock();
|
|
bsp_hw_i2c_config(i2c_cfg, dev_addr, reg_addr, data);
|
|
bsp_i2c0_unlock();
|
|
}
|
|
|
|
void bsp_hw_i2c_tx_buf(u32 i2c_cfg, u16 dev_addr, u16 reg_addr, u8 *buf, u16 len)
|
|
{
|
|
int i;
|
|
u32 cfg;
|
|
if (buf == NULL || len == 0) {
|
|
return;
|
|
}
|
|
|
|
bsp_i2c0_lock();
|
|
|
|
for (i = 0; i < len; i++) {
|
|
cfg = WDATA;
|
|
if (i == 0) { //收第1byte
|
|
cfg |= i2c_cfg;
|
|
}
|
|
if (i == (len - 1)) { //收最后1byte
|
|
cfg |= STOP_FLAG;
|
|
}
|
|
bsp_hw_i2c_config(cfg | DATA_CNT_1B, dev_addr, reg_addr, buf[i]);
|
|
}
|
|
|
|
bsp_i2c0_unlock();
|
|
}
|
|
|
|
void bsp_hw_i2c_rx_buf(u32 i2c_cfg, u16 dev_addr, u16 reg_addr, u8 *buf, u16 len)
|
|
{
|
|
int i;
|
|
u32 cfg;
|
|
if (buf == NULL || len == 0) {
|
|
return;
|
|
}
|
|
|
|
bsp_i2c0_lock();
|
|
|
|
for (i = 0; i < len; i++) {
|
|
cfg = RDATA;
|
|
if (i == 0) { //收第1byte
|
|
cfg |= i2c_cfg;
|
|
}
|
|
if (i == (len - 1)) { //收最后1byte
|
|
cfg |= STOP_FLAG | NACK;
|
|
}
|
|
buf[i] = bsp_hw_i2c_config(cfg | DATA_CNT_1B, dev_addr, reg_addr, 0);
|
|
}
|
|
|
|
bsp_i2c0_unlock();
|
|
}
|
|
|
|
void i2c_init(void)
|
|
{
|
|
#if CHIP_PACKAGE_QFN40
|
|
CLKCON1 |= BIT(7); // x26m_clkdiv8
|
|
CLKGAT2 |= BIT(0); // en iic0 clk
|
|
RSTCON0 |= BIT(3); // Release IIC0
|
|
#else
|
|
#if (CHIP_PACKAGE_SELECT == CHIP_5682C)
|
|
CLKCON1 |= BIT(7); // x26m_clkdiv8
|
|
CLKGAT2 |= BIT(0); // en iic0 clk
|
|
RSTCON0 |= BIT(3); // Release IIC0
|
|
#else
|
|
CLKCON1 |= BIT(8); // x26m_clkdiv8
|
|
CLKGAT2 |= BIT(1); // en iic1 clk
|
|
RSTCON0 |= BIT(7); // Release IIC1
|
|
#endif
|
|
#endif
|
|
|
|
#if CHIP_PACKAGE_QFN40
|
|
GPIOEDIR |= BIT(4) | BIT(5); // SCL SDA
|
|
GPIOEPU |= BIT(4) | BIT(5);
|
|
GPIOEDE |= BIT(4) | BIT(5);
|
|
GPIOEFEN |= BIT(4) | BIT(5);
|
|
#else
|
|
GPIOBDIR |= BIT(2) | BIT(1); // SCL SDA
|
|
GPIOBPU |= BIT(2) | BIT(1);
|
|
GPIOBDE |= BIT(2) | BIT(1);
|
|
GPIOBFEN |= BIT(2) | BIT(1);
|
|
#endif
|
|
|
|
#if CHIP_PACKAGE_QFN40
|
|
HW_IIC->map->FUNCMCONx = (0xf << 8);
|
|
HW_IIC->map->FUNCMCONx = (4 << 8);
|
|
#else
|
|
#if (CHIP_PACKAGE_SELECT == CHIP_5682C)
|
|
HW_IIC->map->FUNCMCONx = (0xf << 8);
|
|
HW_IIC->map->FUNCMCONx = (2 << 8);
|
|
#else
|
|
HW_IIC->map->FUNCMCONx = (0xf << 12);
|
|
HW_IIC->map->FUNCMCONx = (2 << 12);
|
|
#endif
|
|
#endif
|
|
|
|
HW_IIC->sfr->IICxCON0 = 1 << 0 | // IIC EN
|
|
0 << 1 | // IIC INT
|
|
0 << 2 | // IIC HOLD CNT [3:2]
|
|
20 << 4 | // IIC POSDIV [9:4]
|
|
1 << 10; // IIC WSCL_OPT
|
|
|
|
delay_5ms(8);
|
|
}
|
|
#endif
|
|
|
|
#if SECURITY_PAY_EN
|
|
static i2c_t __IIC1 = {
|
|
.sfr = (i2c_sfr_t *) &IIC1CON0,
|
|
.map = (i2c_map_t *) &FUNCMCON2,
|
|
};
|
|
|
|
i2c_t *HS_IIC = &__IIC1;
|
|
|
|
void ctp_int_isr(void);
|
|
|
|
AT(.text.bsp.i2c)
|
|
void bsp_hs_i2c_tx_buf(u16 dev_addr, u8 *buf, u16 len)
|
|
{
|
|
|
|
u32 ticks;
|
|
HS_IIC->sfr->IICxCMDA = (buf[0]<<8) | dev_addr;
|
|
|
|
HS_IIC->sfr->IICxCON1 = BIT(12) | BIT(11) | BIT(10) | BIT(5) | BIT(4) | BIT(3);
|
|
HS_IIC->sfr->IICxDMAADR = DMA_ADR(&buf[1]);
|
|
HS_IIC->sfr->IICxDMACNT = ((len - 2) << 16) | BIT(1) |BIT(0);
|
|
HS_IIC->sfr->IICxCON0 |= BIT(28); //KICK
|
|
// printf("IICxCMDA: 0x%x, IICxDMAADR: 0x%x, IICxDMACNT: 0x%x, IICxCON0: 0x%x, IICxCON1: 0x%x\n",
|
|
// HS_IIC->sfr->IICxCMDA, HS_IIC->sfr->IICxDMAADR, HS_IIC->sfr->IICxDMACNT, HS_IIC->sfr->IICxCON0, HS_IIC->sfr->IICxCON1);
|
|
ticks = tick_get();
|
|
while (!(HS_IIC->sfr->IICxCON0 & BIT(31))) {
|
|
if (tick_check_expire(ticks, 1000)) {
|
|
printf("i2c_write time out ERROR\n");
|
|
return;
|
|
}
|
|
}
|
|
HS_IIC->sfr->IICxCON0 |= BIT(29); //Clear Pending
|
|
}
|
|
|
|
AT(.text.bsp.i2c)
|
|
void bsp_hs_i2c_rx_buf(u16 dev_addr, u8 *buf, u16 len)
|
|
{
|
|
u32 ticks;
|
|
HS_IIC->sfr->IICxCMDA = dev_addr<<24;
|
|
HS_IIC->sfr->IICxCON1 = BIT(12) | BIT(11) | BIT(9) | BIT(8) | BIT(7);
|
|
HS_IIC->sfr->IICxDMAADR = DMA_ADR(buf);
|
|
HS_IIC->sfr->IICxDMACNT = ((len - 1) << 16) | BIT(0);
|
|
HS_IIC->sfr->IICxCON0 |= BIT(28); //KICK
|
|
|
|
ticks = tick_get();
|
|
while (!(HS_IIC->sfr->IICxCON0 & BIT(31))) {
|
|
if (tick_check_expire(ticks, 2000)) {
|
|
printf("alipay_i2c_read time out ERROR\n");
|
|
return;
|
|
}
|
|
}
|
|
HS_IIC->sfr->IICxCON0 |= BIT(29); //Clear Pending
|
|
}
|
|
|
|
AT(.text.bsp.i2c)
|
|
void bsp_hs_i2c_rx_byte(u16 dev_addr, u8 *buf)
|
|
{
|
|
u32 ticks;
|
|
HS_IIC->sfr->IICxCMDA = dev_addr<<24;
|
|
HS_IIC->sfr->IICxCON1 = BIT(12) | BIT(11) | BIT(9) | BIT(8) | BIT(7);
|
|
HS_IIC->sfr->IICxDMAADR = DMA_ADR(buf);
|
|
HS_IIC->sfr->IICxDMACNT = BIT(0);
|
|
HS_IIC->sfr->IICxCON0 |= BIT(28); //KICK
|
|
|
|
ticks = tick_get();
|
|
while (!(HS_IIC->sfr->IICxCON0 & BIT(31))) {
|
|
if (tick_check_expire(ticks, 50)) {
|
|
printf("alipay_i2c_read time out ERROR\n");
|
|
return;
|
|
}
|
|
}
|
|
HS_IIC->sfr->IICxCON0 |= BIT(29); //Clear Pending
|
|
}
|
|
#endif // SECURITY_PAY_EN
|
|
|
|
AT(.text.bsp.i2c)
|
|
void bsp_i2c_init(void)
|
|
{
|
|
#if I2C_SW_EN
|
|
I2C_SDA_SCL_OUT();
|
|
I2C_SDA_H();
|
|
delay_5ms(2);
|
|
#endif
|
|
|
|
#if I2C_HW_EN
|
|
i2c_init();
|
|
sys_irq_init(IRQ_I2C_VECTOR, 0, bsp_i2c_isr);
|
|
#endif
|
|
}
|