376 lines
8.5 KiB
C
376 lines
8.5 KiB
C
#include "sitronix_ts_custom_func.h"
|
|
#include "sitronix_ts.h"
|
|
|
|
static DEFINE_MUTEX(i2c_rw_mutex);
|
|
|
|
s32 stx_i2c_write(struct i2c_client *client, u8 *buf, int len)
|
|
{
|
|
s32 ret;
|
|
|
|
struct i2c_msg msg = {
|
|
.flags = 0,
|
|
#ifdef CONFIG_MTK_I2C_EXTENSION
|
|
.addr = (client->addr & I2C_MASK_FLAG) |
|
|
(I2C_ENEXT_FLAG), /*remain*/
|
|
.timing = I2C_MASTER_CLOCK,
|
|
#else
|
|
.addr = client->addr, /*remain*/
|
|
#endif
|
|
.len = len,
|
|
.buf = buf,
|
|
};
|
|
mutex_lock(&i2c_rw_mutex);
|
|
ret = i2c_transfer(client->adapter, &msg, 1);
|
|
if (ret < 0) {
|
|
STX_ERROR("Sitronix I2C error in tpd_i2c_write, ret = %d", ret);
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
return ret;
|
|
}
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
return ret;
|
|
}
|
|
|
|
int stx_i2c_read(struct i2c_client *client, u8 *buffer, int len, u8 addr)
|
|
{
|
|
int ret;
|
|
u8 txbuf = addr;
|
|
|
|
struct i2c_msg msgs[2] = {
|
|
{
|
|
#ifdef CONFIG_MTK_I2C_EXTENSION
|
|
.addr = ((client->addr & I2C_MASK_FLAG) |
|
|
(I2C_ENEXT_FLAG)),
|
|
.timing = I2C_MASTER_CLOCK,
|
|
#else
|
|
.addr = client->addr,
|
|
#endif
|
|
.flags = 0,
|
|
.buf = &txbuf,
|
|
.len = 1,
|
|
},
|
|
{
|
|
#ifdef CONFIG_MTK_I2C_EXTENSION
|
|
.addr = ((client->addr & I2C_MASK_FLAG) |
|
|
(I2C_ENEXT_FLAG)),
|
|
.timing = I2C_MASTER_CLOCK,
|
|
#else
|
|
.addr = client->addr,
|
|
#endif
|
|
.flags = I2C_M_RD,
|
|
|
|
.len = len,
|
|
.buf = buffer,
|
|
},
|
|
};
|
|
mutex_lock(&i2c_rw_mutex);
|
|
ret = i2c_transfer(client->adapter, msgs, 2);
|
|
if (ret < 0) {
|
|
STX_ERROR("Sitronix I2C error in tpd_i2c_read, ret = %d", ret);
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
return ret;
|
|
}
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
return len;
|
|
}
|
|
|
|
int stx_i2c_read_direct(st_u8 *rxbuf, int len)
|
|
{
|
|
int ret = 0;
|
|
|
|
mutex_lock(&i2c_rw_mutex);
|
|
ret = i2c_master_recv(stx_gpts.client, rxbuf, len);
|
|
if (ret < 0) {
|
|
STX_ERROR("read direct error (%d)", ret);
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
return ret;
|
|
}
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
udelay(50);
|
|
return len;
|
|
}
|
|
|
|
int stx_i2c_read_bytes(st_u8 addr, st_u8 *rxbuf, int len)
|
|
{
|
|
int ret = 0;
|
|
st_u8 txbuf = addr;
|
|
|
|
mutex_lock(&i2c_rw_mutex);
|
|
ret = i2c_master_send(stx_gpts.client, &txbuf, 1);
|
|
if (ret < 0) {
|
|
STX_ERROR("stx_i2c_read_bytes write 0x%x error (%d)", addr,
|
|
ret);
|
|
goto unlock;
|
|
}
|
|
udelay(50);
|
|
ret = i2c_master_recv(stx_gpts.client, rxbuf, len);
|
|
if (ret < 0) {
|
|
STX_ERROR("stx_i2c_read_bytes read 0x%x error (%d)", addr, ret);
|
|
goto unlock;
|
|
}
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
udelay(50);
|
|
return len;
|
|
unlock:
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
return ret;
|
|
}
|
|
|
|
int stx_i2c_write_bytes(st_u8 *txbuf, int len)
|
|
{
|
|
int ret = 0;
|
|
if (txbuf == NULL)
|
|
return -1;
|
|
|
|
mutex_lock(&i2c_rw_mutex);
|
|
ret = i2c_master_send(stx_gpts.client, txbuf, len);
|
|
if (ret < 0) {
|
|
STX_ERROR("stx_i2c_write_bytes write 0x%x error (%d)", *txbuf,
|
|
ret);
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
return ret;
|
|
}
|
|
mutex_unlock(&i2c_rw_mutex);
|
|
udelay(50);
|
|
return len;
|
|
}
|
|
|
|
struct CommandIoPacket
|
|
{
|
|
unsigned char CmdID;
|
|
unsigned char ValidDataSize;
|
|
unsigned char CmdData[30];
|
|
};
|
|
|
|
static void STChecksumCalculation(unsigned short *pChecksum,
|
|
unsigned char *pInData, unsigned long Len)
|
|
{
|
|
unsigned long i;
|
|
unsigned char LowByteChecksum;
|
|
|
|
for (i = 0; i < Len; i++) {
|
|
*pChecksum += (unsigned short)pInData[i];
|
|
LowByteChecksum = (unsigned char)(*pChecksum & 0xFF);
|
|
LowByteChecksum = (LowByteChecksum) >> 7 | (LowByteChecksum)
|
|
<< 1;
|
|
*pChecksum = (*pChecksum & 0xFF00) | LowByteChecksum;
|
|
}
|
|
}
|
|
|
|
static bool stx_SetH2DReady(void)
|
|
{
|
|
int ret;
|
|
bool bRet = false;
|
|
unsigned char buf[2];
|
|
|
|
buf[0] = 0xF8;
|
|
buf[1] = 0x01;
|
|
ret = stx_i2c_write_bytes(buf, 2);
|
|
if (ret <= 0) {
|
|
STX_ERROR("stx_SetH2DReady: write ready error.");
|
|
bRet = false;
|
|
} else {
|
|
bRet = true;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
static bool stx_GetH2DReady(void)
|
|
{
|
|
bool bRet = false;
|
|
unsigned char tmp = 0xff;
|
|
int ret, retry = 0;
|
|
|
|
do {
|
|
msleep(1);
|
|
ret = stx_i2c_read_bytes(0xF8, &tmp, 1);
|
|
if (ret <= 0) {
|
|
STX_ERROR("stx_GetH2DReady: retry(%d) read ready.",
|
|
retry++);
|
|
} else {
|
|
if (tmp == 0x01) {
|
|
STX_ERROR("retry ............");
|
|
retry = 0;
|
|
continue;
|
|
}
|
|
}
|
|
if (retry > 1000) {
|
|
STX_ERROR("stx_GetH2DReady: time out");
|
|
bRet = false;
|
|
return bRet;
|
|
}
|
|
} while (ret <= 0);
|
|
|
|
if (tmp == 0x00) { /* OK */
|
|
bRet = true;
|
|
} else if (tmp == 0x80) {
|
|
STX_ERROR("stx_ReadIOCommand: Unknown Command ID.");
|
|
bRet = false;
|
|
} else if (tmp == 0x81) {
|
|
STX_ERROR(
|
|
"stx_ReadIOCommand: Host to device command checksum error.");
|
|
bRet = false;
|
|
} else {
|
|
STX_ERROR("Unknown Error(0x%02X).", tmp);
|
|
bRet = false;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
static bool stx_ReadIOCommand(struct CommandIoPacket *packet)
|
|
{
|
|
bool bRet = false;
|
|
int ret;
|
|
unsigned char tmp[32];
|
|
/* process commmand */
|
|
memset(tmp, 0, 32);
|
|
ret = stx_i2c_read_bytes(0xD0, tmp, 32);
|
|
if (ret <= 0) {
|
|
STX_ERROR("stx_ReadIOCommand: read packet error.");
|
|
bRet = false;
|
|
} else {
|
|
memcpy((void *)packet, (const void *)tmp, 32);
|
|
bRet = true;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
static bool stx_WriteIOCommand(struct CommandIoPacket *packet)
|
|
{
|
|
bool bRet = false;
|
|
int ret;
|
|
unsigned char tmp[33];
|
|
|
|
memset(tmp, 0x00, 33);
|
|
memcpy((void *)tmp + 1, (const void *)packet, 32);
|
|
tmp[0] = 0xD0;
|
|
ret = stx_i2c_write_bytes(tmp, 33);
|
|
if (ret <= 0) {
|
|
STX_ERROR("stx_WriteIOCommand: write packet error.");
|
|
bRet = false;
|
|
} else {
|
|
bRet = true;
|
|
}
|
|
return bRet;
|
|
}
|
|
int stx_cmdio_read(int type, int address, unsigned char *buf, int len)
|
|
{
|
|
int getLen = 0, offset = 0;
|
|
struct CommandIoPacket outPacket;
|
|
struct CommandIoPacket inPacket;
|
|
int remain = len;
|
|
int pktDataSize = 0;
|
|
unsigned short chksum, vchksum;
|
|
int retry = 0;
|
|
|
|
do {
|
|
pktDataSize = (remain > 24) ? 24 : remain;
|
|
outPacket.CmdID = 0x02; /* read RAM/ROM */
|
|
outPacket.ValidDataSize = 5;
|
|
outPacket.CmdData[0] = type; /* RAM */
|
|
outPacket.CmdData[1] =
|
|
(((address + offset) >> 8) & 0xFF); /* high byte */
|
|
outPacket.CmdData[2] =
|
|
(((address + offset)) & 0xFF); /* low byte */
|
|
outPacket.CmdData[3] = pktDataSize;
|
|
chksum = 0;
|
|
STChecksumCalculation(&chksum, (unsigned char *)&outPacket, 6);
|
|
outPacket.CmdData[4] = (chksum & 0xFF);
|
|
|
|
if (!stx_WriteIOCommand(&outPacket)) {
|
|
STX_ERROR("stx_cmdio_read: (E)stx_WriteIOCommand.");
|
|
return getLen;
|
|
}
|
|
if (!stx_SetH2DReady()) {
|
|
STX_ERROR("stx_cmdio_read: (E)stx_SetH2DReady.");
|
|
return getLen;
|
|
}
|
|
if (!stx_GetH2DReady()) {
|
|
STX_ERROR("stx_cmdio_read: (E)stx_GetH2DReady.");
|
|
return getLen;
|
|
}
|
|
if (!stx_ReadIOCommand(&inPacket)) {
|
|
STX_ERROR("stx_cmdio_read: (E)stx_ReadIOCommand.");
|
|
return getLen;
|
|
}
|
|
if (inPacket.CmdID == 0x82 && inPacket.CmdData[0] == type) {
|
|
vchksum = 0;
|
|
STChecksumCalculation(&vchksum,
|
|
(unsigned char *)&inPacket,
|
|
inPacket.ValidDataSize + 1);
|
|
vchksum = (vchksum & 0xFF);
|
|
if (vchksum ==
|
|
inPacket.CmdData[inPacket.ValidDataSize - 1]) {
|
|
memcpy(buf + offset, &(inPacket.CmdData[2]),
|
|
inPacket.CmdData[1]);
|
|
remain -= inPacket.CmdData[1]; /* data size */
|
|
offset += inPacket.CmdData[1];
|
|
getLen += inPacket.CmdData[1];
|
|
} else {
|
|
/* drop packet */
|
|
STX_ERROR(
|
|
"Invalid Cheksum Expect(0x%02x) Get(0x%02X)",
|
|
vchksum,
|
|
inPacket.CmdData[inPacket.ValidDataSize -
|
|
1]);
|
|
}
|
|
retry = 0;
|
|
} else {
|
|
/* drop packet */
|
|
STX_ERROR("Unexpect CmdID (0x%02x) or Type (0x%02X)",
|
|
inPacket.CmdID, inPacket.CmdData[0]);
|
|
retry++;
|
|
if (retry > 10)
|
|
return -1;
|
|
}
|
|
} while (remain > 0);
|
|
return getLen;
|
|
}
|
|
|
|
int stx_cmdio_write(int type, int address, unsigned char *buf, int len)
|
|
{
|
|
int setLen = 0, offset = 0;
|
|
struct CommandIoPacket outPacket;
|
|
int remain = len;
|
|
int pktDataSize = 0;
|
|
unsigned short chksum; /* , vchksum; */
|
|
|
|
do {
|
|
pktDataSize = (remain > 24) ? 24 : remain;
|
|
outPacket.CmdID = 0x01; /* write RAM/ROM */
|
|
outPacket.ValidDataSize = pktDataSize + 5;
|
|
outPacket.CmdData[0] = type;
|
|
outPacket.CmdData[1] =
|
|
(((address + offset) >> 8) & 0xFF); /* high byte */
|
|
outPacket.CmdData[2] =
|
|
(((address + offset)) & 0xFF); /* low byte */
|
|
outPacket.CmdData[3] = pktDataSize;
|
|
memcpy((void *)&(outPacket.CmdData[4]),
|
|
(const void *)(buf + offset), pktDataSize);
|
|
chksum = 0;
|
|
STChecksumCalculation(&chksum, (unsigned char *)&outPacket,
|
|
outPacket.ValidDataSize + 1);
|
|
outPacket.CmdData[outPacket.ValidDataSize - 1] =
|
|
(chksum & 0xFF);
|
|
if (!stx_WriteIOCommand(&outPacket)) {
|
|
STX_ERROR("TDU_SetDeviceRam: (E)stx_WriteIOCommand.");
|
|
return setLen;
|
|
}
|
|
if (!stx_SetH2DReady()) {
|
|
STX_ERROR("TDU_SetDeviceRam: (E)stx_SetH2DReady.");
|
|
return setLen;
|
|
}
|
|
/* check processing result */
|
|
if (!stx_GetH2DReady()) {
|
|
STX_ERROR("TDU_SetDeviceRam: (E)stx_GetH2DReady.");
|
|
return setLen;
|
|
} else {
|
|
/* processing write command OK */
|
|
remain -= pktDataSize;
|
|
offset += pktDataSize;
|
|
setLen += pktDataSize;
|
|
}
|
|
|
|
} while (remain > 0);
|
|
|
|
return setLen;
|
|
} |