Add functions to i2c_smbus for pure i2c block transactions - Only implemented in Linux for now

Commit amended to rework API and change for code style by Adam Honse <calcprogrammer1@gmail.com>
This commit is contained in:
1000001101000
2021-11-17 23:24:09 -06:00
committed by Adam Honse
parent 2648923366
commit 21301660ed
6 changed files with 92 additions and 8 deletions

View File

@@ -165,7 +165,8 @@ s32 i2c_smbus_interface::i2c_smbus_xfer_call(u8 addr, char read_write, u8 comman
i2c_read_write = read_write;
i2c_command = command;
i2c_size = size;
i2c_data = data;
i2c_data_smbus = data;
smbus_xfer = true;
std::unique_lock<std::mutex> start_lock(i2c_smbus_start_mutex);
i2c_smbus_start = true;
@@ -182,6 +183,41 @@ s32 i2c_smbus_interface::i2c_smbus_xfer_call(u8 addr, char read_write, u8 comman
return(i2c_ret);
}
s32 i2c_smbus_interface::i2c_xfer_call(u8 addr, char read_write, u8 size, u8 *data)
{
i2c_smbus_xfer_mutex.lock();
i2c_addr = addr;
i2c_read_write = read_write;
i2c_size = size;
i2c_data = data;
smbus_xfer = false;
std::unique_lock<std::mutex> start_lock(i2c_smbus_start_mutex);
i2c_smbus_start = true;
i2c_smbus_start_cv.notify_all();
start_lock.unlock();
std::unique_lock<std::mutex> done_lock(i2c_smbus_done_mutex);
i2c_smbus_done_cv.wait(done_lock, [this]{ return i2c_smbus_done.load(); });
i2c_smbus_done = false;
i2c_smbus_xfer_mutex.unlock();
return(i2c_ret);
}
s32 i2c_smbus_interface::i2c_read_block(u8 addr, int size, u8* data)
{
return i2c_xfer_call(addr, I2C_SMBUS_READ, size, data);
}
s32 i2c_smbus_interface::i2c_write_block(u8 addr, int size, u8 *data)
{
return i2c_xfer_call(addr, I2C_SMBUS_WRITE, size, data);
}
void i2c_smbus_interface::i2c_smbus_thread_function()
{
while(1)
@@ -196,11 +232,18 @@ void i2c_smbus_interface::i2c_smbus_thread_function()
break;
}
i2c_ret = i2c_smbus_xfer(i2c_addr, i2c_read_write, i2c_command, i2c_size, i2c_data);
if(smbus_xfer)
{
i2c_ret = i2c_smbus_xfer(i2c_addr, i2c_read_write, i2c_command, i2c_size, i2c_data_smbus);
}
else
{
i2c_ret = i2c_xfer(i2c_addr, i2c_read_write, i2c_size, i2c_data);
}
std::unique_lock<std::mutex> done_lock(i2c_smbus_done_mutex);
i2c_smbus_done = true;
i2c_smbus_done_cv.notify_all();
done_lock.unlock();
}
}
}

View File

@@ -70,6 +70,7 @@ union i2c_smbus_data
#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
#define I2C_SMBUS_I2C_BLOCK_DATA 8
class i2c_smbus_interface
{
public:
@@ -99,10 +100,15 @@ public:
s32 i2c_smbus_read_i2c_block_data(u8 addr, u8 command, u8 length, u8 *values);
s32 i2c_smbus_write_i2c_block_data(u8 addr, u8 command, u8 length, const u8 *values);
s32 i2c_smbus_xfer_call(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
//Addtional functions added for pure I2C
s32 i2c_read_block(u8 addr, int size, u8* data);
s32 i2c_write_block(u8 addr, int size, u8* data);
s32 i2c_smbus_xfer_call(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer_call(u8 addr, char read_write, u8 size, u8 *data);
//Virtual function to be implemented by the driver
virtual s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) = 0;
virtual s32 i2c_xfer(u8 addr, char read_write, u8 size, u8* data) = 0;
private:
std::thread * i2c_smbus_thread;
@@ -122,8 +128,10 @@ private:
char i2c_read_write;
u16 i2c_command;
int i2c_size;
i2c_smbus_data* i2c_data;
i2c_smbus_data* i2c_data_smbus;
u8* i2c_data;
s32 i2c_ret;
bool smbus_xfer;
};
#endif /* I2C_SMBUS_H */

View File

@@ -12,9 +12,11 @@
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <cstring>
s32 i2c_smbus_linux::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, union i2c_smbus_data* data)
{
struct i2c_smbus_ioctl_data args;
//Tell I2C host which slave address to transfer to
@@ -28,6 +30,24 @@ s32 i2c_smbus_linux::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int si
return ioctl(handle, I2C_SMBUS, &args);
}
s32 i2c_smbus_linux::i2c_xfer(u8 addr, char read_write, u8 size, u8* data)
{
i2c_rdwr_ioctl_data rdwr;
i2c_msg msg;
msg.addr = addr;
msg.flags = read_write;
msg.len = size;
msg.buf = (u8*)malloc(size);
memcpy(&msg.buf, &data, size);
rdwr.msgs = &msg;
rdwr.nmsgs = 1;
ioctl(handle, I2C_SLAVE, addr);
return ioctl(handle, I2C_RDWR, &rdwr);
}
#include "Detector.h"
#include <fcntl.h>
#include <unistd.h>

View File

@@ -16,4 +16,5 @@ public:
private:
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer(u8 addr, char read_write, u8 size, u8* data);
};

View File

@@ -20,7 +20,7 @@ s32 i2c_smbus_nvapi::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int mo
NV_I2C_INFO_V3 i2c_data;
uint8_t data_buf[I2C_SMBUS_BLOCK_MAX];
uint8_t chip_addr;
// Set up chip register address to command, one byte in length
chip_addr = command;
i2c_data.i2c_reg_address = &chip_addr;
@@ -114,10 +114,20 @@ s32 i2c_smbus_nvapi::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int mo
break;
}
}
return(ret);
}
s32 i2c_smbus_nvapi::i2c_read_block_data(u8 addr, u8 length, u8 *values)
{
return i2c_smbus_read_i2c_block_data(addr, NULL, length, values);
}
s32 i2c_smbus_nvapi::i2c_write_block_data(u8 addr, u8 length, u8 *values)
{
return i2c_smbus_write_i2c_block_data(addr, NULL, length, values);
}
#include "Detector.h"
bool i2c_smbus_nvapi_detect()

View File

@@ -16,6 +16,8 @@ class i2c_smbus_nvapi : public i2c_smbus_interface
{
public:
i2c_smbus_nvapi(NV_PHYSICAL_GPU_HANDLE handle);
s32 i2c_read_block_data(u8 addr, u8 length, u8 *values);
s32 i2c_write_block_data(u8 addr, u8 length, u8 *values);
private:
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int mode, i2c_smbus_data* data);