From fe7d7df29bdc7b12c2c1b775ecad03f648c39e4a Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Mon, 20 May 2019 22:21:10 -0500 Subject: [PATCH] Initial SMBus driver for Nuvoton NCT6793D Super IO chip used on Prime Z270-A (and other Intel boards) --- OpenAuraSDK/OpenAuraSDK.cpp | 6 + OpenAuraSDK/OpenAuraSDK.vcxproj | 12 +- OpenAuraSDK/OpenAuraSDK.vcxproj.filters | 6 + OpenAuraSDK/Resource.rc | Bin 12192 -> 12170 bytes OpenAuraSDK/i2c_smbus_nuvoton_nct6793d.cpp | 171 +++++++++++++++++++++ OpenAuraSDK/i2c_smbus_nuvoton_nct6793d.h | 52 +++++++ 6 files changed, 242 insertions(+), 5 deletions(-) create mode 100644 OpenAuraSDK/i2c_smbus_nuvoton_nct6793d.cpp create mode 100644 OpenAuraSDK/i2c_smbus_nuvoton_nct6793d.h diff --git a/OpenAuraSDK/OpenAuraSDK.cpp b/OpenAuraSDK/OpenAuraSDK.cpp index 6305c391..10f8dc48 100644 --- a/OpenAuraSDK/OpenAuraSDK.cpp +++ b/OpenAuraSDK/OpenAuraSDK.cpp @@ -20,6 +20,7 @@ #include "I2CDetectDialog.h" #include "i2c_smbus_piix4.h" #include "i2c_smbus_i801.h" +#include "i2c_smbus_nuvoton_nct6793d.h" #include "wmi.h" #else /* WIN32 */ @@ -62,6 +63,11 @@ void DetectI2CBusses() return; } + //bus = new i2c_smbus_nuvoton_nct6793d(); + //strcpy(bus->device_name, "Nuvoton NCT6793D"); + //((i2c_smbus_nuvoton_nct6793d *)bus)->nuvoton_nct6793d_smba = 0x02C0; + //busses.push_back(bus); + // For each detected SMBus adapter, try enumerating it as either AMD or Intel for (QueryObj &i : q_res_PnPSignedDriver) { diff --git a/OpenAuraSDK/OpenAuraSDK.vcxproj b/OpenAuraSDK/OpenAuraSDK.vcxproj index f03cd865..9922f313 100644 --- a/OpenAuraSDK/OpenAuraSDK.vcxproj +++ b/OpenAuraSDK/OpenAuraSDK.vcxproj @@ -23,20 +23,20 @@ {6D22BFF3-C1DF-407A-8816-05D63919A991} Win32Proj OpenAuraSDK - 10.0.17134.0 + 10.0 Application true - v141 + v142 Unicode Dynamic Application false - v141 + v142 true Unicode Dynamic @@ -44,14 +44,14 @@ Application true - v141 + v142 Unicode Dynamic Application false - v141 + v142 true Unicode Dynamic @@ -181,6 +181,7 @@ + @@ -193,6 +194,7 @@ + diff --git a/OpenAuraSDK/OpenAuraSDK.vcxproj.filters b/OpenAuraSDK/OpenAuraSDK.vcxproj.filters index 4026b777..34e09051 100644 --- a/OpenAuraSDK/OpenAuraSDK.vcxproj.filters +++ b/OpenAuraSDK/OpenAuraSDK.vcxproj.filters @@ -42,6 +42,9 @@ Header Files + + Header Files + @@ -71,6 +74,9 @@ Source Files + + Source Files + diff --git a/OpenAuraSDK/Resource.rc b/OpenAuraSDK/Resource.rc index 9e8df40a8a4174b25102c9928bfa415e6c41c6a4..4b9f39fbdc0e84ce623ba1044adce76622db48ad 100644 GIT binary patch delta 24 gcmZ1w-xa?hg=?|{ztvotaaUD_t0C0>5n*aa+ delta 28 jcmeB*Ul6|`g^S;r!HFT5A)X +#include "inpout32.h" + +#pragma comment(lib, "inpout32.lib") + +s32 i2c_smbus_nuvoton_nct6793d::nct6793d_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data) +{ + int i, len, status, cnt; + + Out32(SMBHSTCTL, NCT6793D_SOFT_RESET); + + switch (size) + { + case I2C_SMBUS_QUICK: + Out32(SMBHSTADD, (addr << 1) | read_write); + break; + case I2C_SMBUS_BYTE: + case I2C_SMBUS_BYTE_DATA: + Out32(SMBHSTADD, (addr << 1) | read_write); + Out32(SMBHSTIDX, command); + if (read_write == I2C_SMBUS_WRITE) + { + Out32(SMBHSTDAT, data->byte); + Out32(SMBHSTCMD, NCT6793D_WRITE_BYTE); + } + else + { + Out32(SMBHSTCMD, NCT6793D_READ_BYTE); + } + break; + case I2C_SMBUS_WORD_DATA: + Out32(SMBHSTADD, (addr << 1) | read_write); + Out32(SMBHSTIDX, command); + if (read_write == I2C_SMBUS_WRITE) + { + Out32(SMBHSTDAT, data->word & 0xFF); + Out32(SMBHSTDAT, (data->word & 0xFF00) >> 8); + Out32(SMBHSTCMD, NCT6793D_WRITE_WORD); + } + else + { + Out32(SMBHSTCMD, NCT6793D_READ_WORD); + } + break; + case I2C_SMBUS_BLOCK_DATA: + Out32(SMBHSTADD, (addr << 1) | read_write); + Out32(SMBHSTIDX, command); + if (read_write == I2C_SMBUS_WRITE) + { + len = data->block[0]; + if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) + { + return -EINVAL; + } + Out32(SMBBLKSZ, len); + + //Load 4 bytes into FIFO + cnt = 1; + if (len >= 4) + { + for (i = cnt; i <= 4; i++) + { + Out32(SMBHSTDAT, data->block[i]); + } + + len -= 4; + cnt += 4; + } + else + { + for (i = cnt; i <= len; i++) + { + Out32(SMBHSTDAT, data->block[i]); + } + + len = 0; + } + + Out32(SMBHSTCMD, NCT6793D_WRITE_BLOCK); + } + else + { + Out32(SMBHSTCMD, NCT6793D_READ_BLOCK); + } + break; + default: + return -EOPNOTSUPP; + } + + Out32(SMBHSTCTL, NCT6793D_MANUAL_START); + + while ((size == I2C_SMBUS_BLOCK_DATA) && (len > 0)) + { + if (read_write == I2C_SMBUS_WRITE) + { + while ((Inp32(SMBHSTSTS) & NCT6793D_FIFO_EMPTY) == 0); + + //Load more bytes into FIFO + if (len >= 4) + { + for (i = cnt; i <= 4; i++) + { + Out32(SMBHSTDAT, data->block[i]); + } + + len -= 4; + cnt += 4; + } + else + { + for (i = cnt; i <= len; i++) + { + Out32(SMBHSTDAT, data->block[i]); + } + + len = 0; + } + } + } + + //wait for manual mode to complete + while ((Inp32(SMBHSTSTS) & NCT6793D_MANUAL_ACTIVE) != 0); + + if ((Inp32(SMBHSTERR) & NCT6793D_NO_ACK) != 0) + { + return -EPROTO; + } + else if ((read_write == I2C_SMBUS_WRITE) || (size == I2C_SMBUS_QUICK)) + { + return 0; + } + + switch (size) + { + case I2C_SMBUS_QUICK: + case I2C_SMBUS_BYTE_DATA: + data->byte = (u8)Inp32(SMBHSTDAT); + break; + case I2C_SMBUS_WORD_DATA: + data->word = Inp32(SMBHSTDAT) + (Inp32(SMBHSTDAT) << 8); + break; + case I2C_SMBUS_BLOCK_DATA: + data->block[0] = (u8)Inp32(SMBHSTDAT); + if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX) + { + return -EPROTO; + } + Inp32(SMBBLKSZ); + for (i = 1; i <= data->block[0]; i++) + { + data->block[i] = (u8)Inp32(SMBHSTDAT); + } + break; + } + + return 0; +} + +s32 i2c_smbus_nuvoton_nct6793d::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) +{ + return nct6793d_access(addr, read_write, command, size, data); +} \ No newline at end of file diff --git a/OpenAuraSDK/i2c_smbus_nuvoton_nct6793d.h b/OpenAuraSDK/i2c_smbus_nuvoton_nct6793d.h new file mode 100644 index 00000000..c0ddbe55 --- /dev/null +++ b/OpenAuraSDK/i2c_smbus_nuvoton_nct6793d.h @@ -0,0 +1,52 @@ +/*-----------------------------------------*\ +| i2c_smbus_nuvoton_nct6793d.h | +| | +| Nuvoton NCT6793D SMBUS driver for Windows| +| | +| Adam Honse (CalcProgrammer1) 5/19/2019 | +\*-----------------------------------------*/ + +#include "i2c_smbus.h" + +#pragma once + +#define SMBHSTDAT (0 + nuvoton_nct6793d_smba) +#define SMBBLKSZ (1 + nuvoton_nct6793d_smba) +#define SMBHSTCMD (2 + nuvoton_nct6793d_smba) +#define SMBHSTIDX (3 + nuvoton_nct6793d_smba) //Index field is the Command field on other controllers +#define SMBHSTCTL (4 + nuvoton_nct6793d_smba) +#define SMBHSTADD (5 + nuvoton_nct6793d_smba) +#define SMBHSTERR (9 + nuvoton_nct6793d_smba) +#define SMBHSTSTS (0xE + nuvoton_nct6793d_smba) + +/* Command register */ +#define NCT6793D_READ_BYTE 0 +#define NCT6793D_READ_WORD 1 +#define NCT6793D_READ_BLOCK 2 +#define NCT6793D_BLOCK_WRITE_READ_PROC_CALL 3 +#define NCT6793D_PROC_CALL 4 +#define NCT6793D_WRITE_BYTE 8 +#define NCT6793D_WRITE_WORD 9 +#define NCT6793D_WRITE_BLOCK 10 + +/* Control register */ +#define NCT6793D_MANUAL_START 128 +#define NCT6793D_SOFT_RESET 64 + +/* Error register */ +#define NCT6793D_NO_ACK 32 + +/* Status register */ +#define NCT6793D_MANUAL_ACTIVE 4 +#define NCT6793D_FIFO_EMPTY 1 + +class i2c_smbus_nuvoton_nct6793d : public i2c_smbus_interface +{ +public: + u16 nuvoton_nct6793d_smba = 0x0290; + +private: + s32 nct6793d_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data); + s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); + +}; \ No newline at end of file