Publish curated LumaOps source from c85ee9ef8f1454f5c305398902afbb9e6738de40
Managed validation / full (push) Failing after 8s
Managed validation / full (push) Failing after 8s
This commit is contained in:
1 parent
91f8b3e3c1
commit
def7920856
2271 files changed
+501225
-501178
No files matched your search
+542
-542
File diff suppressed because it is too large.
Load diff
+104
-104
@@ -1,104 +1,104 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_i801.h |
|
||||
| |
|
||||
| i801 SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 29 Jan 2019 |
|
||||
| Portions based on Linux source code |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "i2c_smbus.h"
|
||||
|
||||
/* BIT shifting macro */
|
||||
#define BIT(x) ( 1 << x )
|
||||
|
||||
/* I801 SMBus address offsets */
|
||||
#define SMBHSTSTS (0 + i801_smba)
|
||||
#define SMBHSTCNT (2 + i801_smba)
|
||||
#define SMBHSTCMD (3 + i801_smba)
|
||||
#define SMBHSTADD (4 + i801_smba)
|
||||
#define SMBHSTDAT0 (5 + i801_smba)
|
||||
#define SMBHSTDAT1 (6 + i801_smba)
|
||||
#define SMBBLKDAT (7 + i801_smba)
|
||||
#define SMBPEC (8 + i801_smba) /* ICH3 and later */
|
||||
#define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */
|
||||
#define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */
|
||||
#define SMBSLVSTS (16 + i801_smba) /* ICH3 and later */
|
||||
#define SMBSLVCMD (17 + i801_smba) /* ICH3 and later */
|
||||
#define SMBNTFDADD (20 + i801_smba) /* ICH3 and later */
|
||||
|
||||
|
||||
/* Auxiliary status register bits, ICH4+ only */
|
||||
#define SMBAUXSTS_CRCE BIT(0)
|
||||
#define SMBAUXSTS_STCO BIT(1)
|
||||
|
||||
/* Auxiliary control register bits, ICH4+ only */
|
||||
#define SMBAUXCTL_CRC BIT(0)
|
||||
#define SMBAUXCTL_E32B BIT(1)
|
||||
|
||||
/* Other settings */
|
||||
#define MAX_RETRIES 400
|
||||
|
||||
/* I801 command constants */
|
||||
#define I801_QUICK 0x00
|
||||
#define I801_BYTE 0x04
|
||||
#define I801_BYTE_DATA 0x08
|
||||
#define I801_WORD_DATA 0x0C
|
||||
#define I801_PROC_CALL 0x10 /* unimplemented */
|
||||
#define I801_BLOCK_DATA 0x14
|
||||
#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
|
||||
|
||||
/* I801 Host Control register bits */
|
||||
#define SMBHSTCNT_INTREN BIT(0)
|
||||
#define SMBHSTCNT_KILL BIT(1)
|
||||
#define SMBHSTCNT_LAST_BYTE BIT(5)
|
||||
#define SMBHSTCNT_START BIT(6)
|
||||
#define SMBHSTCNT_PEC_EN BIT(7) /* ICH3 and later */
|
||||
|
||||
/* I801 Hosts Status register bits */
|
||||
#define SMBHSTSTS_BYTE_DONE BIT(7)
|
||||
#define SMBHSTSTS_INUSE_STS BIT(6)
|
||||
#define SMBHSTSTS_SMBALERT_STS BIT(5)
|
||||
#define SMBHSTSTS_FAILED BIT(4)
|
||||
#define SMBHSTSTS_BUS_ERR BIT(3)
|
||||
#define SMBHSTSTS_DEV_ERR BIT(2)
|
||||
#define SMBHSTSTS_INTR BIT(1)
|
||||
#define SMBHSTSTS_HOST_BUSY BIT(0)
|
||||
|
||||
/* Host Notify Status register bits */
|
||||
#define SMBSLVSTS_HST_NTFY_STS BIT(0)
|
||||
|
||||
/* Host Notify Command register bits */
|
||||
#define SMBSLVCMD_HST_NTFY_INTREN BIT(0)
|
||||
|
||||
#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR)
|
||||
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | STATUS_ERROR_FLAGS)
|
||||
|
||||
/* I801 Host Config */
|
||||
#define SMBHSTCFG 0x040
|
||||
#define SMBHSTCFG_HST_EN BIT(0)
|
||||
|
||||
class i2c_smbus_i801 : public i2c_smbus_interface
|
||||
{
|
||||
public:
|
||||
u16 i801_smba = 0xF000;
|
||||
i2c_smbus_i801();
|
||||
~i2c_smbus_i801();
|
||||
|
||||
private:
|
||||
s32 i801_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
|
||||
int i801_block_transaction(i2c_smbus_data *data, char read_write, int command, int hwpec);
|
||||
int i801_block_transaction_byte_by_byte(i2c_smbus_data *data, char read_write, int command, int hwpec);
|
||||
int i801_check_post(int status);
|
||||
int i801_check_pre();
|
||||
int i801_transaction(int xact);
|
||||
int i801_wait_byte_done();
|
||||
int i801_wait_intr();
|
||||
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, int* size, u8* data);
|
||||
};
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_i801.h |
|
||||
| |
|
||||
| i801 SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 29 Jan 2019 |
|
||||
| Portions based on Linux source code |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "i2c_smbus.h"
|
||||
|
||||
/* BIT shifting macro */
|
||||
#define BIT(x) ( 1 << x )
|
||||
|
||||
/* I801 SMBus address offsets */
|
||||
#define SMBHSTSTS (0 + i801_smba)
|
||||
#define SMBHSTCNT (2 + i801_smba)
|
||||
#define SMBHSTCMD (3 + i801_smba)
|
||||
#define SMBHSTADD (4 + i801_smba)
|
||||
#define SMBHSTDAT0 (5 + i801_smba)
|
||||
#define SMBHSTDAT1 (6 + i801_smba)
|
||||
#define SMBBLKDAT (7 + i801_smba)
|
||||
#define SMBPEC (8 + i801_smba) /* ICH3 and later */
|
||||
#define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */
|
||||
#define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */
|
||||
#define SMBSLVSTS (16 + i801_smba) /* ICH3 and later */
|
||||
#define SMBSLVCMD (17 + i801_smba) /* ICH3 and later */
|
||||
#define SMBNTFDADD (20 + i801_smba) /* ICH3 and later */
|
||||
|
||||
|
||||
/* Auxiliary status register bits, ICH4+ only */
|
||||
#define SMBAUXSTS_CRCE BIT(0)
|
||||
#define SMBAUXSTS_STCO BIT(1)
|
||||
|
||||
/* Auxiliary control register bits, ICH4+ only */
|
||||
#define SMBAUXCTL_CRC BIT(0)
|
||||
#define SMBAUXCTL_E32B BIT(1)
|
||||
|
||||
/* Other settings */
|
||||
#define MAX_RETRIES 400
|
||||
|
||||
/* I801 command constants */
|
||||
#define I801_QUICK 0x00
|
||||
#define I801_BYTE 0x04
|
||||
#define I801_BYTE_DATA 0x08
|
||||
#define I801_WORD_DATA 0x0C
|
||||
#define I801_PROC_CALL 0x10 /* unimplemented */
|
||||
#define I801_BLOCK_DATA 0x14
|
||||
#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
|
||||
|
||||
/* I801 Host Control register bits */
|
||||
#define SMBHSTCNT_INTREN BIT(0)
|
||||
#define SMBHSTCNT_KILL BIT(1)
|
||||
#define SMBHSTCNT_LAST_BYTE BIT(5)
|
||||
#define SMBHSTCNT_START BIT(6)
|
||||
#define SMBHSTCNT_PEC_EN BIT(7) /* ICH3 and later */
|
||||
|
||||
/* I801 Hosts Status register bits */
|
||||
#define SMBHSTSTS_BYTE_DONE BIT(7)
|
||||
#define SMBHSTSTS_INUSE_STS BIT(6)
|
||||
#define SMBHSTSTS_SMBALERT_STS BIT(5)
|
||||
#define SMBHSTSTS_FAILED BIT(4)
|
||||
#define SMBHSTSTS_BUS_ERR BIT(3)
|
||||
#define SMBHSTSTS_DEV_ERR BIT(2)
|
||||
#define SMBHSTSTS_INTR BIT(1)
|
||||
#define SMBHSTSTS_HOST_BUSY BIT(0)
|
||||
|
||||
/* Host Notify Status register bits */
|
||||
#define SMBSLVSTS_HST_NTFY_STS BIT(0)
|
||||
|
||||
/* Host Notify Command register bits */
|
||||
#define SMBSLVCMD_HST_NTFY_INTREN BIT(0)
|
||||
|
||||
#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR)
|
||||
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | STATUS_ERROR_FLAGS)
|
||||
|
||||
/* I801 Host Config */
|
||||
#define SMBHSTCFG 0x040
|
||||
#define SMBHSTCFG_HST_EN BIT(0)
|
||||
|
||||
class i2c_smbus_i801 : public i2c_smbus_interface
|
||||
{
|
||||
public:
|
||||
u16 i801_smba = 0xF000;
|
||||
i2c_smbus_i801();
|
||||
~i2c_smbus_i801();
|
||||
|
||||
private:
|
||||
s32 i801_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
|
||||
int i801_block_transaction(i2c_smbus_data *data, char read_write, int command, int hwpec);
|
||||
int i801_block_transaction_byte_by_byte(i2c_smbus_data *data, char read_write, int command, int hwpec);
|
||||
int i801_check_post(int status);
|
||||
int i801_check_pre();
|
||||
int i801_transaction(int xact);
|
||||
int i801_wait_byte_done();
|
||||
int i801_wait_intr();
|
||||
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, int* size, u8* data);
|
||||
};
|
||||
@@ -1,275 +1,275 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_nct6775.cpp |
|
||||
| |
|
||||
| Nuvoton NCT67xx SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 19 May 2019 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "macUSPCIOAccess.h"
|
||||
|
||||
#include "Detector.h"
|
||||
#include "i2c_smbus_nct6775.h"
|
||||
#include "LogManager.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "SettingsManager.h"
|
||||
#include "super_io.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
i2c_smbus_nct6775::i2c_smbus_nct6775()
|
||||
{
|
||||
}
|
||||
|
||||
i2c_smbus_nct6775::~i2c_smbus_nct6775()
|
||||
{
|
||||
}
|
||||
|
||||
s32 i2c_smbus_nct6775::nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data)
|
||||
{
|
||||
int i, len, cnt;
|
||||
i2c_smbus_data tmp_data;
|
||||
int timeout = 0;
|
||||
|
||||
tmp_data.word = 0;
|
||||
cnt = 0;
|
||||
len = 0;
|
||||
|
||||
WriteIoPortByte(SMBHSTCTL, NCT6775_SOFT_RESET);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case I2C_SMBUS_QUICK:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
tmp_data.byte = data->byte;
|
||||
case I2C_SMBUS_BYTE:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTIDX, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, tmp_data.byte);
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_WRITE_BYTE);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_READ_BYTE);
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTIDX, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->word & 0xFF);
|
||||
WriteIoPortByte(SMBHSTDAT, (data->word & 0xFF00) >> 8);
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_WRITE_WORD);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_READ_WORD);
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTIDX, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
len = data->block[0];
|
||||
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
WriteIoPortByte(SMBBLKSZ, len);
|
||||
|
||||
//Load 4 bytes into FIFO
|
||||
cnt = 1;
|
||||
if (len >= 4)
|
||||
{
|
||||
for (i = cnt; i <= 4; i++)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->block[i]);
|
||||
}
|
||||
|
||||
len -= 4;
|
||||
cnt += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = cnt; i <= len; i++)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->block[i]);
|
||||
}
|
||||
|
||||
len = 0;
|
||||
}
|
||||
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_WRITE_BLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
//Out32(SMBHSTCMD, NCT6775_READ_BLOCK);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
WriteIoPortByte(SMBHSTCTL, NCT6775_MANUAL_START);
|
||||
|
||||
while ((size == I2C_SMBUS_BLOCK_DATA) && (len > 0))
|
||||
{
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
timeout = 0;
|
||||
while ((ReadIoPortByte(SMBHSTSTS) & NCT6775_FIFO_EMPTY) == 0)
|
||||
{
|
||||
if(timeout > NCT6775_MAX_RETRIES)
|
||||
{
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
std::this_thread::sleep_for(1ms);;
|
||||
timeout++;
|
||||
}
|
||||
|
||||
//Load more bytes into FIFO
|
||||
if (len >= 4)
|
||||
{
|
||||
for (i = cnt; i <= (cnt + 4); i++)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->block[i]);
|
||||
}
|
||||
|
||||
len -= 4;
|
||||
cnt += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = cnt; i <= (cnt + len); i++)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->block[i]);
|
||||
}
|
||||
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
//wait for manual mode to complete
|
||||
timeout = 0;
|
||||
while ((ReadIoPortByte(SMBHSTSTS) & NCT6775_MANUAL_ACTIVE) != 0)
|
||||
{
|
||||
if(timeout > NCT6775_MAX_RETRIES)
|
||||
{
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
std::this_thread::sleep_for(1ms);;
|
||||
timeout++;
|
||||
}
|
||||
|
||||
if ((ReadIoPortByte(SMBHSTERR) & NCT6775_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)ReadIoPortByte(SMBHSTDAT);
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
data->word = ReadIoPortByte(SMBHSTDAT) + (ReadIoPortByte(SMBHSTDAT) << 8);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 i2c_smbus_nct6775::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
|
||||
{
|
||||
s32 result = nct6775_access(addr, read_write, command, size, data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 i2c_smbus_nct6775::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, u8* /*data*/)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool i2c_smbus_nct6775_detect()
|
||||
{
|
||||
if(!GetMacUSPCIODriverStatus())
|
||||
{
|
||||
LOG_INFO("macUSPCIO is not loaded, nct6775 I2C bus detection aborted");
|
||||
return(false);
|
||||
}
|
||||
|
||||
i2c_smbus_interface* bus;
|
||||
int sioaddr = 0x2E;
|
||||
superio_enter(sioaddr);
|
||||
|
||||
int val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) | superio_inb(sioaddr, SIO_REG_DEVID + 1);
|
||||
|
||||
switch (val & SIO_ID_MASK)
|
||||
{
|
||||
case SIO_NCT5577_ID:
|
||||
case SIO_NCT6102_ID:
|
||||
case SIO_NCT6793_ID:
|
||||
case SIO_NCT6796_ID:
|
||||
case SIO_NCT6798_ID:
|
||||
// Create new nct6775 bus and invalidate the PCI ID information
|
||||
bus = new i2c_smbus_nct6775();
|
||||
bus->pci_vendor = 0xFFFF;
|
||||
bus->pci_device = 0xFFFF;
|
||||
bus->pci_subsystem_vendor = 0xFFFF;
|
||||
bus->pci_subsystem_device = 0xFFFF;
|
||||
|
||||
// Set logical device register to get SMBus base address
|
||||
superio_outb(sioaddr, SIO_REG_LOGDEV, SIO_LOGDEV_SMBUS);
|
||||
|
||||
// Get SMBus base address from configuration register
|
||||
int smba = (superio_inb(sioaddr, SIO_REG_SMBA) << 8) | superio_inb(sioaddr, SIO_REG_SMBA + 1);
|
||||
((i2c_smbus_nct6775*)bus)->nct6775_smba = smba;
|
||||
|
||||
// Set device name string
|
||||
switch (val & SIO_ID_MASK)
|
||||
{
|
||||
case SIO_NCT5577_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT5577D SMBus at %X", smba);
|
||||
break;
|
||||
case SIO_NCT6102_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT6102D/NCT6106D SMBus at %X", smba);
|
||||
break;
|
||||
case SIO_NCT6793_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT6793D SMBus at %X", smba);
|
||||
break;
|
||||
case SIO_NCT6796_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT6796D SMBus at %X", smba);
|
||||
break;
|
||||
case SIO_NCT6798_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT6798D SMBus at %X", smba);
|
||||
break;
|
||||
}
|
||||
|
||||
ResourceManager::get()->RegisterI2CBus(bus);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_nct6775_detect);
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_nct6775.cpp |
|
||||
| |
|
||||
| Nuvoton NCT67xx SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 19 May 2019 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "macUSPCIOAccess.h"
|
||||
|
||||
#include "Detector.h"
|
||||
#include "i2c_smbus_nct6775.h"
|
||||
#include "LogManager.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "SettingsManager.h"
|
||||
#include "super_io.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
i2c_smbus_nct6775::i2c_smbus_nct6775()
|
||||
{
|
||||
}
|
||||
|
||||
i2c_smbus_nct6775::~i2c_smbus_nct6775()
|
||||
{
|
||||
}
|
||||
|
||||
s32 i2c_smbus_nct6775::nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data)
|
||||
{
|
||||
int i, len, cnt;
|
||||
i2c_smbus_data tmp_data;
|
||||
int timeout = 0;
|
||||
|
||||
tmp_data.word = 0;
|
||||
cnt = 0;
|
||||
len = 0;
|
||||
|
||||
WriteIoPortByte(SMBHSTCTL, NCT6775_SOFT_RESET);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case I2C_SMBUS_QUICK:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
tmp_data.byte = data->byte;
|
||||
case I2C_SMBUS_BYTE:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTIDX, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, tmp_data.byte);
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_WRITE_BYTE);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_READ_BYTE);
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTIDX, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->word & 0xFF);
|
||||
WriteIoPortByte(SMBHSTDAT, (data->word & 0xFF00) >> 8);
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_WRITE_WORD);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_READ_WORD);
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTIDX, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
len = data->block[0];
|
||||
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
WriteIoPortByte(SMBBLKSZ, len);
|
||||
|
||||
//Load 4 bytes into FIFO
|
||||
cnt = 1;
|
||||
if (len >= 4)
|
||||
{
|
||||
for (i = cnt; i <= 4; i++)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->block[i]);
|
||||
}
|
||||
|
||||
len -= 4;
|
||||
cnt += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = cnt; i <= len; i++)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->block[i]);
|
||||
}
|
||||
|
||||
len = 0;
|
||||
}
|
||||
|
||||
WriteIoPortByte(SMBHSTCMD, NCT6775_WRITE_BLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
//Out32(SMBHSTCMD, NCT6775_READ_BLOCK);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
WriteIoPortByte(SMBHSTCTL, NCT6775_MANUAL_START);
|
||||
|
||||
while ((size == I2C_SMBUS_BLOCK_DATA) && (len > 0))
|
||||
{
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
timeout = 0;
|
||||
while ((ReadIoPortByte(SMBHSTSTS) & NCT6775_FIFO_EMPTY) == 0)
|
||||
{
|
||||
if(timeout > NCT6775_MAX_RETRIES)
|
||||
{
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
std::this_thread::sleep_for(1ms);;
|
||||
timeout++;
|
||||
}
|
||||
|
||||
//Load more bytes into FIFO
|
||||
if (len >= 4)
|
||||
{
|
||||
for (i = cnt; i <= (cnt + 4); i++)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->block[i]);
|
||||
}
|
||||
|
||||
len -= 4;
|
||||
cnt += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = cnt; i <= (cnt + len); i++)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT, data->block[i]);
|
||||
}
|
||||
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
//wait for manual mode to complete
|
||||
timeout = 0;
|
||||
while ((ReadIoPortByte(SMBHSTSTS) & NCT6775_MANUAL_ACTIVE) != 0)
|
||||
{
|
||||
if(timeout > NCT6775_MAX_RETRIES)
|
||||
{
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
std::this_thread::sleep_for(1ms);;
|
||||
timeout++;
|
||||
}
|
||||
|
||||
if ((ReadIoPortByte(SMBHSTERR) & NCT6775_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)ReadIoPortByte(SMBHSTDAT);
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
data->word = ReadIoPortByte(SMBHSTDAT) + (ReadIoPortByte(SMBHSTDAT) << 8);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 i2c_smbus_nct6775::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
|
||||
{
|
||||
s32 result = nct6775_access(addr, read_write, command, size, data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 i2c_smbus_nct6775::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, u8* /*data*/)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool i2c_smbus_nct6775_detect()
|
||||
{
|
||||
if(!GetMacUSPCIODriverStatus())
|
||||
{
|
||||
LOG_INFO("macUSPCIO is not loaded, nct6775 I2C bus detection aborted");
|
||||
return(false);
|
||||
}
|
||||
|
||||
i2c_smbus_interface* bus;
|
||||
int sioaddr = 0x2E;
|
||||
superio_enter(sioaddr);
|
||||
|
||||
int val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) | superio_inb(sioaddr, SIO_REG_DEVID + 1);
|
||||
|
||||
switch (val & SIO_ID_MASK)
|
||||
{
|
||||
case SIO_NCT5577_ID:
|
||||
case SIO_NCT6102_ID:
|
||||
case SIO_NCT6793_ID:
|
||||
case SIO_NCT6796_ID:
|
||||
case SIO_NCT6798_ID:
|
||||
// Create new nct6775 bus and invalidate the PCI ID information
|
||||
bus = new i2c_smbus_nct6775();
|
||||
bus->pci_vendor = 0xFFFF;
|
||||
bus->pci_device = 0xFFFF;
|
||||
bus->pci_subsystem_vendor = 0xFFFF;
|
||||
bus->pci_subsystem_device = 0xFFFF;
|
||||
|
||||
// Set logical device register to get SMBus base address
|
||||
superio_outb(sioaddr, SIO_REG_LOGDEV, SIO_LOGDEV_SMBUS);
|
||||
|
||||
// Get SMBus base address from configuration register
|
||||
int smba = (superio_inb(sioaddr, SIO_REG_SMBA) << 8) | superio_inb(sioaddr, SIO_REG_SMBA + 1);
|
||||
((i2c_smbus_nct6775*)bus)->nct6775_smba = smba;
|
||||
|
||||
// Set device name string
|
||||
switch (val & SIO_ID_MASK)
|
||||
{
|
||||
case SIO_NCT5577_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT5577D SMBus at %X", smba);
|
||||
break;
|
||||
case SIO_NCT6102_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT6102D/NCT6106D SMBus at %X", smba);
|
||||
break;
|
||||
case SIO_NCT6793_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT6793D SMBus at %X", smba);
|
||||
break;
|
||||
case SIO_NCT6796_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT6796D SMBus at %X", smba);
|
||||
break;
|
||||
case SIO_NCT6798_ID:
|
||||
snprintf(bus->device_name, 512, "Nuvoton NCT6798D SMBus at %X", smba);
|
||||
break;
|
||||
}
|
||||
|
||||
ResourceManager::get()->RegisterI2CBus(bus);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_nct6775_detect);
|
||||
@@ -1,61 +1,61 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_nct6775.h |
|
||||
| |
|
||||
| Nuvoton NCT67xx SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 19 May 2019 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "i2c_smbus.h"
|
||||
|
||||
#define SMBHSTDAT (0 + nct6775_smba)
|
||||
#define SMBBLKSZ (1 + nct6775_smba)
|
||||
#define SMBHSTCMD (2 + nct6775_smba)
|
||||
#define SMBHSTIDX (3 + nct6775_smba) //Index field is the Command field on other controllers
|
||||
#define SMBHSTCTL (4 + nct6775_smba)
|
||||
#define SMBHSTADD (5 + nct6775_smba)
|
||||
#define SMBHSTERR (9 + nct6775_smba)
|
||||
#define SMBHSTSTS (0xE + nct6775_smba)
|
||||
|
||||
/* Command register */
|
||||
#define NCT6775_READ_BYTE 0
|
||||
#define NCT6775_READ_WORD 1
|
||||
#define NCT6775_READ_BLOCK 2
|
||||
#define NCT6775_BLOCK_WRITE_READ_PROC_CALL 3
|
||||
#define NCT6775_PROC_CALL 4
|
||||
#define NCT6775_WRITE_BYTE 8
|
||||
#define NCT6775_WRITE_WORD 9
|
||||
#define NCT6775_WRITE_BLOCK 10
|
||||
|
||||
/* Control register */
|
||||
#define NCT6775_MANUAL_START 128
|
||||
#define NCT6775_SOFT_RESET 64
|
||||
|
||||
/* Error register */
|
||||
#define NCT6775_NO_ACK 32
|
||||
|
||||
/* Status register */
|
||||
#define NCT6775_FIFO_EMPTY 1
|
||||
#define NCT6775_FIFO_FULL 2
|
||||
#define NCT6775_MANUAL_ACTIVE 4
|
||||
|
||||
/* Other settings */
|
||||
#define NCT6775_MAX_RETRIES 400
|
||||
|
||||
class i2c_smbus_nct6775: public i2c_smbus_interface
|
||||
{
|
||||
public:
|
||||
u16 nct6775_smba = 0x0290;
|
||||
i2c_smbus_nct6775();
|
||||
~i2c_smbus_nct6775();
|
||||
|
||||
private:
|
||||
s32 nct6775_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);
|
||||
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
|
||||
};
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_nct6775.h |
|
||||
| |
|
||||
| Nuvoton NCT67xx SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 19 May 2019 |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "i2c_smbus.h"
|
||||
|
||||
#define SMBHSTDAT (0 + nct6775_smba)
|
||||
#define SMBBLKSZ (1 + nct6775_smba)
|
||||
#define SMBHSTCMD (2 + nct6775_smba)
|
||||
#define SMBHSTIDX (3 + nct6775_smba) //Index field is the Command field on other controllers
|
||||
#define SMBHSTCTL (4 + nct6775_smba)
|
||||
#define SMBHSTADD (5 + nct6775_smba)
|
||||
#define SMBHSTERR (9 + nct6775_smba)
|
||||
#define SMBHSTSTS (0xE + nct6775_smba)
|
||||
|
||||
/* Command register */
|
||||
#define NCT6775_READ_BYTE 0
|
||||
#define NCT6775_READ_WORD 1
|
||||
#define NCT6775_READ_BLOCK 2
|
||||
#define NCT6775_BLOCK_WRITE_READ_PROC_CALL 3
|
||||
#define NCT6775_PROC_CALL 4
|
||||
#define NCT6775_WRITE_BYTE 8
|
||||
#define NCT6775_WRITE_WORD 9
|
||||
#define NCT6775_WRITE_BLOCK 10
|
||||
|
||||
/* Control register */
|
||||
#define NCT6775_MANUAL_START 128
|
||||
#define NCT6775_SOFT_RESET 64
|
||||
|
||||
/* Error register */
|
||||
#define NCT6775_NO_ACK 32
|
||||
|
||||
/* Status register */
|
||||
#define NCT6775_FIFO_EMPTY 1
|
||||
#define NCT6775_FIFO_FULL 2
|
||||
#define NCT6775_MANUAL_ACTIVE 4
|
||||
|
||||
/* Other settings */
|
||||
#define NCT6775_MAX_RETRIES 400
|
||||
|
||||
class i2c_smbus_nct6775: public i2c_smbus_interface
|
||||
{
|
||||
public:
|
||||
u16 nct6775_smba = 0x0290;
|
||||
i2c_smbus_nct6775();
|
||||
~i2c_smbus_nct6775();
|
||||
|
||||
private:
|
||||
s32 nct6775_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);
|
||||
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
|
||||
};
|
||||
+288
-288
@@ -1,288 +1,288 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_piix4.cpp |
|
||||
| |
|
||||
| PIIX4 SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 08 Aug 2018 |
|
||||
| Portions based on Linux source code |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "macUSPCIOAccess.h"
|
||||
|
||||
#include "Detector.h"
|
||||
#include "i2c_smbus_piix4.h"
|
||||
#include "LogManager.h"
|
||||
#include "pci_ids.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "SettingsManager.h"
|
||||
|
||||
i2c_smbus_piix4::i2c_smbus_piix4()
|
||||
{
|
||||
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
|
||||
|
||||
bool amd_smbus_reduce_cpu = false;
|
||||
if(drivers_settings.contains("amd_smbus_reduce_cpu"))
|
||||
{
|
||||
amd_smbus_reduce_cpu = drivers_settings["amd_smbus_reduce_cpu"].get<bool>();
|
||||
}
|
||||
|
||||
delay_timer = amd_smbus_reduce_cpu;
|
||||
}
|
||||
|
||||
i2c_smbus_piix4::~i2c_smbus_piix4()
|
||||
{
|
||||
}
|
||||
|
||||
//Logic adapted from piix4_transaction() in i2c-piix4.c
|
||||
int i2c_smbus_piix4::piix4_transaction()
|
||||
{
|
||||
int result = 0;
|
||||
int temp;
|
||||
int timeout = 0;
|
||||
|
||||
/* start the transaction by setting bit 6 */
|
||||
temp = ReadIoPortByte(SMBHSTCNT);
|
||||
WriteIoPortByte(SMBHSTCNT, temp | 0x040);
|
||||
|
||||
/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
|
||||
/*---------------------------------------------------------------------------------------------------------------*\
|
||||
| The above comment from 2002 or earlier is still relevant for the Zen 4 architecture. |
|
||||
| AMD takes bug-for-bug compatibility seriously. It's the least they can do since they've classified Ryzen |
|
||||
| system programming documentation as trade secret. |
|
||||
| |
|
||||
| Instead of just waiting for an unspecified amount of time, we try to follow exactly what the |
|
||||
| Intel 83271 Specification Update says about SMBHSTSTS. |
|
||||
| |
|
||||
|-----------------------------------------------------------------------------------------------------------------|
|
||||
| [Bit] 1 SMBus Interrupt/Host Completion (INTER)—R/WC. |
|
||||
| 1 = Indicates that the host transaction has completed or that the source of an SMBus interrupt was the |
|
||||
| completion of the last host command. |
|
||||
| 0 = Host transaction has not completed or that an SMBus interrupt was not caused by host command completion. |
|
||||
| This bit is only set by hardware and can only be reset by writing a 1 to this bit position. |
|
||||
|-----------------------------------------------------------------------------------------------------------------|
|
||||
| [Bit] 0 Host Busy (HOST_BUSY)—RO. |
|
||||
| 1 = Indicates that the SMBus controller host interface is in the process of completing a command. |
|
||||
| 0 = SMBus controller host interface is not processing a command. None of the other registers should be accessed |
|
||||
| if this bit is set. Note that there may be moderate latency before the transaction begins and the Host Busy bit |
|
||||
| gets set. |
|
||||
\*---------------------------------------------------------------------------------------------------------------*/
|
||||
temp = 0;
|
||||
|
||||
if(delay_timer)
|
||||
{
|
||||
do
|
||||
{
|
||||
usleep(RETRY_DELAY_US);
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
}
|
||||
while((++timeout < MAX_TIMEOUT) && ((temp & 0x03) != 0x02));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(500);
|
||||
do
|
||||
{
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
}
|
||||
while((std::chrono::steady_clock::now() < deadline) && ((temp & 0x03) != 0x02));
|
||||
temp = ReadIoPortByte(SMBHSTSTS); // we can be preempted between reading the register and checking for the timeout
|
||||
}
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (temp & 0x01)
|
||||
{
|
||||
result = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (temp & 0x10)
|
||||
{
|
||||
result = -EIO;
|
||||
}
|
||||
|
||||
if (temp & 0x08)
|
||||
{
|
||||
result = -EIO;
|
||||
}
|
||||
|
||||
if (temp & 0x04)
|
||||
{
|
||||
result = -ENXIO;
|
||||
}
|
||||
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
if (temp != 0x00)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTSTS, temp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//Logic adapted from piix4_access() in i2c-piix4.c
|
||||
s32 i2c_smbus_piix4::piix4_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data)
|
||||
{
|
||||
int i, len, status, temp;
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
if (temp != 0x00)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTSTS, temp);
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
if (temp != 0x00)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case I2C_SMBUS_QUICK:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
size = PIIX4_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTCMD, command);
|
||||
}
|
||||
size = PIIX4_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTCMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT0, data->byte);
|
||||
}
|
||||
size = PIIX4_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTCMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT0, data->word & 0xFF);
|
||||
WriteIoPortByte(SMBHSTDAT1, (data->word & 0xFF00) >> 8);
|
||||
}
|
||||
size = PIIX4_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTCMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
len = data->block[0];
|
||||
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
WriteIoPortByte(SMBHSTDAT0, len);
|
||||
ReadIoPortByte(SMBHSTCNT);
|
||||
for (i = 1; i <= len; i++)
|
||||
{
|
||||
WriteIoPortByte(SMBBLKDAT, data->block[i]);
|
||||
}
|
||||
}
|
||||
size = PIIX4_BLOCK_DATA;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
WriteIoPortByte(SMBHSTCNT, (size & 0x1C));
|
||||
|
||||
status = piix4_transaction();
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
|
||||
return 0;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case PIIX4_BYTE:
|
||||
case PIIX4_BYTE_DATA:
|
||||
data->byte = (u8)ReadIoPortByte(SMBHSTDAT0);
|
||||
break;
|
||||
case PIIX4_WORD_DATA:
|
||||
data->word = ReadIoPortByte(SMBHSTDAT0) + (ReadIoPortByte(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
case PIIX4_BLOCK_DATA:
|
||||
data->block[0] = (u8)ReadIoPortByte(SMBHSTDAT0);
|
||||
if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
|
||||
{
|
||||
return -EPROTO;
|
||||
}
|
||||
ReadIoPortByte(SMBHSTCNT);
|
||||
for (i = 1; i <= data->block[0]; i++)
|
||||
{
|
||||
data->block[i] = (u8)ReadIoPortByte(SMBBLKDAT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 i2c_smbus_piix4::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
|
||||
{
|
||||
s32 result = piix4_access(addr, read_write, command, size, data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 i2c_smbus_piix4::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, u8* /*data*/)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool i2c_smbus_piix4_detect()
|
||||
{
|
||||
if(!GetMacUSPCIODriverStatus())
|
||||
{
|
||||
LOG_INFO("macUSPCIO is not loaded, piix4 I2C bus detection aborted");
|
||||
return(false);
|
||||
}
|
||||
|
||||
// addresses are referenced from: https://opensource.apple.com/source/IOPCIFamily/IOPCIFamily-146/IOKit/pci/IOPCIDevice.h.auto.html
|
||||
uint16_t vendor_id = ReadConfigPortWord(0x00);
|
||||
uint16_t device_id = ReadConfigPortWord(0x02);
|
||||
uint16_t subsystem_vendor_id = ReadConfigPortWord(0x2c);
|
||||
uint16_t subsystem_device_id = ReadConfigPortWord(0x2e);
|
||||
|
||||
if(vendor_id != AMD_VEN || !device_id || !subsystem_vendor_id || !subsystem_device_id)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
i2c_smbus_interface * bus;
|
||||
|
||||
bus = new i2c_smbus_piix4();
|
||||
bus->pci_vendor = vendor_id;
|
||||
bus->pci_device = device_id;
|
||||
bus->pci_subsystem_vendor = subsystem_vendor_id;
|
||||
bus->pci_subsystem_device = subsystem_device_id;
|
||||
strcpy(bus->device_name, "Advanced Micro Devices, Inc PIIX4 SMBus at 0x0B00");
|
||||
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B00;
|
||||
ResourceManager::get()->RegisterI2CBus(bus);
|
||||
|
||||
bus = new i2c_smbus_piix4();
|
||||
bus->pci_vendor = vendor_id;
|
||||
bus->pci_device = device_id;
|
||||
bus->pci_subsystem_vendor = subsystem_vendor_id;
|
||||
bus->pci_subsystem_device = subsystem_device_id;
|
||||
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B20;
|
||||
strcpy(bus->device_name, "Advanced Micro Devices, Inc PIIX4 SMBus at 0x0B20");
|
||||
ResourceManager::get()->RegisterI2CBus(bus);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_piix4_detect);
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_piix4.cpp |
|
||||
| |
|
||||
| PIIX4 SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 08 Aug 2018 |
|
||||
| Portions based on Linux source code |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "macUSPCIOAccess.h"
|
||||
|
||||
#include "Detector.h"
|
||||
#include "i2c_smbus_piix4.h"
|
||||
#include "LogManager.h"
|
||||
#include "pci_ids.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "SettingsManager.h"
|
||||
|
||||
i2c_smbus_piix4::i2c_smbus_piix4()
|
||||
{
|
||||
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
|
||||
|
||||
bool amd_smbus_reduce_cpu = false;
|
||||
if(drivers_settings.contains("amd_smbus_reduce_cpu"))
|
||||
{
|
||||
amd_smbus_reduce_cpu = drivers_settings["amd_smbus_reduce_cpu"].get<bool>();
|
||||
}
|
||||
|
||||
delay_timer = amd_smbus_reduce_cpu;
|
||||
}
|
||||
|
||||
i2c_smbus_piix4::~i2c_smbus_piix4()
|
||||
{
|
||||
}
|
||||
|
||||
//Logic adapted from piix4_transaction() in i2c-piix4.c
|
||||
int i2c_smbus_piix4::piix4_transaction()
|
||||
{
|
||||
int result = 0;
|
||||
int temp;
|
||||
int timeout = 0;
|
||||
|
||||
/* start the transaction by setting bit 6 */
|
||||
temp = ReadIoPortByte(SMBHSTCNT);
|
||||
WriteIoPortByte(SMBHSTCNT, temp | 0x040);
|
||||
|
||||
/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
|
||||
/*---------------------------------------------------------------------------------------------------------------*\
|
||||
| The above comment from 2002 or earlier is still relevant for the Zen 4 architecture. |
|
||||
| AMD takes bug-for-bug compatibility seriously. It's the least they can do since they've classified Ryzen |
|
||||
| system programming documentation as trade secret. |
|
||||
| |
|
||||
| Instead of just waiting for an unspecified amount of time, we try to follow exactly what the |
|
||||
| Intel 83271 Specification Update says about SMBHSTSTS. |
|
||||
| |
|
||||
|-----------------------------------------------------------------------------------------------------------------|
|
||||
| [Bit] 1 SMBus Interrupt/Host Completion (INTER)—R/WC. |
|
||||
| 1 = Indicates that the host transaction has completed or that the source of an SMBus interrupt was the |
|
||||
| completion of the last host command. |
|
||||
| 0 = Host transaction has not completed or that an SMBus interrupt was not caused by host command completion. |
|
||||
| This bit is only set by hardware and can only be reset by writing a 1 to this bit position. |
|
||||
|-----------------------------------------------------------------------------------------------------------------|
|
||||
| [Bit] 0 Host Busy (HOST_BUSY)—RO. |
|
||||
| 1 = Indicates that the SMBus controller host interface is in the process of completing a command. |
|
||||
| 0 = SMBus controller host interface is not processing a command. None of the other registers should be accessed |
|
||||
| if this bit is set. Note that there may be moderate latency before the transaction begins and the Host Busy bit |
|
||||
| gets set. |
|
||||
\*---------------------------------------------------------------------------------------------------------------*/
|
||||
temp = 0;
|
||||
|
||||
if(delay_timer)
|
||||
{
|
||||
do
|
||||
{
|
||||
usleep(RETRY_DELAY_US);
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
}
|
||||
while((++timeout < MAX_TIMEOUT) && ((temp & 0x03) != 0x02));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(500);
|
||||
do
|
||||
{
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
}
|
||||
while((std::chrono::steady_clock::now() < deadline) && ((temp & 0x03) != 0x02));
|
||||
temp = ReadIoPortByte(SMBHSTSTS); // we can be preempted between reading the register and checking for the timeout
|
||||
}
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (temp & 0x01)
|
||||
{
|
||||
result = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (temp & 0x10)
|
||||
{
|
||||
result = -EIO;
|
||||
}
|
||||
|
||||
if (temp & 0x08)
|
||||
{
|
||||
result = -EIO;
|
||||
}
|
||||
|
||||
if (temp & 0x04)
|
||||
{
|
||||
result = -ENXIO;
|
||||
}
|
||||
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
if (temp != 0x00)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTSTS, temp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//Logic adapted from piix4_access() in i2c-piix4.c
|
||||
s32 i2c_smbus_piix4::piix4_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data)
|
||||
{
|
||||
int i, len, status, temp;
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
if (temp != 0x00)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTSTS, temp);
|
||||
temp = ReadIoPortByte(SMBHSTSTS);
|
||||
if (temp != 0x00)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case I2C_SMBUS_QUICK:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
size = PIIX4_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTCMD, command);
|
||||
}
|
||||
size = PIIX4_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTCMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT0, data->byte);
|
||||
}
|
||||
size = PIIX4_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTCMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
WriteIoPortByte(SMBHSTDAT0, data->word & 0xFF);
|
||||
WriteIoPortByte(SMBHSTDAT1, (data->word & 0xFF00) >> 8);
|
||||
}
|
||||
size = PIIX4_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
WriteIoPortByte(SMBHSTADD, (addr << 1) | read_write);
|
||||
WriteIoPortByte(SMBHSTCMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
{
|
||||
len = data->block[0];
|
||||
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
WriteIoPortByte(SMBHSTDAT0, len);
|
||||
ReadIoPortByte(SMBHSTCNT);
|
||||
for (i = 1; i <= len; i++)
|
||||
{
|
||||
WriteIoPortByte(SMBBLKDAT, data->block[i]);
|
||||
}
|
||||
}
|
||||
size = PIIX4_BLOCK_DATA;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
WriteIoPortByte(SMBHSTCNT, (size & 0x1C));
|
||||
|
||||
status = piix4_transaction();
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
|
||||
return 0;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case PIIX4_BYTE:
|
||||
case PIIX4_BYTE_DATA:
|
||||
data->byte = (u8)ReadIoPortByte(SMBHSTDAT0);
|
||||
break;
|
||||
case PIIX4_WORD_DATA:
|
||||
data->word = ReadIoPortByte(SMBHSTDAT0) + (ReadIoPortByte(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
case PIIX4_BLOCK_DATA:
|
||||
data->block[0] = (u8)ReadIoPortByte(SMBHSTDAT0);
|
||||
if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
|
||||
{
|
||||
return -EPROTO;
|
||||
}
|
||||
ReadIoPortByte(SMBHSTCNT);
|
||||
for (i = 1; i <= data->block[0]; i++)
|
||||
{
|
||||
data->block[i] = (u8)ReadIoPortByte(SMBBLKDAT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 i2c_smbus_piix4::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
|
||||
{
|
||||
s32 result = piix4_access(addr, read_write, command, size, data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 i2c_smbus_piix4::i2c_xfer(u8 /*addr*/, char /*read_write*/, int* /*size*/, u8* /*data*/)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool i2c_smbus_piix4_detect()
|
||||
{
|
||||
if(!GetMacUSPCIODriverStatus())
|
||||
{
|
||||
LOG_INFO("macUSPCIO is not loaded, piix4 I2C bus detection aborted");
|
||||
return(false);
|
||||
}
|
||||
|
||||
// addresses are referenced from: https://opensource.apple.com/source/IOPCIFamily/IOPCIFamily-146/IOKit/pci/IOPCIDevice.h.auto.html
|
||||
uint16_t vendor_id = ReadConfigPortWord(0x00);
|
||||
uint16_t device_id = ReadConfigPortWord(0x02);
|
||||
uint16_t subsystem_vendor_id = ReadConfigPortWord(0x2c);
|
||||
uint16_t subsystem_device_id = ReadConfigPortWord(0x2e);
|
||||
|
||||
if(vendor_id != AMD_VEN || !device_id || !subsystem_vendor_id || !subsystem_device_id)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
i2c_smbus_interface * bus;
|
||||
|
||||
bus = new i2c_smbus_piix4();
|
||||
bus->pci_vendor = vendor_id;
|
||||
bus->pci_device = device_id;
|
||||
bus->pci_subsystem_vendor = subsystem_vendor_id;
|
||||
bus->pci_subsystem_device = subsystem_device_id;
|
||||
strcpy(bus->device_name, "Advanced Micro Devices, Inc PIIX4 SMBus at 0x0B00");
|
||||
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B00;
|
||||
ResourceManager::get()->RegisterI2CBus(bus);
|
||||
|
||||
bus = new i2c_smbus_piix4();
|
||||
bus->pci_vendor = vendor_id;
|
||||
bus->pci_device = device_id;
|
||||
bus->pci_subsystem_vendor = subsystem_vendor_id;
|
||||
bus->pci_subsystem_device = subsystem_device_id;
|
||||
((i2c_smbus_piix4 *)bus)->piix4_smba = 0x0B20;
|
||||
strcpy(bus->device_name, "Advanced Micro Devices, Inc PIIX4 SMBus at 0x0B20");
|
||||
ResourceManager::get()->RegisterI2CBus(bus);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
REGISTER_I2C_BUS_DETECTOR(i2c_smbus_piix4_detect);
|
||||
@@ -1,55 +1,55 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_piix4.h |
|
||||
| |
|
||||
| PIIX4 SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 08 Aug 2018 |
|
||||
| Portions based on Linux source code |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "i2c_smbus.h"
|
||||
|
||||
// PIIX4 SMBus address offsets
|
||||
#define SMBHSTSTS (0 + piix4_smba)
|
||||
#define SMBHSLVSTS (1 + piix4_smba)
|
||||
#define SMBHSTCNT (2 + piix4_smba)
|
||||
#define SMBHSTCMD (3 + piix4_smba)
|
||||
#define SMBHSTADD (4 + piix4_smba)
|
||||
#define SMBHSTDAT0 (5 + piix4_smba)
|
||||
#define SMBHSTDAT1 (6 + piix4_smba)
|
||||
#define SMBBLKDAT (7 + piix4_smba)
|
||||
#define SMBSLVCNT (8 + piix4_smba)
|
||||
#define SMBSHDWCMD (9 + piix4_smba)
|
||||
#define SMBSLVEVT (0xA + piix4_smba)
|
||||
#define SMBSLVDAT (0xC + piix4_smba)
|
||||
|
||||
#define MAX_TIMEOUT 5000
|
||||
#define RETRY_DELAY_US 250
|
||||
|
||||
// PIIX4 constants
|
||||
#define PIIX4_QUICK 0x00
|
||||
#define PIIX4_BYTE 0x04
|
||||
#define PIIX4_BYTE_DATA 0x08
|
||||
#define PIIX4_WORD_DATA 0x0C
|
||||
#define PIIX4_BLOCK_DATA 0x14
|
||||
|
||||
class i2c_smbus_piix4 : public i2c_smbus_interface
|
||||
{
|
||||
public:
|
||||
u16 piix4_smba = 0x0B00;
|
||||
i2c_smbus_piix4();
|
||||
~i2c_smbus_piix4();
|
||||
|
||||
private:
|
||||
int piix4_transaction();
|
||||
s32 piix4_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);
|
||||
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
|
||||
|
||||
bool delay_timer;
|
||||
};
|
||||
/*---------------------------------------------------------*\
|
||||
| i2c_smbus_piix4.h |
|
||||
| |
|
||||
| PIIX4 SMBUS driver for MacOS |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 08 Aug 2018 |
|
||||
| Portions based on Linux source code |
|
||||
| |
|
||||
| This file is part of the OpenRGB project |
|
||||
| SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "i2c_smbus.h"
|
||||
|
||||
// PIIX4 SMBus address offsets
|
||||
#define SMBHSTSTS (0 + piix4_smba)
|
||||
#define SMBHSLVSTS (1 + piix4_smba)
|
||||
#define SMBHSTCNT (2 + piix4_smba)
|
||||
#define SMBHSTCMD (3 + piix4_smba)
|
||||
#define SMBHSTADD (4 + piix4_smba)
|
||||
#define SMBHSTDAT0 (5 + piix4_smba)
|
||||
#define SMBHSTDAT1 (6 + piix4_smba)
|
||||
#define SMBBLKDAT (7 + piix4_smba)
|
||||
#define SMBSLVCNT (8 + piix4_smba)
|
||||
#define SMBSHDWCMD (9 + piix4_smba)
|
||||
#define SMBSLVEVT (0xA + piix4_smba)
|
||||
#define SMBSLVDAT (0xC + piix4_smba)
|
||||
|
||||
#define MAX_TIMEOUT 5000
|
||||
#define RETRY_DELAY_US 250
|
||||
|
||||
// PIIX4 constants
|
||||
#define PIIX4_QUICK 0x00
|
||||
#define PIIX4_BYTE 0x04
|
||||
#define PIIX4_BYTE_DATA 0x08
|
||||
#define PIIX4_WORD_DATA 0x0C
|
||||
#define PIIX4_BLOCK_DATA 0x14
|
||||
|
||||
class i2c_smbus_piix4 : public i2c_smbus_interface
|
||||
{
|
||||
public:
|
||||
u16 piix4_smba = 0x0B00;
|
||||
i2c_smbus_piix4();
|
||||
~i2c_smbus_piix4();
|
||||
|
||||
private:
|
||||
int piix4_transaction();
|
||||
s32 piix4_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);
|
||||
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
|
||||
|
||||
bool delay_timer;
|
||||
};
|
||||
Reference in new issue
Block a user