From 21301660ede7e1b62abf6417178f29946ddc9cd9 Mon Sep 17 00:00:00 2001 From: 1000001101000 <1000001101000> Date: Wed, 17 Nov 2021 23:24:09 -0600 Subject: [PATCH] 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 --- i2c_smbus/i2c_smbus.cpp | 49 ++++++++++++++++++++++++++++++++--- i2c_smbus/i2c_smbus.h | 14 +++++++--- i2c_smbus/i2c_smbus_linux.cpp | 20 ++++++++++++++ i2c_smbus/i2c_smbus_linux.h | 1 + i2c_smbus/i2c_smbus_nvapi.cpp | 14 ++++++++-- i2c_smbus/i2c_smbus_nvapi.h | 2 ++ 6 files changed, 92 insertions(+), 8 deletions(-) diff --git a/i2c_smbus/i2c_smbus.cpp b/i2c_smbus/i2c_smbus.cpp index e747180dc..d52c78c8a 100644 --- a/i2c_smbus/i2c_smbus.cpp +++ b/i2c_smbus/i2c_smbus.cpp @@ -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 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 start_lock(i2c_smbus_start_mutex); + i2c_smbus_start = true; + i2c_smbus_start_cv.notify_all(); + start_lock.unlock(); + + std::unique_lock 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 done_lock(i2c_smbus_done_mutex); i2c_smbus_done = true; i2c_smbus_done_cv.notify_all(); done_lock.unlock(); } -} +} \ No newline at end of file diff --git a/i2c_smbus/i2c_smbus.h b/i2c_smbus/i2c_smbus.h index 0fecc950d..17dca33d9 100644 --- a/i2c_smbus/i2c_smbus.h +++ b/i2c_smbus/i2c_smbus.h @@ -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 */ diff --git a/i2c_smbus/i2c_smbus_linux.cpp b/i2c_smbus/i2c_smbus_linux.cpp index 95658050a..3d6d99399 100644 --- a/i2c_smbus/i2c_smbus_linux.cpp +++ b/i2c_smbus/i2c_smbus_linux.cpp @@ -12,9 +12,11 @@ #include #include #include +#include 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 #include diff --git a/i2c_smbus/i2c_smbus_linux.h b/i2c_smbus/i2c_smbus_linux.h index 939886ab4..0472f2a41 100644 --- a/i2c_smbus/i2c_smbus_linux.h +++ b/i2c_smbus/i2c_smbus_linux.h @@ -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); }; diff --git a/i2c_smbus/i2c_smbus_nvapi.cpp b/i2c_smbus/i2c_smbus_nvapi.cpp index 363e2ffed..0d79c0a8e 100644 --- a/i2c_smbus/i2c_smbus_nvapi.cpp +++ b/i2c_smbus/i2c_smbus_nvapi.cpp @@ -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() diff --git a/i2c_smbus/i2c_smbus_nvapi.h b/i2c_smbus/i2c_smbus_nvapi.h index 0f6b84489..9565c31b9 100644 --- a/i2c_smbus/i2c_smbus_nvapi.h +++ b/i2c_smbus/i2c_smbus_nvapi.h @@ -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);