mirror of
https://github.com/lm-sensors/lm-sensors.git
synced 2026-11-07 16:01:34 +00:00
`indent -kr -i8' on all kernel sources
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@707 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
1 parent
83d5845df5
commit
6a2c82b491
29 files changed
+10217
-9155
No files matched your search
+332
-301
@@ -86,7 +86,7 @@
|
||||
#define SMBBLKDAT (6 + ali15x3_smba)
|
||||
|
||||
/* PCI Address Constants */
|
||||
#define SMBCOM 0x004
|
||||
#define SMBCOM 0x004
|
||||
#define SMBBA 0x014
|
||||
#define SMBATPC 0x05B /* used to unlock xxxBA registers */
|
||||
#define SMBHSTCFG 0x0E0
|
||||
@@ -118,9 +118,9 @@
|
||||
#define ALI15X3_BLOCK_CLR 0x80
|
||||
|
||||
/* ALI15X3 status register bits */
|
||||
#define ALI15X3_STS_IDLE 0x04
|
||||
#define ALI15X3_STS_BUSY 0x08
|
||||
#define ALI15X3_STS_DONE 0x10
|
||||
#define ALI15X3_STS_IDLE 0x04
|
||||
#define ALI15X3_STS_BUSY 0x08
|
||||
#define ALI15X3_STS_DONE 0x10
|
||||
#define ALI15X3_STS_DEV 0x20 /* device error */
|
||||
#define ALI15X3_STS_COLL 0x40 /* collision or no response */
|
||||
#define ALI15X3_STS_TERM 0x80 /* terminated by abort */
|
||||
@@ -132,13 +132,14 @@ static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init i2c_ali15x3_init(void);
|
||||
int __init i2c_ali15x3_init(void);
|
||||
static int __init ali15x3_cleanup(void);
|
||||
static int ali15x3_setup(void);
|
||||
static s32 ali15x3_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags,char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data);
|
||||
static void ali15x3_do_pause( unsigned int amount );
|
||||
static s32 ali15x3_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size,
|
||||
union i2c_smbus_data *data);
|
||||
static void ali15x3_do_pause(unsigned int amount);
|
||||
static int ali15x3_transaction(void);
|
||||
static void ali15x3_inc(struct i2c_adapter *adapter);
|
||||
static void ali15x3_dec(struct i2c_adapter *adapter);
|
||||
@@ -147,28 +148,28 @@ static u32 ali15x3_func(struct i2c_adapter *adapter);
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ ali15x3_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ ali15x3_func,
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ ali15x3_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ ali15x3_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter ali15x3_adapter = {
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
ali15x3_inc,
|
||||
ali15x3_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
ali15x3_inc,
|
||||
ali15x3_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __initdata ali15x3_initialized;
|
||||
@@ -181,27 +182,27 @@ static unsigned short ali15x3_smba = 0;
|
||||
defined to make the transition easier. */
|
||||
int ali15x3_setup(void)
|
||||
{
|
||||
int error_return=0;
|
||||
unsigned char temp;
|
||||
int error_return = 0;
|
||||
unsigned char temp;
|
||||
|
||||
struct pci_dev *ALI15X3_dev;
|
||||
struct pci_dev *ALI15X3_dev;
|
||||
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-ali15x3.o: Error: No PCI-bus found!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-ali15x3.o: Error: No PCI-bus found!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Look for the ALI15X3, M7101 device */
|
||||
ALI15X3_dev = NULL;
|
||||
ALI15X3_dev = pci_find_device(PCI_VENDOR_ID_AL,
|
||||
PCI_DEVICE_ID_AL_M7101, ALI15X3_dev);
|
||||
if(ALI15X3_dev == NULL) {
|
||||
printk("i2c-ali15x3.o: Error: Can't detect ali15x3!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* Look for the ALI15X3, M7101 device */
|
||||
ALI15X3_dev = NULL;
|
||||
ALI15X3_dev = pci_find_device(PCI_VENDOR_ID_AL,
|
||||
PCI_DEVICE_ID_AL_M7101, ALI15X3_dev);
|
||||
if (ALI15X3_dev == NULL) {
|
||||
printk("i2c-ali15x3.o: Error: Can't detect ali15x3!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Check the following things:
|
||||
- SMB I/O address is initialized
|
||||
@@ -214,66 +215,71 @@ int ali15x3_setup(void)
|
||||
if the lock bits are 1, but in fact the address registers
|
||||
are zero unless you clear the lock bits.
|
||||
*/
|
||||
pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);
|
||||
if(temp & ALI15X3_LOCK)
|
||||
{
|
||||
temp &= ~ALI15X3_LOCK;
|
||||
pci_write_config_byte(ALI15X3_dev, SMBATPC, temp);
|
||||
}
|
||||
pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);
|
||||
if (temp & ALI15X3_LOCK) {
|
||||
temp &= ~ALI15X3_LOCK;
|
||||
pci_write_config_byte(ALI15X3_dev, SMBATPC, temp);
|
||||
}
|
||||
|
||||
/* Determine the address of the SMBus area */
|
||||
pci_read_config_word(ALI15X3_dev, SMBBA,&ali15x3_smba);
|
||||
ali15x3_smba &= (0xffff & ~ (ALI15X3_SMB_IOSIZE - 1));
|
||||
if(ali15x3_smba == 0) {
|
||||
printk("i2c-ali15x3.o: ALI15X3_smb region uninitialized - upgrade BIOS?\n");
|
||||
error_return=-ENODEV;
|
||||
}
|
||||
pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba);
|
||||
ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1));
|
||||
if (ali15x3_smba == 0) {
|
||||
printk
|
||||
("i2c-ali15x3.o: ALI15X3_smb region uninitialized - upgrade BIOS?\n");
|
||||
error_return = -ENODEV;
|
||||
}
|
||||
|
||||
if(error_return == -ENODEV)
|
||||
goto END;
|
||||
if (error_return == -ENODEV)
|
||||
goto END;
|
||||
|
||||
if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) {
|
||||
printk("i2c-ali15x3.o: ALI15X3_smb region 0x%x already in use!\n", ali15x3_smba);
|
||||
error_return=-ENODEV;
|
||||
}
|
||||
if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) {
|
||||
printk
|
||||
("i2c-ali15x3.o: ALI15X3_smb region 0x%x already in use!\n",
|
||||
ali15x3_smba);
|
||||
error_return = -ENODEV;
|
||||
}
|
||||
|
||||
if(error_return == -ENODEV)
|
||||
goto END;
|
||||
if (error_return == -ENODEV)
|
||||
goto END;
|
||||
|
||||
/* check if whole device is enabled */
|
||||
pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);
|
||||
if ((temp & 1) == 0) {
|
||||
printk("SMBUS: Error: SMB device not enabled - upgrade BIOS?\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);
|
||||
if ((temp & 1) == 0) {
|
||||
printk
|
||||
("SMBUS: Error: SMB device not enabled - upgrade BIOS?\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Is SMB Host controller enabled? */
|
||||
pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
|
||||
pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
|
||||
#ifdef FORCE_ALI15X3_ENABLE
|
||||
/* This should never need to be done.
|
||||
NOTE: This assumes I/O space and other allocations WERE
|
||||
done by the Bios! Don't complain if your hardware does weird
|
||||
things after enabling this. :') Check for Bios updates before
|
||||
resorting to this. */
|
||||
if ((temp & 1) == 0) {
|
||||
pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 1);
|
||||
printk("i2c-ali15x3.o: WARNING: ALI15X3 SMBus interface has been FORCEFULLY "
|
||||
"ENABLED!!\n");
|
||||
}
|
||||
#else /* FORCE_ALI15X3_ENABLE */
|
||||
if ((temp & 1) == 0) {
|
||||
printk("SMBUS: Error: Host SMBus controller not enabled - upgrade BIOS?\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
#endif /* FORCE_ALI15X3_ENABLE */
|
||||
if ((temp & 1) == 0) {
|
||||
pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 1);
|
||||
printk
|
||||
("i2c-ali15x3.o: WARNING: ALI15X3 SMBus interface has been FORCEFULLY "
|
||||
"ENABLED!!\n");
|
||||
}
|
||||
#else /* FORCE_ALI15X3_ENABLE */
|
||||
if ((temp & 1) == 0) {
|
||||
printk
|
||||
("SMBUS: Error: Host SMBus controller not enabled - upgrade BIOS?\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
#endif /* FORCE_ALI15X3_ENABLE */
|
||||
|
||||
/* set SMB clock to 74KHz as recommended in data sheet */
|
||||
pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
|
||||
pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
|
||||
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb");
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb");
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
@@ -283,43 +289,44 @@ int ali15x3_setup(void)
|
||||
if ((....... & 0x0F) == 1)
|
||||
printk("i2c-ali15x3.o: ALI15X3 using Interrupt 9 for SMBus.\n");
|
||||
*/
|
||||
pci_read_config_byte(ALI15X3_dev, SMBREV, &temp);
|
||||
printk("i2c-ali15x3.o: SMBREV = 0x%X\n",temp);
|
||||
printk("i2c-ali15x3.o: ALI15X3_smba = 0x%X\n",ali15x3_smba);
|
||||
#endif /* DEBUG */
|
||||
pci_read_config_byte(ALI15X3_dev, SMBREV, &temp);
|
||||
printk("i2c-ali15x3.o: SMBREV = 0x%X\n", temp);
|
||||
printk("i2c-ali15x3.o: ALI15X3_smba = 0x%X\n", ali15x3_smba);
|
||||
#endif /* DEBUG */
|
||||
|
||||
END:
|
||||
return error_return;
|
||||
END:
|
||||
return error_return;
|
||||
}
|
||||
|
||||
|
||||
/* Internally used pause function */
|
||||
void ali15x3_do_pause( unsigned int amount )
|
||||
void ali15x3_do_pause(unsigned int amount)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
}
|
||||
|
||||
/* Another internally used function */
|
||||
int ali15x3_transaction(void)
|
||||
int ali15x3_transaction(void)
|
||||
{
|
||||
int temp;
|
||||
int result=0;
|
||||
int timeout=0;
|
||||
int temp;
|
||||
int result = 0;
|
||||
int timeout = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
|
||||
"DAT1=%02x\n",
|
||||
inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
|
||||
"DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
|
||||
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
|
||||
/* get status */
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
/* get status */
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
/* Check the busy bit first */
|
||||
if (temp & ALI15X3_STS_BUSY) {
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
/* Check the busy bit first */
|
||||
if (temp & ALI15X3_STS_BUSY) {
|
||||
/*
|
||||
If the host controller is still busy, it may have timed out in the previous transaction,
|
||||
resulting in a "SMBus Timeout" printk.
|
||||
@@ -341,61 +348,67 @@ int ali15x3_transaction(void)
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
if (temp & ALI15X3_STS_BUSY) {
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Try resetting entire SMB bus, including other devices -
|
||||
This may not work either - it clears the BUSY bit but
|
||||
then the BUSY bit may come back on when you try and use the chip again.
|
||||
If that's the case you are stuck.
|
||||
*/
|
||||
printk("i2c-ali15x3.o: Resetting entire SMB Bus to clear busy condition (%02x)\n",temp);
|
||||
outb_p(ALI15X3_T_OUT, SMBHSTCNT);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
}
|
||||
printk
|
||||
("i2c-ali15x3.o: Resetting entire SMB Bus to clear busy condition (%02x)\n",
|
||||
temp);
|
||||
outb_p(ALI15X3_T_OUT, SMBHSTCNT);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
}
|
||||
/*
|
||||
}
|
||||
*/
|
||||
|
||||
/* now check the error bits and the busy bit */
|
||||
if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
|
||||
/* do a clear-on-write */
|
||||
outb_p(0xFF, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
|
||||
/* this is probably going to be correctable only by a power reset
|
||||
as one of the bits now appears to be stuck */
|
||||
/* This may be a bus or device with electrical problems. */
|
||||
printk("i2c-ali15x3.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n",temp);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* check and clear done bit */
|
||||
if (temp & ALI15X3_STS_DONE) {
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
}
|
||||
}
|
||||
/* now check the error bits and the busy bit */
|
||||
if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
|
||||
/* do a clear-on-write */
|
||||
outb_p(0xFF, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) &
|
||||
(ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
|
||||
/* this is probably going to be correctable only by a power reset
|
||||
as one of the bits now appears to be stuck */
|
||||
/* This may be a bus or device with electrical problems. */
|
||||
printk
|
||||
("i2c-ali15x3.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n",
|
||||
temp);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* check and clear done bit */
|
||||
if (temp & ALI15X3_STS_DONE) {
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
}
|
||||
}
|
||||
|
||||
/* start the transaction by writing anything to the start register */
|
||||
outb_p(0xFF, SMBHSTSTART);
|
||||
/* start the transaction by writing anything to the start register */
|
||||
outb_p(0xFF, SMBHSTSTART);
|
||||
|
||||
/* We will always wait for a fraction of a second! */
|
||||
timeout = 0;
|
||||
do {
|
||||
ali15x3_do_pause(1);
|
||||
temp=inb_p(SMBHSTSTS);
|
||||
} while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE))) && (timeout++ < MAX_TIMEOUT));
|
||||
/* We will always wait for a fraction of a second! */
|
||||
timeout = 0;
|
||||
do {
|
||||
ali15x3_do_pause(1);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
} while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))
|
||||
&& (timeout++ < MAX_TIMEOUT));
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
result = -1;
|
||||
printk("i2c-ali15x3.o: SMBus Timeout!\n");
|
||||
}
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
result = -1;
|
||||
printk("i2c-ali15x3.o: SMBus Timeout!\n");
|
||||
}
|
||||
|
||||
if (temp & ALI15X3_STS_TERM) {
|
||||
result = -1;
|
||||
if (temp & ALI15X3_STS_TERM) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-ali15x3.o: Error: Failed bus transaction\n");
|
||||
printk("i2c-ali15x3.o: Error: Failed bus transaction\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Unfortunately the ALI SMB controller maps "no response" and "bus collision"
|
||||
@@ -403,136 +416,148 @@ int ali15x3_transaction(void)
|
||||
do a printk.
|
||||
This means that bus collisions go unreported.
|
||||
*/
|
||||
if (temp & ALI15X3_STS_COLL) {
|
||||
result = -1;
|
||||
if (temp & ALI15X3_STS_COLL) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-ali15x3.o: Error: no response or bus collision ADD=%02x\n", inb_p(SMBHSTADD));
|
||||
printk
|
||||
("i2c-ali15x3.o: Error: no response or bus collision ADD=%02x\n",
|
||||
inb_p(SMBHSTADD));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* haven't ever seen this */
|
||||
if (temp & ALI15X3_STS_DEV) {
|
||||
result = -1;
|
||||
printk("i2c-ali15x3.o: Error: device error\n");
|
||||
}
|
||||
|
||||
if (temp & ALI15X3_STS_DEV) {
|
||||
result = -1;
|
||||
printk("i2c-ali15x3.o: Error: device error\n");
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("i2c-ali15x3.o: Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n",
|
||||
inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-ali15x3.o: Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
|
||||
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return -1 on error. See smbus.h for more information */
|
||||
s32 ali15x3_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
|
||||
char read_write, u8 command, int size,
|
||||
union i2c_smbus_data * data)
|
||||
s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
|
||||
unsigned short flags, char read_write, u8 command,
|
||||
int size, union i2c_smbus_data * data)
|
||||
{
|
||||
int i,len;
|
||||
int temp;
|
||||
int timeout;
|
||||
int i, len;
|
||||
int temp;
|
||||
int timeout;
|
||||
|
||||
/* clear all the bits (clear-on-write) */
|
||||
outb_p(0xFF, SMBHSTSTS);
|
||||
outb_p(0xFF, SMBHSTSTS);
|
||||
/* make sure SMBus is idle */
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
for(timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++)
|
||||
{
|
||||
ali15x3_do_pause(1);
|
||||
temp=inb_p(SMBHSTSTS);
|
||||
}
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
printk("i2c-ali15x3.o: Idle wait Timeout! STS=0x%02x\n", temp);
|
||||
}
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
for (timeout = 0;
|
||||
(timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);
|
||||
timeout++) {
|
||||
ali15x3_do_pause(1);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
}
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
printk("i2c-ali15x3.o: Idle wait Timeout! STS=0x%02x\n",
|
||||
temp);
|
||||
}
|
||||
|
||||
switch(size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk("i2c-ali15x3.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
size = ALI15X3_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMBHSTCMD);
|
||||
size = ALI15X3_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->byte,SMBHSTDAT0);
|
||||
size = ALI15X3_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->word & 0xff,SMBHSTDAT0);
|
||||
outb_p((data->word & 0xff00) >> 8,SMBHSTDAT1);
|
||||
}
|
||||
size = ALI15X3_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 0) {
|
||||
len = 0;
|
||||
data->block[0] = len;
|
||||
}
|
||||
if (len > 32) {
|
||||
len = 32;
|
||||
data->block[0] = len;
|
||||
}
|
||||
outb_p(len,SMBHSTDAT0);
|
||||
outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= len; i++)
|
||||
outb_p(data->block[i],SMBBLKDAT);
|
||||
}
|
||||
size = ALI15X3_BLOCK_DATA;
|
||||
break;
|
||||
}
|
||||
switch (size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk
|
||||
("i2c-ali15x3.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
size = ALI15X3_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMBHSTCMD);
|
||||
size = ALI15X3_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->byte, SMBHSTDAT0);
|
||||
size = ALI15X3_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->word & 0xff, SMBHSTDAT0);
|
||||
outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
|
||||
}
|
||||
size = ALI15X3_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 0) {
|
||||
len = 0;
|
||||
data->block[0] = len;
|
||||
}
|
||||
if (len > 32) {
|
||||
len = 32;
|
||||
data->block[0] = len;
|
||||
}
|
||||
outb_p(len, SMBHSTDAT0);
|
||||
outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= len; i++)
|
||||
outb_p(data->block[i], SMBBLKDAT);
|
||||
}
|
||||
size = ALI15X3_BLOCK_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
outb_p(size, SMBHSTCNT); /* output command */
|
||||
outb_p(size, SMBHSTCNT); /* output command */
|
||||
|
||||
if (ali15x3_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
|
||||
return 0;
|
||||
|
||||
if (ali15x3_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
switch(size) {
|
||||
case ALI15X3_BYTE: /* Result put in SMBHSTDAT0 */
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case ALI15X3_BYTE_DATA:
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case ALI15X3_WORD_DATA:
|
||||
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
case ALI15X3_BLOCK_DATA:
|
||||
len = inb_p(SMBHSTDAT0);
|
||||
if(len > 32)
|
||||
len = 32;
|
||||
data->block[0] = len;
|
||||
outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= data->block[0]; i++) {
|
||||
data->block[i] = inb_p(SMBBLKDAT);
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
|
||||
return 0;
|
||||
|
||||
|
||||
switch (size) {
|
||||
case ALI15X3_BYTE: /* Result put in SMBHSTDAT0 */
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case ALI15X3_BYTE_DATA:
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case ALI15X3_WORD_DATA:
|
||||
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
case ALI15X3_BLOCK_DATA:
|
||||
len = inb_p(SMBHSTDAT0);
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
data->block[0] = len;
|
||||
outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= data->block[0]; i++) {
|
||||
data->block[i] = inb_p(SMBBLKDAT);
|
||||
#ifdef DEBUG
|
||||
printk("i2c-ali15x3.o: Blk: len=%d, i=%d, data=%02x\n", len, i, data->block[i]);
|
||||
#endif DEBUG
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
printk
|
||||
("i2c-ali15x3.o: Blk: len=%d, i=%d, data=%02x\n",
|
||||
len, i, data->block[i]);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ali15x3_inc(struct i2c_adapter *adapter)
|
||||
@@ -549,72 +574,78 @@ void ali15x3_dec(struct i2c_adapter *adapter)
|
||||
u32 ali15x3_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
}
|
||||
|
||||
int __init i2c_ali15x3_init(void)
|
||||
{
|
||||
int res;
|
||||
printk("ali15x3.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
int res;
|
||||
printk("ali15x3.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
#ifdef DEBUG
|
||||
/* PE- It might be good to make this a permanent part of the code! */
|
||||
if (ali15x3_initialized) {
|
||||
printk("i2c-ali15x3.o: Oops, ali15x3_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (ali15x3_initialized) {
|
||||
printk
|
||||
("i2c-ali15x3.o: Oops, ali15x3_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
ali15x3_initialized = 0;
|
||||
if ((res = ali15x3_setup())) {
|
||||
printk("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n");
|
||||
ali15x3_cleanup();
|
||||
return res;
|
||||
}
|
||||
ali15x3_initialized ++;
|
||||
sprintf(ali15x3_adapter.name,"SMBus ALI15X3 adapter at %04x",ali15x3_smba);
|
||||
if ((res = i2c_add_adapter(&ali15x3_adapter))) {
|
||||
printk("i2c-ali15x3.o: Adapter registration failed, module not inserted.\n");
|
||||
ali15x3_cleanup();
|
||||
return res;
|
||||
}
|
||||
ali15x3_initialized++;
|
||||
printk("i2c-ali15x3.o: ALI15X3 SMBus Controller detected and initialized\n");
|
||||
return 0;
|
||||
ali15x3_initialized = 0;
|
||||
if ((res = ali15x3_setup())) {
|
||||
printk
|
||||
("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n");
|
||||
ali15x3_cleanup();
|
||||
return res;
|
||||
}
|
||||
ali15x3_initialized++;
|
||||
sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
|
||||
ali15x3_smba);
|
||||
if ((res = i2c_add_adapter(&ali15x3_adapter))) {
|
||||
printk
|
||||
("i2c-ali15x3.o: Adapter registration failed, module not inserted.\n");
|
||||
ali15x3_cleanup();
|
||||
return res;
|
||||
}
|
||||
ali15x3_initialized++;
|
||||
printk
|
||||
("i2c-ali15x3.o: ALI15X3 SMBus Controller detected and initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init ali15x3_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
if (ali15x3_initialized >= 2)
|
||||
{
|
||||
if ((res = i2c_del_adapter(&ali15x3_adapter))) {
|
||||
printk("i2c-ali15x3.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
ali15x3_initialized--;
|
||||
}
|
||||
if (ali15x3_initialized >= 1) {
|
||||
release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
|
||||
ali15x3_initialized--;
|
||||
}
|
||||
return 0;
|
||||
int res;
|
||||
if (ali15x3_initialized >= 2) {
|
||||
if ((res = i2c_del_adapter(&ali15x3_adapter))) {
|
||||
printk
|
||||
("i2c-ali15x3.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
ali15x3_initialized--;
|
||||
}
|
||||
if (ali15x3_initialized >= 1) {
|
||||
release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
|
||||
ali15x3_initialized--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
|
||||
MODULE_DESCRIPTION("ALI15X3 SMBus driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_ali15x3_init();
|
||||
return i2c_ali15x3_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return ali15x3_cleanup();
|
||||
return ali15x3_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
+285
-263
@@ -54,10 +54,10 @@
|
||||
/* PCI Address Constants */
|
||||
|
||||
/* address of I/O space */
|
||||
#define SMBBA 0x058 /* mh */
|
||||
#define SMBBA 0x058 /* mh */
|
||||
|
||||
/* general configuration */
|
||||
#define SMBGCFG 0x041 /* mh */
|
||||
#define SMBGCFG 0x041 /* mh */
|
||||
|
||||
/* silicon revision code */
|
||||
#define SMBREV 0x008
|
||||
@@ -80,13 +80,13 @@ static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init i2c_amd756_init(void);
|
||||
int __init i2c_amd756_init(void);
|
||||
static int __init amd756_cleanup(void);
|
||||
static int amd756_setup(void);
|
||||
static s32 amd756_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data);
|
||||
static void amd756_do_pause( unsigned int amount );
|
||||
static s32 amd756_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data *data);
|
||||
static void amd756_do_pause(unsigned int amount);
|
||||
static int amd756_transaction(void);
|
||||
static void amd756_inc(struct i2c_adapter *adapter);
|
||||
static void amd756_dec(struct i2c_adapter *adapter);
|
||||
@@ -95,28 +95,28 @@ static u32 amd756_func(struct i2c_adapter *adapter);
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ amd756_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ amd756_func,
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ amd756_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ amd756_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter amd756_adapter = {
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
amd756_inc,
|
||||
amd756_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
amd756_inc,
|
||||
amd756_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __initdata amd756_initialized;
|
||||
@@ -131,72 +131,77 @@ static unsigned short amd756_smba = 0;
|
||||
defined to make the transition easier. */
|
||||
int amd756_setup(void)
|
||||
{
|
||||
int error_return=0;
|
||||
unsigned char temp;
|
||||
int error_return = 0;
|
||||
unsigned char temp;
|
||||
|
||||
struct pci_dev *AMD756_dev;
|
||||
struct pci_dev *AMD756_dev;
|
||||
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-amd756.o: Error: No PCI-bus found!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-amd756.o: Error: No PCI-bus found!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Look for the AMD756, function 3 */
|
||||
/* Note: we keep on searching until we have found 'function 3' */
|
||||
AMD756_dev = NULL;
|
||||
do
|
||||
AMD756_dev = pci_find_device(PCI_VENDOR_ID_AMD,
|
||||
PCI_DEVICE_ID_AMD_756, AMD756_dev);
|
||||
while (AMD756_dev && (PCI_FUNC(AMD756_dev->devfn) != 3));
|
||||
if(AMD756_dev == NULL) {
|
||||
printk("i2c-amd756.o: Error: Can't detect AMD756, function 3!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* Look for the AMD756, function 3 */
|
||||
/* Note: we keep on searching until we have found 'function 3' */
|
||||
AMD756_dev = NULL;
|
||||
do
|
||||
AMD756_dev = pci_find_device(PCI_VENDOR_ID_AMD,
|
||||
PCI_DEVICE_ID_AMD_756,
|
||||
AMD756_dev);
|
||||
while (AMD756_dev && (PCI_FUNC(AMD756_dev->devfn) != 3));
|
||||
if (AMD756_dev == NULL) {
|
||||
printk
|
||||
("i2c-amd756.o: Error: Can't detect AMD756, function 3!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Determine the address of the SMBus areas */
|
||||
|
||||
/* Technically it is a dword but... */
|
||||
pci_read_config_word(AMD756_dev, SMBBA, &amd756_smba);
|
||||
amd756_smba &= 0xfff0;
|
||||
/* Technically it is a dword but... */
|
||||
pci_read_config_word(AMD756_dev, SMBBA, &amd756_smba);
|
||||
amd756_smba &= 0xfff0;
|
||||
|
||||
if (check_region(amd756_smba, 8)) {
|
||||
printk("i2c-amd756.o: AMD756_smb region 0x%x already in use!\n", amd756_smba);
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
if (check_region(amd756_smba, 8)) {
|
||||
printk
|
||||
("i2c-amd756.o: AMD756_smb region 0x%x already in use!\n",
|
||||
amd756_smba);
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pci_read_config_byte(AMD756_dev, SMBGCFG, &temp);
|
||||
pci_read_config_byte(AMD756_dev, SMBGCFG, &temp);
|
||||
|
||||
if ((temp & 128) == 0) {
|
||||
printk("SMBUS: Error: Host SMBus controller I/O not enabled!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
if ((temp & 128) == 0) {
|
||||
printk
|
||||
("SMBUS: Error: Host SMBus controller I/O not enabled!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(amd756_smba, 8, "amd756-smbus");
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(amd756_smba, 8, "amd756-smbus");
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
if ((temp & 0x0E) == 8)
|
||||
printk("i2c-amd756.o: AMD756 using Interrupt 9 for SMBus.\n");
|
||||
else if ((temp & 0x0E) == 0)
|
||||
printk("i2c-amd756.o: AMD756 using Interrupt SMI# for SMBus.\n");
|
||||
else
|
||||
printk("i2c-amd756.o: AMD756: Illegal Interrupt configuration (or code out "
|
||||
"of date)!\n");
|
||||
*/
|
||||
/*
|
||||
if ((temp & 0x0E) == 8)
|
||||
printk("i2c-amd756.o: AMD756 using Interrupt 9 for SMBus.\n");
|
||||
else if ((temp & 0x0E) == 0)
|
||||
printk("i2c-amd756.o: AMD756 using Interrupt SMI# for SMBus.\n");
|
||||
else
|
||||
printk("i2c-amd756.o: AMD756: Illegal Interrupt configuration (or code out "
|
||||
"of date)!\n");
|
||||
*/
|
||||
|
||||
pci_read_config_byte(AMD756_dev, SMBREV, &temp);
|
||||
printk("i2c-amd756.o: SMBREV = 0x%X\n",temp);
|
||||
printk("i2c-amd756.o: AMD756_smba = 0x%X\n",amd756_smba);
|
||||
#endif /* DEBUG */
|
||||
pci_read_config_byte(AMD756_dev, SMBREV, &temp);
|
||||
printk("i2c-amd756.o: SMBREV = 0x%X\n", temp);
|
||||
printk("i2c-amd756.o: AMD756_smba = 0x%X\n", amd756_smba);
|
||||
#endif /* DEBUG */
|
||||
|
||||
END:
|
||||
return error_return;
|
||||
END:
|
||||
return error_return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -206,13 +211,13 @@ END:
|
||||
*/
|
||||
|
||||
/* Internally used pause function */
|
||||
void amd756_do_pause( unsigned int amount )
|
||||
void amd756_do_pause(unsigned int amount)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
}
|
||||
|
||||
#define GS_ABRT_STS (1 << 0)
|
||||
#define GS_ABRT_STS (1 << 0)
|
||||
#define GS_COL_STS (1 << 1)
|
||||
#define GS_PRERR_STS (1 << 2)
|
||||
#define GS_HST_STS (1 << 3)
|
||||
@@ -222,186 +227,200 @@ void amd756_do_pause( unsigned int amount )
|
||||
#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \
|
||||
GS_HCYC_STS | GS_TO_STS )
|
||||
|
||||
#define GE_CYC_TYPE_MASK (7)
|
||||
#define GE_HOST_STC (1 << 3)
|
||||
|
||||
#define GE_CYC_TYPE_MASK (7)
|
||||
#define GE_HOST_STC (1 << 3)
|
||||
|
||||
/* Another internally used function */
|
||||
int amd756_transaction(void)
|
||||
int amd756_transaction(void)
|
||||
{
|
||||
int temp;
|
||||
int result=0;
|
||||
int timeout=0;
|
||||
int temp;
|
||||
int result = 0;
|
||||
int timeout = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("i2c-amd756.o: Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
|
||||
inw_p(SMB_GLOBAL_STATUS),inw_p(SMB_GLOBAL_ENABLE),inw_p(SMB_HOST_ADDRESS),inb_p(SMB_HOST_DATA));
|
||||
printk
|
||||
("i2c-amd756.o: Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
|
||||
inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
|
||||
inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
|
||||
#endif
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
/* TODO: What about SM_BSY? */
|
||||
if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_HST_STS) != 0x00) {
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
/* TODO: What about SM_BSY? */
|
||||
if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_HST_STS) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-amd756.o: SMBus busy (%04x). Resetting (NOT)... \n",temp);
|
||||
printk
|
||||
("i2c-amd756.o: SMBus busy (%04x). Resetting (NOT)... \n",
|
||||
temp);
|
||||
#endif
|
||||
/* TODO: How to reset the AMD?
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
*/
|
||||
if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_HST_STS) != 0x00) {
|
||||
/* TODO: How to reset the AMD?
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
*/
|
||||
if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_HST_STS) !=
|
||||
0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-amd756.o: Failed! (%04x)\n",temp);
|
||||
printk("i2c-amd756.o: Failed! (%04x)\n", temp);
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-amd756.o: Successfull!\n");
|
||||
printk("i2c-amd756.o: Successfull!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* start the transaction by setting bit 6 */
|
||||
outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE);
|
||||
/* start the transaction by setting bit 6 */
|
||||
outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE);
|
||||
|
||||
/* We will always wait for a fraction of a second! */
|
||||
do {
|
||||
amd756_do_pause(1);
|
||||
temp=inw_p(SMB_GLOBAL_STATUS);
|
||||
} while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
|
||||
/* We will always wait for a fraction of a second! */
|
||||
do {
|
||||
amd756_do_pause(1);
|
||||
temp = inw_p(SMB_GLOBAL_STATUS);
|
||||
} while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-amd756.o: SMBus explicit timeout!\n");
|
||||
result = -1;
|
||||
printk("i2c-amd756.o: SMBus explicit timeout!\n");
|
||||
result = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & GS_PRERR_STS) {
|
||||
result = -1;
|
||||
if (temp & GS_PRERR_STS) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-amd756.o: SMBus Protocol error!\n");
|
||||
printk("i2c-amd756.o: SMBus Protocol error!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & GS_COL_STS) {
|
||||
result = -1;
|
||||
printk("i2c-amd756.o: SMBus collision!\n");
|
||||
/* TODO: Clear Collision Status with a 1 */
|
||||
}
|
||||
if (temp & GS_COL_STS) {
|
||||
result = -1;
|
||||
printk("i2c-amd756.o: SMBus collision!\n");
|
||||
/* TODO: Clear Collision Status with a 1 */
|
||||
}
|
||||
|
||||
if (temp & GS_TO_STS) {
|
||||
result = -1;
|
||||
if (temp & GS_TO_STS) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-amd756.o: SMBus protocol timeout!\n");
|
||||
printk("i2c-amd756.o: SMBus protocol timeout!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (temp & GS_HCYC_STS) {
|
||||
printk("i2c-amd756.o: SMBus protocol success!\n");
|
||||
}
|
||||
if (temp & GS_HCYC_STS) {
|
||||
printk("i2c-amd756.o: SMBus protocol success!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
outw_p (GS_CLEAR_STS, SMB_GLOBAL_STATUS);
|
||||
outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
|
||||
|
||||
if (((temp = inw_p (SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) {
|
||||
if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-amd756.o: Failed reset at end of transaction (%04x)\n",temp);
|
||||
printk
|
||||
("i2c-amd756.o: Failed reset at end of transaction (%04x)\n",
|
||||
temp);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("i2c-amd756.o: Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
|
||||
inw_p(SMB_GLOBAL_STATUS),inw_p(SMB_GLOBAL_ENABLE),inw_p(SMB_HOST_ADDRESS),inb_p(SMB_HOST_DATA));
|
||||
printk
|
||||
("i2c-amd756.o: Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
|
||||
inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
|
||||
inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return -1 on error. See smbus.h for more information */
|
||||
s32 amd756_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
s32 amd756_access(struct i2c_adapter * adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
{
|
||||
int i,len;
|
||||
|
||||
int i, len;
|
||||
|
||||
/** TODO: Should I supporte the 10-bit transfers? */
|
||||
switch(size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk("i2c-amd756.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
/* TODO: Well... It is supported, I'm just not sure what to do here... */
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outw_p (((addr & 0x7f) << 1) | (read_write & 0x01), SMB_HOST_ADDRESS);
|
||||
size = AMD756_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outw_p (((addr & 0x7f) << 1) | (read_write & 0x01), SMB_HOST_ADDRESS);
|
||||
/* TODO: Why only during write? */
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p (command, SMB_HOST_COMMAND);
|
||||
size = AMD756_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outw_p (((addr & 0x7f) << 1) | (read_write & 0x01), SMB_HOST_ADDRESS);
|
||||
outb_p (command, SMB_HOST_COMMAND);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outw_p(data->byte, SMB_HOST_DATA);
|
||||
size = AMD756_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outw_p (((addr & 0x7f) << 1) | (read_write & 0x01), SMB_HOST_ADDRESS);
|
||||
outb_p (command, SMB_HOST_COMMAND);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outw_p (data->word, SMB_HOST_DATA); /* TODO: endian???? */
|
||||
size = AMD756_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outw_p (((addr & 0x7f) << 1) | (read_write & 0x01), SMB_HOST_ADDRESS);
|
||||
outb_p (command, SMB_HOST_COMMAND);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
outw_p (len, SMB_HOST_DATA);
|
||||
/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
|
||||
for (i = 1; i <= len; i ++)
|
||||
outb_p (data->block[i], SMB_HOST_BLOCK_DATA);
|
||||
}
|
||||
size = AMD756_BLOCK_DATA;
|
||||
break;
|
||||
}
|
||||
switch (size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk
|
||||
("i2c-amd756.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
/* TODO: Well... It is supported, I'm just not sure what to do here... */
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMB_HOST_ADDRESS);
|
||||
size = AMD756_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMB_HOST_ADDRESS);
|
||||
/* TODO: Why only during write? */
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMB_HOST_COMMAND);
|
||||
size = AMD756_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMB_HOST_ADDRESS);
|
||||
outb_p(command, SMB_HOST_COMMAND);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outw_p(data->byte, SMB_HOST_DATA);
|
||||
size = AMD756_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMB_HOST_ADDRESS);
|
||||
outb_p(command, SMB_HOST_COMMAND);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */
|
||||
size = AMD756_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMB_HOST_ADDRESS);
|
||||
outb_p(command, SMB_HOST_COMMAND);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
outw_p(len, SMB_HOST_DATA);
|
||||
/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
|
||||
for (i = 1; i <= len; i++)
|
||||
outb_p(data->block[i],
|
||||
SMB_HOST_BLOCK_DATA);
|
||||
}
|
||||
size = AMD756_BLOCK_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
/* How about enabling interrupts... */
|
||||
outw_p (size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
|
||||
/* How about enabling interrupts... */
|
||||
outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
|
||||
|
||||
if (amd756_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
|
||||
return 0;
|
||||
|
||||
if (amd756_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
switch(size) {
|
||||
case AMD756_BYTE:
|
||||
data->byte = inw_p (SMB_HOST_DATA);
|
||||
break;
|
||||
case AMD756_BYTE_DATA:
|
||||
data->byte = inw_p (SMB_HOST_DATA);
|
||||
break;
|
||||
case AMD756_WORD_DATA:
|
||||
data->word = inw_p (SMB_HOST_DATA); /* TODO: endian???? */
|
||||
break;
|
||||
case AMD756_BLOCK_DATA:
|
||||
data->block[0] = inw_p (SMB_HOST_DATA & 63);
|
||||
/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
|
||||
for (i = 1; i <= data->block[0]; i++)
|
||||
data->block[i] = inb_p (SMB_HOST_BLOCK_DATA);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
|
||||
return 0;
|
||||
|
||||
|
||||
switch (size) {
|
||||
case AMD756_BYTE:
|
||||
data->byte = inw_p(SMB_HOST_DATA);
|
||||
break;
|
||||
case AMD756_BYTE_DATA:
|
||||
data->byte = inw_p(SMB_HOST_DATA);
|
||||
break;
|
||||
case AMD756_WORD_DATA:
|
||||
data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */
|
||||
break;
|
||||
case AMD756_BLOCK_DATA:
|
||||
data->block[0] = inw_p(SMB_HOST_DATA & 63);
|
||||
/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
|
||||
for (i = 1; i <= data->block[0]; i++)
|
||||
data->block[i] = inb_p(SMB_HOST_BLOCK_DATA);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amd756_inc(struct i2c_adapter *adapter)
|
||||
@@ -417,56 +436,60 @@ void amd756_dec(struct i2c_adapter *adapter)
|
||||
|
||||
u32 amd756_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL;
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL;
|
||||
}
|
||||
|
||||
int __init i2c_amd756_init(void)
|
||||
{
|
||||
int res;
|
||||
printk("amd756.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
int res;
|
||||
printk("amd756.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
#ifdef DEBUG
|
||||
/* PE- It might be good to make this a permanent part of the code! */
|
||||
if (amd756_initialized) {
|
||||
printk("i2c-amd756.o: Oops, amd756_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (amd756_initialized) {
|
||||
printk
|
||||
("i2c-amd756.o: Oops, amd756_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
amd756_initialized = 0;
|
||||
if ((res = amd756_setup())) {
|
||||
printk("i2c-amd756.o: AMD756 not detected, module not inserted.\n");
|
||||
amd756_cleanup();
|
||||
return res;
|
||||
}
|
||||
amd756_initialized ++;
|
||||
sprintf(amd756_adapter.name,"SMBus AMD756 adapter at %04x",amd756_smba);
|
||||
if ((res = i2c_add_adapter(&amd756_adapter))) {
|
||||
printk("i2c-amd756.o: Adapter registration failed, module not inserted.\n");
|
||||
amd756_cleanup();
|
||||
return res;
|
||||
}
|
||||
amd756_initialized++;
|
||||
printk("i2c-amd756.o: AMD756 bus detected and initialized\n");
|
||||
return 0;
|
||||
amd756_initialized = 0;
|
||||
if ((res = amd756_setup())) {
|
||||
printk
|
||||
("i2c-amd756.o: AMD756 not detected, module not inserted.\n");
|
||||
amd756_cleanup();
|
||||
return res;
|
||||
}
|
||||
amd756_initialized++;
|
||||
sprintf(amd756_adapter.name, "SMBus AMD756 adapter at %04x",
|
||||
amd756_smba);
|
||||
if ((res = i2c_add_adapter(&amd756_adapter))) {
|
||||
printk
|
||||
("i2c-amd756.o: Adapter registration failed, module not inserted.\n");
|
||||
amd756_cleanup();
|
||||
return res;
|
||||
}
|
||||
amd756_initialized++;
|
||||
printk("i2c-amd756.o: AMD756 bus detected and initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init amd756_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
if (amd756_initialized >= 2)
|
||||
{
|
||||
if ((res = i2c_del_adapter(&amd756_adapter))) {
|
||||
printk("i2c-amd756.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
amd756_initialized--;
|
||||
}
|
||||
if (amd756_initialized >= 1) {
|
||||
release_region(amd756_smba, 8);
|
||||
amd756_initialized--;
|
||||
}
|
||||
return 0;
|
||||
int res;
|
||||
if (amd756_initialized >= 2) {
|
||||
if ((res = i2c_del_adapter(&amd756_adapter))) {
|
||||
printk
|
||||
("i2c-amd756.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
amd756_initialized--;
|
||||
}
|
||||
if (amd756_initialized >= 1) {
|
||||
release_region(amd756_smba, 8);
|
||||
amd756_initialized--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
@@ -478,13 +501,12 @@ MODULE_DESCRIPTION("AMD756 SMBus driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_amd756_init();
|
||||
return i2c_amd756_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return amd756_cleanup();
|
||||
return amd756_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+29
-29
@@ -57,37 +57,37 @@ static unsigned long hydra_base;
|
||||
|
||||
static inline void pdregw(u32 val)
|
||||
{
|
||||
writel(val, hydra_base+HYDRA_CACHE_PD);
|
||||
writel(val, hydra_base + HYDRA_CACHE_PD);
|
||||
}
|
||||
|
||||
static inline u32 pdregr(void)
|
||||
{
|
||||
u32 val = readl(hydra_base+HYDRA_CACHE_PD);
|
||||
u32 val = readl(hydra_base + HYDRA_CACHE_PD);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void bit_hydra_setscl(void *data, int state)
|
||||
{
|
||||
u32 val = pdregr();
|
||||
if (state)
|
||||
val &= ~ HYDRA_SCLK_OE;
|
||||
else {
|
||||
val &= ~HYDRA_SCLK;
|
||||
val |= HYDRA_SCLK_OE;
|
||||
}
|
||||
pdregw(val);
|
||||
u32 val = pdregr();
|
||||
if (state)
|
||||
val &= ~HYDRA_SCLK_OE;
|
||||
else {
|
||||
val &= ~HYDRA_SCLK;
|
||||
val |= HYDRA_SCLK_OE;
|
||||
}
|
||||
pdregw(val);
|
||||
}
|
||||
|
||||
static void bit_hydra_setsda(void *data, int state)
|
||||
{
|
||||
u32 val = pdregr();
|
||||
if (state)
|
||||
val &= ~ HYDRA_SDAT_OE;
|
||||
else {
|
||||
val &= ~HYDRA_SDAT;
|
||||
val |= HYDRA_SDAT_OE;
|
||||
}
|
||||
pdregw(val);
|
||||
u32 val = pdregr();
|
||||
if (state)
|
||||
val &= ~HYDRA_SDAT_OE;
|
||||
else {
|
||||
val &= ~HYDRA_SDAT;
|
||||
val |= HYDRA_SDAT_OE;
|
||||
}
|
||||
pdregw(val);
|
||||
}
|
||||
|
||||
static int bit_hydra_getscl(void *data)
|
||||
@@ -118,7 +118,7 @@ struct i2c_algo_bit_data bit_hydra_data = {
|
||||
bit_hydra_setscl,
|
||||
bit_hydra_getsda,
|
||||
bit_hydra_getscl,
|
||||
5, 5, 100, /*waits, timeout */
|
||||
5, 5, 100, /*waits, timeout */
|
||||
};
|
||||
|
||||
struct i2c_adapter bit_hydra_ops = {
|
||||
@@ -140,20 +140,19 @@ static int find_hydra(void)
|
||||
|
||||
if (!pci_present())
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
dev = pci_find_device(VENDOR, DEVICE, NULL);
|
||||
if (!dev) {
|
||||
printk("Hydra not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)
|
||||
base_addr = dev->resource[0].start;
|
||||
#else
|
||||
base_addr = dev->base_address[0];
|
||||
#endif
|
||||
hydra_base = (unsigned long)ioremap(base_addr, 0x100);
|
||||
hydra_base = (unsigned long) ioremap(base_addr, 0x100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -163,21 +162,22 @@ static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init i2c_hydra_init(void)
|
||||
int __init i2c_hydra_init(void)
|
||||
{
|
||||
if (find_hydra() < 0) {
|
||||
printk("Error while reading PCI configuration\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pdregw(0); /* clear SCLK_OE and SDAT_OE */
|
||||
pdregw(0); /* clear SCLK_OE and SDAT_OE */
|
||||
|
||||
if (i2c_bit_add_bus(&bit_hydra_ops) == 0) {
|
||||
printk("Hydra i2c: Module succesfully loaded\n");
|
||||
return 0;
|
||||
} else {
|
||||
iounmap((void *)hydra_base);
|
||||
printk("Hydra i2c: Algo-bit error, couldn't register bus\n");
|
||||
iounmap((void *) hydra_base);
|
||||
printk
|
||||
("Hydra i2c: Algo-bit error, couldn't register bus\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
@@ -188,17 +188,17 @@ EXPORT_NO_SYMBOLS;
|
||||
MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
|
||||
MODULE_DESCRIPTION("i2c for Apple Hydra Mac I/O");
|
||||
|
||||
int init_module(void)
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_hydra_init();
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
void cleanup_module(void)
|
||||
{
|
||||
i2c_bit_del_bus(&bit_hydra_ops);
|
||||
if (hydra_base) {
|
||||
pdregw(0); /* clear SCLK_OE and SDAT_OE */
|
||||
iounmap((void *)hydra_base);
|
||||
iounmap((void *) hydra_base);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+398
-361
@@ -23,7 +23,7 @@
|
||||
This driver supports the Intel 82801AA and 82801AB
|
||||
I/O Controller Hubs (ICH). They are similar to the PIIX4 and are part
|
||||
of Intel's '810' chipset. See the doc/busses/i2c-i801 file for details.
|
||||
*/
|
||||
*/
|
||||
|
||||
/* Note: we assume there can only be one I801, with one SMBus interface */
|
||||
|
||||
@@ -79,24 +79,26 @@
|
||||
/* If force is set to anything different from 0, we forcibly enable the
|
||||
I801. DANGEROUS! */
|
||||
static int force = 0;
|
||||
MODULE_PARM(force,"i");
|
||||
MODULE_PARM_DESC(force,"Forcibly enable the I801. DANGEROUS!");
|
||||
MODULE_PARM(force, "i");
|
||||
MODULE_PARM_DESC(force, "Forcibly enable the I801. DANGEROUS!");
|
||||
|
||||
/* If force_addr is set to anything different from 0, we forcibly enable
|
||||
the I801 at the given address. VERY DANGEROUS! */
|
||||
static int force_addr = 0;
|
||||
MODULE_PARM(force_addr,"i");
|
||||
MODULE_PARM_DESC(force_addr,"Forcibly enable the I801 at the given address. "
|
||||
"EXTREMELY DANGEROUS!");
|
||||
MODULE_PARM(force_addr, "i");
|
||||
MODULE_PARM_DESC(force_addr,
|
||||
"Forcibly enable the I801 at the given address. "
|
||||
"EXTREMELY DANGEROUS!");
|
||||
|
||||
static int __init i801_cleanup(void);
|
||||
static int i801_setup(void);
|
||||
static s32 i801_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data);
|
||||
static void i801_do_pause( unsigned int amount );
|
||||
static s32 i801_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data *data);
|
||||
static void i801_do_pause(unsigned int amount);
|
||||
static int i801_transaction(void);
|
||||
static int i801_block_transaction(union i2c_smbus_data *data, char read_write);
|
||||
static int i801_block_transaction(union i2c_smbus_data *data,
|
||||
char read_write);
|
||||
static void i801_inc(struct i2c_adapter *adapter);
|
||||
static void i801_dec(struct i2c_adapter *adapter);
|
||||
static u32 i801_func(struct i2c_adapter *adapter);
|
||||
@@ -104,28 +106,28 @@ static u32 i801_func(struct i2c_adapter *adapter);
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ i801_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ i801_func,
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ i801_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ i801_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter i801_adapter = {
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
i801_inc,
|
||||
i801_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
i801_inc,
|
||||
i801_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __initdata i801_initialized;
|
||||
@@ -138,393 +140,424 @@ static unsigned short i801_smba = 0;
|
||||
defined to make the transition easier. */
|
||||
int i801_setup(void)
|
||||
{
|
||||
int error_return=0;
|
||||
unsigned char temp;
|
||||
int error_return = 0;
|
||||
unsigned char temp;
|
||||
|
||||
struct pci_dev *I801_dev;
|
||||
struct pci_dev *I801_dev;
|
||||
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-i801.o: Error: No PCI-bus found!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-i801.o: Error: No PCI-bus found!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Look for the I801, function 3 */
|
||||
/* Have to check for both the 82801AA and 82801AB */
|
||||
/* Note: we keep on searching until we have found 'function 3' */
|
||||
I801_dev = NULL;
|
||||
do
|
||||
I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82801AA_3, I801_dev);
|
||||
while(I801_dev && (PCI_FUNC(I801_dev->devfn) != 3));
|
||||
if(I801_dev == NULL) {
|
||||
do
|
||||
I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82801AB_3, I801_dev);
|
||||
while(I801_dev && (PCI_FUNC(I801_dev->devfn) != 3));
|
||||
}
|
||||
if(I801_dev == NULL) {
|
||||
printk("i2c-i801.o: Error: Can't detect I801, function 3!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* Look for the I801, function 3 */
|
||||
/* Have to check for both the 82801AA and 82801AB */
|
||||
/* Note: we keep on searching until we have found 'function 3' */
|
||||
I801_dev = NULL;
|
||||
do
|
||||
I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82801AA_3,
|
||||
I801_dev);
|
||||
while (I801_dev && (PCI_FUNC(I801_dev->devfn) != 3));
|
||||
if (I801_dev == NULL) {
|
||||
do
|
||||
I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82801AB_3,
|
||||
I801_dev);
|
||||
while (I801_dev && (PCI_FUNC(I801_dev->devfn) != 3));
|
||||
}
|
||||
if (I801_dev == NULL) {
|
||||
printk
|
||||
("i2c-i801.o: Error: Can't detect I801, function 3!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Determine the address of the SMBus areas */
|
||||
if (force_addr) {
|
||||
i801_smba = force_addr & 0xfff0;
|
||||
force = 0;
|
||||
} else {
|
||||
pci_read_config_word(I801_dev, SMBBA,&i801_smba);
|
||||
i801_smba &= 0xfff0;
|
||||
}
|
||||
if (force_addr) {
|
||||
i801_smba = force_addr & 0xfff0;
|
||||
force = 0;
|
||||
} else {
|
||||
pci_read_config_word(I801_dev, SMBBA, &i801_smba);
|
||||
i801_smba &= 0xfff0;
|
||||
}
|
||||
|
||||
if (check_region(i801_smba, 8)) {
|
||||
printk("i2c-i801.o: I801_smb region 0x%x already in use!\n", i801_smba);
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
if (check_region(i801_smba, 8)) {
|
||||
printk
|
||||
("i2c-i801.o: I801_smb region 0x%x already in use!\n",
|
||||
i801_smba);
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
|
||||
pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
|
||||
/* If force_addr is set, we program the new address here. Just to make
|
||||
sure, we disable the I801 first. */
|
||||
if (force_addr) {
|
||||
pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
|
||||
pci_write_config_word(I801_dev, SMBBA,i801_smba);
|
||||
pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
|
||||
printk("i2c-i801.o: WARNING: I801 SMBus interface set to new "
|
||||
"address %04x!\n",i801_smba);
|
||||
} else if ((temp & 1) == 0) {
|
||||
if (force) {
|
||||
if (force_addr) {
|
||||
pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
|
||||
pci_write_config_word(I801_dev, SMBBA, i801_smba);
|
||||
pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
|
||||
printk
|
||||
("i2c-i801.o: WARNING: I801 SMBus interface set to new "
|
||||
"address %04x!\n", i801_smba);
|
||||
} else if ((temp & 1) == 0) {
|
||||
if (force) {
|
||||
/* This should never need to be done, but has been noted that
|
||||
many Dell machines have the SMBus interface on the PIIX4
|
||||
disabled!? NOTE: This assumes I/O space and other allocations WERE
|
||||
done by the Bios! Don't complain if your hardware does weird
|
||||
things after enabling this. :') Check for Bios updates before
|
||||
resorting to this. */
|
||||
pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1);
|
||||
printk("i2c-i801.o: WARNING: I801 SMBus interface has been FORCEFULLY "
|
||||
"ENABLED!\n");
|
||||
} else {
|
||||
printk("SMBUS: Error: Host SMBus controller not enabled!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
}
|
||||
pci_write_config_byte(I801_dev, SMBHSTCFG,
|
||||
temp | 1);
|
||||
printk
|
||||
("i2c-i801.o: WARNING: I801 SMBus interface has been FORCEFULLY "
|
||||
"ENABLED!\n");
|
||||
} else {
|
||||
printk
|
||||
("SMBUS: Error: Host SMBus controller not enabled!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
}
|
||||
|
||||
/* note: we assumed that the BIOS picked SMBus or I2C Bus timing
|
||||
appropriately (bit 2 in SMBHSTCFG) */
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(i801_smba, 8, "i801-smbus");
|
||||
/* note: we assumed that the BIOS picked SMBus or I2C Bus timing
|
||||
appropriately (bit 2 in SMBHSTCFG) */
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(i801_smba, 8, "i801-smbus");
|
||||
|
||||
#ifdef DEBUG
|
||||
if (temp & 0x02)
|
||||
printk("i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n");
|
||||
else
|
||||
printk("i2c-i801.o: I801 using PCI Interrupt for SMBus.\n");
|
||||
if (temp & 0x02)
|
||||
printk
|
||||
("i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n");
|
||||
else
|
||||
printk
|
||||
("i2c-i801.o: I801 using PCI Interrupt for SMBus.\n");
|
||||
|
||||
pci_read_config_byte(I801_dev, SMBREV, &temp);
|
||||
printk("i2c-i801.o: SMBREV = 0x%X\n",temp);
|
||||
printk("i2c-i801.o: I801_smba = 0x%X\n",i801_smba);
|
||||
#endif /* DEBUG */
|
||||
pci_read_config_byte(I801_dev, SMBREV, &temp);
|
||||
printk("i2c-i801.o: SMBREV = 0x%X\n", temp);
|
||||
printk("i2c-i801.o: I801_smba = 0x%X\n", i801_smba);
|
||||
#endif /* DEBUG */
|
||||
|
||||
END:
|
||||
return error_return;
|
||||
END:
|
||||
return error_return;
|
||||
}
|
||||
|
||||
|
||||
/* Internally used pause function */
|
||||
void i801_do_pause( unsigned int amount )
|
||||
void i801_do_pause(unsigned int amount)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
}
|
||||
|
||||
/* Another internally used function */
|
||||
int i801_transaction(void)
|
||||
int i801_transaction(void)
|
||||
{
|
||||
int temp;
|
||||
int result=0;
|
||||
int timeout=0;
|
||||
int temp;
|
||||
int result = 0;
|
||||
int timeout = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
|
||||
"DAT1=%02x\n",
|
||||
inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
|
||||
"DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
|
||||
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
|
||||
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
|
||||
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: SMBus busy (%02x). Resetting... \n",temp);
|
||||
printk("i2c-i801.o: SMBus busy (%02x). Resetting... \n",
|
||||
temp);
|
||||
#endif
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Failed! (%02x)\n",temp);
|
||||
printk("i2c-i801.o: Failed! (%02x)\n", temp);
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Successfull!\n");
|
||||
printk("i2c-i801.o: Successfull!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* start the transaction by setting bit 6 */
|
||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
/* start the transaction by setting bit 6 */
|
||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
|
||||
/* We will always wait for a fraction of a second! */
|
||||
do {
|
||||
i801_do_pause(1);
|
||||
temp=inb_p(SMBHSTSTS);
|
||||
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
|
||||
/* We will always wait for a fraction of a second! */
|
||||
do {
|
||||
i801_do_pause(1);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: SMBus Timeout!\n");
|
||||
result = -1;
|
||||
printk("i2c-i801.o: SMBus Timeout!\n");
|
||||
result = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Error: Failed bus transaction\n");
|
||||
printk("i2c-i801.o: Error: Failed bus transaction\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & 0x08) {
|
||||
result = -1;
|
||||
printk("i2c-i801.o: Bus collision! SMBus may be locked until next hard
|
||||
reset. (sorry!)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
}
|
||||
if (temp & 0x08) {
|
||||
result = -1;
|
||||
printk
|
||||
("i2c-i801.o: Bus collision! SMBus may be locked until next hard\n"
|
||||
"reset. (sorry!)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
}
|
||||
|
||||
if (temp & 0x04) {
|
||||
result = -1;
|
||||
if (temp & 0x04) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Error: no response!\n");
|
||||
printk("i2c-i801.o: Error: no response!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
|
||||
outb_p( inb(SMBHSTSTS), SMBHSTSTS);
|
||||
if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
|
||||
outb_p(inb(SMBHSTSTS), SMBHSTSTS);
|
||||
|
||||
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
|
||||
if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Failed reset at end of transaction (%02x)\n",temp);
|
||||
printk
|
||||
("i2c-i801.o: Failed reset at end of transaction (%02x)\n",
|
||||
temp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n",
|
||||
inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
|
||||
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* All-inclusive block transaction function */
|
||||
int i801_block_transaction(union i2c_smbus_data *data, char read_write)
|
||||
{
|
||||
int i, len;
|
||||
int smbcmd;
|
||||
int temp;
|
||||
int result=0;
|
||||
int timeout=0;
|
||||
int i, len;
|
||||
int smbcmd;
|
||||
int temp;
|
||||
int result = 0;
|
||||
int timeout = 0;
|
||||
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 1)
|
||||
len = 1;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
outb_p(len,SMBHSTDAT0);
|
||||
outb_p(data->block[1],SMBBLKDAT);
|
||||
} else {
|
||||
len = 32; /* max for reads */
|
||||
}
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 1)
|
||||
len = 1;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
outb_p(len, SMBHSTDAT0);
|
||||
outb_p(data->block[1], SMBBLKDAT);
|
||||
} else {
|
||||
len = 32; /* max for reads */
|
||||
}
|
||||
|
||||
for(i = 1; i <= len; i++)
|
||||
{
|
||||
if(i == len && read_write == I2C_SMBUS_READ)
|
||||
smbcmd = I801_BLOCK_LAST;
|
||||
else
|
||||
smbcmd = I801_BLOCK_DATA;
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->block[i],SMBBLKDAT);
|
||||
outb_p((smbcmd & 0x3C) + (ENABLE_INT9 & 1), SMBHSTCNT);
|
||||
for (i = 1; i <= len; i++) {
|
||||
if (i == len && read_write == I2C_SMBUS_READ)
|
||||
smbcmd = I801_BLOCK_LAST;
|
||||
else
|
||||
smbcmd = I801_BLOCK_DATA;
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->block[i], SMBBLKDAT);
|
||||
outb_p((smbcmd & 0x3C) + (ENABLE_INT9 & 1), SMBHSTCNT);
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n",
|
||||
inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
|
||||
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
|
||||
/* 0x9e = Byte_Done, Failed, Bus_Err, Dev_Err, Intr */
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
if (((i == 1) && ((temp & 0x1f) != 0x00)) ||
|
||||
((i != 1) && ((temp & 0x9e) != 0x00)))
|
||||
{
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
|
||||
/* 0x9e = Byte_Done, Failed, Bus_Err, Dev_Err, Intr */
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
if (((i == 1) && ((temp & 0x1f) != 0x00)) ||
|
||||
((i != 1) && ((temp & 0x9e) != 0x00))) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: SMBus busy (%02x). Resetting... \n",temp);
|
||||
printk
|
||||
("i2c-i801.o: SMBus busy (%02x). Resetting... \n",
|
||||
temp);
|
||||
#endif
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if (((temp = inb_p(SMBHSTSTS)) & 0x9f) != 0x00)
|
||||
{
|
||||
printk("i2c-i801.o: Reset failed! (%02x)\n",temp);
|
||||
return -1;
|
||||
}
|
||||
if(i != 1)
|
||||
return -1; /* if die in middle of block transaction, fail */
|
||||
}
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if (((temp = inb_p(SMBHSTSTS)) & 0x9f) != 0x00) {
|
||||
printk
|
||||
("i2c-i801.o: Reset failed! (%02x)\n",
|
||||
temp);
|
||||
return -1;
|
||||
}
|
||||
if (i != 1)
|
||||
return -1; /* if die in middle of block transaction, fail */
|
||||
}
|
||||
|
||||
/* start the transaction by setting bit 6 */
|
||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
/* start the transaction by setting bit 6 */
|
||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
|
||||
/* We will always wait for a fraction of a second! */
|
||||
do {
|
||||
i801_do_pause(1);
|
||||
temp=inb_p(SMBHSTSTS);
|
||||
} while ((((i >= len) && (temp & 0x01)) || ((i < len) && (temp & 0x80)))
|
||||
&& (timeout++ < MAX_TIMEOUT));
|
||||
/* We will always wait for a fraction of a second! */
|
||||
do {
|
||||
i801_do_pause(1);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
}
|
||||
while (
|
||||
(((i >= len) && (temp & 0x01))
|
||||
|| ((i < len) && (temp & 0x80)))
|
||||
&& (timeout++ < MAX_TIMEOUT));
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
result = -1;
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: SMBus Timeout!\n");
|
||||
printk("i2c-i801.o: SMBus Timeout!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Error: Failed bus transaction\n");
|
||||
printk
|
||||
("i2c-i801.o: Error: Failed bus transaction\n");
|
||||
#endif
|
||||
} else if (temp & 0x08) {
|
||||
result = -1;
|
||||
printk("i2c-i801.o: Bus collision! SMBus may be locked until next hard"
|
||||
" reset. (sorry!)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
} else if (temp & 0x04) {
|
||||
result = -1;
|
||||
} else if (temp & 0x08) {
|
||||
result = -1;
|
||||
printk
|
||||
("i2c-i801.o: Bus collision! SMBus may be locked until next hard"
|
||||
" reset. (sorry!)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
} else if (temp & 0x04) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Error: no response!\n");
|
||||
printk("i2c-i801.o: Error: no response!\n");
|
||||
#endif
|
||||
} else if (temp & 0x80) {
|
||||
result = -1;
|
||||
} else if (temp & 0x80) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Error: Failed in middle of block!\n");
|
||||
printk
|
||||
("i2c-i801.o: Error: Failed in middle of block!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if ((temp & 0x9f) != 0x00)
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if ((temp & 0x9f) != 0x00)
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
|
||||
if ((temp = (0x9f & inb_p(SMBHSTSTS))) != 0x00) {
|
||||
if ((temp = (0x9f & inb_p(SMBHSTSTS))) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Failed reset at end of transaction (%02x)\n",temp);
|
||||
printk
|
||||
("i2c-i801.o: Failed reset at end of transaction (%02x)\n",
|
||||
temp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n",
|
||||
inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
|
||||
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
|
||||
if (i == 1 && read_write == I2C_SMBUS_READ) {
|
||||
len = inb_p(SMBHSTDAT0);
|
||||
if (len < 1)
|
||||
len = 1;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
data->block[0] = len;
|
||||
}
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
data->block[i] = inb_p(SMBBLKDAT);
|
||||
if (i == 1 && read_write == I2C_SMBUS_READ) {
|
||||
len = inb_p(SMBHSTDAT0);
|
||||
if (len < 1)
|
||||
len = 1;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
data->block[0] = len;
|
||||
}
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
data->block[i] = inb_p(SMBBLKDAT);
|
||||
|
||||
if(result < 0)
|
||||
return(result);
|
||||
}
|
||||
return(0);
|
||||
if (result < 0)
|
||||
return (result);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Return -1 on error. See smbus.h for more information */
|
||||
s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
|
||||
char read_write, u8 command, int size,
|
||||
union i2c_smbus_data * data)
|
||||
s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
|
||||
char read_write, u8 command, int size,
|
||||
union i2c_smbus_data * data)
|
||||
{
|
||||
|
||||
switch(size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk("i2c-i801.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
size = I801_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMBHSTCMD);
|
||||
size = I801_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->byte,SMBHSTDAT0);
|
||||
size = I801_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->word & 0xff,SMBHSTDAT0);
|
||||
outb_p((data->word & 0xff00) >> 8,SMBHSTDAT1);
|
||||
}
|
||||
size = I801_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
/* Block transactions are very different from piix4 block
|
||||
and from the other i801 transactions. Handle in the
|
||||
i801_block_transaction() routine. */
|
||||
return(i801_block_transaction(data, read_write));
|
||||
}
|
||||
switch (size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk("i2c-i801.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
size = I801_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMBHSTCMD);
|
||||
size = I801_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->byte, SMBHSTDAT0);
|
||||
size = I801_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->word & 0xff, SMBHSTDAT0);
|
||||
outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
|
||||
}
|
||||
size = I801_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
/* Block transactions are very different from piix4 block
|
||||
and from the other i801 transactions. Handle in the
|
||||
i801_block_transaction() routine. */
|
||||
return (i801_block_transaction(data, read_write));
|
||||
}
|
||||
|
||||
/* 'size' is really the transaction type */
|
||||
outb_p((size & 0x3C) + (ENABLE_INT9 & 1), SMBHSTCNT);
|
||||
/* 'size' is really the transaction type */
|
||||
outb_p((size & 0x3C) + (ENABLE_INT9 & 1), SMBHSTCNT);
|
||||
|
||||
if (i801_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == I801_QUICK))
|
||||
return 0;
|
||||
|
||||
if (i801_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
switch(size) {
|
||||
case I801_BYTE: /* Result put in SMBHSTDAT0 */
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case I801_BYTE_DATA:
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case I801_WORD_DATA:
|
||||
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == I801_QUICK))
|
||||
return 0;
|
||||
|
||||
|
||||
switch (size) {
|
||||
case I801_BYTE: /* Result put in SMBHSTDAT0 */
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case I801_BYTE_DATA:
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case I801_WORD_DATA:
|
||||
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i801_inc(struct i2c_adapter *adapter)
|
||||
@@ -539,74 +572,78 @@ void i801_dec(struct i2c_adapter *adapter)
|
||||
|
||||
u32 i801_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
}
|
||||
|
||||
int __init i2c_i801_init(void)
|
||||
{
|
||||
int res;
|
||||
printk("i801.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
int res;
|
||||
printk("i801.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
#ifdef DEBUG
|
||||
/* PE- It might be good to make this a permanent part of the code! */
|
||||
if (i801_initialized) {
|
||||
printk("i2c-i801.o: Oops, i801_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (i801_initialized) {
|
||||
printk
|
||||
("i2c-i801.o: Oops, i801_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
i801_initialized = 0;
|
||||
if ((res = i801_setup())) {
|
||||
printk("i2c-i801.o: I801 not detected, module not inserted.\n");
|
||||
i801_cleanup();
|
||||
return res;
|
||||
}
|
||||
i801_initialized ++;
|
||||
sprintf(i801_adapter.name,"SMBus I801 adapter at %04x",i801_smba);
|
||||
if ((res = i2c_add_adapter(&i801_adapter))) {
|
||||
printk("i2c-i801.o: Adapter registration failed, module not inserted.\n");
|
||||
i801_cleanup();
|
||||
return res;
|
||||
}
|
||||
i801_initialized++;
|
||||
printk("i2c-i801.o: I801 bus detected and initialized\n");
|
||||
return 0;
|
||||
i801_initialized = 0;
|
||||
if ((res = i801_setup())) {
|
||||
printk
|
||||
("i2c-i801.o: I801 not detected, module not inserted.\n");
|
||||
i801_cleanup();
|
||||
return res;
|
||||
}
|
||||
i801_initialized++;
|
||||
sprintf(i801_adapter.name, "SMBus I801 adapter at %04x",
|
||||
i801_smba);
|
||||
if ((res = i2c_add_adapter(&i801_adapter))) {
|
||||
printk
|
||||
("i2c-i801.o: Adapter registration failed, module not inserted.\n");
|
||||
i801_cleanup();
|
||||
return res;
|
||||
}
|
||||
i801_initialized++;
|
||||
printk("i2c-i801.o: I801 bus detected and initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init i801_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
if (i801_initialized >= 2)
|
||||
{
|
||||
if ((res = i2c_del_adapter(&i801_adapter))) {
|
||||
printk("i2c-i801.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
i801_initialized--;
|
||||
}
|
||||
if (i801_initialized >= 1) {
|
||||
release_region(i801_smba, 8);
|
||||
i801_initialized--;
|
||||
}
|
||||
return 0;
|
||||
int res;
|
||||
if (i801_initialized >= 2) {
|
||||
if ((res = i2c_del_adapter(&i801_adapter))) {
|
||||
printk
|
||||
("i2c-i801.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
i801_initialized--;
|
||||
}
|
||||
if (i801_initialized >= 1) {
|
||||
release_region(i801_smba, 8);
|
||||
i801_initialized--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
|
||||
MODULE_DESCRIPTION("I801 SMBus driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_i801_init();
|
||||
return i2c_i801_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return i801_cleanup();
|
||||
return i801_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+55
-55
@@ -36,8 +36,8 @@
|
||||
#include "version.h"
|
||||
#include "i2c-isa.h"
|
||||
|
||||
static void isa_inc_use (struct i2c_adapter *adapter);
|
||||
static void isa_dec_use (struct i2c_adapter *adapter);
|
||||
static void isa_inc_use(struct i2c_adapter *adapter);
|
||||
static void isa_dec_use(struct i2c_adapter *adapter);
|
||||
static u32 isa_func(struct i2c_adapter *adapter);
|
||||
|
||||
#ifdef MODULE
|
||||
@@ -45,95 +45,96 @@ static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init i2c_isa_init(void);
|
||||
int __init i2c_isa_init(void);
|
||||
static int __init isa_cleanup(void);
|
||||
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
/* This is the actual algorithm we define */
|
||||
static struct i2c_algorithm isa_algorithm = {
|
||||
/* name */ "ISA bus algorithm",
|
||||
/* id */ I2C_ALGO_ISA,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ NULL,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ &isa_func,
|
||||
/* name */ "ISA bus algorithm",
|
||||
/* id */ I2C_ALGO_ISA,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ NULL,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ &isa_func,
|
||||
};
|
||||
|
||||
/* There can only be one... */
|
||||
static struct i2c_adapter isa_adapter = {
|
||||
/* name */ "ISA main adapter",
|
||||
/* id */ I2C_ALGO_ISA | I2C_HW_ISA,
|
||||
/* algorithm */ &isa_algorithm,
|
||||
/* algo_data */ NULL,
|
||||
/* inc_use */ &isa_inc_use,
|
||||
/* dec_use */ &isa_dec_use,
|
||||
/* data */ NULL,
|
||||
/* Other fields not initialized */
|
||||
/* name */ "ISA main adapter",
|
||||
/* id */ I2C_ALGO_ISA | I2C_HW_ISA,
|
||||
/* algorithm */ &isa_algorithm,
|
||||
/* algo_data */ NULL,
|
||||
/* inc_use */ &isa_inc_use,
|
||||
/* dec_use */ &isa_dec_use,
|
||||
/* data */ NULL,
|
||||
/* Other fields not initialized */
|
||||
};
|
||||
|
||||
/* Used in isa_init/cleanup */
|
||||
static int __initdata isa_initialized;
|
||||
|
||||
void isa_inc_use (struct i2c_adapter *adapter)
|
||||
void isa_inc_use(struct i2c_adapter *adapter)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_INC_USE_COUNT;
|
||||
MOD_INC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
void isa_dec_use (struct i2c_adapter *adapter)
|
||||
void isa_dec_use(struct i2c_adapter *adapter)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_DEC_USE_COUNT;
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* We can't do a thing... */
|
||||
static u32 isa_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init i2c_isa_init(void)
|
||||
{
|
||||
int res;
|
||||
printk("i2c-isa.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
int res;
|
||||
printk("i2c-isa.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
#ifdef DEBUG
|
||||
if (isa_initialized) {
|
||||
printk("i2c-isa.o: Oops, isa_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (isa_initialized) {
|
||||
printk
|
||||
("i2c-isa.o: Oops, isa_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
isa_initialized = 0;
|
||||
if ((res = i2c_add_adapter(&isa_adapter))) {
|
||||
printk("i2c-isa.o: Adapter registration failed, "
|
||||
"module i2c-isa.o is not inserted\n.");
|
||||
isa_cleanup();
|
||||
return res;
|
||||
}
|
||||
isa_initialized++;
|
||||
printk("i2c-isa.o: ISA bus access for i2c modules initialized.\n");
|
||||
return 0;
|
||||
isa_initialized = 0;
|
||||
if ((res = i2c_add_adapter(&isa_adapter))) {
|
||||
printk("i2c-isa.o: Adapter registration failed, "
|
||||
"module i2c-isa.o is not inserted\n.");
|
||||
isa_cleanup();
|
||||
return res;
|
||||
}
|
||||
isa_initialized++;
|
||||
printk("i2c-isa.o: ISA bus access for i2c modules initialized.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init isa_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
if (isa_initialized >= 1)
|
||||
{
|
||||
if ((res = i2c_del_adapter(&isa_adapter))) {
|
||||
printk("i2c-isa.o: Adapter deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
} else
|
||||
isa_initialized--;
|
||||
}
|
||||
return 0;
|
||||
int res;
|
||||
if (isa_initialized >= 1) {
|
||||
if ((res = i2c_del_adapter(&isa_adapter))) {
|
||||
printk
|
||||
("i2c-isa.o: Adapter deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
} else
|
||||
isa_initialized--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
@@ -145,13 +146,12 @@ MODULE_DESCRIPTION("ISA bus access through i2c");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_isa_init();
|
||||
return i2c_isa_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return isa_cleanup();
|
||||
return isa_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+300
-274
@@ -72,28 +72,29 @@
|
||||
/* If force is set to anything different from 0, we forcibly enable the
|
||||
PIIX4. DANGEROUS! */
|
||||
static int force = 0;
|
||||
MODULE_PARM(force,"i");
|
||||
MODULE_PARM_DESC(force,"Forcibly enable the PIIX4. DANGEROUS!");
|
||||
MODULE_PARM(force, "i");
|
||||
MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
|
||||
|
||||
/* If force_addr is set to anything different from 0, we forcibly enable
|
||||
the PIIX4 at the given address. VERY DANGEROUS! */
|
||||
static int force_addr = 0;
|
||||
MODULE_PARM(force_addr,"i");
|
||||
MODULE_PARM_DESC(force_addr,"Forcibly enable the PIIX4 at the given address. "
|
||||
"EXTREMELY DANGEROUS!");
|
||||
MODULE_PARM(force_addr, "i");
|
||||
MODULE_PARM_DESC(force_addr,
|
||||
"Forcibly enable the PIIX4 at the given address. "
|
||||
"EXTREMELY DANGEROUS!");
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init i2c_piix4_init(void);
|
||||
int __init i2c_piix4_init(void);
|
||||
static int __init piix4_cleanup(void);
|
||||
static int piix4_setup(void);
|
||||
static s32 piix4_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data);
|
||||
static void piix4_do_pause( unsigned int amount );
|
||||
static s32 piix4_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data *data);
|
||||
static void piix4_do_pause(unsigned int amount);
|
||||
static int piix4_transaction(void);
|
||||
static void piix4_inc(struct i2c_adapter *adapter);
|
||||
static void piix4_dec(struct i2c_adapter *adapter);
|
||||
@@ -102,28 +103,28 @@ static u32 piix4_func(struct i2c_adapter *adapter);
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ piix4_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ piix4_func,
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ piix4_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ piix4_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter piix4_adapter = {
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
piix4_inc,
|
||||
piix4_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
piix4_inc,
|
||||
piix4_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __initdata piix4_initialized;
|
||||
@@ -136,275 +137,296 @@ static unsigned short piix4_smba = 0;
|
||||
defined to make the transition easier. */
|
||||
int piix4_setup(void)
|
||||
{
|
||||
int error_return=0;
|
||||
unsigned char temp;
|
||||
int error_return = 0;
|
||||
unsigned char temp;
|
||||
|
||||
struct pci_dev *PIIX4_dev;
|
||||
struct pci_dev *PIIX4_dev;
|
||||
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-piix4.o: Error: No PCI-bus found!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-piix4.o: Error: No PCI-bus found!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Look for the PIIX4, function 3 */
|
||||
/* Note: we keep on searching until we have found 'function 3' */
|
||||
PIIX4_dev = NULL;
|
||||
do
|
||||
PIIX4_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82371AB_3, PIIX4_dev);
|
||||
while(PIIX4_dev && (PCI_FUNC(PIIX4_dev->devfn) != 3));
|
||||
if(PIIX4_dev == NULL) {
|
||||
printk("i2c-piix4.o: Error: Can't detect PIIX4, function 3!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* Look for the PIIX4, function 3 */
|
||||
/* Note: we keep on searching until we have found 'function 3' */
|
||||
PIIX4_dev = NULL;
|
||||
do
|
||||
PIIX4_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_82371AB_3,
|
||||
PIIX4_dev);
|
||||
while (PIIX4_dev && (PCI_FUNC(PIIX4_dev->devfn) != 3));
|
||||
if (PIIX4_dev == NULL) {
|
||||
printk
|
||||
("i2c-piix4.o: Error: Can't detect PIIX4, function 3!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Determine the address of the SMBus areas */
|
||||
if (force_addr) {
|
||||
piix4_smba = force_addr & 0xfff0;
|
||||
force = 0;
|
||||
} else {
|
||||
if (force_addr) {
|
||||
piix4_smba = force_addr & 0xfff0;
|
||||
force = 0;
|
||||
} else {
|
||||
|
||||
pci_read_config_word(PIIX4_dev, SMBBA,&piix4_smba);
|
||||
piix4_smba &= 0xfff0;
|
||||
}
|
||||
pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
|
||||
piix4_smba &= 0xfff0;
|
||||
}
|
||||
|
||||
if (check_region(piix4_smba, 8)) {
|
||||
printk("i2c-piix4.o: PIIX4_smb region 0x%x already in use!\n", piix4_smba);
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
if (check_region(piix4_smba, 8)) {
|
||||
printk
|
||||
("i2c-piix4.o: PIIX4_smb region 0x%x already in use!\n",
|
||||
piix4_smba);
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
|
||||
pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
|
||||
/* If force_addr is set, we program the new address here. Just to make
|
||||
sure, we disable the PIIX4 first. */
|
||||
if (force_addr) {
|
||||
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe);
|
||||
pci_write_config_word(PIIX4_dev, SMBBA,piix4_smba);
|
||||
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01);
|
||||
printk("i2c-piix4.o: WARNING: PIIX4 SMBus interface set to new "
|
||||
"address %04x!\n",piix4_smba);
|
||||
} else if ((temp & 1) == 0) {
|
||||
if (force) {
|
||||
if (force_addr) {
|
||||
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe);
|
||||
pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba);
|
||||
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01);
|
||||
printk
|
||||
("i2c-piix4.o: WARNING: PIIX4 SMBus interface set to new "
|
||||
"address %04x!\n", piix4_smba);
|
||||
} else if ((temp & 1) == 0) {
|
||||
if (force) {
|
||||
/* This should never need to be done, but has been noted that
|
||||
many Dell machines have the SMBus interface on the PIIX4
|
||||
disabled!? NOTE: This assumes I/O space and other allocations WERE
|
||||
done by the Bios! Don't complain if your hardware does weird
|
||||
things after enabling this. :') Check for Bios updates before
|
||||
resorting to this. */
|
||||
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 1);
|
||||
printk("i2c-piix4.o: WARNING: PIIX4 SMBus interface has been FORCEFULLY "
|
||||
"ENABLED!\n");
|
||||
} else {
|
||||
printk("SMBUS: Error: Host SMBus controller not enabled!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
}
|
||||
pci_write_config_byte(PIIX4_dev, SMBHSTCFG,
|
||||
temp | 1);
|
||||
printk
|
||||
("i2c-piix4.o: WARNING: PIIX4 SMBus interface has been FORCEFULLY "
|
||||
"ENABLED!\n");
|
||||
} else {
|
||||
printk
|
||||
("SMBUS: Error: Host SMBus controller not enabled!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
}
|
||||
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(piix4_smba, 8, "piix4-smbus");
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(piix4_smba, 8, "piix4-smbus");
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((temp & 0x0E) == 8)
|
||||
printk("i2c-piix4.o: PIIX4 using Interrupt 9 for SMBus.\n");
|
||||
else if ((temp & 0x0E) == 0)
|
||||
printk("i2c-piix4.o: PIIX4 using Interrupt SMI# for SMBus.\n");
|
||||
else
|
||||
printk("i2c-piix4.o: PIIX4: Illegal Interrupt configuration (or code out "
|
||||
"of date)!\n");
|
||||
if ((temp & 0x0E) == 8)
|
||||
printk
|
||||
("i2c-piix4.o: PIIX4 using Interrupt 9 for SMBus.\n");
|
||||
else if ((temp & 0x0E) == 0)
|
||||
printk
|
||||
("i2c-piix4.o: PIIX4 using Interrupt SMI# for SMBus.\n");
|
||||
else
|
||||
printk
|
||||
("i2c-piix4.o: PIIX4: Illegal Interrupt configuration (or code out "
|
||||
"of date)!\n");
|
||||
|
||||
pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
|
||||
printk("i2c-piix4.o: SMBREV = 0x%X\n",temp);
|
||||
printk("i2c-piix4.o: PIIX4_smba = 0x%X\n",piix4_smba);
|
||||
#endif /* DEBUG */
|
||||
pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
|
||||
printk("i2c-piix4.o: SMBREV = 0x%X\n", temp);
|
||||
printk("i2c-piix4.o: PIIX4_smba = 0x%X\n", piix4_smba);
|
||||
#endif /* DEBUG */
|
||||
|
||||
END:
|
||||
return error_return;
|
||||
END:
|
||||
return error_return;
|
||||
}
|
||||
|
||||
|
||||
/* Internally used pause function */
|
||||
void piix4_do_pause( unsigned int amount )
|
||||
void piix4_do_pause(unsigned int amount)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
}
|
||||
|
||||
/* Another internally used function */
|
||||
int piix4_transaction(void)
|
||||
int piix4_transaction(void)
|
||||
{
|
||||
int temp;
|
||||
int result=0;
|
||||
int timeout=0;
|
||||
int temp;
|
||||
int result = 0;
|
||||
int timeout = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
|
||||
"DAT1=%02x\n",
|
||||
inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
|
||||
"DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
|
||||
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-piix4.o: SMBus busy (%02x). Resetting... \n",temp);
|
||||
printk("i2c-piix4.o: SMBus busy (%02x). Resetting... \n",
|
||||
temp);
|
||||
#endif
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-piix4.o: Failed! (%02x)\n",temp);
|
||||
printk("i2c-piix4.o: Failed! (%02x)\n", temp);
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-piix4.o: Successfull!\n");
|
||||
printk("i2c-piix4.o: Successfull!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* start the transaction by setting bit 6 */
|
||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
/* start the transaction by setting bit 6 */
|
||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
|
||||
/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
|
||||
do {
|
||||
piix4_do_pause(1);
|
||||
temp=inb_p(SMBHSTSTS);
|
||||
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
|
||||
/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
|
||||
do {
|
||||
piix4_do_pause(1);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-piix4.o: SMBus Timeout!\n");
|
||||
result = -1;
|
||||
printk("i2c-piix4.o: SMBus Timeout!\n");
|
||||
result = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-piix4.o: Error: Failed bus transaction\n");
|
||||
printk("i2c-piix4.o: Error: Failed bus transaction\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & 0x08) {
|
||||
result = -1;
|
||||
printk("i2c-piix4.o: Bus collision! SMBus may be locked until next hard
|
||||
reset. (sorry!)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
}
|
||||
if (temp & 0x08) {
|
||||
result = -1;
|
||||
printk
|
||||
("i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n"
|
||||
"reset. (sorry!)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
}
|
||||
|
||||
if (temp & 0x04) {
|
||||
result = -1;
|
||||
if (temp & 0x04) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-piix4.o: Error: no response!\n");
|
||||
printk("i2c-piix4.o: Error: no response!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (inb_p(SMBHSTSTS) != 0x00)
|
||||
outb_p( inb(SMBHSTSTS), SMBHSTSTS);
|
||||
if (inb_p(SMBHSTSTS) != 0x00)
|
||||
outb_p(inb(SMBHSTSTS), SMBHSTSTS);
|
||||
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-piix4.o: Failed reset at end of transaction (%02x)\n",temp);
|
||||
printk
|
||||
("i2c-piix4.o: Failed reset at end of transaction (%02x)\n",
|
||||
temp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n",
|
||||
inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
|
||||
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return -1 on error. See smbus.h for more information */
|
||||
s32 piix4_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
s32 piix4_access(struct i2c_adapter * adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
{
|
||||
int i,len;
|
||||
int i, len;
|
||||
|
||||
switch(size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk("i2c-piix4.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
size = PIIX4_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMBHSTCMD);
|
||||
size = PIIX4_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->byte,SMBHSTDAT0);
|
||||
size = PIIX4_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->word & 0xff,SMBHSTDAT0);
|
||||
outb_p((data->word & 0xff00) >> 8,SMBHSTDAT1);
|
||||
}
|
||||
size = PIIX4_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
outb_p(len,SMBHSTDAT0);
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= len; i ++)
|
||||
outb_p(data->block[i],SMBBLKDAT);
|
||||
}
|
||||
size = PIIX4_BLOCK_DATA;
|
||||
break;
|
||||
}
|
||||
switch (size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk
|
||||
("i2c-piix4.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
size = PIIX4_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMBHSTCMD);
|
||||
size = PIIX4_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->byte, SMBHSTDAT0);
|
||||
size = PIIX4_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->word & 0xff, SMBHSTDAT0);
|
||||
outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
|
||||
}
|
||||
size = PIIX4_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
outb_p(len, SMBHSTDAT0);
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= len; i++)
|
||||
outb_p(data->block[i], SMBBLKDAT);
|
||||
}
|
||||
size = PIIX4_BLOCK_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
|
||||
outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
|
||||
|
||||
if (piix4_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
|
||||
return 0;
|
||||
|
||||
if (piix4_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
switch(size) {
|
||||
case PIIX4_BYTE: /* Where is the result put? I assume here it is in
|
||||
SMBHSTDAT0 but it might just as well be in the
|
||||
SMBHSTCMD. No clue in the docs */
|
||||
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case PIIX4_BYTE_DATA:
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case PIIX4_WORD_DATA:
|
||||
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
case PIIX4_BLOCK_DATA:
|
||||
data->block[0] = inb_p(SMBHSTDAT0);
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= data->block[0]; i++)
|
||||
data->block[i] = inb_p(SMBBLKDAT);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
|
||||
return 0;
|
||||
|
||||
|
||||
switch (size) {
|
||||
case PIIX4_BYTE: /* Where is the result put? I assume here it is in
|
||||
SMBHSTDAT0 but it might just as well be in the
|
||||
SMBHSTCMD. No clue in the docs */
|
||||
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case PIIX4_BYTE_DATA:
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case PIIX4_WORD_DATA:
|
||||
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
case PIIX4_BLOCK_DATA:
|
||||
data->block[0] = inb_p(SMBHSTDAT0);
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= data->block[0]; i++)
|
||||
data->block[i] = inb_p(SMBBLKDAT);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void piix4_inc(struct i2c_adapter *adapter)
|
||||
@@ -420,74 +442,78 @@ void piix4_dec(struct i2c_adapter *adapter)
|
||||
|
||||
u32 piix4_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
}
|
||||
|
||||
int __init i2c_piix4_init(void)
|
||||
{
|
||||
int res;
|
||||
printk("piix4.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
int res;
|
||||
printk("piix4.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
#ifdef DEBUG
|
||||
/* PE- It might be good to make this a permanent part of the code! */
|
||||
if (piix4_initialized) {
|
||||
printk("i2c-piix4.o: Oops, piix4_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (piix4_initialized) {
|
||||
printk
|
||||
("i2c-piix4.o: Oops, piix4_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
piix4_initialized = 0;
|
||||
if ((res = piix4_setup())) {
|
||||
printk("i2c-piix4.o: PIIX4 not detected, module not inserted.\n");
|
||||
piix4_cleanup();
|
||||
return res;
|
||||
}
|
||||
piix4_initialized ++;
|
||||
sprintf(piix4_adapter.name,"SMBus PIIX4 adapter at %04x",piix4_smba);
|
||||
if ((res = i2c_add_adapter(&piix4_adapter))) {
|
||||
printk("i2c-piix4.o: Adapter registration failed, module not inserted.\n");
|
||||
piix4_cleanup();
|
||||
return res;
|
||||
}
|
||||
piix4_initialized++;
|
||||
printk("i2c-piix4.o: PIIX4 bus detected and initialized\n");
|
||||
return 0;
|
||||
piix4_initialized = 0;
|
||||
if ((res = piix4_setup())) {
|
||||
printk
|
||||
("i2c-piix4.o: PIIX4 not detected, module not inserted.\n");
|
||||
piix4_cleanup();
|
||||
return res;
|
||||
}
|
||||
piix4_initialized++;
|
||||
sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
|
||||
piix4_smba);
|
||||
if ((res = i2c_add_adapter(&piix4_adapter))) {
|
||||
printk
|
||||
("i2c-piix4.o: Adapter registration failed, module not inserted.\n");
|
||||
piix4_cleanup();
|
||||
return res;
|
||||
}
|
||||
piix4_initialized++;
|
||||
printk("i2c-piix4.o: PIIX4 bus detected and initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init piix4_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
if (piix4_initialized >= 2)
|
||||
{
|
||||
if ((res = i2c_del_adapter(&piix4_adapter))) {
|
||||
printk("i2c-piix4.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
piix4_initialized--;
|
||||
}
|
||||
if (piix4_initialized >= 1) {
|
||||
release_region(piix4_smba, 8);
|
||||
piix4_initialized--;
|
||||
}
|
||||
return 0;
|
||||
int res;
|
||||
if (piix4_initialized >= 2) {
|
||||
if ((res = i2c_del_adapter(&piix4_adapter))) {
|
||||
printk
|
||||
("i2c-piix4.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
piix4_initialized--;
|
||||
}
|
||||
if (piix4_initialized >= 1) {
|
||||
release_region(piix4_smba, 8);
|
||||
piix4_initialized--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_DESCRIPTION("PIIX4 SMBus driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_piix4_init();
|
||||
return i2c_piix4_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return piix4_cleanup();
|
||||
return piix4_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+238
-209
@@ -77,13 +77,14 @@ static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init i2c_sis5595_init(void);
|
||||
int __init i2c_sis5595_init(void);
|
||||
static int __init sis5595_cleanup(void);
|
||||
static int sis5595_setup(void);
|
||||
static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data);
|
||||
static void sis5595_do_pause( unsigned int amount );
|
||||
static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size,
|
||||
union i2c_smbus_data *data);
|
||||
static void sis5595_do_pause(unsigned int amount);
|
||||
static int sis5595_transaction(void);
|
||||
static void sis5595_inc(struct i2c_adapter *adapter);
|
||||
static void sis5595_dec(struct i2c_adapter *adapter);
|
||||
@@ -92,28 +93,28 @@ static u32 sis5595_func(struct i2c_adapter *adapter);
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ sis5595_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ sis5595_func,
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ sis5595_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ sis5595_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter sis5595_adapter = {
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS5595,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
sis5595_inc,
|
||||
sis5595_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS5595,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
sis5595_inc,
|
||||
sis5595_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __initdata sis5595_initialized;
|
||||
@@ -121,14 +122,14 @@ static unsigned short sis5595_base = 0;
|
||||
|
||||
static u8 sis5595_read(u8 reg)
|
||||
{
|
||||
outb(reg,sis5595_base+SMB_INDEX);
|
||||
return inb(sis5595_base+SMB_DAT);
|
||||
outb(reg, sis5595_base + SMB_INDEX);
|
||||
return inb(sis5595_base + SMB_DAT);
|
||||
}
|
||||
|
||||
static void sis5595_write(u8 reg, u8 data)
|
||||
{
|
||||
outb(reg,sis5595_base+SMB_INDEX);
|
||||
outb(data,sis5595_base+SMB_DAT);
|
||||
outb(reg, sis5595_base + SMB_INDEX);
|
||||
outb(data, sis5595_base + SMB_DAT);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,192 +139,217 @@ static void sis5595_write(u8 reg, u8 data)
|
||||
defined to make the transition easier. */
|
||||
int sis5595_setup(void)
|
||||
{
|
||||
int error_return=0;
|
||||
int error_return = 0;
|
||||
|
||||
struct pci_dev *SIS5595_dev;
|
||||
struct pci_dev *SIS5595_dev;
|
||||
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-sis5595.o: Error: No PCI-bus found!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-sis5595.o: Error: No PCI-bus found!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Look for the SIS5595, function 3 */
|
||||
SIS5595_dev = NULL;
|
||||
if (!(SIS5595_dev = pci_find_device(PCI_VENDOR_ID_SI,
|
||||
PCI_DEVICE_ID_SI_503, SIS5595_dev))) {
|
||||
printk("i2c-sis5595.o: Error: Can't detect SIS5595!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* Look for the SIS5595, function 3 */
|
||||
SIS5595_dev = NULL;
|
||||
if (!(SIS5595_dev = pci_find_device(PCI_VENDOR_ID_SI,
|
||||
PCI_DEVICE_ID_SI_503,
|
||||
SIS5595_dev))) {
|
||||
printk("i2c-sis5595.o: Error: Can't detect SIS5595!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Determine the address of the SMBus areas */
|
||||
pci_read_config_word(SIS5595_dev, ACPI_BASE,&sis5595_base);
|
||||
pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base);
|
||||
#ifdef DEBUG
|
||||
printk("ACPI Base address: %04x\n",sis5595_base);
|
||||
printk("ACPI Base address: %04x\n", sis5595_base);
|
||||
#endif
|
||||
/* NB: We grab just the two SMBus registers here, but this may still
|
||||
* interfere with ACPI :-( */
|
||||
if (check_region(sis5595_base + SMB_INDEX, 2)) {
|
||||
printk("i2c-sis5595.o: SMBus registers 0x%4x-0x%4x already in use!\n",
|
||||
sis5595_base + SMB_INDEX,sis5595_base + SMB_INDEX+1);
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* NB: We grab just the two SMBus registers here, but this may still
|
||||
* interfere with ACPI :-( */
|
||||
if (check_region(sis5595_base + SMB_INDEX, 2)) {
|
||||
printk
|
||||
("i2c-sis5595.o: SMBus registers 0x%4x-0x%4x already in use!\n",
|
||||
sis5595_base + SMB_INDEX,
|
||||
sis5595_base + SMB_INDEX + 1);
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus");
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus");
|
||||
|
||||
END:
|
||||
return error_return;
|
||||
END:
|
||||
return error_return;
|
||||
}
|
||||
|
||||
|
||||
/* Internally used pause function */
|
||||
void sis5595_do_pause( unsigned int amount )
|
||||
void sis5595_do_pause(unsigned int amount)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
}
|
||||
|
||||
/* Another internally used function */
|
||||
int sis5595_transaction(void)
|
||||
int sis5595_transaction(void)
|
||||
{
|
||||
int temp;
|
||||
int result=0;
|
||||
int timeout=0;
|
||||
int temp;
|
||||
int result = 0;
|
||||
int timeout = 0;
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8))
|
||||
!= 0x00) {
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
if (
|
||||
(temp =
|
||||
sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
|
||||
0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-sis5595.o: SMBus busy (%04x). Resetting... \n",temp);
|
||||
printk("i2c-sis5595.o: SMBus busy (%04x). Resetting... \n",
|
||||
temp);
|
||||
#endif
|
||||
sis5595_write(SMB_STS_LO,temp & 0xff);
|
||||
sis5595_write(SMB_STS_HI,temp >> 8);
|
||||
if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8))
|
||||
!= 0x00) {
|
||||
sis5595_write(SMB_STS_LO, temp & 0xff);
|
||||
sis5595_write(SMB_STS_HI, temp >> 8);
|
||||
if (
|
||||
(temp =
|
||||
sis5595_read(SMB_STS_LO) +
|
||||
(sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-sis5595.o: Failed! (%02x)\n",temp);
|
||||
printk("i2c-sis5595.o: Failed! (%02x)\n", temp);
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-sis5595.o: Successfull!\n");
|
||||
printk("i2c-sis5595.o: Successfull!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* start the transaction by setting bit 4 */
|
||||
sis5595_write(SMB_CTL_LO,sis5595_read(SMB_CTL_LO)|0x10);
|
||||
/* start the transaction by setting bit 4 */
|
||||
sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
|
||||
|
||||
/* We will always wait for a fraction of a second! */
|
||||
do {
|
||||
sis5595_do_pause(1);
|
||||
temp=sis5595_read(SMB_STS_LO);
|
||||
} while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
|
||||
/* We will always wait for a fraction of a second! */
|
||||
do {
|
||||
sis5595_do_pause(1);
|
||||
temp = sis5595_read(SMB_STS_LO);
|
||||
} while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-sis5595.o: SMBus Timeout!\n");
|
||||
printk("i2c-sis5595.o: SMBus Timeout!\n");
|
||||
#endif
|
||||
result = -1;
|
||||
}
|
||||
result = -1;
|
||||
}
|
||||
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-sis5595.o: Error: Failed bus transaction\n");
|
||||
printk("i2c-sis5595.o: Error: Failed bus transaction\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & 0x20) {
|
||||
result = -1;
|
||||
printk("i2c-sis5595.o: Bus collision! SMBus may be locked until next hard
|
||||
reset (or not...)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
}
|
||||
if (temp & 0x20) {
|
||||
result = -1;
|
||||
printk
|
||||
("i2c-sis5595.o: Bus collision! SMBus may be locked until next hard\n"
|
||||
"reset (or not...)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
}
|
||||
|
||||
if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8))
|
||||
!= 0x00) {
|
||||
sis5595_write(SMB_STS_LO,temp & 0xff);
|
||||
sis5595_write(SMB_STS_HI,temp >> 8);
|
||||
}
|
||||
if (
|
||||
(temp =
|
||||
sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
|
||||
0x00) {
|
||||
sis5595_write(SMB_STS_LO, temp & 0xff);
|
||||
sis5595_write(SMB_STS_HI, temp >> 8);
|
||||
}
|
||||
|
||||
if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8))
|
||||
!= 0x00) {
|
||||
if (
|
||||
(temp =
|
||||
sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) !=
|
||||
0x00) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("i2c-sis5595.o: Failed reset at end of transaction (%02x)\n",temp);
|
||||
printk
|
||||
("i2c-sis5595.o: Failed reset at end of transaction (%02x)\n",
|
||||
temp);
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return -1 on error. See smbus.h for more information */
|
||||
s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
s32 sis5595_access(struct i2c_adapter * adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
{
|
||||
switch(size) {
|
||||
case I2C_SMBUS_QUICK:
|
||||
sis5595_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
|
||||
size = SIS5595_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
sis5595_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
sis5595_write(SMB_CMD,command);
|
||||
size = SIS5595_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
sis5595_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
|
||||
sis5595_write(SMB_CMD,command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
sis5595_write(SMB_BYTE,data->byte);
|
||||
size = SIS5595_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
sis5595_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
|
||||
sis5595_write(SMB_CMD,command);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
sis5595_write(SMB_BYTE,data->word & 0xff);
|
||||
sis5595_write(SMB_BYTE+1,(data->word & 0xff00) >> 8);
|
||||
}
|
||||
size = (size==I2C_SMBUS_PROC_CALL)?SIS5595_PROC_CALL:SIS5595_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
printk("sis5595.o: Block data not yet implemented!\n");
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
switch (size) {
|
||||
case I2C_SMBUS_QUICK:
|
||||
sis5595_write(SMB_ADDR,
|
||||
((addr & 0x7f) << 1) | (read_write & 0x01));
|
||||
size = SIS5595_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
sis5595_write(SMB_ADDR,
|
||||
((addr & 0x7f) << 1) | (read_write & 0x01));
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
sis5595_write(SMB_CMD, command);
|
||||
size = SIS5595_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
sis5595_write(SMB_ADDR,
|
||||
((addr & 0x7f) << 1) | (read_write & 0x01));
|
||||
sis5595_write(SMB_CMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
sis5595_write(SMB_BYTE, data->byte);
|
||||
size = SIS5595_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
sis5595_write(SMB_ADDR,
|
||||
((addr & 0x7f) << 1) | (read_write & 0x01));
|
||||
sis5595_write(SMB_CMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
sis5595_write(SMB_BYTE, data->word & 0xff);
|
||||
sis5595_write(SMB_BYTE + 1,
|
||||
(data->word & 0xff00) >> 8);
|
||||
}
|
||||
size =
|
||||
(size ==
|
||||
I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL :
|
||||
SIS5595_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
printk("sis5595.o: Block data not yet implemented!\n");
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
sis5595_write(SMB_CTL_LO,((size & 0x0E)));
|
||||
sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
|
||||
|
||||
if (sis5595_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
if ((size != SIS5595_PROC_CALL) &&
|
||||
((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
|
||||
return 0;
|
||||
|
||||
if (sis5595_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
switch(size) {
|
||||
case SIS5595_BYTE: /* Where is the result put? I assume here it is in
|
||||
SMB_DATA but it might just as well be in the
|
||||
SMB_CMD. No clue in the docs */
|
||||
case SIS5595_BYTE_DATA:
|
||||
data->byte = sis5595_read(SMB_BYTE);
|
||||
break;
|
||||
case SIS5595_WORD_DATA:
|
||||
case SIS5595_PROC_CALL:
|
||||
data->word = sis5595_read(SMB_BYTE) + (sis5595_read(SMB_BYTE+1) << 8);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
if ((size != SIS5595_PROC_CALL) &&
|
||||
((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
|
||||
return 0;
|
||||
|
||||
|
||||
switch (size) {
|
||||
case SIS5595_BYTE: /* Where is the result put? I assume here it is in
|
||||
SMB_DATA but it might just as well be in the
|
||||
SMB_CMD. No clue in the docs */
|
||||
case SIS5595_BYTE_DATA:
|
||||
data->byte = sis5595_read(SMB_BYTE);
|
||||
break;
|
||||
case SIS5595_WORD_DATA:
|
||||
case SIS5595_PROC_CALL:
|
||||
data->word =
|
||||
sis5595_read(SMB_BYTE) +
|
||||
(sis5595_read(SMB_BYTE + 1) << 8);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sis5595_inc(struct i2c_adapter *adapter)
|
||||
@@ -339,56 +365,60 @@ void sis5595_dec(struct i2c_adapter *adapter)
|
||||
|
||||
u32 sis5595_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_PROC_CALL;
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_PROC_CALL;
|
||||
}
|
||||
|
||||
int __init i2c_sis5595_init(void)
|
||||
{
|
||||
int res;
|
||||
printk("sis5595.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
int res;
|
||||
printk("sis5595.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
#ifdef DEBUG
|
||||
/* PE- It might be good to make this a permanent part of the code! */
|
||||
if (sis5595_initialized) {
|
||||
printk("i2c-sis5595.o: Oops, sis5595_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (sis5595_initialized) {
|
||||
printk
|
||||
("i2c-sis5595.o: Oops, sis5595_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
sis5595_initialized = 0;
|
||||
if ((res = sis5595_setup())) {
|
||||
printk("i2c-sis5595.o: SIS5595 not detected, module not inserted.\n");
|
||||
sis5595_cleanup();
|
||||
return res;
|
||||
}
|
||||
sis5595_initialized ++;
|
||||
sprintf(sis5595_adapter.name,"SMBus SIS5595 adapter at %04x",sis5595_base + SMB_INDEX);
|
||||
if ((res = i2c_add_adapter(&sis5595_adapter))) {
|
||||
printk("i2c-sis5595.o: Adapter registration failed, module not inserted.\n");
|
||||
sis5595_cleanup();
|
||||
return res;
|
||||
}
|
||||
sis5595_initialized++;
|
||||
printk("i2c-sis5595.o: SIS5595 bus detected and initialized\n");
|
||||
return 0;
|
||||
sis5595_initialized = 0;
|
||||
if ((res = sis5595_setup())) {
|
||||
printk
|
||||
("i2c-sis5595.o: SIS5595 not detected, module not inserted.\n");
|
||||
sis5595_cleanup();
|
||||
return res;
|
||||
}
|
||||
sis5595_initialized++;
|
||||
sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
|
||||
sis5595_base + SMB_INDEX);
|
||||
if ((res = i2c_add_adapter(&sis5595_adapter))) {
|
||||
printk
|
||||
("i2c-sis5595.o: Adapter registration failed, module not inserted.\n");
|
||||
sis5595_cleanup();
|
||||
return res;
|
||||
}
|
||||
sis5595_initialized++;
|
||||
printk("i2c-sis5595.o: SIS5595 bus detected and initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init sis5595_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
if (sis5595_initialized >= 2)
|
||||
{
|
||||
if ((res = i2c_del_adapter(&sis5595_adapter))) {
|
||||
printk("i2c-sis5595.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
sis5595_initialized--;
|
||||
}
|
||||
if (sis5595_initialized >= 1) {
|
||||
release_region(sis5595_base + SMB_INDEX, 2);
|
||||
sis5595_initialized--;
|
||||
}
|
||||
return 0;
|
||||
int res;
|
||||
if (sis5595_initialized >= 2) {
|
||||
if ((res = i2c_del_adapter(&sis5595_adapter))) {
|
||||
printk
|
||||
("i2c-sis5595.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
sis5595_initialized--;
|
||||
}
|
||||
if (sis5595_initialized >= 1) {
|
||||
release_region(sis5595_base + SMB_INDEX, 2);
|
||||
sis5595_initialized--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
@@ -400,13 +430,12 @@ MODULE_DESCRIPTION("SIS5595 SMBus driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_sis5595_init();
|
||||
return i2c_sis5595_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return sis5595_cleanup();
|
||||
return sis5595_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+47
-42
@@ -40,14 +40,14 @@
|
||||
|
||||
/* Power management registers */
|
||||
|
||||
#define PM_CFG_REVID 0x08 /* silicon revision code */
|
||||
#define PM_CFG_REVID 0x08 /* silicon revision code */
|
||||
#define PM_CFG_IOBASE0 0x20
|
||||
#define PM_CFG_IOBASE1 0x48
|
||||
|
||||
#define I2C_DIR (pm_io_base+0x40)
|
||||
#define I2C_OUT (pm_io_base+0x42)
|
||||
#define I2C_IN (pm_io_base+0x44)
|
||||
#define I2C_SCL 0x02 /* clock bit in DIR/OUT/IN register */
|
||||
#define I2C_SCL 0x02 /* clock bit in DIR/OUT/IN register */
|
||||
#define I2C_SDA 0x04
|
||||
|
||||
/* io-region reservation */
|
||||
@@ -55,9 +55,9 @@
|
||||
#define IOTEXT "via-i2c"
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
#define DEB(x) x /* silicon revision, io addresses */
|
||||
#define DEB2(x) x /* line status */
|
||||
#define DEBE(x) /* */
|
||||
#define DEB(x) x /* silicon revision, io addresses */
|
||||
#define DEB2(x) x /* line status */
|
||||
#define DEBE(x) /* */
|
||||
|
||||
/* ----- local functions ---------------------------------------------- */
|
||||
|
||||
@@ -65,22 +65,24 @@ static u16 pm_io_base;
|
||||
|
||||
static void bit_via_setscl(void *data, int state)
|
||||
{
|
||||
outb(state ? inb(I2C_OUT)|I2C_SCL : inb(I2C_OUT)&~I2C_SCL, I2C_OUT);
|
||||
outb(state ? inb(I2C_OUT) | I2C_SCL : inb(I2C_OUT) & ~I2C_SCL,
|
||||
I2C_OUT);
|
||||
}
|
||||
|
||||
static void bit_via_setsda(void *data, int state)
|
||||
{
|
||||
outb(state ? inb(I2C_OUT)|I2C_SDA : inb(I2C_OUT)&~I2C_SDA, I2C_OUT);
|
||||
outb(state ? inb(I2C_OUT) | I2C_SDA : inb(I2C_OUT) & ~I2C_SDA,
|
||||
I2C_OUT);
|
||||
}
|
||||
|
||||
static int bit_via_getscl(void *data)
|
||||
{
|
||||
return (0 != (inb(I2C_IN) & I2C_SCL) );
|
||||
return (0 != (inb(I2C_IN) & I2C_SCL));
|
||||
}
|
||||
|
||||
static int bit_via_getsda(void *data)
|
||||
{
|
||||
return (0 != (inb(I2C_IN) & I2C_SDA) );
|
||||
return (0 != (inb(I2C_IN) & I2C_SDA));
|
||||
}
|
||||
|
||||
static void bit_via_inc(struct i2c_adapter *adapter)
|
||||
@@ -101,7 +103,7 @@ static struct i2c_algo_bit_data bit_data = {
|
||||
bit_via_setscl,
|
||||
bit_via_getsda,
|
||||
bit_via_getscl,
|
||||
5, 5, 100, /*waits, timeout */
|
||||
5, 5, 100, /*waits, timeout */
|
||||
};
|
||||
|
||||
static struct i2c_adapter bit_via_ops = {
|
||||
@@ -122,38 +124,40 @@ static int find_via(void)
|
||||
struct pci_dev *s_bridge;
|
||||
u16 base;
|
||||
u8 rev;
|
||||
|
||||
if (! pci_present())
|
||||
|
||||
if (!pci_present())
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
s_bridge = pci_find_device(VENDOR, DEVICE, NULL);
|
||||
|
||||
if (! s_bridge) {
|
||||
|
||||
if (!s_bridge) {
|
||||
printk("vt82c586b not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ( PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_byte(s_bridge, PM_CFG_REVID, &rev))
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_byte(s_bridge, PM_CFG_REVID, &rev))
|
||||
return -ENODEV;
|
||||
|
||||
switch(rev)
|
||||
{
|
||||
case 0x00: base = PM_CFG_IOBASE0;
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x10: base = PM_CFG_IOBASE1;
|
||||
break;
|
||||
|
||||
default : base = PM_CFG_IOBASE1;
|
||||
/* later revision */
|
||||
}
|
||||
switch (rev) {
|
||||
case 0x00:
|
||||
base = PM_CFG_IOBASE0;
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x10:
|
||||
base = PM_CFG_IOBASE1;
|
||||
break;
|
||||
|
||||
if ( PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_word(s_bridge, base, &pm_io_base))
|
||||
return -ENODEV;
|
||||
|
||||
pm_io_base &= (0xff<<8);
|
||||
default:
|
||||
base = PM_CFG_IOBASE1;
|
||||
/* later revision */
|
||||
}
|
||||
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_word(s_bridge, base, &pm_io_base))
|
||||
return -ENODEV;
|
||||
|
||||
pm_io_base &= (0xff << 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -162,30 +166,31 @@ static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init i2c_via_init(void)
|
||||
int __init i2c_via_init(void)
|
||||
{
|
||||
if (find_via() < 0) {
|
||||
printk("Error while reading PCI configuration\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ( check_region(I2C_DIR, IOSPACE) < 0) {
|
||||
if (check_region(I2C_DIR, IOSPACE) < 0) {
|
||||
printk("IO 0x%x-0x%x already in use\n",
|
||||
I2C_DIR, I2C_DIR+IOSPACE);
|
||||
I2C_DIR, I2C_DIR + IOSPACE);
|
||||
return -EBUSY;
|
||||
} else {
|
||||
request_region(I2C_DIR, IOSPACE, IOTEXT);
|
||||
outb(inb(I2C_DIR) | I2C_SDA | I2C_SCL, I2C_DIR);
|
||||
outb(inb(I2C_OUT) | I2C_SDA | I2C_SCL, I2C_OUT);
|
||||
outb(inb(I2C_OUT) | I2C_SDA | I2C_SCL, I2C_OUT);
|
||||
}
|
||||
|
||||
|
||||
if (i2c_bit_add_bus(&bit_via_ops) == 0) {
|
||||
printk("i2c-via.o: Module succesfully loaded\n");
|
||||
return 0;
|
||||
} else {
|
||||
outb(inb(I2C_DIR)&~(I2C_SDA|I2C_SCL), I2C_DIR);
|
||||
outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR);
|
||||
release_region(I2C_DIR, IOSPACE);
|
||||
printk("i2c-via.o: Algo-bit error, couldn't register bus\n");
|
||||
printk
|
||||
("i2c-via.o: Algo-bit error, couldn't register bus\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
@@ -196,12 +201,12 @@ EXPORT_NO_SYMBOLS;
|
||||
MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>");
|
||||
MODULE_DESCRIPTION("i2c for Via vt82c586b southbridge");
|
||||
|
||||
int init_module(void)
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_via_init();
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
void cleanup_module(void)
|
||||
{
|
||||
i2c_bit_del_bus(&bit_via_ops);
|
||||
release_region(I2C_DIR, IOSPACE);
|
||||
|
||||
+311
-284
@@ -88,28 +88,29 @@ static unsigned short smb_cf_hstcfg;
|
||||
/* If force is set to anything different from 0, we forcibly enable the
|
||||
VT596. DANGEROUS! */
|
||||
static int force = 0;
|
||||
MODULE_PARM(force,"i");
|
||||
MODULE_PARM_DESC(force,"Forcibly enable the VT82C596 SMBus. DANGEROUS!");
|
||||
MODULE_PARM(force, "i");
|
||||
MODULE_PARM_DESC(force, "Forcibly enable the VT82C596 SMBus. DANGEROUS!");
|
||||
|
||||
/* If force_addr is set to anything different from 0, we forcibly enable
|
||||
the VT596 at the given address. VERY DANGEROUS! */
|
||||
static int force_addr = 0;
|
||||
MODULE_PARM(force_addr,"i");
|
||||
MODULE_PARM_DESC(force_addr,"Forcibly enable the VT82C596 SMBus at the given address. "
|
||||
"EXTREMELY DANGEROUS!");
|
||||
MODULE_PARM(force_addr, "i");
|
||||
MODULE_PARM_DESC(force_addr,
|
||||
"Forcibly enable the VT82C596 SMBus at the given address. "
|
||||
"EXTREMELY DANGEROUS!");
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init i2c_vt596_init(void);
|
||||
int __init i2c_vt596_init(void);
|
||||
static int __init vt596_cleanup(void);
|
||||
static int vt596_setup(void);
|
||||
static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags,char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data);
|
||||
static void vt596_do_pause( unsigned int amount );
|
||||
static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data *data);
|
||||
static void vt596_do_pause(unsigned int amount);
|
||||
static int vt596_transaction(void);
|
||||
static void vt596_inc(struct i2c_adapter *adapter);
|
||||
static void vt596_dec(struct i2c_adapter *adapter);
|
||||
@@ -118,28 +119,28 @@ static u32 vt596_func(struct i2c_adapter *adapter);
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
static struct i2c_algorithm smbus_algorithm = {
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ vt596_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ vt596_func,
|
||||
/* name */ "Non-I2C SMBus adapter",
|
||||
/* id */ I2C_ALGO_SMBUS,
|
||||
/* master_xfer */ NULL,
|
||||
/* smbus_access */ vt596_access,
|
||||
/* slave_send */ NULL,
|
||||
/* slave_rcv */ NULL,
|
||||
/* algo_control */ NULL,
|
||||
/* functionality */ vt596_func,
|
||||
};
|
||||
|
||||
static struct i2c_adapter vt596_adapter = {
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
vt596_inc,
|
||||
vt596_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
"unset",
|
||||
I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2,
|
||||
&smbus_algorithm,
|
||||
NULL,
|
||||
vt596_inc,
|
||||
vt596_dec,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __initdata vt596_initialized;
|
||||
@@ -152,286 +153,308 @@ static unsigned short vt596_smba = 0;
|
||||
defined to make the transition easier. */
|
||||
int vt596_setup(void)
|
||||
{
|
||||
int error_return=0;
|
||||
unsigned char temp;
|
||||
int error_return = 0;
|
||||
unsigned char temp;
|
||||
|
||||
struct pci_dev *VT596_dev;
|
||||
struct pci_dev *VT596_dev;
|
||||
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-viapro.o: Error: No PCI-bus found!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
/* First check whether we can access PCI at all */
|
||||
if (pci_present() == 0) {
|
||||
printk("i2c-viapro.o: Error: No PCI-bus found!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Look for the VT596 function 3 _or_ VT686 function 4 */
|
||||
VT596_dev = NULL;
|
||||
VT596_dev = pci_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_82C596_3, VT596_dev);
|
||||
if (VT596_dev == NULL)
|
||||
VT596_dev = pci_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_82C686_4, VT596_dev);
|
||||
/* Look for the VT596 function 3 _or_ VT686 function 4 */
|
||||
VT596_dev = NULL;
|
||||
VT596_dev = pci_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_82C596_3, VT596_dev);
|
||||
if (VT596_dev == NULL)
|
||||
VT596_dev = pci_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_82C686_4,
|
||||
VT596_dev);
|
||||
|
||||
if (VT596_dev == NULL) {
|
||||
printk("i2c-viapro.o: Error: Can't detect vt82c596 or vt82c686");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
if (VT596_dev == NULL) {
|
||||
printk
|
||||
("i2c-viapro.o: Error: Can't detect vt82c596 or vt82c686");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Determine the configuration space registers for the SMBus areas */
|
||||
if ((! pci_read_config_word(VT596_dev, SMBBA1, &vt596_smba)) && (vt596_smba & 0x1)) {
|
||||
smb_cf_base = SMBBA1;
|
||||
smb_cf_hstcfg = 0xD2;
|
||||
} else if ((! pci_read_config_word(VT596_dev, SMBBA2, &vt596_smba)) && (vt596_smba & 0x1)) {
|
||||
smb_cf_base = SMBBA2;
|
||||
smb_cf_hstcfg = 0x84;
|
||||
} else {
|
||||
printk("i2c-viapro.o: Cannot configure SMBus I/O Base address\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
if ((!pci_read_config_word(VT596_dev, SMBBA1, &vt596_smba))
|
||||
&& (vt596_smba & 0x1)) {
|
||||
smb_cf_base = SMBBA1;
|
||||
smb_cf_hstcfg = 0xD2;
|
||||
} else if ((!pci_read_config_word(VT596_dev, SMBBA2, &vt596_smba))
|
||||
&& (vt596_smba & 0x1)) {
|
||||
smb_cf_base = SMBBA2;
|
||||
smb_cf_hstcfg = 0x84;
|
||||
} else {
|
||||
printk
|
||||
("i2c-viapro.o: Cannot configure SMBus I/O Base address\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
/* Determine the address of the SMBus areas */
|
||||
if (force_addr) {
|
||||
vt596_smba = force_addr & 0xfff0;
|
||||
force = 0;
|
||||
} else {
|
||||
vt596_smba &= 0xfff0;
|
||||
}
|
||||
if (force_addr) {
|
||||
vt596_smba = force_addr & 0xfff0;
|
||||
force = 0;
|
||||
} else {
|
||||
vt596_smba &= 0xfff0;
|
||||
}
|
||||
|
||||
if (check_region(vt596_smba, 8)) {
|
||||
printk("i2c-viapro.o: vt82c596_smb region 0x%x already in use!\n", vt596_smba);
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
if (check_region(vt596_smba, 8)) {
|
||||
printk
|
||||
("i2c-viapro.o: vt82c596_smb region 0x%x already in use!\n",
|
||||
vt596_smba);
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
|
||||
pci_read_config_byte(VT596_dev, SMBHSTCFG, &temp);
|
||||
pci_read_config_byte(VT596_dev, SMBHSTCFG, &temp);
|
||||
/* If force_addr is set, we program the new address here. Just to make
|
||||
sure, we disable the VT596 first. */
|
||||
if (force_addr) {
|
||||
pci_write_config_byte(VT596_dev, SMBHSTCFG, temp & 0xfe);
|
||||
pci_write_config_word(VT596_dev, SMBBA,vt596_smba);
|
||||
pci_write_config_byte(VT596_dev, SMBHSTCFG, temp | 0x01);
|
||||
printk("i2c-viapro.o: WARNING: VT596 SMBus interface set to new "
|
||||
"address %04x!\n",vt596_smba);
|
||||
} else if ((temp & 1) == 0) {
|
||||
if (force) {
|
||||
if (force_addr) {
|
||||
pci_write_config_byte(VT596_dev, SMBHSTCFG, temp & 0xfe);
|
||||
pci_write_config_word(VT596_dev, SMBBA, vt596_smba);
|
||||
pci_write_config_byte(VT596_dev, SMBHSTCFG, temp | 0x01);
|
||||
printk
|
||||
("i2c-viapro.o: WARNING: VT596 SMBus interface set to new "
|
||||
"address %04x!\n", vt596_smba);
|
||||
} else if ((temp & 1) == 0) {
|
||||
if (force) {
|
||||
/* NOTE: This assumes I/O space and other allocations WERE
|
||||
done by the Bios! Don't complain if your hardware does weird
|
||||
things after enabling this. :') Check for Bios updates before
|
||||
resorting to this. */
|
||||
pci_write_config_byte(VT596_dev, SMBHSTCFG, temp | 1);
|
||||
printk("i2c-viapro.o: WARNING: SMBus interface has been FORCEFULLY "
|
||||
"ENABLED!\n");
|
||||
} else {
|
||||
printk("SMBUS: Error: Host SMBus controller not enabled!\n");
|
||||
error_return=-ENODEV;
|
||||
goto END;
|
||||
}
|
||||
}
|
||||
pci_write_config_byte(VT596_dev, SMBHSTCFG,
|
||||
temp | 1);
|
||||
printk
|
||||
("i2c-viapro.o: WARNING: SMBus interface has been FORCEFULLY "
|
||||
"ENABLED!\n");
|
||||
} else {
|
||||
printk
|
||||
("SMBUS: Error: Host SMBus controller not enabled!\n");
|
||||
error_return = -ENODEV;
|
||||
goto END;
|
||||
}
|
||||
}
|
||||
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(vt596_smba, 8, "via2-smbus");
|
||||
/* Everything is happy, let's grab the memory and set things up. */
|
||||
request_region(vt596_smba, 8, "via2-smbus");
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((temp & 0x0E) == 8)
|
||||
printk("i2c-viapro.o: using Interrupt 9 for SMBus.\n");
|
||||
else if ((temp & 0x0E) == 0)
|
||||
printk("i2c-viapro.o: using Interrupt SMI# for SMBus.\n");
|
||||
else
|
||||
printk("i2c-viapro.o: Illegal Interrupt configuration (or code out "
|
||||
"of date)!\n");
|
||||
if ((temp & 0x0E) == 8)
|
||||
printk("i2c-viapro.o: using Interrupt 9 for SMBus.\n");
|
||||
else if ((temp & 0x0E) == 0)
|
||||
printk("i2c-viapro.o: using Interrupt SMI# for SMBus.\n");
|
||||
else
|
||||
printk
|
||||
("i2c-viapro.o: Illegal Interrupt configuration (or code out "
|
||||
"of date)!\n");
|
||||
|
||||
pci_read_config_byte(VT596_dev, SMBREV, &temp);
|
||||
printk("i2c-viapro.o: SMBREV = 0x%X\n",temp);
|
||||
printk("i2c-viapro.o: VT596_smba = 0x%X\n",vt596_smba);
|
||||
#endif /* DEBUG */
|
||||
pci_read_config_byte(VT596_dev, SMBREV, &temp);
|
||||
printk("i2c-viapro.o: SMBREV = 0x%X\n", temp);
|
||||
printk("i2c-viapro.o: VT596_smba = 0x%X\n", vt596_smba);
|
||||
#endif /* DEBUG */
|
||||
|
||||
END:
|
||||
return error_return;
|
||||
END:
|
||||
return error_return;
|
||||
}
|
||||
|
||||
|
||||
/* Internally used pause function */
|
||||
void vt596_do_pause( unsigned int amount )
|
||||
void vt596_do_pause(unsigned int amount)
|
||||
{
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(amount);
|
||||
}
|
||||
|
||||
/* Another internally used function */
|
||||
int vt596_transaction(void)
|
||||
int vt596_transaction(void)
|
||||
{
|
||||
int temp;
|
||||
int result=0;
|
||||
int timeout=0;
|
||||
int temp;
|
||||
int result = 0;
|
||||
int timeout = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("i2c-viapro.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
|
||||
"DAT1=%02x\n",
|
||||
inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-viapro.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
|
||||
"DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
|
||||
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
/* Make sure the SMBus host is ready to start transmitting */
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-viapro.o: SMBus busy (%02x). Resetting... \n",temp);
|
||||
printk("i2c-viapro.o: SMBus busy (%02x). Resetting... \n",
|
||||
temp);
|
||||
#endif
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
outb_p(temp, SMBHSTSTS);
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-viapro.o: Failed! (%02x)\n",temp);
|
||||
printk("i2c-viapro.o: Failed! (%02x)\n", temp);
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-viapro.o: Successfull!\n");
|
||||
printk("i2c-viapro.o: Successfull!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* start the transaction by setting bit 6 */
|
||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
/* start the transaction by setting bit 6 */
|
||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
|
||||
/* We will always wait for a fraction of a second!
|
||||
I don't know if VIA needs this, Intel did */
|
||||
do {
|
||||
vt596_do_pause(1);
|
||||
temp=inb_p(SMBHSTSTS);
|
||||
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
|
||||
/* We will always wait for a fraction of a second!
|
||||
I don't know if VIA needs this, Intel did */
|
||||
do {
|
||||
vt596_do_pause(1);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-viapro.o: SMBus Timeout!\n");
|
||||
result = -1;
|
||||
printk("i2c-viapro.o: SMBus Timeout!\n");
|
||||
result = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
if (temp & 0x10) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-viapro.o: Error: Failed bus transaction\n");
|
||||
printk("i2c-viapro.o: Error: Failed bus transaction\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & 0x08) {
|
||||
result = -1;
|
||||
printk("i2c-viapro.o: Bus collision! SMBus may be locked until next hard
|
||||
reset. (sorry!)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
}
|
||||
if (temp & 0x08) {
|
||||
result = -1;
|
||||
printk
|
||||
("i2c-viapro.o: Bus collision! SMBus may be locked until next hard\n"
|
||||
"reset. (sorry!)\n");
|
||||
/* Clock stops and slave is stuck in mid-transmission */
|
||||
}
|
||||
|
||||
if (temp & 0x04) {
|
||||
result = -1;
|
||||
if (temp & 0x04) {
|
||||
result = -1;
|
||||
#ifdef DEBUG
|
||||
printk("i2c-viapro.o: Error: no response!\n");
|
||||
printk("i2c-viapro.o: Error: no response!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (inb_p(SMBHSTSTS) != 0x00)
|
||||
outb_p( inb(SMBHSTSTS), SMBHSTSTS);
|
||||
if (inb_p(SMBHSTSTS) != 0x00)
|
||||
outb_p(inb(SMBHSTSTS), SMBHSTSTS);
|
||||
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
|
||||
#ifdef DEBUG
|
||||
printk("i2c-viapro.o: Failed reset at end of transaction (%02x)\n",temp);
|
||||
printk
|
||||
("i2c-viapro.o: Failed reset at end of transaction (%02x)\n",
|
||||
temp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("i2c-viapro.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n",
|
||||
inb_p(SMBHSTCNT),inb_p(SMBHSTCMD),inb_p(SMBHSTADD),inb_p(SMBHSTDAT0),
|
||||
inb_p(SMBHSTDAT1));
|
||||
printk
|
||||
("i2c-viapro.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
|
||||
"DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
|
||||
inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
|
||||
#endif
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return -1 on error. See smbus.h for more information */
|
||||
s32 vt596_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
|
||||
char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
s32 vt596_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
|
||||
char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
{
|
||||
int i,len;
|
||||
int i, len;
|
||||
|
||||
switch(size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk("i2c-viapro.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
size = VT596_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMBHSTCMD);
|
||||
size = VT596_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->byte,SMBHSTDAT0);
|
||||
size = VT596_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->word & 0xff,SMBHSTDAT0);
|
||||
outb_p((data->word & 0xff00) >> 8,SMBHSTDAT1);
|
||||
}
|
||||
size = VT596_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
outb_p(len,SMBHSTDAT0);
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= len; i ++)
|
||||
outb_p(data->block[i],SMBBLKDAT);
|
||||
}
|
||||
size = VT596_BLOCK_DATA;
|
||||
break;
|
||||
}
|
||||
switch (size) {
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
printk
|
||||
("i2c-viapro.o: I2C_SMBUS_PROC_CALL not supported!\n");
|
||||
return -1;
|
||||
case I2C_SMBUS_QUICK:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
size = VT596_QUICK;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(command, SMBHSTCMD);
|
||||
size = VT596_BYTE;
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outb_p(data->byte, SMBHSTDAT0);
|
||||
size = VT596_BYTE_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->word & 0xff, SMBHSTDAT0);
|
||||
outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
|
||||
}
|
||||
size = VT596_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
|
||||
SMBHSTADD);
|
||||
outb_p(command, SMBHSTCMD);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
if (len > 32)
|
||||
len = 32;
|
||||
outb_p(len, SMBHSTDAT0);
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= len; i++)
|
||||
outb_p(data->block[i], SMBBLKDAT);
|
||||
}
|
||||
size = VT596_BLOCK_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
|
||||
outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
|
||||
|
||||
if (vt596_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
|
||||
return 0;
|
||||
|
||||
if (vt596_transaction()) /* Error in transaction */
|
||||
return -1;
|
||||
|
||||
switch(size) {
|
||||
case VT596_BYTE: /* Where is the result put? I assume here it is in
|
||||
SMBHSTDAT0 but it might just as well be in the
|
||||
SMBHSTCMD. No clue in the docs */
|
||||
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case VT596_BYTE_DATA:
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case VT596_WORD_DATA:
|
||||
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
case VT596_BLOCK_DATA:
|
||||
data->block[0] = inb_p(SMBHSTDAT0);
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= data->block[0]; i++)
|
||||
data->block[i] = inb_p(SMBBLKDAT);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
|
||||
return 0;
|
||||
|
||||
|
||||
switch (size) {
|
||||
case VT596_BYTE: /* Where is the result put? I assume here it is in
|
||||
SMBHSTDAT0 but it might just as well be in the
|
||||
SMBHSTCMD. No clue in the docs */
|
||||
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case VT596_BYTE_DATA:
|
||||
data->byte = inb_p(SMBHSTDAT0);
|
||||
break;
|
||||
case VT596_WORD_DATA:
|
||||
data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
|
||||
break;
|
||||
case VT596_BLOCK_DATA:
|
||||
data->block[0] = inb_p(SMBHSTDAT0);
|
||||
i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
|
||||
for (i = 1; i <= data->block[0]; i++)
|
||||
data->block[i] = inb_p(SMBBLKDAT);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vt596_inc(struct i2c_adapter *adapter)
|
||||
@@ -448,74 +471,78 @@ void vt596_dec(struct i2c_adapter *adapter)
|
||||
u32 vt596_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
}
|
||||
|
||||
int __init i2c_vt596_init(void)
|
||||
{
|
||||
int res;
|
||||
printk("via2.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
int res;
|
||||
printk("via2.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
#ifdef DEBUG
|
||||
/* PE- It might be good to make this a permanent part of the code! */
|
||||
if (vt596_initialized) {
|
||||
printk("i2c-viapro.o: Oops, vt596_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (vt596_initialized) {
|
||||
printk
|
||||
("i2c-viapro.o: Oops, vt596_init called a second time!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
vt596_initialized = 0;
|
||||
if ((res = vt596_setup())) {
|
||||
printk("i2c-viapro.o: vt82c596 not detected, module not inserted.\n");
|
||||
vt596_cleanup();
|
||||
return res;
|
||||
}
|
||||
vt596_initialized ++;
|
||||
sprintf(vt596_adapter.name,"SMBus vt82c596 adapter at %04x",vt596_smba);
|
||||
if ((res = i2c_add_adapter(&vt596_adapter))) {
|
||||
printk("i2c-viapro.o: Adapter registration failed, module not inserted.\n");
|
||||
vt596_cleanup();
|
||||
return res;
|
||||
}
|
||||
vt596_initialized++;
|
||||
printk("i2c-viapro.o: vt82c596 bus detected and initialized\n");
|
||||
return 0;
|
||||
vt596_initialized = 0;
|
||||
if ((res = vt596_setup())) {
|
||||
printk
|
||||
("i2c-viapro.o: vt82c596 not detected, module not inserted.\n");
|
||||
vt596_cleanup();
|
||||
return res;
|
||||
}
|
||||
vt596_initialized++;
|
||||
sprintf(vt596_adapter.name, "SMBus vt82c596 adapter at %04x",
|
||||
vt596_smba);
|
||||
if ((res = i2c_add_adapter(&vt596_adapter))) {
|
||||
printk
|
||||
("i2c-viapro.o: Adapter registration failed, module not inserted.\n");
|
||||
vt596_cleanup();
|
||||
return res;
|
||||
}
|
||||
vt596_initialized++;
|
||||
printk("i2c-viapro.o: vt82c596 bus detected and initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init vt596_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
if (vt596_initialized >= 2)
|
||||
{
|
||||
if ((res = i2c_del_adapter(&vt596_adapter))) {
|
||||
printk("i2c-viapro.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
vt596_initialized--;
|
||||
}
|
||||
if (vt596_initialized >= 1) {
|
||||
release_region(vt596_smba, 8);
|
||||
vt596_initialized--;
|
||||
}
|
||||
return 0;
|
||||
int res;
|
||||
if (vt596_initialized >= 2) {
|
||||
if ((res = i2c_del_adapter(&vt596_adapter))) {
|
||||
printk
|
||||
("i2c-viapro.o: i2c_del_adapter failed, module not removed\n");
|
||||
return res;
|
||||
} else
|
||||
vt596_initialized--;
|
||||
}
|
||||
if (vt596_initialized >= 1) {
|
||||
release_region(vt596_smba, 8);
|
||||
vt596_initialized--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_DESCRIPTION("vt82c596 SMBus driver");
|
||||
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return i2c_vt596_init();
|
||||
return i2c_vt596_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return vt596_cleanup();
|
||||
return vt596_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+630
-506
File diff suppressed because it is too large.
Load diff
+322
-292
@@ -38,14 +38,15 @@
|
||||
#endif
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = {SENSORS_I2C_END};
|
||||
static unsigned short normal_i2c_range[] = {0x18,0x1a,0x29,0x2b,
|
||||
0x4c,0x4e,SENSORS_I2C_END};
|
||||
static unsigned int normal_isa[] = {SENSORS_ISA_END};
|
||||
static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
|
||||
static unsigned short normal_i2c[] = { SENSORS_I2C_END };
|
||||
static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b,
|
||||
0x4c, 0x4e, SENSORS_I2C_END
|
||||
};
|
||||
static unsigned int normal_isa[] = { SENSORS_ISA_END };
|
||||
static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_6(adm1021,max1617,max1617a,thmc10,lm84,gl523sm);
|
||||
SENSORS_INSMOD_6(adm1021, max1617, max1617a, thmc10, lm84, gl523sm);
|
||||
|
||||
/* adm1021 constants specified below */
|
||||
|
||||
@@ -54,9 +55,9 @@ SENSORS_INSMOD_6(adm1021,max1617,max1617a,thmc10,lm84,gl523sm);
|
||||
#define ADM1021_REG_TEMP 0x00
|
||||
#define ADM1021_REG_REMOTE_TEMP 0x01
|
||||
#define ADM1021_REG_STATUS 0x02
|
||||
#define ADM1021_REG_MAN_ID 0x0FE /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys */
|
||||
#define ADM1021_REG_DEV_ID 0x0FF /* ADM1021 */
|
||||
#define ADM1021_REG_DIE_CODE 0x0FF /* MAX1617A */
|
||||
#define ADM1021_REG_MAN_ID 0x0FE /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys */
|
||||
#define ADM1021_REG_DEV_ID 0x0FF /* ADM1021 */
|
||||
#define ADM1021_REG_DIE_CODE 0x0FF /* MAX1617A */
|
||||
/* These use different addresses for reading/writing */
|
||||
#define ADM1021_REG_CONFIG_R 0x03
|
||||
#define ADM1021_REG_CONFIG_W 0x09
|
||||
@@ -95,61 +96,63 @@ clearing it. Weird, ey? --Phil */
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct adm1021_data {
|
||||
int sysctl_id;
|
||||
enum chips type;
|
||||
int sysctl_id;
|
||||
enum chips type;
|
||||
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u8 temp,temp_os,temp_hyst; /* Register values */
|
||||
u8 remote_temp,remote_temp_os,remote_temp_hyst,alarms,die_code;
|
||||
u8 temp, temp_os, temp_hyst; /* Register values */
|
||||
u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms, die_code;
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init sensors_adm1021_init(void);
|
||||
int __init sensors_adm1021_init(void);
|
||||
static int __init adm1021_cleanup(void);
|
||||
static int adm1021_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int adm1021_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static int adm1021_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static void adm1021_init_client(struct i2c_client *client);
|
||||
static int adm1021_detach_client(struct i2c_client *client);
|
||||
static int adm1021_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *arg);
|
||||
static void adm1021_inc_use (struct i2c_client *client);
|
||||
static void adm1021_dec_use (struct i2c_client *client);
|
||||
void *arg);
|
||||
static void adm1021_inc_use(struct i2c_client *client);
|
||||
static void adm1021_dec_use(struct i2c_client *client);
|
||||
static int adm1021_read_value(struct i2c_client *client, u8 reg);
|
||||
static int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value);
|
||||
static void adm1021_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void adm1021_remote_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void adm1021_die_code(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static int adm1021_write_value(struct i2c_client *client, u8 reg,
|
||||
u16 value);
|
||||
static void adm1021_temp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void adm1021_remote_temp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag,
|
||||
long *results);
|
||||
static void adm1021_alarms(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void adm1021_die_code(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void adm1021_update_client(struct i2c_client *client);
|
||||
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver adm1021_driver = {
|
||||
/* name */ "ADM1021, MAX1617 sensor driver",
|
||||
/* id */ I2C_DRIVERID_ADM1021,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &adm1021_attach_adapter,
|
||||
/* detach_client */ &adm1021_detach_client,
|
||||
/* command */ &adm1021_command,
|
||||
/* inc_use */ &adm1021_inc_use,
|
||||
/* dec_use */ &adm1021_dec_use
|
||||
/* name */ "ADM1021, MAX1617 sensor driver",
|
||||
/* id */ I2C_DRIVERID_ADM1021,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &adm1021_attach_adapter,
|
||||
/* detach_client */ &adm1021_detach_client,
|
||||
/* command */ &adm1021_command,
|
||||
/* inc_use */ &adm1021_inc_use,
|
||||
/* dec_use */ &adm1021_dec_use
|
||||
};
|
||||
|
||||
/* These files are created for each detected adm1021. This is just a template;
|
||||
@@ -158,25 +161,25 @@ static struct i2c_driver adm1021_driver = {
|
||||
is done through one of the 'extra' fields which are initialized
|
||||
when a new copy is allocated. */
|
||||
static ctl_table adm1021_dir_table_template[] = {
|
||||
{ ADM1021_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_temp },
|
||||
{ADM1021_SYSCTL_REMOTE_TEMP, "remote_temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_remote_temp },
|
||||
{ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_die_code },
|
||||
{ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_alarms },
|
||||
{ 0 }
|
||||
{ADM1021_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_temp},
|
||||
{ADM1021_SYSCTL_REMOTE_TEMP, "remote_temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_remote_temp},
|
||||
{ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_die_code},
|
||||
{ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_alarms},
|
||||
{0}
|
||||
};
|
||||
|
||||
static ctl_table adm1021_max_dir_table_template[] = {
|
||||
{ ADM1021_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_temp },
|
||||
{ADM1021_SYSCTL_REMOTE_TEMP, "remote_temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_remote_temp },
|
||||
{ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_alarms },
|
||||
{ 0 }
|
||||
{ADM1021_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_temp},
|
||||
{ADM1021_SYSCTL_REMOTE_TEMP, "remote_temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_remote_temp},
|
||||
{ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &adm1021_alarms},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
||||
@@ -190,166 +193,177 @@ static int adm1021_id = 0;
|
||||
|
||||
int adm1021_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return sensors_detect(adapter,&addr_data,adm1021_detect);
|
||||
return sensors_detect(adapter, &addr_data, adm1021_detect);
|
||||
}
|
||||
|
||||
static int adm1021_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
{
|
||||
int i;
|
||||
struct i2c_client *new_client;
|
||||
struct adm1021_data *data;
|
||||
int err=0;
|
||||
const char *type_name = "";
|
||||
const char *client_name = "";
|
||||
static int adm1021_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
{
|
||||
int i;
|
||||
struct i2c_client *new_client;
|
||||
struct adm1021_data *data;
|
||||
int err = 0;
|
||||
const char *type_name = "";
|
||||
const char *client_name = "";
|
||||
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
#ifdef DEBUG
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk
|
||||
("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto ERROR0;
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto ERROR0;
|
||||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access adm1021_{read,write}_value. */
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access adm1021_{read,write}_value. */
|
||||
|
||||
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct adm1021_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct adm1021_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
data = (struct adm1021_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &adm1021_driver;
|
||||
new_client->flags = 0;
|
||||
data = (struct adm1021_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &adm1021_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we do the remaining detection. */
|
||||
/* Now, we do the remaining detection. */
|
||||
|
||||
if (kind < 0) {
|
||||
if ((adm1021_read_value(new_client,ADM1021_REG_STATUS) & 0x03) != 0x00)
|
||||
goto ERROR1;
|
||||
}
|
||||
if (kind < 0) {
|
||||
if (
|
||||
(adm1021_read_value(new_client, ADM1021_REG_STATUS) &
|
||||
0x03) != 0x00)
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Determine the chip type. */
|
||||
|
||||
if (kind <= 0) {
|
||||
i = adm1021_read_value(new_client,ADM1021_REG_MAN_ID);
|
||||
if (i == 0x41)
|
||||
kind = adm1021;
|
||||
else if (i == 0x49)
|
||||
kind = thmc10;
|
||||
else if (i == 0x23)
|
||||
kind = gl523sm;
|
||||
else if ((i== 0x4d) &&
|
||||
(adm1021_read_value(new_client,ADM1021_REG_DEV_ID) == 0x01))
|
||||
kind = max1617a;
|
||||
/* LM84 Mfr ID in a different place */
|
||||
else if (adm1021_read_value(new_client,ADM1021_REG_CONV_RATE_R) == 0x00)
|
||||
kind = lm84;
|
||||
else
|
||||
kind = max1617;
|
||||
}
|
||||
/* Determine the chip type. */
|
||||
|
||||
if (kind == max1617) {
|
||||
type_name = "max1617";
|
||||
client_name = "MAX1617 chip";
|
||||
} else if (kind == max1617a) {
|
||||
type_name = "max1617a";
|
||||
client_name = "MAX1617A chip";
|
||||
} else if (kind == adm1021) {
|
||||
type_name = "adm1021";
|
||||
client_name = "ADM1021 chip";
|
||||
} else if (kind == thmc10) {
|
||||
type_name = "thmc10";
|
||||
client_name = "THMC10 chip";
|
||||
} else {
|
||||
if (kind <= 0) {
|
||||
i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
|
||||
if (i == 0x41)
|
||||
kind = adm1021;
|
||||
else if (i == 0x49)
|
||||
kind = thmc10;
|
||||
else if (i == 0x23)
|
||||
kind = gl523sm;
|
||||
else if ((i == 0x4d) &&
|
||||
(adm1021_read_value
|
||||
(new_client, ADM1021_REG_DEV_ID) == 0x01))
|
||||
kind = max1617a;
|
||||
/* LM84 Mfr ID in a different place */
|
||||
else
|
||||
if (adm1021_read_value
|
||||
(new_client, ADM1021_REG_CONV_RATE_R) == 0x00)
|
||||
kind = lm84;
|
||||
else
|
||||
kind = max1617;
|
||||
}
|
||||
|
||||
if (kind == max1617) {
|
||||
type_name = "max1617";
|
||||
client_name = "MAX1617 chip";
|
||||
} else if (kind == max1617a) {
|
||||
type_name = "max1617a";
|
||||
client_name = "MAX1617A chip";
|
||||
} else if (kind == adm1021) {
|
||||
type_name = "adm1021";
|
||||
client_name = "ADM1021 chip";
|
||||
} else if (kind == thmc10) {
|
||||
type_name = "thmc10";
|
||||
client_name = "THMC10 chip";
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("adm1021.o: Internal error: unknown kind (%d)?!?",kind);
|
||||
printk("adm1021.o: Internal error: unknown kind (%d)?!?",
|
||||
kind);
|
||||
#endif
|
||||
goto ERROR1;
|
||||
}
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name,client_name);
|
||||
data->type = kind;
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name, client_name);
|
||||
data->type = kind;
|
||||
|
||||
new_client->id = adm1021_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
new_client->id = adm1021_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client,
|
||||
type_name,
|
||||
data->type==adm1021?adm1021_dir_table_template:
|
||||
adm1021_max_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client,
|
||||
type_name,
|
||||
data->type ==
|
||||
adm1021 ?
|
||||
adm1021_dir_table_template :
|
||||
adm1021_max_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
|
||||
/* Initialize the ADM1021 chip */
|
||||
adm1021_init_client(new_client);
|
||||
return 0;
|
||||
/* Initialize the ADM1021 chip */
|
||||
adm1021_init_client(new_client);
|
||||
return 0;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
}
|
||||
|
||||
void adm1021_init_client(struct i2c_client *client)
|
||||
{
|
||||
/* Initialize the adm1021 chip */
|
||||
adm1021_write_value(client,ADM1021_REG_TOS_W,
|
||||
TEMP_TO_REG(adm1021_INIT_TOS));
|
||||
adm1021_write_value(client,ADM1021_REG_THYST_W,
|
||||
TEMP_TO_REG(adm1021_INIT_THYST));
|
||||
adm1021_write_value(client,ADM1021_REG_REMOTE_TOS_W,
|
||||
TEMP_TO_REG(adm1021_INIT_REMOTE_TOS));
|
||||
adm1021_write_value(client,ADM1021_REG_REMOTE_THYST_W,
|
||||
TEMP_TO_REG(adm1021_INIT_REMOTE_THYST));
|
||||
/* Enable ADC and disable suspend mode */
|
||||
adm1021_write_value(client,ADM1021_REG_CONFIG_W,0);
|
||||
/* Set Conversion rate to 1/sec (this can be tinkered with) */
|
||||
adm1021_write_value(client,ADM1021_REG_CONV_RATE_W,0x04);
|
||||
/* Initialize the adm1021 chip */
|
||||
adm1021_write_value(client, ADM1021_REG_TOS_W,
|
||||
TEMP_TO_REG(adm1021_INIT_TOS));
|
||||
adm1021_write_value(client, ADM1021_REG_THYST_W,
|
||||
TEMP_TO_REG(adm1021_INIT_THYST));
|
||||
adm1021_write_value(client, ADM1021_REG_REMOTE_TOS_W,
|
||||
TEMP_TO_REG(adm1021_INIT_REMOTE_TOS));
|
||||
adm1021_write_value(client, ADM1021_REG_REMOTE_THYST_W,
|
||||
TEMP_TO_REG(adm1021_INIT_REMOTE_THYST));
|
||||
/* Enable ADC and disable suspend mode */
|
||||
adm1021_write_value(client, ADM1021_REG_CONFIG_W, 0);
|
||||
/* Set Conversion rate to 1/sec (this can be tinkered with) */
|
||||
adm1021_write_value(client, ADM1021_REG_CONV_RATE_W, 0x04);
|
||||
}
|
||||
|
||||
int adm1021_detach_client(struct i2c_client *client)
|
||||
{
|
||||
|
||||
int err;
|
||||
int err;
|
||||
|
||||
sensors_deregister_entry(((struct adm1021_data *)(client->data))->sysctl_id);
|
||||
sensors_deregister_entry(((struct adm1021_data *) (client->data))->
|
||||
sysctl_id);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("adm1021.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk
|
||||
("adm1021.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(client);
|
||||
kfree(client);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -357,188 +371,204 @@ int adm1021_detach_client(struct i2c_client *client)
|
||||
/* No commands defined yet */
|
||||
int adm1021_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void adm1021_inc_use (struct i2c_client *client)
|
||||
void adm1021_inc_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_INC_USE_COUNT;
|
||||
MOD_INC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
void adm1021_dec_use (struct i2c_client *client)
|
||||
void adm1021_dec_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_DEC_USE_COUNT;
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* All registers are byte-sized */
|
||||
int adm1021_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
return i2c_smbus_read_byte_data(client,reg);
|
||||
return i2c_smbus_read_byte_data(client, reg);
|
||||
}
|
||||
|
||||
int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
return i2c_smbus_write_byte_data(client,reg,value);
|
||||
return i2c_smbus_write_byte_data(client, reg, value);
|
||||
}
|
||||
|
||||
void adm1021_update_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm1021_data *data = client->data;
|
||||
struct adm1021_data *data = client->data;
|
||||
|
||||
down(&data->update_lock);
|
||||
down(&data->update_lock);
|
||||
|
||||
if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
|
||||
(jiffies < data->last_updated) || ! data->valid) {
|
||||
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
|
||||
(jiffies < data->last_updated) || !data->valid) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("Starting adm1021 update\n");
|
||||
printk("Starting adm1021 update\n");
|
||||
#endif
|
||||
|
||||
data->temp = adm1021_read_value(client,ADM1021_REG_TEMP);
|
||||
data->temp_os = adm1021_read_value(client,ADM1021_REG_TOS_R);
|
||||
data->temp_hyst = adm1021_read_value(client,ADM1021_REG_THYST_R);
|
||||
data->remote_temp = adm1021_read_value(client,ADM1021_REG_REMOTE_TEMP);
|
||||
data->remote_temp_os = adm1021_read_value(client,ADM1021_REG_REMOTE_TOS_R);
|
||||
data->remote_temp_hyst = adm1021_read_value(client,ADM1021_REG_REMOTE_THYST_R);
|
||||
data->alarms = adm1021_read_value(client,ADM1021_REG_STATUS) & 0xec;
|
||||
if (data->type == adm1021)
|
||||
data->die_code = adm1021_read_value(client,ADM1021_REG_DIE_CODE);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
data->temp = adm1021_read_value(client, ADM1021_REG_TEMP);
|
||||
data->temp_os =
|
||||
adm1021_read_value(client, ADM1021_REG_TOS_R);
|
||||
data->temp_hyst =
|
||||
adm1021_read_value(client, ADM1021_REG_THYST_R);
|
||||
data->remote_temp =
|
||||
adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
|
||||
data->remote_temp_os =
|
||||
adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
|
||||
data->remote_temp_hyst =
|
||||
adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
|
||||
data->alarms =
|
||||
adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
|
||||
if (data->type == adm1021)
|
||||
data->die_code =
|
||||
adm1021_read_value(client,
|
||||
ADM1021_REG_DIE_CODE);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
up(&data->update_lock);
|
||||
up(&data->update_lock);
|
||||
}
|
||||
|
||||
|
||||
void adm1021_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct adm1021_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
adm1021_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->temp_os = TEMP_TO_REG(results[0]);
|
||||
adm1021_write_value(client,ADM1021_REG_TOS_W,data->temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->temp_hyst = TEMP_TO_REG(results[1]);
|
||||
adm1021_write_value(client,ADM1021_REG_THYST_W,data->temp_hyst);
|
||||
}
|
||||
}
|
||||
struct adm1021_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
adm1021_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->temp_os = TEMP_TO_REG(results[0]);
|
||||
adm1021_write_value(client, ADM1021_REG_TOS_W,
|
||||
data->temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->temp_hyst = TEMP_TO_REG(results[1]);
|
||||
adm1021_write_value(client, ADM1021_REG_THYST_W,
|
||||
data->temp_hyst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void adm1021_remote_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void adm1021_remote_temp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct adm1021_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
adm1021_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->remote_temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->remote_temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->remote_temp_os = TEMP_TO_REG(results[0]);
|
||||
adm1021_write_value(client,ADM1021_REG_REMOTE_TOS_W,data->remote_temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->remote_temp_hyst = TEMP_TO_REG(results[1]);
|
||||
adm1021_write_value(client,ADM1021_REG_REMOTE_THYST_W,data->remote_temp_hyst);
|
||||
}
|
||||
}
|
||||
struct adm1021_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
adm1021_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->remote_temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->remote_temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->remote_temp_os = TEMP_TO_REG(results[0]);
|
||||
adm1021_write_value(client,
|
||||
ADM1021_REG_REMOTE_TOS_W,
|
||||
data->remote_temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->remote_temp_hyst = TEMP_TO_REG(results[1]);
|
||||
adm1021_write_value(client,
|
||||
ADM1021_REG_REMOTE_THYST_W,
|
||||
data->remote_temp_hyst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void adm1021_die_code(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void adm1021_die_code(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct adm1021_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
adm1021_update_client(client);
|
||||
results[0] = data->die_code;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
/* Can't write to it */
|
||||
}
|
||||
struct adm1021_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
adm1021_update_client(client);
|
||||
results[0] = data->die_code;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
/* Can't write to it */
|
||||
}
|
||||
}
|
||||
|
||||
void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct adm1021_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
adm1021_update_client(client);
|
||||
results[0] = data->alarms;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
/* Can't write to it */
|
||||
}
|
||||
struct adm1021_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
adm1021_update_client(client);
|
||||
results[0] = data->alarms;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
/* Can't write to it */
|
||||
}
|
||||
}
|
||||
|
||||
int __init sensors_adm1021_init(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
printk("adm1021.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
adm1021_initialized = 0;
|
||||
if ((res = i2c_add_driver(&adm1021_driver))) {
|
||||
printk("adm1021.o: Driver registration failed, module not inserted.\n");
|
||||
adm1021_cleanup();
|
||||
return res;
|
||||
}
|
||||
adm1021_initialized ++;
|
||||
return 0;
|
||||
printk("adm1021.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
adm1021_initialized = 0;
|
||||
if ((res = i2c_add_driver(&adm1021_driver))) {
|
||||
printk
|
||||
("adm1021.o: Driver registration failed, module not inserted.\n");
|
||||
adm1021_cleanup();
|
||||
return res;
|
||||
}
|
||||
adm1021_initialized++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init adm1021_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
if (adm1021_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&adm1021_driver))) {
|
||||
printk("adm1021.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
adm1021_initialized --;
|
||||
}
|
||||
if (adm1021_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&adm1021_driver))) {
|
||||
printk
|
||||
("adm1021.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
adm1021_initialized--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_DESCRIPTION("adm1021 driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return sensors_adm1021_init();
|
||||
return sensors_adm1021_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return adm1021_cleanup();
|
||||
return adm1021_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+484
-415
File diff suppressed because it is too large.
Load diff
+341
-325
@@ -40,12 +40,12 @@
|
||||
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = {SENSORS_I2C_END};
|
||||
static unsigned short normal_i2c[] = { SENSORS_I2C_END };
|
||||
|
||||
/* found only at 0x44 or 0x45 */
|
||||
static unsigned short normal_i2c_range[] = {0x44,0x45,SENSORS_I2C_END};
|
||||
static unsigned int normal_isa[] = {SENSORS_ISA_END};
|
||||
static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
|
||||
static unsigned short normal_i2c_range[] = { 0x44, 0x45, SENSORS_I2C_END };
|
||||
static unsigned int normal_isa[] = { SENSORS_ISA_END };
|
||||
static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(bt869);
|
||||
@@ -59,76 +59,76 @@ SENSORS_INSMOD_1(bt869);
|
||||
variants. Note that you should be a bit careful with which arguments
|
||||
these macros are called: arguments may be evaluated more than once.
|
||||
Fixing this is just not worth it. */
|
||||
|
||||
/*none*/
|
||||
|
||||
/*none */
|
||||
|
||||
/* Initial values */
|
||||
/*none*/
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct bt869_data {
|
||||
int sysctl_id;
|
||||
int sysctl_id;
|
||||
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u8 status[3]; /* Register values */
|
||||
u16 res[2]; /* Resolution XxY */
|
||||
u8 ntsc; /* 1=NTSC, 0=PAL */
|
||||
u8 half; /* go half res */
|
||||
u8 depth; /* screen depth */
|
||||
u8 colorbars; /* turn on/off colorbar calibration screen */
|
||||
u8 status[3]; /* Register values */
|
||||
u16 res[2]; /* Resolution XxY */
|
||||
u8 ntsc; /* 1=NTSC, 0=PAL */
|
||||
u8 half; /* go half res */
|
||||
u8 depth; /* screen depth */
|
||||
u8 colorbars; /* turn on/off colorbar calibration screen */
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init sensors_bt869_init(void);
|
||||
int __init sensors_bt869_init(void);
|
||||
static int __init bt869_cleanup(void);
|
||||
static int bt869_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int bt869_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static int bt869_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static void bt869_init_client(struct i2c_client *client);
|
||||
static int bt869_detach_client(struct i2c_client *client);
|
||||
static int bt869_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *arg);
|
||||
static void bt869_inc_use (struct i2c_client *client);
|
||||
static void bt869_dec_use (struct i2c_client *client);
|
||||
void *arg);
|
||||
static void bt869_inc_use(struct i2c_client *client);
|
||||
static void bt869_dec_use(struct i2c_client *client);
|
||||
static int bt869_read_value(struct i2c_client *client, u8 reg);
|
||||
static int bt869_write_value(struct i2c_client *client, u8 reg, u16 value);
|
||||
static void bt869_status(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void bt869_ntsc(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void bt869_res(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void bt869_half(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void bt869_colorbars(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void bt869_depth(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void bt869_status(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void bt869_ntsc(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void bt869_res(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void bt869_half(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void bt869_colorbars(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void bt869_depth(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void bt869_update_client(struct i2c_client *client);
|
||||
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver bt869_driver = {
|
||||
/* name */ "BT869 video-output chip driver",
|
||||
/* id */ I2C_DRIVERID_BT869,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &bt869_attach_adapter,
|
||||
/* detach_client */ &bt869_detach_client,
|
||||
/* command */ &bt869_command,
|
||||
/* inc_use */ &bt869_inc_use,
|
||||
/* dec_use */ &bt869_dec_use
|
||||
/* name */ "BT869 video-output chip driver",
|
||||
/* id */ I2C_DRIVERID_BT869,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &bt869_attach_adapter,
|
||||
/* detach_client */ &bt869_detach_client,
|
||||
/* command */ &bt869_command,
|
||||
/* inc_use */ &bt869_inc_use,
|
||||
/* dec_use */ &bt869_dec_use
|
||||
};
|
||||
|
||||
/* These files are created for each detected bt869. This is just a template;
|
||||
@@ -137,19 +137,19 @@ static struct i2c_driver bt869_driver = {
|
||||
is done through one of the 'extra' fields which are initialized
|
||||
when a new copy is allocated. */
|
||||
static ctl_table bt869_dir_table_template[] = {
|
||||
{ BT869_SYSCTL_STATUS, "status", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_status },
|
||||
{ BT869_SYSCTL_NTSC, "ntsc", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_ntsc },
|
||||
{ BT869_SYSCTL_RES, "res", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_res },
|
||||
{ BT869_SYSCTL_HALF, "half", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_half },
|
||||
{ BT869_SYSCTL_COLORBARS, "colorbars", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_colorbars },
|
||||
{ BT869_SYSCTL_DEPTH, "depth", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_depth },
|
||||
{ 0 }
|
||||
{BT869_SYSCTL_STATUS, "status", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_status},
|
||||
{BT869_SYSCTL_NTSC, "ntsc", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_ntsc},
|
||||
{BT869_SYSCTL_RES, "res", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_res},
|
||||
{BT869_SYSCTL_HALF, "half", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_half},
|
||||
{BT869_SYSCTL_COLORBARS, "colorbars", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_colorbars},
|
||||
{BT869_SYSCTL_DEPTH, "depth", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &bt869_depth},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* Used by init/cleanup */
|
||||
@@ -159,142 +159,146 @@ int bt869_id = 0;
|
||||
|
||||
int bt869_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return sensors_detect(adapter,&addr_data,bt869_detect);
|
||||
return sensors_detect(adapter, &addr_data, bt869_detect);
|
||||
}
|
||||
|
||||
/* This function is called by sensors_detect */
|
||||
int bt869_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
int bt869_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
{
|
||||
int i,cur;
|
||||
struct i2c_client *new_client;
|
||||
struct bt869_data *data;
|
||||
int err=0;
|
||||
const char *type_name,*client_name;
|
||||
int i, cur;
|
||||
struct i2c_client *new_client;
|
||||
struct bt869_data *data;
|
||||
int err = 0;
|
||||
const char *type_name, *client_name;
|
||||
|
||||
|
||||
printk("bt869.o: probing address %d .\n",address);
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
printk("bt869.o: probing address %d .\n", address);
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
#ifdef DEBUG
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk("bt869.o: bt869_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk
|
||||
("bt869.o: bt869_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_READ_BYTE|
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
|
||||
goto ERROR0;
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE |
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
|
||||
goto ERROR0;
|
||||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access bt869_{read,write}_value. */
|
||||
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct bt869_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access bt869_{read,write}_value. */
|
||||
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct bt869_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
data = (struct bt869_data *) (((struct i2c_client *) new_client) + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &bt869_driver;
|
||||
new_client->flags = 0;
|
||||
data =
|
||||
(struct bt869_data *) (((struct i2c_client *) new_client) + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &bt869_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we do the remaining detection. It is lousy. */
|
||||
i2c_smbus_write_byte_data(new_client,0xC4,0); /* set status bank 0 */
|
||||
cur = i2c_smbus_read_byte(new_client);
|
||||
printk("bt869.o: address 0x%X testing-->0x%X\n",address,cur);
|
||||
if ((cur & 0xE0) != 0x20)
|
||||
goto ERROR1;
|
||||
|
||||
/* Determine the chip type */
|
||||
kind = ((cur & 0x20)>>5);
|
||||
/* Now, we do the remaining detection. It is lousy. */
|
||||
i2c_smbus_write_byte_data(new_client, 0xC4, 0); /* set status bank 0 */
|
||||
cur = i2c_smbus_read_byte(new_client);
|
||||
printk("bt869.o: address 0x%X testing-->0x%X\n", address, cur);
|
||||
if ((cur & 0xE0) != 0x20)
|
||||
goto ERROR1;
|
||||
|
||||
if (kind) {
|
||||
type_name = "bt869";
|
||||
client_name = "bt869 chip";
|
||||
printk("bt869.o: BT869 detected\n");
|
||||
} else {
|
||||
type_name = "bt868";
|
||||
client_name = "bt868 chip";
|
||||
printk("bt869.o: BT868 detected\n");
|
||||
}
|
||||
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name,client_name);
|
||||
/* Determine the chip type */
|
||||
kind = ((cur & 0x20) >> 5);
|
||||
|
||||
new_client->id = bt869_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
if (kind) {
|
||||
type_name = "bt869";
|
||||
client_name = "bt869 chip";
|
||||
printk("bt869.o: BT869 detected\n");
|
||||
} else {
|
||||
type_name = "bt868";
|
||||
client_name = "bt868 chip";
|
||||
printk("bt869.o: BT868 detected\n");
|
||||
}
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client,type_name,
|
||||
bt869_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name, client_name);
|
||||
|
||||
bt869_init_client((struct i2c_client *) new_client);
|
||||
return 0;
|
||||
new_client->id = bt869_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client, type_name,
|
||||
bt869_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
|
||||
bt869_init_client((struct i2c_client *) new_client);
|
||||
return 0;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt869_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
|
||||
sensors_deregister_entry(((struct bt869_data *)(client->data))->sysctl_id);
|
||||
sensors_deregister_entry(((struct bt869_data *) (client->data))->
|
||||
sysctl_id);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("bt869.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk
|
||||
("bt869.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(client);
|
||||
kfree(client);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* No commands defined yet */
|
||||
int bt869_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nothing here yet */
|
||||
void bt869_inc_use (struct i2c_client *client)
|
||||
void bt869_inc_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_INC_USE_COUNT;
|
||||
MOD_INC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Nothing here yet */
|
||||
void bt869_dec_use (struct i2c_client *client)
|
||||
void bt869_dec_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_DEC_USE_COUNT;
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -303,7 +307,7 @@ void bt869_dec_use (struct i2c_client *client)
|
||||
the usual practice. */
|
||||
int bt869_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
return i2c_smbus_read_byte(client);
|
||||
return i2c_smbus_read_byte(client);
|
||||
}
|
||||
|
||||
/* All registers are byte-sized.
|
||||
@@ -311,249 +315,261 @@ int bt869_read_value(struct i2c_client *client, u8 reg)
|
||||
the usual practice. */
|
||||
int bt869_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
return i2c_smbus_write_byte_data(client,reg,value);
|
||||
return i2c_smbus_write_byte_data(client, reg, value);
|
||||
}
|
||||
|
||||
void bt869_init_client(struct i2c_client *client)
|
||||
{
|
||||
struct bt869_data *data = client->data;
|
||||
|
||||
/* Initialize the bt869 chip */
|
||||
bt869_write_value(client,0x0ba,0x80);
|
||||
// bt869_write_value(client,0x0D6, 0x00);
|
||||
/* Be a slave to the clock on the Voodoo3 */
|
||||
bt869_write_value(client,0xa0,0x80);
|
||||
bt869_write_value(client,0xba,0x20);
|
||||
/* depth =16bpp */
|
||||
bt869_write_value(client,0x0C6, 0x001);
|
||||
bt869_write_value(client,0xC4,1);
|
||||
/* Flicker free enable and config */
|
||||
bt869_write_value(client,0xC8,0);
|
||||
data->res[0]=640;
|
||||
data->res[1]=480;
|
||||
data->ntsc=1;
|
||||
data->half=0;
|
||||
data->colorbars=0;
|
||||
data->depth=16;
|
||||
|
||||
struct bt869_data *data = client->data;
|
||||
|
||||
/* Initialize the bt869 chip */
|
||||
bt869_write_value(client, 0x0ba, 0x80);
|
||||
// bt869_write_value(client,0x0D6, 0x00);
|
||||
/* Be a slave to the clock on the Voodoo3 */
|
||||
bt869_write_value(client, 0xa0, 0x80);
|
||||
bt869_write_value(client, 0xba, 0x20);
|
||||
/* depth =16bpp */
|
||||
bt869_write_value(client, 0x0C6, 0x001);
|
||||
bt869_write_value(client, 0xC4, 1);
|
||||
/* Flicker free enable and config */
|
||||
bt869_write_value(client, 0xC8, 0);
|
||||
data->res[0] = 640;
|
||||
data->res[1] = 480;
|
||||
data->ntsc = 1;
|
||||
data->half = 0;
|
||||
data->colorbars = 0;
|
||||
data->depth = 16;
|
||||
|
||||
}
|
||||
|
||||
void bt869_update_client(struct i2c_client *client)
|
||||
{
|
||||
struct bt869_data *data = client->data;
|
||||
struct bt869_data *data = client->data;
|
||||
|
||||
down(&data->update_lock);
|
||||
down(&data->update_lock);
|
||||
|
||||
if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
|
||||
(jiffies < data->last_updated) || ! data->valid) {
|
||||
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
|
||||
(jiffies < data->last_updated) || !data->valid) {
|
||||
#ifdef DEBUG
|
||||
printk("Starting bt869 update\n");
|
||||
printk("Starting bt869 update\n");
|
||||
#endif
|
||||
/* Set values of device */
|
||||
if ((data->res[0] == 640) && (data->res[1] == 480)) {
|
||||
bt869_write_value(client,0xB8,(! data->ntsc));
|
||||
bt869_write_value(client,0xa0,0x80 + 0x0C);
|
||||
printk("bt869.o: writing into config -->0x%X\n",(0 + (! data->ntsc)));
|
||||
} else if ((data->res[0] == 800) && (data->res[1] == 600)) {
|
||||
bt869_write_value(client,0xB8,(2 + (! data->ntsc)));
|
||||
bt869_write_value(client,0xa0,0x80 + 0x11);
|
||||
printk("bt869.o: writing into config -->0x%X\n",(2 + (! data->ntsc)));
|
||||
} else {
|
||||
bt869_write_value(client,0xB8,(! data->ntsc));
|
||||
bt869_write_value(client,0xa0,0x80 + 0x0C);
|
||||
printk("bt869.o: writing into config -->0x%X\n",(0 + (! data->ntsc)));
|
||||
printk("bt869.o: Warning: arbitrary resolutions not supported yet. Using 640x480.\n");
|
||||
data->res[0] = 640;
|
||||
data->res[1] = 480;
|
||||
}
|
||||
if ((data->depth!=24) && (data->depth!=16))
|
||||
data->depth=16;
|
||||
if (data->depth==16)
|
||||
bt869_write_value(client,0x0C6, 0x001);
|
||||
if (data->depth==24)
|
||||
bt869_write_value(client,0x0C6, 0x000);
|
||||
bt869_write_value(client,0xD4,data->half<<6);
|
||||
/* Be a slave to the clock on the Voodoo3 */
|
||||
bt869_write_value(client,0xba,0x20);
|
||||
/* depth =16bpp */
|
||||
bt869_write_value(client,0x0C6, 0x001);
|
||||
bt869_write_value(client,0xC4,1);
|
||||
if ((data->res[0] == 640) && (data->res[1] == 480)) {
|
||||
bt869_write_value(client, 0xB8, (!data->ntsc));
|
||||
bt869_write_value(client, 0xa0, 0x80 + 0x0C);
|
||||
printk("bt869.o: writing into config -->0x%X\n",
|
||||
(0 + (!data->ntsc)));
|
||||
} else if ((data->res[0] == 800) && (data->res[1] == 600)) {
|
||||
bt869_write_value(client, 0xB8,
|
||||
(2 + (!data->ntsc)));
|
||||
bt869_write_value(client, 0xa0, 0x80 + 0x11);
|
||||
printk("bt869.o: writing into config -->0x%X\n",
|
||||
(2 + (!data->ntsc)));
|
||||
} else {
|
||||
bt869_write_value(client, 0xB8, (!data->ntsc));
|
||||
bt869_write_value(client, 0xa0, 0x80 + 0x0C);
|
||||
printk("bt869.o: writing into config -->0x%X\n",
|
||||
(0 + (!data->ntsc)));
|
||||
printk
|
||||
("bt869.o: Warning: arbitrary resolutions not supported yet. Using 640x480.\n");
|
||||
data->res[0] = 640;
|
||||
data->res[1] = 480;
|
||||
}
|
||||
if ((data->depth != 24) && (data->depth != 16))
|
||||
data->depth = 16;
|
||||
if (data->depth == 16)
|
||||
bt869_write_value(client, 0x0C6, 0x001);
|
||||
if (data->depth == 24)
|
||||
bt869_write_value(client, 0x0C6, 0x000);
|
||||
bt869_write_value(client, 0xD4, data->half << 6);
|
||||
/* Be a slave to the clock on the Voodoo3 */
|
||||
bt869_write_value(client, 0xba, 0x20);
|
||||
/* depth =16bpp */
|
||||
bt869_write_value(client, 0x0C6, 0x001);
|
||||
bt869_write_value(client, 0xC4, 1);
|
||||
|
||||
/* Get status */
|
||||
bt869_write_value(client,0xC4,1 | (data->colorbars << 2));
|
||||
data->status[0] = bt869_read_value(client,1);
|
||||
bt869_write_value(client,0xC4,0x41 | (data->colorbars << 2));
|
||||
data->status[1] = bt869_read_value(client,1);
|
||||
bt869_write_value(client,0xC4,0x81 | (data->colorbars << 2));
|
||||
data->status[2] = bt869_read_value(client,1);
|
||||
bt869_write_value(client,0xC4,0x0C1 | (data->colorbars << 2));
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
up(&data->update_lock);
|
||||
bt869_write_value(client, 0xC4,
|
||||
1 | (data->colorbars << 2));
|
||||
data->status[0] = bt869_read_value(client, 1);
|
||||
bt869_write_value(client, 0xC4,
|
||||
0x41 | (data->colorbars << 2));
|
||||
data->status[1] = bt869_read_value(client, 1);
|
||||
bt869_write_value(client, 0xC4,
|
||||
0x81 | (data->colorbars << 2));
|
||||
data->status[2] = bt869_read_value(client, 1);
|
||||
bt869_write_value(client, 0xC4,
|
||||
0x0C1 | (data->colorbars << 2));
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
up(&data->update_lock);
|
||||
}
|
||||
|
||||
|
||||
void bt869_status(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->status[0];
|
||||
results[1] = data->status[1];
|
||||
results[2] = data->status[2];
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
printk("bt869.o: Warning: write was requested on read-only proc file: status\n");
|
||||
}
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->status[0];
|
||||
results[1] = data->status[1];
|
||||
results[2] = data->status[2];
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
printk
|
||||
("bt869.o: Warning: write was requested on read-only proc file: status\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bt869_ntsc(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->ntsc;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->ntsc = (results[0] > 0);
|
||||
}
|
||||
bt869_update_client(client);
|
||||
}
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->ntsc;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->ntsc = (results[0] > 0);
|
||||
}
|
||||
bt869_update_client(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bt869_res(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->res[0];
|
||||
results[1] = data->res[1];
|
||||
*nrels_mag = 2;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->res[0] = results[0];
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->res[1] = results[1];
|
||||
}
|
||||
bt869_update_client(client);
|
||||
}
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->res[0];
|
||||
results[1] = data->res[1];
|
||||
*nrels_mag = 2;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->res[0] = results[0];
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->res[1] = results[1];
|
||||
}
|
||||
bt869_update_client(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bt869_half(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->half;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->half = (results[0] > 0);
|
||||
bt869_update_client(client);
|
||||
}
|
||||
}
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->half;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->half = (results[0] > 0);
|
||||
bt869_update_client(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bt869_colorbars(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void bt869_colorbars(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->colorbars;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->colorbars = (results[0] > 0);
|
||||
bt869_update_client(client);
|
||||
}
|
||||
}
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->colorbars;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->colorbars = (results[0] > 0);
|
||||
bt869_update_client(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bt869_depth(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->depth;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->depth = results[0];
|
||||
bt869_update_client(client);
|
||||
}
|
||||
}
|
||||
struct bt869_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
bt869_update_client(client);
|
||||
results[0] = data->depth;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->depth = results[0];
|
||||
bt869_update_client(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int __init sensors_bt869_init(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
printk("bt869.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
bt869_initialized = 0;
|
||||
if ((res = i2c_add_driver(&bt869_driver))) {
|
||||
printk("bt869.o: Driver registration failed, module not inserted.\n");
|
||||
bt869_cleanup();
|
||||
return res;
|
||||
}
|
||||
bt869_initialized ++;
|
||||
return 0;
|
||||
printk("bt869.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
bt869_initialized = 0;
|
||||
if ((res = i2c_add_driver(&bt869_driver))) {
|
||||
printk
|
||||
("bt869.o: Driver registration failed, module not inserted.\n");
|
||||
bt869_cleanup();
|
||||
return res;
|
||||
}
|
||||
bt869_initialized++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init bt869_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
if (bt869_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&bt869_driver))) {
|
||||
printk("bt869.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
bt869_initialized --;
|
||||
}
|
||||
if (bt869_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&bt869_driver))) {
|
||||
printk
|
||||
("bt869.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
bt869_initialized--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_DESCRIPTION("bt869 driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return sensors_bt869_init();
|
||||
return sensors_bt869_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return bt869_cleanup();
|
||||
return bt869_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+239
-216
@@ -38,17 +38,18 @@
|
||||
#endif
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = {SENSORS_I2C_END};
|
||||
static unsigned short normal_i2c_range[] = {0x50,0x57,SENSORS_I2C_END};
|
||||
static unsigned int normal_isa[] = {SENSORS_ISA_END};
|
||||
static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
|
||||
static unsigned short normal_i2c[] = { SENSORS_I2C_END };
|
||||
static unsigned short normal_i2c_range[] = { 0x50, 0x57, SENSORS_I2C_END };
|
||||
static unsigned int normal_isa[] = { SENSORS_ISA_END };
|
||||
static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(eeprom);
|
||||
|
||||
static int checksum = 0;
|
||||
MODULE_PARM(checksum,"i");
|
||||
MODULE_PARM_DESC(checksum,"Only accept eeproms whose checksum is correct");
|
||||
MODULE_PARM(checksum, "i");
|
||||
MODULE_PARM_DESC(checksum,
|
||||
"Only accept eeproms whose checksum is correct");
|
||||
|
||||
|
||||
/* Many constants specified below */
|
||||
@@ -69,58 +70,59 @@ MODULE_PARM_DESC(checksum,"Only accept eeproms whose checksum is correct");
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct eeprom_data {
|
||||
int sysctl_id;
|
||||
int sysctl_id;
|
||||
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u8 data[EEPROM_SIZE]; /* Register values */
|
||||
int memtype;
|
||||
u8 data[EEPROM_SIZE]; /* Register values */
|
||||
int memtype;
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init sensors_eeprom_init(void);
|
||||
int __init sensors_eeprom_init(void);
|
||||
static int __init eeprom_cleanup(void);
|
||||
|
||||
static int eeprom_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int eeprom_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static int eeprom_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static int eeprom_detach_client(struct i2c_client *client);
|
||||
static int eeprom_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *arg);
|
||||
|
||||
static void eeprom_inc_use (struct i2c_client *client);
|
||||
static void eeprom_dec_use (struct i2c_client *client);
|
||||
void *arg);
|
||||
|
||||
static void eeprom_inc_use(struct i2c_client *client);
|
||||
static void eeprom_dec_use(struct i2c_client *client);
|
||||
|
||||
#if 0
|
||||
static int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value);
|
||||
static int eeprom_write_value(struct i2c_client *client, u8 reg,
|
||||
u16 value);
|
||||
#endif
|
||||
|
||||
static void eeprom_contents(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void eeprom_contents(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void eeprom_update_client(struct i2c_client *client);
|
||||
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver eeprom_driver = {
|
||||
/* name */ "EEPROM READER",
|
||||
/* id */ I2C_DRIVERID_EEPROM,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &eeprom_attach_adapter,
|
||||
/* detach_client */ &eeprom_detach_client,
|
||||
/* command */ &eeprom_command,
|
||||
/* inc_use */ &eeprom_inc_use,
|
||||
/* dec_use */ &eeprom_dec_use
|
||||
/* name */ "EEPROM READER",
|
||||
/* id */ I2C_DRIVERID_EEPROM,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &eeprom_attach_adapter,
|
||||
/* detach_client */ &eeprom_detach_client,
|
||||
/* command */ &eeprom_command,
|
||||
/* inc_use */ &eeprom_inc_use,
|
||||
/* dec_use */ &eeprom_dec_use
|
||||
};
|
||||
|
||||
/* These files are created for each detected EEPROM. This is just a template;
|
||||
@@ -129,23 +131,23 @@ static struct i2c_driver eeprom_driver = {
|
||||
is done through one of the 'extra' fields which are initialized
|
||||
when a new copy is allocated. */
|
||||
static ctl_table eeprom_dir_table_template[] = {
|
||||
{ EEPROM_SYSCTL1, "data0-15", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents },
|
||||
{ EEPROM_SYSCTL2, "data16-31", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents },
|
||||
{ EEPROM_SYSCTL3, "data32-47", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents },
|
||||
{ EEPROM_SYSCTL4, "data48-63", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents },
|
||||
{ EEPROM_SYSCTL5, "data64-79", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents },
|
||||
{ EEPROM_SYSCTL6, "data80-95", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents },
|
||||
{ EEPROM_SYSCTL7, "data96-111", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents },
|
||||
{ EEPROM_SYSCTL8, "data112-127", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents },
|
||||
{ 0 }
|
||||
{EEPROM_SYSCTL1, "data0-15", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents},
|
||||
{EEPROM_SYSCTL2, "data16-31", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents},
|
||||
{EEPROM_SYSCTL3, "data32-47", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents},
|
||||
{EEPROM_SYSCTL4, "data48-63", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents},
|
||||
{EEPROM_SYSCTL5, "data64-79", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents},
|
||||
{EEPROM_SYSCTL6, "data80-95", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents},
|
||||
{EEPROM_SYSCTL7, "data96-111", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents},
|
||||
{EEPROM_SYSCTL8, "data112-127", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &eeprom_contents},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* Used by init/cleanup */
|
||||
@@ -155,142 +157,147 @@ static int eeprom_id = 0;
|
||||
|
||||
int eeprom_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return sensors_detect(adapter,&addr_data,eeprom_detect);
|
||||
return sensors_detect(adapter, &addr_data, eeprom_detect);
|
||||
}
|
||||
|
||||
/* This function is called by sensors_detect */
|
||||
int eeprom_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
int eeprom_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
{
|
||||
int i,cs;
|
||||
struct i2c_client *new_client;
|
||||
struct eeprom_data *data;
|
||||
int err=0;
|
||||
const char *type_name,*client_name;
|
||||
int i, cs;
|
||||
struct i2c_client *new_client;
|
||||
struct eeprom_data *data;
|
||||
int err = 0;
|
||||
const char *type_name, *client_name;
|
||||
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
#ifdef DEBUG
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk("eeprom.o: eeprom_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk
|
||||
("eeprom.o: eeprom_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WRITE_WORD_DATA))
|
||||
goto ERROR0;
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WRITE_WORD_DATA))
|
||||
goto ERROR0;
|
||||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access eeprom_{read,write}_value. */
|
||||
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct eeprom_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access eeprom_{read,write}_value. */
|
||||
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct eeprom_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
data = (struct eeprom_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &eeprom_driver;
|
||||
new_client->flags = 0;
|
||||
data = (struct eeprom_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &eeprom_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we do the remaining detection. It is not there, unless you force
|
||||
the checksum to work out. */
|
||||
if (checksum) {
|
||||
cs = 0;
|
||||
for (i = 0; i <= 0x3e; i++)
|
||||
cs += i2c_smbus_read_byte_data(new_client,i);
|
||||
cs &= 0xff;
|
||||
if (i2c_smbus_read_byte_data(new_client,EEPROM_REG_CHECKSUM) != cs)
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Determine the chip type - only one kind supported! */
|
||||
if (kind <= 0)
|
||||
kind = eeprom;
|
||||
/* Now, we do the remaining detection. It is not there, unless you force
|
||||
the checksum to work out. */
|
||||
if (checksum) {
|
||||
cs = 0;
|
||||
for (i = 0; i <= 0x3e; i++)
|
||||
cs += i2c_smbus_read_byte_data(new_client, i);
|
||||
cs &= 0xff;
|
||||
if (i2c_smbus_read_byte_data
|
||||
(new_client, EEPROM_REG_CHECKSUM) != cs)
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
if (kind == eeprom) {
|
||||
type_name = "eeprom";
|
||||
client_name = "EEPROM chip";
|
||||
} else {
|
||||
/* Determine the chip type - only one kind supported! */
|
||||
if (kind <= 0)
|
||||
kind = eeprom;
|
||||
|
||||
if (kind == eeprom) {
|
||||
type_name = "eeprom";
|
||||
client_name = "EEPROM chip";
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("eeprom.o: Internal error: unknown kind (%d)?!?",kind);
|
||||
printk("eeprom.o: Internal error: unknown kind (%d)?!?",
|
||||
kind);
|
||||
#endif
|
||||
goto ERROR1;
|
||||
}
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name,client_name);
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name, client_name);
|
||||
|
||||
new_client->id = eeprom_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
new_client->id = eeprom_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client,type_name,
|
||||
eeprom_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client, type_name,
|
||||
eeprom_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
}
|
||||
|
||||
int eeprom_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
|
||||
sensors_deregister_entry(((struct eeprom_data *)(client->data))->sysctl_id);
|
||||
sensors_deregister_entry(((struct eeprom_data *) (client->data))->
|
||||
sysctl_id);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("eeprom.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk
|
||||
("eeprom.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(client);
|
||||
kfree(client);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* No commands defined yet */
|
||||
int eeprom_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void eeprom_inc_use (struct i2c_client *client)
|
||||
void eeprom_inc_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_INC_USE_COUNT;
|
||||
MOD_INC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
void eeprom_dec_use (struct i2c_client *client)
|
||||
void eeprom_dec_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_DEC_USE_COUNT;
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -298,129 +305,145 @@ void eeprom_dec_use (struct i2c_client *client)
|
||||
/* No writes yet (PAE) */
|
||||
int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
if (reg == EEPROM_REG_CONF)
|
||||
return i2c_smbus_write_byte_data(client,reg,value);
|
||||
else
|
||||
return i2c_smbus_write_word_data(client,reg,value); */
|
||||
|
||||
return 0;
|
||||
if (reg == EEPROM_REG_CONF)
|
||||
return i2c_smbus_write_byte_data(client, reg, value);
|
||||
else
|
||||
return i2c_smbus_write_word_data(client, reg, value);
|
||||
*/return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void eeprom_update_client(struct i2c_client *client)
|
||||
{
|
||||
struct eeprom_data *data = client->data;
|
||||
int i;
|
||||
struct eeprom_data *data = client->data;
|
||||
int i;
|
||||
|
||||
down(&data->update_lock);
|
||||
down(&data->update_lock);
|
||||
|
||||
if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
|
||||
(jiffies < data->last_updated) || ! data->valid) {
|
||||
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
|
||||
(jiffies < data->last_updated) || !data->valid) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("Starting eeprom update\n");
|
||||
printk("Starting eeprom update\n");
|
||||
#endif
|
||||
|
||||
if (i2c_smbus_write_byte(client,0)) {
|
||||
if (i2c_smbus_write_byte(client, 0)) {
|
||||
#ifdef DEBUG
|
||||
printk("eeprom read start has failed!\n");
|
||||
#endif
|
||||
}
|
||||
for (i=0;i<EEPROM_SIZE;i++) {
|
||||
data->data[i] = (u8)i2c_smbus_read_byte(client);
|
||||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
printk("eeprom read start has failed!\n");
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < EEPROM_SIZE; i++) {
|
||||
data->data[i] = (u8) i2c_smbus_read_byte(client);
|
||||
}
|
||||
|
||||
up(&data->update_lock);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
up(&data->update_lock);
|
||||
}
|
||||
|
||||
|
||||
void eeprom_contents(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void eeprom_contents(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
int i;
|
||||
int base=0;
|
||||
struct eeprom_data *data = client->data;
|
||||
|
||||
if (ctl_name == EEPROM_SYSCTL2){ base=16; }
|
||||
if (ctl_name == EEPROM_SYSCTL3){ base=32; }
|
||||
if (ctl_name == EEPROM_SYSCTL4){ base=48; }
|
||||
if (ctl_name == EEPROM_SYSCTL5){ base=64; }
|
||||
if (ctl_name == EEPROM_SYSCTL6){ base=80; }
|
||||
if (ctl_name == EEPROM_SYSCTL7){ base=96; }
|
||||
if (ctl_name == EEPROM_SYSCTL8){ base=112; }
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
eeprom_update_client(client);
|
||||
for (i=0; i<16; i++) {
|
||||
results[i]=data->data[i + base];
|
||||
}
|
||||
int i;
|
||||
int base = 0;
|
||||
struct eeprom_data *data = client->data;
|
||||
|
||||
if (ctl_name == EEPROM_SYSCTL2) {
|
||||
base = 16;
|
||||
}
|
||||
if (ctl_name == EEPROM_SYSCTL3) {
|
||||
base = 32;
|
||||
}
|
||||
if (ctl_name == EEPROM_SYSCTL4) {
|
||||
base = 48;
|
||||
}
|
||||
if (ctl_name == EEPROM_SYSCTL5) {
|
||||
base = 64;
|
||||
}
|
||||
if (ctl_name == EEPROM_SYSCTL6) {
|
||||
base = 80;
|
||||
}
|
||||
if (ctl_name == EEPROM_SYSCTL7) {
|
||||
base = 96;
|
||||
}
|
||||
if (ctl_name == EEPROM_SYSCTL8) {
|
||||
base = 112;
|
||||
}
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
eeprom_update_client(client);
|
||||
for (i = 0; i < 16; i++) {
|
||||
results[i] = data->data[i + base];
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("eeprom.o: 0x%X EEPROM Contents (base %d): ",client->addr,base);
|
||||
for (i=0; i<16; i++) {
|
||||
printk(" 0x%X",data->data[i + base]);
|
||||
}
|
||||
printk(" .\n");
|
||||
printk("eeprom.o: 0x%X EEPROM Contents (base %d): ",
|
||||
client->addr, base);
|
||||
for (i = 0; i < 16; i++) {
|
||||
printk(" 0x%X", data->data[i + base]);
|
||||
}
|
||||
printk(" .\n");
|
||||
#endif
|
||||
*nrels_mag = 16;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
*nrels_mag = 16;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
|
||||
/* No writes to the EEPROM (yet, anyway) (PAE) */
|
||||
printk("eeprom.o: No writes to EEPROMs supported!\n");
|
||||
}
|
||||
printk("eeprom.o: No writes to EEPROMs supported!\n");
|
||||
}
|
||||
}
|
||||
|
||||
int __init sensors_eeprom_init(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
printk("eeprom.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
eeprom_initialized = 0;
|
||||
if ((res = i2c_add_driver(&eeprom_driver))) {
|
||||
printk("eeprom.o: Driver registration failed, module not inserted.\n");
|
||||
eeprom_cleanup();
|
||||
return res;
|
||||
}
|
||||
eeprom_initialized ++;
|
||||
return 0;
|
||||
printk("eeprom.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
eeprom_initialized = 0;
|
||||
if ((res = i2c_add_driver(&eeprom_driver))) {
|
||||
printk
|
||||
("eeprom.o: Driver registration failed, module not inserted.\n");
|
||||
eeprom_cleanup();
|
||||
return res;
|
||||
}
|
||||
eeprom_initialized++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init eeprom_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
if (eeprom_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&eeprom_driver))) {
|
||||
printk("eeprom.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
} else
|
||||
eeprom_initialized --;
|
||||
if (eeprom_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&eeprom_driver))) {
|
||||
printk
|
||||
("eeprom.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
} else
|
||||
eeprom_initialized--;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_DESCRIPTION("EEPROM driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return sensors_eeprom_init();
|
||||
return sensors_eeprom_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return eeprom_cleanup();
|
||||
return eeprom_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+710
-654
File diff suppressed because it is too large.
Load diff
+579
-522
File diff suppressed because it is too large.
Load diff
+177
-165
@@ -53,56 +53,57 @@
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct icspll_data {
|
||||
int sysctl_id;
|
||||
int sysctl_id;
|
||||
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u8 data[ICSPLL_SIZE]; /* Register values */
|
||||
int memtype;
|
||||
u8 data[ICSPLL_SIZE]; /* Register values */
|
||||
int memtype;
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init sensors_icspll_init(void);
|
||||
int __init sensors_icspll_init(void);
|
||||
static int __init icspll_cleanup(void);
|
||||
|
||||
static int icspll_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int icspll_detach_client(struct i2c_client *client);
|
||||
static int icspll_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *arg);
|
||||
|
||||
static void icspll_inc_use (struct i2c_client *client);
|
||||
static void icspll_dec_use (struct i2c_client *client);
|
||||
void *arg);
|
||||
|
||||
static void icspll_inc_use(struct i2c_client *client);
|
||||
static void icspll_dec_use(struct i2c_client *client);
|
||||
|
||||
#if 0
|
||||
static int icspll_write_value(struct i2c_client *client, u8 reg, u16 value);
|
||||
static int icspll_write_value(struct i2c_client *client, u8 reg,
|
||||
u16 value);
|
||||
#endif
|
||||
|
||||
static void icspll_contents(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void icspll_contents(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void icspll_update_client(struct i2c_client *client);
|
||||
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver icspll_driver = {
|
||||
/* name */ "ICS/PLL clock reader",
|
||||
/* id */ I2C_DRIVERID_ICSPLL,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &icspll_attach_adapter,
|
||||
/* detach_client */ &icspll_detach_client,
|
||||
/* command */ &icspll_command,
|
||||
/* inc_use */ &icspll_inc_use,
|
||||
/* dec_use */ &icspll_dec_use
|
||||
/* name */ "ICS/PLL clock reader",
|
||||
/* id */ I2C_DRIVERID_ICSPLL,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &icspll_attach_adapter,
|
||||
/* detach_client */ &icspll_detach_client,
|
||||
/* command */ &icspll_command,
|
||||
/* inc_use */ &icspll_inc_use,
|
||||
/* dec_use */ &icspll_dec_use
|
||||
};
|
||||
|
||||
/* These files are created for each detected ICSPLL. This is just a template;
|
||||
@@ -111,9 +112,9 @@ static struct i2c_driver icspll_driver = {
|
||||
is done through one of the 'extra' fields which are initialized
|
||||
when a new copy is allocated. */
|
||||
static ctl_table icspll_dir_table_template[] = {
|
||||
{ ICSPLL_SYSCTL1, "reg0-6", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &icspll_contents },
|
||||
{ 0 }
|
||||
{ICSPLL_SYSCTL1, "reg0-6", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &icspll_contents},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* holding place for data - block read could be as much as 32 */
|
||||
@@ -125,119 +126,124 @@ static int __initdata icspll_initialized = 0;
|
||||
static int icspll_id = 0;
|
||||
int icspll_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
int address,err,i;
|
||||
struct i2c_client *new_client;
|
||||
struct icspll_data *data;
|
||||
int address, err, i;
|
||||
struct i2c_client *new_client;
|
||||
struct icspll_data *data;
|
||||
|
||||
err = 0;
|
||||
/* Make sure we aren't probing the ISA bus!! */
|
||||
if (i2c_is_isa_adapter(adapter)) return 0;
|
||||
|
||||
/* OK, this is no detection. I know. It will do for now, though. */
|
||||
err = 0;
|
||||
/* Make sure we aren't probing the ISA bus!! */
|
||||
if (i2c_is_isa_adapter(adapter))
|
||||
return 0;
|
||||
|
||||
/* Set err only if a global error would make registering other clients
|
||||
impossible too (like out-of-memory). */
|
||||
|
||||
/* ICS and PLL clock chips seem to all be at 0x69.
|
||||
Don't know what is out there at 0x6A, don't scan that yet. */
|
||||
/* OK, this is no detection. I know. It will do for now, though. */
|
||||
|
||||
for (address = 0x69; (! err) && (address <= 0x69); address ++) {
|
||||
/* Set err only if a global error would make registering other clients
|
||||
impossible too (like out-of-memory). */
|
||||
|
||||
/* Later on, we will keep a list of registered addresses for each
|
||||
adapter, and check whether they are used here */
|
||||
|
||||
/* these chips only support block transfers so use that for detection */
|
||||
if(i2c_smbus_read_block_data(adapter, address, 0x00, tempdata) < 0) {
|
||||
/* ICS and PLL clock chips seem to all be at 0x69.
|
||||
Don't know what is out there at 0x6A, don't scan that yet. */
|
||||
|
||||
for (address = 0x69; (!err) && (address <= 0x69); address++) {
|
||||
|
||||
/* Later on, we will keep a list of registered addresses for each
|
||||
adapter, and check whether they are used here */
|
||||
|
||||
/* these chips only support block transfers so use that for detection */
|
||||
if (i2c_smbus_read_block_data
|
||||
(adapter, address, 0x00, tempdata) < 0) {
|
||||
#ifdef DEBUG
|
||||
printk("icspll.o: No icspll found at: 0x%X\n",address);
|
||||
printk("icspll.o: No icspll found at: 0x%X\n",
|
||||
address);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Real detection code goes here */
|
||||
/* Real detection code goes here */
|
||||
|
||||
/* Allocate space for a new client structure */
|
||||
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct icspll_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
continue;
|
||||
}
|
||||
/* Allocate space for a new client structure */
|
||||
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct icspll_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fill the new client structure with data */
|
||||
data = (struct icspll_data *) (new_client + 1);
|
||||
new_client->data = data;
|
||||
new_client->id = icspll_id++;
|
||||
new_client->addr = address;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &icspll_driver;
|
||||
new_client->flags = 0;
|
||||
strcpy(new_client->name,"ICSPLL chip");
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
/* Fill the new client structure with data */
|
||||
data = (struct icspll_data *) (new_client + 1);
|
||||
new_client->data = data;
|
||||
new_client->id = icspll_id++;
|
||||
new_client->addr = address;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &icspll_driver;
|
||||
new_client->flags = 0;
|
||||
strcpy(new_client->name, "ICSPLL chip");
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
/* fill data structure so unknown registers are 0xFF */
|
||||
data->data[0] = ICSPLL_SIZE;
|
||||
for(i = 1; i <= ICSPLL_SIZE; i++)
|
||||
data->data[i] = 0xFF;
|
||||
|
||||
/* Tell i2c-core a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR2;
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((err = sensors_register_entry(new_client,"icspll",
|
||||
icspll_dir_table_template
|
||||
THIS_MODULE)) < 0)
|
||||
goto ERROR3;
|
||||
data->sysctl_id = err;
|
||||
err = 0;
|
||||
data->data[0] = ICSPLL_SIZE;
|
||||
for (i = 1; i <= ICSPLL_SIZE; i++)
|
||||
data->data[i] = 0xFF;
|
||||
|
||||
continue;
|
||||
/* Tell i2c-core a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR2;
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((err = sensors_register_entry(new_client, "icspll",
|
||||
icspll_dir_table_template
|
||||
THIS_MODULE)) < 0)
|
||||
goto ERROR3;
|
||||
data->sysctl_id = err;
|
||||
err = 0;
|
||||
|
||||
continue;
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
ERROR3:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR2:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
}
|
||||
return err;
|
||||
ERROR3:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR2:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int icspll_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err,i;
|
||||
int err, i;
|
||||
|
||||
sensors_deregister_entry(((struct icspll_data *)(client->data))->sysctl_id);
|
||||
sensors_deregister_entry(((struct icspll_data *) (client->data))->
|
||||
sysctl_id);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("icspll.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk
|
||||
("icspll.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(client);
|
||||
return 0;
|
||||
kfree(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* No commands defined yet */
|
||||
int icspll_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void icspll_inc_use (struct i2c_client *client)
|
||||
void icspll_inc_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_INC_USE_COUNT;
|
||||
MOD_INC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
void icspll_dec_use (struct i2c_client *client)
|
||||
void icspll_dec_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_DEC_USE_COUNT;
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -245,111 +251,117 @@ void icspll_dec_use (struct i2c_client *client)
|
||||
/* No writes yet (PAE) */
|
||||
int icspll_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
return i2c_smbus_write_block_data(client->adapter,client->addr,reg,value);
|
||||
return i2c_smbus_write_block_data(client->adapter, client->addr,
|
||||
reg, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
void icspll_update_client(struct i2c_client *client)
|
||||
{
|
||||
struct icspll_data *data = client->data;
|
||||
int i, len;
|
||||
struct icspll_data *data = client->data;
|
||||
int i, len;
|
||||
|
||||
down(&data->update_lock);
|
||||
down(&data->update_lock);
|
||||
|
||||
if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
|
||||
(jiffies < data->last_updated) || ! data->valid) {
|
||||
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
|
||||
(jiffies < data->last_updated) || !data->valid) {
|
||||
|
||||
len = i2c_smbus_read_block_data(client->adapter, client->addr, 0x00, tempdata);
|
||||
len =
|
||||
i2c_smbus_read_block_data(client->adapter,
|
||||
client->addr, 0x00,
|
||||
tempdata);
|
||||
#ifdef DEBUG
|
||||
printk("icspll.o: read returned %d values\n", len);
|
||||
printk("icspll.o: read returned %d values\n", len);
|
||||
#endif
|
||||
if(len > ICSPLL_SIZE)
|
||||
len = ICSPLL_SIZE;
|
||||
for(i = 0; i < len; i++)
|
||||
data->data[i] = tempdata[i];
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
if (len > ICSPLL_SIZE)
|
||||
len = ICSPLL_SIZE;
|
||||
for (i = 0; i < len; i++)
|
||||
data->data[i] = tempdata[i];
|
||||
|
||||
up(&data->update_lock);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
up(&data->update_lock);
|
||||
}
|
||||
|
||||
|
||||
void icspll_contents(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void icspll_contents(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
int i;
|
||||
struct icspll_data *data = client->data;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
icspll_update_client(client);
|
||||
for (i=0; i< ICSPLL_SIZE; i++) {
|
||||
results[i]=data->data[i];
|
||||
}
|
||||
int i;
|
||||
struct icspll_data *data = client->data;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
icspll_update_client(client);
|
||||
for (i = 0; i < ICSPLL_SIZE; i++) {
|
||||
results[i] = data->data[i];
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("icspll.o: 0x%X ICSPLL Contents: ",client->addr);
|
||||
for (i=0; i< ICSPLL_SIZE; i++) {
|
||||
printk(" 0x%X",data->data[i]);
|
||||
}
|
||||
printk(" .\n");
|
||||
printk("icspll.o: 0x%X ICSPLL Contents: ", client->addr);
|
||||
for (i = 0; i < ICSPLL_SIZE; i++) {
|
||||
printk(" 0x%X", data->data[i]);
|
||||
}
|
||||
printk(" .\n");
|
||||
#endif
|
||||
*nrels_mag = ICSPLL_SIZE;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
*nrels_mag = ICSPLL_SIZE;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
|
||||
/* No writes to the ICSPLL (yet, anyway) (PAE) */
|
||||
printk("icspll.o: No writes to ICSPLLs supported!\n");
|
||||
}
|
||||
printk("icspll.o: No writes to ICSPLLs supported!\n");
|
||||
}
|
||||
}
|
||||
|
||||
int __init sensors_icspll_init(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
printk("icspll.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
icspll_initialized = 0;
|
||||
if ((res = i2c_add_driver(&icspll_driver))) {
|
||||
printk("icspll.o: Driver registration failed, module not inserted.\n");
|
||||
icspll_cleanup();
|
||||
return res;
|
||||
}
|
||||
icspll_initialized ++;
|
||||
return 0;
|
||||
printk("icspll.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
icspll_initialized = 0;
|
||||
if ((res = i2c_add_driver(&icspll_driver))) {
|
||||
printk
|
||||
("icspll.o: Driver registration failed, module not inserted.\n");
|
||||
icspll_cleanup();
|
||||
return res;
|
||||
}
|
||||
icspll_initialized++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init icspll_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
if (icspll_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&icspll_driver))) {
|
||||
printk("icspll.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
} else
|
||||
icspll_initialized --;
|
||||
if (icspll_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&icspll_driver))) {
|
||||
printk
|
||||
("icspll.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
} else
|
||||
icspll_initialized--;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark Studebaker <mdsxyz123@yahoo.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark Studebaker <mdsxyz123@yahoo.com>");
|
||||
MODULE_DESCRIPTION("ICSPLL driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return sensors_icspll_init();
|
||||
return sensors_icspll_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return icspll_cleanup();
|
||||
return icspll_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+209
-195
@@ -37,10 +37,10 @@
|
||||
#endif
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = {SENSORS_I2C_END};
|
||||
static unsigned short normal_i2c_range[] = {0x48,0x4f,SENSORS_I2C_END};
|
||||
static unsigned int normal_isa[] = {SENSORS_ISA_END};
|
||||
static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
|
||||
static unsigned short normal_i2c[] = { SENSORS_I2C_END };
|
||||
static unsigned short normal_i2c_range[] = { 0x48, 0x4f, SENSORS_I2C_END };
|
||||
static unsigned int normal_isa[] = { SENSORS_ISA_END };
|
||||
static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(lm75);
|
||||
@@ -66,54 +66,54 @@ SENSORS_INSMOD_1(lm75);
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct lm75_data {
|
||||
int sysctl_id;
|
||||
int sysctl_id;
|
||||
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u16 temp,temp_os,temp_hyst; /* Register values */
|
||||
u16 temp, temp_os, temp_hyst; /* Register values */
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init sensors_lm75_init(void);
|
||||
int __init sensors_lm75_init(void);
|
||||
static int __init lm75_cleanup(void);
|
||||
static int lm75_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int lm75_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static int lm75_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static void lm75_init_client(struct i2c_client *client);
|
||||
static int lm75_detach_client(struct i2c_client *client);
|
||||
static int lm75_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *arg);
|
||||
static void lm75_inc_use (struct i2c_client *client);
|
||||
static void lm75_dec_use (struct i2c_client *client);
|
||||
void *arg);
|
||||
static void lm75_inc_use(struct i2c_client *client);
|
||||
static void lm75_dec_use(struct i2c_client *client);
|
||||
static u16 swap_bytes(u16 val);
|
||||
static int lm75_read_value(struct i2c_client *client, u8 reg);
|
||||
static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value);
|
||||
static void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void lm75_temp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void lm75_update_client(struct i2c_client *client);
|
||||
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver lm75_driver = {
|
||||
/* name */ "LM75 sensor chip driver",
|
||||
/* id */ I2C_DRIVERID_LM75,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &lm75_attach_adapter,
|
||||
/* detach_client */ &lm75_detach_client,
|
||||
/* command */ &lm75_command,
|
||||
/* inc_use */ &lm75_inc_use,
|
||||
/* dec_use */ &lm75_dec_use
|
||||
/* name */ "LM75 sensor chip driver",
|
||||
/* id */ I2C_DRIVERID_LM75,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &lm75_attach_adapter,
|
||||
/* detach_client */ &lm75_detach_client,
|
||||
/* command */ &lm75_command,
|
||||
/* inc_use */ &lm75_inc_use,
|
||||
/* dec_use */ &lm75_dec_use
|
||||
};
|
||||
|
||||
/* These files are created for each detected LM75. This is just a template;
|
||||
@@ -122,9 +122,9 @@ static struct i2c_driver lm75_driver = {
|
||||
is done through one of the 'extra' fields which are initialized
|
||||
when a new copy is allocated. */
|
||||
static ctl_table lm75_dir_table_template[] = {
|
||||
{ LM75_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &lm75_temp },
|
||||
{ 0 }
|
||||
{LM75_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &lm75_temp},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* Used by init/cleanup */
|
||||
@@ -134,153 +134,163 @@ static int lm75_id = 0;
|
||||
|
||||
int lm75_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return sensors_detect(adapter,&addr_data,lm75_detect);
|
||||
return sensors_detect(adapter, &addr_data, lm75_detect);
|
||||
}
|
||||
|
||||
/* This function is called by sensors_detect */
|
||||
int lm75_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
int lm75_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
{
|
||||
int i,cur,conf,hyst,os;
|
||||
struct i2c_client *new_client;
|
||||
struct lm75_data *data;
|
||||
int err=0;
|
||||
const char *type_name,*client_name;
|
||||
int i, cur, conf, hyst, os;
|
||||
struct i2c_client *new_client;
|
||||
struct lm75_data *data;
|
||||
int err = 0;
|
||||
const char *type_name, *client_name;
|
||||
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
#ifdef DEBUG
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk("lm75.o: lm75_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk
|
||||
("lm75.o: lm75_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
goto ERROR0;
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
goto ERROR0;
|
||||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access lm75_{read,write}_value. */
|
||||
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct lm75_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access lm75_{read,write}_value. */
|
||||
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct lm75_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
data = (struct lm75_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &lm75_driver;
|
||||
new_client->flags = 0;
|
||||
data = (struct lm75_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &lm75_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we do the remaining detection. It is lousy. */
|
||||
if (kind < 0) {
|
||||
cur = i2c_smbus_read_word_data(new_client,0);
|
||||
conf = i2c_smbus_read_byte_data(new_client,1);
|
||||
hyst = i2c_smbus_read_word_data(new_client,2);
|
||||
os = i2c_smbus_read_word_data(new_client,3);
|
||||
for (i = 0; i <= 0x1f; i++)
|
||||
if ((i2c_smbus_read_byte_data(new_client,i*8+1) != conf) ||
|
||||
(i2c_smbus_read_word_data(new_client,i*8+2) != hyst) ||
|
||||
(i2c_smbus_read_word_data(new_client,i*8+3) != os))
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Determine the chip type - only one kind supported! */
|
||||
if (kind <= 0)
|
||||
kind = lm75;
|
||||
/* Now, we do the remaining detection. It is lousy. */
|
||||
if (kind < 0) {
|
||||
cur = i2c_smbus_read_word_data(new_client, 0);
|
||||
conf = i2c_smbus_read_byte_data(new_client, 1);
|
||||
hyst = i2c_smbus_read_word_data(new_client, 2);
|
||||
os = i2c_smbus_read_word_data(new_client, 3);
|
||||
for (i = 0; i <= 0x1f; i++)
|
||||
if (
|
||||
(i2c_smbus_read_byte_data
|
||||
(new_client, i * 8 + 1) != conf)
|
||||
||
|
||||
(i2c_smbus_read_word_data
|
||||
(new_client, i * 8 + 2) != hyst)
|
||||
||
|
||||
(i2c_smbus_read_word_data
|
||||
(new_client, i * 8 + 3) != os))
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
if (kind == lm75) {
|
||||
type_name = "lm75";
|
||||
client_name = "LM75 chip";
|
||||
} else {
|
||||
/* Determine the chip type - only one kind supported! */
|
||||
if (kind <= 0)
|
||||
kind = lm75;
|
||||
|
||||
if (kind == lm75) {
|
||||
type_name = "lm75";
|
||||
client_name = "LM75 chip";
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("lm75.o: Internal error: unknown kind (%d)?!?",kind);
|
||||
printk("lm75.o: Internal error: unknown kind (%d)?!?",
|
||||
kind);
|
||||
#endif
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name,client_name);
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
new_client->id = lm75_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name, client_name);
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client,type_name,
|
||||
lm75_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
new_client->id = lm75_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
lm75_init_client(new_client);
|
||||
return 0;
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client, type_name,
|
||||
lm75_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
|
||||
lm75_init_client(new_client);
|
||||
return 0;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
}
|
||||
|
||||
int lm75_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
|
||||
sensors_deregister_entry(((struct lm75_data *)(client->data))->sysctl_id);
|
||||
sensors_deregister_entry(((struct lm75_data *) (client->data))->
|
||||
sysctl_id);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("lm75.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk
|
||||
("lm75.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(client);
|
||||
kfree(client);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* No commands defined yet */
|
||||
int lm75_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nothing here yet */
|
||||
void lm75_inc_use (struct i2c_client *client)
|
||||
void lm75_inc_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_INC_USE_COUNT;
|
||||
MOD_INC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Nothing here yet */
|
||||
void lm75_dec_use (struct i2c_client *client)
|
||||
void lm75_dec_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_DEC_USE_COUNT;
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
u16 swap_bytes(u16 val)
|
||||
{
|
||||
return (val >> 8) | (val << 8);
|
||||
return (val >> 8) | (val << 8);
|
||||
}
|
||||
|
||||
/* All registers are word-sized, except for the configuration register.
|
||||
@@ -288,10 +298,10 @@ u16 swap_bytes(u16 val)
|
||||
the usual practice. */
|
||||
int lm75_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
if (reg == LM75_REG_CONF)
|
||||
return i2c_smbus_read_byte_data(client,reg);
|
||||
else
|
||||
return swap_bytes(i2c_smbus_read_word_data(client,reg));
|
||||
if (reg == LM75_REG_CONF)
|
||||
return i2c_smbus_read_byte_data(client, reg);
|
||||
else
|
||||
return swap_bytes(i2c_smbus_read_word_data(client, reg));
|
||||
}
|
||||
|
||||
/* All registers are word-sized, except for the configuration register.
|
||||
@@ -299,99 +309,104 @@ int lm75_read_value(struct i2c_client *client, u8 reg)
|
||||
the usual practice. */
|
||||
int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
if (reg == LM75_REG_CONF)
|
||||
return i2c_smbus_write_byte_data(client,reg,value);
|
||||
else
|
||||
return i2c_smbus_write_word_data(client,reg,
|
||||
swap_bytes(value));
|
||||
if (reg == LM75_REG_CONF)
|
||||
return i2c_smbus_write_byte_data(client, reg, value);
|
||||
else
|
||||
return i2c_smbus_write_word_data(client, reg,
|
||||
swap_bytes(value));
|
||||
}
|
||||
|
||||
void lm75_init_client(struct i2c_client *client)
|
||||
{
|
||||
/* Initialize the LM75 chip */
|
||||
lm75_write_value(client,LM75_REG_TEMP_OS,
|
||||
TEMP_TO_REG(LM75_INIT_TEMP_OS));
|
||||
lm75_write_value(client,LM75_REG_TEMP_HYST,
|
||||
TEMP_TO_REG(LM75_INIT_TEMP_HYST));
|
||||
lm75_write_value(client,LM75_REG_CONF,0);
|
||||
/* Initialize the LM75 chip */
|
||||
lm75_write_value(client, LM75_REG_TEMP_OS,
|
||||
TEMP_TO_REG(LM75_INIT_TEMP_OS));
|
||||
lm75_write_value(client, LM75_REG_TEMP_HYST,
|
||||
TEMP_TO_REG(LM75_INIT_TEMP_HYST));
|
||||
lm75_write_value(client, LM75_REG_CONF, 0);
|
||||
}
|
||||
|
||||
void lm75_update_client(struct i2c_client *client)
|
||||
{
|
||||
struct lm75_data *data = client->data;
|
||||
struct lm75_data *data = client->data;
|
||||
|
||||
down(&data->update_lock);
|
||||
down(&data->update_lock);
|
||||
|
||||
if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
|
||||
(jiffies < data->last_updated) || ! data->valid) {
|
||||
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
|
||||
(jiffies < data->last_updated) || !data->valid) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("Starting lm75 update\n");
|
||||
printk("Starting lm75 update\n");
|
||||
#endif
|
||||
|
||||
data->temp = lm75_read_value(client,LM75_REG_TEMP);
|
||||
data->temp_os = lm75_read_value(client,LM75_REG_TEMP_OS);
|
||||
data->temp_hyst = lm75_read_value(client,LM75_REG_TEMP_HYST);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
data->temp = lm75_read_value(client, LM75_REG_TEMP);
|
||||
data->temp_os = lm75_read_value(client, LM75_REG_TEMP_OS);
|
||||
data->temp_hyst =
|
||||
lm75_read_value(client, LM75_REG_TEMP_HYST);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
up(&data->update_lock);
|
||||
up(&data->update_lock);
|
||||
}
|
||||
|
||||
|
||||
void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct lm75_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 1;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
lm75_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->temp_os = TEMP_TO_REG(results[0]);
|
||||
lm75_write_value(client,LM75_REG_TEMP_OS,data->temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->temp_hyst = TEMP_TO_REG(results[1]);
|
||||
lm75_write_value(client,LM75_REG_TEMP_HYST,data->temp_hyst);
|
||||
}
|
||||
}
|
||||
struct lm75_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 1;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
lm75_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->temp_os = TEMP_TO_REG(results[0]);
|
||||
lm75_write_value(client, LM75_REG_TEMP_OS,
|
||||
data->temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->temp_hyst = TEMP_TO_REG(results[1]);
|
||||
lm75_write_value(client, LM75_REG_TEMP_HYST,
|
||||
data->temp_hyst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int __init sensors_lm75_init(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
printk("lm75.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
lm75_initialized = 0;
|
||||
if ((res = i2c_add_driver(&lm75_driver))) {
|
||||
printk("lm75.o: Driver registration failed, module not inserted.\n");
|
||||
lm75_cleanup();
|
||||
return res;
|
||||
}
|
||||
lm75_initialized ++;
|
||||
return 0;
|
||||
printk("lm75.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
lm75_initialized = 0;
|
||||
if ((res = i2c_add_driver(&lm75_driver))) {
|
||||
printk
|
||||
("lm75.o: Driver registration failed, module not inserted.\n");
|
||||
lm75_cleanup();
|
||||
return res;
|
||||
}
|
||||
lm75_initialized++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init lm75_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
if (lm75_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&lm75_driver))) {
|
||||
printk("lm75.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
lm75_initialized --;
|
||||
}
|
||||
if (lm75_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&lm75_driver))) {
|
||||
printk
|
||||
("lm75.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
lm75_initialized--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
@@ -403,13 +418,12 @@ MODULE_DESCRIPTION("LM75 driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return sensors_lm75_init();
|
||||
return sensors_lm75_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return lm75_cleanup();
|
||||
return lm75_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+500
-453
File diff suppressed because it is too large.
Load diff
+433
-383
File diff suppressed because it is too large.
Load diff
+186
-179
@@ -60,10 +60,10 @@
|
||||
#endif
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = {SENSORS_I2C_END};
|
||||
static unsigned short normal_i2c_range[] = {0x58,0x5a,SENSORS_I2C_END};
|
||||
static unsigned int normal_isa[] = {SENSORS_ISA_END};
|
||||
static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
|
||||
static unsigned short normal_i2c[] = { SENSORS_I2C_END };
|
||||
static unsigned short normal_i2c_range[] = { 0x58, 0x5a, SENSORS_I2C_END };
|
||||
static unsigned int normal_isa[] = { SENSORS_ISA_END };
|
||||
static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(ltc1710);
|
||||
@@ -73,56 +73,56 @@ SENSORS_INSMOD_1(ltc1710);
|
||||
/* (No registers. [Wow! This thing is SIMPLE!] ) */
|
||||
|
||||
/* Initial values */
|
||||
#define LTC1710_INIT 0 /* Both off */
|
||||
#define LTC1710_INIT 0 /* Both off */
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct ltc1710_data {
|
||||
int sysctl_id;
|
||||
int sysctl_id;
|
||||
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u8 status; /* Register values */
|
||||
u8 status; /* Register values */
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init sensors_ltc1710_init(void);
|
||||
int __init sensors_ltc1710_init(void);
|
||||
static int __init ltc1710_cleanup(void);
|
||||
static int ltc1710_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int ltc1710_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static int ltc1710_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static int ltc1710_detach_client(struct i2c_client *client);
|
||||
static int ltc1710_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *arg);
|
||||
static void ltc1710_inc_use (struct i2c_client *client);
|
||||
static void ltc1710_dec_use (struct i2c_client *client);
|
||||
static void ltc1710_switch1(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void ltc1710_switch2(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
void *arg);
|
||||
static void ltc1710_inc_use(struct i2c_client *client);
|
||||
static void ltc1710_dec_use(struct i2c_client *client);
|
||||
static void ltc1710_switch1(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void ltc1710_switch2(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void ltc1710_update_client(struct i2c_client *client);
|
||||
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver ltc1710_driver = {
|
||||
/* name */ "LTC1710 sensor chip driver",
|
||||
/* id */ I2C_DRIVERID_LTC1710,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ <c1710_attach_adapter,
|
||||
/* detach_client */ <c1710_detach_client,
|
||||
/* command */ <c1710_command,
|
||||
/* inc_use */ <c1710_inc_use,
|
||||
/* dec_use */ <c1710_dec_use
|
||||
/* name */ "LTC1710 sensor chip driver",
|
||||
/* id */ I2C_DRIVERID_LTC1710,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ <c1710_attach_adapter,
|
||||
/* detach_client */ <c1710_detach_client,
|
||||
/* command */ <c1710_command,
|
||||
/* inc_use */ <c1710_inc_use,
|
||||
/* dec_use */ <c1710_dec_use
|
||||
};
|
||||
|
||||
/* These files are created for each detected LTC1710. This is just a template;
|
||||
@@ -131,11 +131,11 @@ static struct i2c_driver ltc1710_driver = {
|
||||
is done through one of the 'extra' fields which are initialized
|
||||
when a new copy is allocated. */
|
||||
static ctl_table ltc1710_dir_table_template[] = {
|
||||
{ LTC1710_SYSCTL_SWITCH_1, "switch1", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, <c1710_switch1 },
|
||||
{ LTC1710_SYSCTL_SWITCH_2, "switch2", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, <c1710_switch2 },
|
||||
{ 0 }
|
||||
{LTC1710_SYSCTL_SWITCH_1, "switch1", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, <c1710_switch1},
|
||||
{LTC1710_SYSCTL_SWITCH_2, "switch2", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, <c1710_switch2},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* Used by init/cleanup */
|
||||
@@ -148,245 +148,252 @@ static int ltc1710_id = 0;
|
||||
|
||||
int ltc1710_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return sensors_detect(adapter,&addr_data,ltc1710_detect);
|
||||
return sensors_detect(adapter, &addr_data, ltc1710_detect);
|
||||
}
|
||||
|
||||
/* This function is called by sensors_detect */
|
||||
int ltc1710_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
int ltc1710_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
{
|
||||
int i;
|
||||
struct i2c_client *new_client;
|
||||
struct ltc1710_data *data;
|
||||
int err=0;
|
||||
const char *type_name,*client_name;
|
||||
int i;
|
||||
struct i2c_client *new_client;
|
||||
struct ltc1710_data *data;
|
||||
int err = 0;
|
||||
const char *type_name, *client_name;
|
||||
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
#ifdef DEBUG
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk("ltc1710.o: ltc1710_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk
|
||||
("ltc1710.o: ltc1710_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_BYTE))
|
||||
goto ERROR0;
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
|
||||
goto ERROR0;
|
||||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access ltc1710_{read,write}_value. */
|
||||
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct ltc1710_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access ltc1710_{read,write}_value. */
|
||||
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct ltc1710_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
data = (struct ltc1710_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = <c1710_driver;
|
||||
new_client->flags = 0;
|
||||
data = (struct ltc1710_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = <c1710_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we would do the remaining detection. But the LTC1710 is plainly
|
||||
impossible to detect! Stupid chip. */
|
||||
/* Now, we would do the remaining detection. But the LTC1710 is plainly
|
||||
impossible to detect! Stupid chip. */
|
||||
|
||||
/* Determine the chip type - only one kind supported! */
|
||||
if (kind <= 0)
|
||||
kind = ltc1710;
|
||||
/* Determine the chip type - only one kind supported! */
|
||||
if (kind <= 0)
|
||||
kind = ltc1710;
|
||||
|
||||
if (kind == ltc1710) {
|
||||
type_name = "ltc1710";
|
||||
client_name = "LTC1710 chip";
|
||||
} else {
|
||||
if (kind == ltc1710) {
|
||||
type_name = "ltc1710";
|
||||
client_name = "LTC1710 chip";
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("ltc1710.o: Internal error: unknown kind (%d)?!?",kind);
|
||||
printk("ltc1710.o: Internal error: unknown kind (%d)?!?",
|
||||
kind);
|
||||
#endif
|
||||
goto ERROR1;
|
||||
}
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name,client_name);
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name, client_name);
|
||||
|
||||
new_client->id = ltc1710_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
new_client->id = ltc1710_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client,type_name,
|
||||
ltc1710_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client, type_name,
|
||||
ltc1710_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int ltc1710_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
|
||||
sensors_deregister_entry(((struct ltc1710_data *)(client->data))->sysctl_id);
|
||||
sensors_deregister_entry(((struct ltc1710_data *) (client->data))->
|
||||
sysctl_id);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("ltc1710.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk
|
||||
("ltc1710.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(client);
|
||||
kfree(client);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* No commands defined yet */
|
||||
int ltc1710_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nothing here yet */
|
||||
void ltc1710_inc_use (struct i2c_client *client)
|
||||
void ltc1710_inc_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_INC_USE_COUNT;
|
||||
MOD_INC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Nothing here yet */
|
||||
void ltc1710_dec_use (struct i2c_client *client)
|
||||
void ltc1710_dec_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_DEC_USE_COUNT;
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ltc1710_update_client(struct i2c_client *client)
|
||||
{
|
||||
struct ltc1710_data *data = client->data;
|
||||
struct ltc1710_data *data = client->data;
|
||||
|
||||
down(&data->update_lock);
|
||||
down(&data->update_lock);
|
||||
|
||||
if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
|
||||
(jiffies < data->last_updated) || ! data->valid) {
|
||||
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
|
||||
(jiffies < data->last_updated) || !data->valid) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("Starting ltc1710 update\n");
|
||||
printk("Starting ltc1710 update\n");
|
||||
#endif
|
||||
|
||||
/* data->status = i2c_smbus_read_byte(client);
|
||||
Unfortunately, reads always fail! */
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
/* data->status = i2c_smbus_read_byte(client);
|
||||
Unfortunately, reads always fail! */
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
up(&data->update_lock);
|
||||
up(&data->update_lock);
|
||||
}
|
||||
|
||||
|
||||
void ltc1710_switch1(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void ltc1710_switch1(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct ltc1710_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
ltc1710_update_client(client);
|
||||
results[0] = data->status & 1;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->status = (data->status & 2) | results[0];
|
||||
i2c_smbus_write_byte(client,data->status);
|
||||
}
|
||||
}
|
||||
struct ltc1710_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
ltc1710_update_client(client);
|
||||
results[0] = data->status & 1;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->status = (data->status & 2) | results[0];
|
||||
i2c_smbus_write_byte(client, data->status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ltc1710_switch2(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void ltc1710_switch2(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct ltc1710_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
ltc1710_update_client(client);
|
||||
results[0] = (data->status & 2) >> 1;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->status = (data->status & 1) | (results[0] << 1);
|
||||
i2c_smbus_write_byte(client,data->status);
|
||||
}
|
||||
}
|
||||
struct ltc1710_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
ltc1710_update_client(client);
|
||||
results[0] = (data->status & 2) >> 1;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->status =
|
||||
(data->status & 1) | (results[0] << 1);
|
||||
i2c_smbus_write_byte(client, data->status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int __init sensors_ltc1710_init(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
printk("ltc1710.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
ltc1710_initialized = 0;
|
||||
if ((res = i2c_add_driver(<c1710_driver))) {
|
||||
printk("ltc1710.o: Driver registration failed, module not inserted.\n");
|
||||
ltc1710_cleanup();
|
||||
return res;
|
||||
}
|
||||
ltc1710_initialized ++;
|
||||
return 0;
|
||||
printk("ltc1710.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
ltc1710_initialized = 0;
|
||||
if ((res = i2c_add_driver(<c1710_driver))) {
|
||||
printk
|
||||
("ltc1710.o: Driver registration failed, module not inserted.\n");
|
||||
ltc1710_cleanup();
|
||||
return res;
|
||||
}
|
||||
ltc1710_initialized++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init ltc1710_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
if (ltc1710_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(<c1710_driver))) {
|
||||
printk("ltc1710.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
ltc1710_initialized --;
|
||||
}
|
||||
if (ltc1710_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(<c1710_driver))) {
|
||||
printk
|
||||
("ltc1710.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
ltc1710_initialized--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_DESCRIPTION("LTC1710 driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return sensors_ltc1710_init();
|
||||
return sensors_ltc1710_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return ltc1710_cleanup();
|
||||
return ltc1710_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+164
-158
@@ -41,10 +41,10 @@
|
||||
#endif
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = {0x2E,SENSORS_I2C_END};
|
||||
static unsigned short normal_i2c_range[] = {SENSORS_I2C_END};
|
||||
static unsigned int normal_isa[] = {SENSORS_ISA_END};
|
||||
static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
|
||||
static unsigned short normal_i2c[] = { 0x2E, SENSORS_I2C_END };
|
||||
static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
|
||||
static unsigned int normal_isa[] = { SENSORS_ISA_END };
|
||||
static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(matorb);
|
||||
@@ -54,51 +54,52 @@ SENSORS_INSMOD_1(matorb);
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct matorb_data {
|
||||
int sysctl_id;
|
||||
int sysctl_id;
|
||||
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init sensors_matorb_init(void);
|
||||
int __init sensors_matorb_init(void);
|
||||
static int __init matorb_cleanup(void);
|
||||
static int matorb_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int matorb_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static int matorb_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static void matorb_init_client(struct i2c_client *client);
|
||||
static int matorb_detach_client(struct i2c_client *client);
|
||||
static int matorb_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *arg);
|
||||
static void matorb_inc_use (struct i2c_client *client);
|
||||
static void matorb_dec_use (struct i2c_client *client);
|
||||
static int matorb_write_value(struct i2c_client *client, u8 reg, u16 value);
|
||||
static void matorb_disp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
void *arg);
|
||||
static void matorb_inc_use(struct i2c_client *client);
|
||||
static void matorb_dec_use(struct i2c_client *client);
|
||||
static int matorb_write_value(struct i2c_client *client, u8 reg,
|
||||
u16 value);
|
||||
static void matorb_disp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void matorb_update_client(struct i2c_client *client);
|
||||
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver matorb_driver = {
|
||||
/* name */ "Matrix Orbital LCD driver",
|
||||
/* id */ I2C_DRIVERID_MATORB,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &matorb_attach_adapter,
|
||||
/* detach_client */ &matorb_detach_client,
|
||||
/* command */ &matorb_command,
|
||||
/* inc_use */ &matorb_inc_use,
|
||||
/* dec_use */ &matorb_dec_use
|
||||
/* name */ "Matrix Orbital LCD driver",
|
||||
/* id */ I2C_DRIVERID_MATORB,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &matorb_attach_adapter,
|
||||
/* detach_client */ &matorb_detach_client,
|
||||
/* command */ &matorb_command,
|
||||
/* inc_use */ &matorb_inc_use,
|
||||
/* dec_use */ &matorb_dec_use
|
||||
};
|
||||
|
||||
/* These files are created for each detected MATORB. This is just a template;
|
||||
@@ -107,9 +108,9 @@ static struct i2c_driver matorb_driver = {
|
||||
is done through one of the 'extra' fields which are initialized
|
||||
when a new copy is allocated. */
|
||||
static ctl_table matorb_dir_table_template[] = {
|
||||
{ MATORB_SYSCTL_DISP, "disp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &matorb_disp },
|
||||
{ 0 }
|
||||
{MATORB_SYSCTL_DISP, "disp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &matorb_disp},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* Used by init/cleanup */
|
||||
@@ -119,126 +120,129 @@ static int matorb_id = 0;
|
||||
|
||||
int matorb_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return sensors_detect(adapter,&addr_data,matorb_detect);
|
||||
return sensors_detect(adapter, &addr_data, matorb_detect);
|
||||
}
|
||||
|
||||
/* This function is called by sensors_detect */
|
||||
int matorb_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
int matorb_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
{
|
||||
int i,cur;
|
||||
struct i2c_client *new_client;
|
||||
struct matorb_data *data;
|
||||
int err=0;
|
||||
const char *type_name="matorb";
|
||||
const char *client_name="matorb";
|
||||
int i, cur;
|
||||
struct i2c_client *new_client;
|
||||
struct matorb_data *data;
|
||||
int err = 0;
|
||||
const char *type_name = "matorb";
|
||||
const char *client_name = "matorb";
|
||||
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
#ifdef DEBUG
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk("matorb.o: matorb_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk
|
||||
("matorb.o: matorb_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WRITE_BYTE |
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
|
||||
goto ERROR0;
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE |
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
|
||||
goto ERROR0;
|
||||
|
||||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access matorb_{read,write}_value. */
|
||||
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct matorb_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access matorb_{read,write}_value. */
|
||||
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct matorb_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
data = (struct matorb_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &matorb_driver;
|
||||
new_client->flags = 0;
|
||||
data = (struct matorb_data *) (new_client + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &matorb_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we do the remaining detection. It is lousy. */
|
||||
cur = i2c_smbus_write_byte_data(new_client,0x0FE, 0x58); /* clear screen */
|
||||
|
||||
printk("matorb.o: debug detect 0x%X\n",cur);
|
||||
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name,client_name);
|
||||
/* Now, we do the remaining detection. It is lousy. */
|
||||
cur = i2c_smbus_write_byte_data(new_client, 0x0FE, 0x58); /* clear screen */
|
||||
|
||||
new_client->id = matorb_id ++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
printk("matorb.o: debug detect 0x%X\n", cur);
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client,type_name,
|
||||
matorb_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name, client_name);
|
||||
|
||||
matorb_init_client(new_client);
|
||||
return 0;
|
||||
new_client->id = matorb_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client, type_name,
|
||||
matorb_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
|
||||
matorb_init_client(new_client);
|
||||
return 0;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
}
|
||||
|
||||
int matorb_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
|
||||
sensors_deregister_entry(((struct matorb_data *)(client->data))->sysctl_id);
|
||||
sensors_deregister_entry(((struct matorb_data *) (client->data))->
|
||||
sysctl_id);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("matorb.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk
|
||||
("matorb.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(client);
|
||||
kfree(client);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* No commands defined yet */
|
||||
int matorb_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nothing here yet */
|
||||
void matorb_inc_use (struct i2c_client *client)
|
||||
void matorb_inc_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_INC_USE_COUNT;
|
||||
MOD_INC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Nothing here yet */
|
||||
void matorb_dec_use (struct i2c_client *client)
|
||||
void matorb_dec_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_DEC_USE_COUNT;
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -248,7 +252,7 @@ void matorb_dec_use (struct i2c_client *client)
|
||||
the usual practice. */
|
||||
int matorb_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
return -1; /* Doesn't support reads */
|
||||
return -1; /* Doesn't support reads */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -257,104 +261,106 @@ int matorb_read_value(struct i2c_client *client, u8 reg)
|
||||
the usual practice. */
|
||||
int matorb_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
if (reg==0) {
|
||||
return i2c_smbus_write_byte(client,value);
|
||||
} else {
|
||||
return i2c_smbus_write_byte_data(client,reg,value);
|
||||
}
|
||||
if (reg == 0) {
|
||||
return i2c_smbus_write_byte(client, value);
|
||||
} else {
|
||||
return i2c_smbus_write_byte_data(client, reg, value);
|
||||
}
|
||||
}
|
||||
|
||||
void matorb_init_client(struct i2c_client *client)
|
||||
{
|
||||
/* Initialize the MATORB chip */
|
||||
/* Initialize the MATORB chip */
|
||||
}
|
||||
|
||||
void matorb_update_client(struct i2c_client *client)
|
||||
{
|
||||
struct matorb_data *data = client->data;
|
||||
struct matorb_data *data = client->data;
|
||||
|
||||
down(&data->update_lock);
|
||||
down(&data->update_lock);
|
||||
|
||||
if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
|
||||
(jiffies < data->last_updated) || ! data->valid) {
|
||||
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
|
||||
(jiffies < data->last_updated) || !data->valid) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("Starting matorb update\n");
|
||||
printk("Starting matorb update\n");
|
||||
#endif
|
||||
|
||||
/* nothing yet */
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
up(&data->update_lock);
|
||||
up(&data->update_lock);
|
||||
}
|
||||
|
||||
|
||||
void matorb_disp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
matorb_update_client(client);
|
||||
results[0] = 0;
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
for (i=1; i<=*nrels_mag;i++) {
|
||||
matorb_write_value(client,0,results[i-1]);
|
||||
}
|
||||
}
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
matorb_update_client(client);
|
||||
results[0] = 0;
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
for (i = 1; i <= *nrels_mag; i++) {
|
||||
matorb_write_value(client, 0, results[i - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int __init sensors_matorb_init(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
printk("matorb.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
matorb_initialized = 0;
|
||||
if ((res = i2c_add_driver(&matorb_driver))) {
|
||||
printk("matorb.o: Driver registration failed, module not inserted.\n");
|
||||
matorb_cleanup();
|
||||
return res;
|
||||
}
|
||||
matorb_initialized ++;
|
||||
return 0;
|
||||
printk("matorb.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
matorb_initialized = 0;
|
||||
if ((res = i2c_add_driver(&matorb_driver))) {
|
||||
printk
|
||||
("matorb.o: Driver registration failed, module not inserted.\n");
|
||||
matorb_cleanup();
|
||||
return res;
|
||||
}
|
||||
matorb_initialized++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init matorb_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
if (matorb_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&matorb_driver))) {
|
||||
printk("matorb.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
matorb_initialized --;
|
||||
}
|
||||
if (matorb_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&matorb_driver))) {
|
||||
printk
|
||||
("matorb.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
matorb_initialized--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_DESCRIPTION("MATORB driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return sensors_matorb_init();
|
||||
return sensors_matorb_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return matorb_cleanup();
|
||||
return matorb_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+441
-412
File diff suppressed because it is too large.
Load diff
+430
-386
File diff suppressed because it is too large.
Load diff
+315
-285
@@ -39,10 +39,10 @@
|
||||
#endif
|
||||
|
||||
/* Addresses to scan */
|
||||
static unsigned short normal_i2c[] = {SENSORS_I2C_END};
|
||||
static unsigned short normal_i2c_range[] = {0x2D,0x2F,SENSORS_I2C_END};
|
||||
static unsigned int normal_isa[] = {SENSORS_ISA_END};
|
||||
static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
|
||||
static unsigned short normal_i2c[] = { SENSORS_I2C_END };
|
||||
static unsigned short normal_i2c_range[] = { 0x2D, 0x2F, SENSORS_I2C_END };
|
||||
static unsigned int normal_isa[] = { SENSORS_ISA_END };
|
||||
static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
|
||||
|
||||
/* Insmod parameters */
|
||||
SENSORS_INSMOD_1(thmc50);
|
||||
@@ -85,66 +85,68 @@ SENSORS_INSMOD_1(thmc50);
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct thmc50_data {
|
||||
int sysctl_id;
|
||||
int sysctl_id;
|
||||
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
struct semaphore update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u16 temp,temp_os,temp_hyst,
|
||||
remote_temp,remote_temp_os,remote_temp_hyst,
|
||||
inter, inter_mask, die_code, analog_out; /* Register values */
|
||||
u16 temp, temp_os, temp_hyst,
|
||||
remote_temp, remote_temp_os, remote_temp_hyst,
|
||||
inter, inter_mask, die_code, analog_out; /* Register values */
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
extern int init_module(void);
|
||||
extern int cleanup_module(void);
|
||||
#endif /* MODULE */
|
||||
#endif /* MODULE */
|
||||
|
||||
#ifdef MODULE
|
||||
static
|
||||
#else
|
||||
extern
|
||||
#endif
|
||||
int __init sensors_thmc50_init(void);
|
||||
int __init sensors_thmc50_init(void);
|
||||
static int __init thmc50_cleanup(void);
|
||||
static int thmc50_attach_adapter(struct i2c_adapter *adapter);
|
||||
static int thmc50_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static int thmc50_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind);
|
||||
static void thmc50_init_client(struct i2c_client *client);
|
||||
static int thmc50_detach_client(struct i2c_client *client);
|
||||
static int thmc50_command(struct i2c_client *client, unsigned int cmd,
|
||||
void *arg);
|
||||
static void thmc50_inc_use (struct i2c_client *client);
|
||||
static void thmc50_dec_use (struct i2c_client *client);
|
||||
void *arg);
|
||||
static void thmc50_inc_use(struct i2c_client *client);
|
||||
static void thmc50_dec_use(struct i2c_client *client);
|
||||
static u16 swap_bytes(u16 val);
|
||||
static int thmc50_read_value(struct i2c_client *client, u8 reg);
|
||||
static int thmc50_write_value(struct i2c_client *client, u8 reg, u16 value);
|
||||
static void thmc50_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void thmc50_remote_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void thmc50_inter(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void thmc50_inter_mask(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void thmc50_die_code(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static void thmc50_analog_out(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
static int thmc50_write_value(struct i2c_client *client, u8 reg,
|
||||
u16 value);
|
||||
static void thmc50_temp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void thmc50_remote_temp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag,
|
||||
long *results);
|
||||
static void thmc50_inter(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void thmc50_inter_mask(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void thmc50_die_code(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void thmc50_analog_out(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results);
|
||||
static void thmc50_update_client(struct i2c_client *client);
|
||||
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver thmc50_driver = {
|
||||
/* name */ "THMC50 sensor chip driver",
|
||||
/* id */ I2C_DRIVERID_THMC50,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &thmc50_attach_adapter,
|
||||
/* detach_client */ &thmc50_detach_client,
|
||||
/* command */ &thmc50_command,
|
||||
/* inc_use */ &thmc50_inc_use,
|
||||
/* dec_use */ &thmc50_dec_use
|
||||
/* name */ "THMC50 sensor chip driver",
|
||||
/* id */ I2C_DRIVERID_THMC50,
|
||||
/* flags */ I2C_DF_NOTIFY,
|
||||
/* attach_adapter */ &thmc50_attach_adapter,
|
||||
/* detach_client */ &thmc50_detach_client,
|
||||
/* command */ &thmc50_command,
|
||||
/* inc_use */ &thmc50_inc_use,
|
||||
/* dec_use */ &thmc50_dec_use
|
||||
};
|
||||
|
||||
/* These files are created for each detected THMC50. This is just a template;
|
||||
@@ -153,19 +155,19 @@ static struct i2c_driver thmc50_driver = {
|
||||
is done through one of the 'extra' fields which are initialized
|
||||
when a new copy is allocated. */
|
||||
static ctl_table thmc50_dir_table_template[] = {
|
||||
{ THMC50_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_temp },
|
||||
{ THMC50_SYSCTL_REMOTE_TEMP, "remote_temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_remote_temp },
|
||||
{ THMC50_SYSCTL_INTER, "inter", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_inter },
|
||||
{ THMC50_SYSCTL_INTER_MASK, "inter_mask", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_inter_mask },
|
||||
{ THMC50_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_die_code },
|
||||
{ THMC50_SYSCTL_ANALOG_OUT, "analog_out", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_analog_out },
|
||||
{ 0 }
|
||||
{THMC50_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_temp},
|
||||
{THMC50_SYSCTL_REMOTE_TEMP, "remote_temp", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_remote_temp},
|
||||
{THMC50_SYSCTL_INTER, "inter", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_inter},
|
||||
{THMC50_SYSCTL_INTER_MASK, "inter_mask", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_inter_mask},
|
||||
{THMC50_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_die_code},
|
||||
{THMC50_SYSCTL_ANALOG_OUT, "analog_out", NULL, 0, 0644, NULL, &sensors_proc_real,
|
||||
&sensors_sysctl_real, NULL, &thmc50_analog_out},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* Used by init/cleanup */
|
||||
@@ -175,150 +177,160 @@ static int thmc50_id = 0;
|
||||
|
||||
int thmc50_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return sensors_detect(adapter,&addr_data,thmc50_detect);
|
||||
return sensors_detect(adapter, &addr_data, thmc50_detect);
|
||||
}
|
||||
|
||||
/* This function is called by sensors_detect */
|
||||
int thmc50_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
int thmc50_detect(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
{
|
||||
int company,i;
|
||||
struct i2c_client *new_client;
|
||||
struct thmc50_data *data;
|
||||
int err=0;
|
||||
const char *type_name,*client_name;
|
||||
int company, i;
|
||||
struct i2c_client *new_client;
|
||||
struct thmc50_data *data;
|
||||
int err = 0;
|
||||
const char *type_name, *client_name;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("thmc50.o: Probing for THMC50 at 0x%2X on bus %d\n",address,adapter->id);
|
||||
printk("thmc50.o: Probing for THMC50 at 0x%2X on bus %d\n",
|
||||
address, adapter->id);
|
||||
#endif
|
||||
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
/* Make sure we aren't probing the ISA bus!! This is just a safety check
|
||||
at this moment; sensors_detect really won't call us. */
|
||||
#ifdef DEBUG
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk("thmc50.o: thmc50_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
if (i2c_is_isa_adapter(adapter)) {
|
||||
printk
|
||||
("thmc50.o: thmc50_detect called for an ISA bus adapter?!?\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto ERROR0;
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
goto ERROR0;
|
||||
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access thmc50_{read,write}_value. */
|
||||
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct thmc50_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
/* OK. For now, we presume we have a valid client. We now create the
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
But it allows us to access thmc50_{read,write}_value. */
|
||||
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
|
||||
sizeof(struct thmc50_data),
|
||||
GFP_KERNEL))) {
|
||||
err = -ENOMEM;
|
||||
goto ERROR0;
|
||||
}
|
||||
|
||||
data = (struct thmc50_data *) (((struct i2c_client *) new_client) + 1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &thmc50_driver;
|
||||
new_client->flags = 0;
|
||||
data =
|
||||
(struct thmc50_data *) (((struct i2c_client *) new_client) +
|
||||
1);
|
||||
new_client->addr = address;
|
||||
new_client->data = data;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &thmc50_driver;
|
||||
new_client->flags = 0;
|
||||
|
||||
/* Now, we do the remaining detection. */
|
||||
company = i2c_smbus_read_byte_data(new_client,THMC50_REG_COMPANY_ID);
|
||||
/* Now, we do the remaining detection. */
|
||||
company =
|
||||
i2c_smbus_read_byte_data(new_client, THMC50_REG_COMPANY_ID);
|
||||
|
||||
if (company != 0x49) {
|
||||
if (company != 0x49) {
|
||||
#ifdef DEBUG
|
||||
printk("thmc50.o: Detect of THMC50 failed (reg 3E: 0x%X)\n",company);
|
||||
printk
|
||||
("thmc50.o: Detect of THMC50 failed (reg 3E: 0x%X)\n",
|
||||
company);
|
||||
#endif
|
||||
goto ERROR1;
|
||||
}
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Determine the chip type - only one kind supported! */
|
||||
kind = thmc50;
|
||||
/* Determine the chip type - only one kind supported! */
|
||||
kind = thmc50;
|
||||
|
||||
if (kind == thmc50) {
|
||||
type_name = "thmc50";
|
||||
client_name = "THMC50 chip";
|
||||
} else {
|
||||
if (kind == thmc50) {
|
||||
type_name = "thmc50";
|
||||
client_name = "THMC50 chip";
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printk("thmc50.o: Internal error: unknown kind (%d)?!?",kind);
|
||||
printk("thmc50.o: Internal error: unknown kind (%d)?!?",
|
||||
kind);
|
||||
#endif
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name,client_name);
|
||||
goto ERROR1;
|
||||
}
|
||||
|
||||
new_client->id = thmc50_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
/* Fill in the remaining client fields and put it into the global list */
|
||||
strcpy(new_client->name, client_name);
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client,type_name,
|
||||
thmc50_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
new_client->id = thmc50_id++;
|
||||
data->valid = 0;
|
||||
init_MUTEX(&data->update_lock);
|
||||
|
||||
thmc50_init_client(new_client);
|
||||
return 0;
|
||||
/* Tell the I2C layer a new client has arrived */
|
||||
if ((err = i2c_attach_client(new_client)))
|
||||
goto ERROR3;
|
||||
|
||||
/* Register a new directory entry with module sensors */
|
||||
if ((i = sensors_register_entry(new_client, type_name,
|
||||
thmc50_dir_table_template,
|
||||
THIS_MODULE)) < 0) {
|
||||
err = i;
|
||||
goto ERROR4;
|
||||
}
|
||||
data->sysctl_id = i;
|
||||
|
||||
thmc50_init_client(new_client);
|
||||
return 0;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
ERROR4:
|
||||
i2c_detach_client(new_client);
|
||||
ERROR3:
|
||||
ERROR1:
|
||||
kfree(new_client);
|
||||
ERROR0:
|
||||
return err;
|
||||
}
|
||||
|
||||
int thmc50_detach_client(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
|
||||
sensors_deregister_entry(((struct thmc50_data *)(client->data))->sysctl_id);
|
||||
sensors_deregister_entry(((struct thmc50_data *) (client->data))->
|
||||
sysctl_id);
|
||||
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("thmc50.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk
|
||||
("thmc50.o: Client deregistration failed, client not detached.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree(client);
|
||||
kfree(client);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* No commands defined yet */
|
||||
int thmc50_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void thmc50_inc_use (struct i2c_client *client)
|
||||
void thmc50_inc_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_INC_USE_COUNT;
|
||||
MOD_INC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
void thmc50_dec_use (struct i2c_client *client)
|
||||
void thmc50_dec_use(struct i2c_client *client)
|
||||
{
|
||||
#ifdef MODULE
|
||||
MOD_DEC_USE_COUNT;
|
||||
MOD_DEC_USE_COUNT;
|
||||
#endif
|
||||
}
|
||||
|
||||
u16 swap_bytes(u16 val)
|
||||
{
|
||||
return (val >> 8) | (val << 8);
|
||||
return (val >> 8) | (val << 8);
|
||||
}
|
||||
|
||||
/* All registers are word-sized, except for the configuration register.
|
||||
@@ -326,7 +338,7 @@ u16 swap_bytes(u16 val)
|
||||
the usual practice. */
|
||||
int thmc50_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
return i2c_smbus_read_byte_data(client,reg);
|
||||
return i2c_smbus_read_byte_data(client, reg);
|
||||
}
|
||||
|
||||
/* All registers are word-sized, except for the configuration register.
|
||||
@@ -334,167 +346,183 @@ int thmc50_read_value(struct i2c_client *client, u8 reg)
|
||||
the usual practice. */
|
||||
int thmc50_write_value(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
return i2c_smbus_write_byte_data(client,reg,value);
|
||||
return i2c_smbus_write_byte_data(client, reg, value);
|
||||
}
|
||||
|
||||
void thmc50_init_client(struct i2c_client *client)
|
||||
{
|
||||
/* Initialize the THMC50 chip */
|
||||
thmc50_write_value(client,THMC50_REG_TEMP_OS,
|
||||
TEMP_TO_REG(THMC50_INIT_TEMP_OS));
|
||||
thmc50_write_value(client,THMC50_REG_TEMP_HYST,
|
||||
TEMP_TO_REG(THMC50_INIT_TEMP_HYST));
|
||||
thmc50_write_value(client,THMC50_REG_CONF,1);
|
||||
/* Initialize the THMC50 chip */
|
||||
thmc50_write_value(client, THMC50_REG_TEMP_OS,
|
||||
TEMP_TO_REG(THMC50_INIT_TEMP_OS));
|
||||
thmc50_write_value(client, THMC50_REG_TEMP_HYST,
|
||||
TEMP_TO_REG(THMC50_INIT_TEMP_HYST));
|
||||
thmc50_write_value(client, THMC50_REG_CONF, 1);
|
||||
}
|
||||
|
||||
void thmc50_update_client(struct i2c_client *client)
|
||||
{
|
||||
struct thmc50_data *data = client->data;
|
||||
struct thmc50_data *data = client->data;
|
||||
|
||||
down(&data->update_lock);
|
||||
down(&data->update_lock);
|
||||
|
||||
if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
|
||||
(jiffies < data->last_updated) || ! data->valid) {
|
||||
if ((jiffies - data->last_updated > HZ + HZ / 2) ||
|
||||
(jiffies < data->last_updated) || !data->valid) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("Starting thmc50 update\n");
|
||||
printk("Starting thmc50 update\n");
|
||||
#endif
|
||||
|
||||
data->temp = thmc50_read_value(client,THMC50_REG_TEMP);
|
||||
data->temp_os = thmc50_read_value(client,THMC50_REG_TEMP_OS);
|
||||
data->temp_hyst = thmc50_read_value(client,THMC50_REG_TEMP_HYST);
|
||||
data->remote_temp = thmc50_read_value(client,THMC50_REG_REMOTE_TEMP);
|
||||
data->remote_temp_os = thmc50_read_value(client,THMC50_REG_REMOTE_TEMP_OS);
|
||||
data->remote_temp_hyst = thmc50_read_value(client,THMC50_REG_REMOTE_TEMP_HYST);
|
||||
data->inter = thmc50_read_value(client,THMC50_REG_INTER);
|
||||
data->inter_mask = thmc50_read_value(client,THMC50_REG_INTER_MASK);
|
||||
data->die_code = thmc50_read_value(client,THMC50_REG_DIE_CODE);
|
||||
data->analog_out = thmc50_read_value(client,THMC50_REG_ANALOG_OUT);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
data->temp = thmc50_read_value(client, THMC50_REG_TEMP);
|
||||
data->temp_os =
|
||||
thmc50_read_value(client, THMC50_REG_TEMP_OS);
|
||||
data->temp_hyst =
|
||||
thmc50_read_value(client, THMC50_REG_TEMP_HYST);
|
||||
data->remote_temp =
|
||||
thmc50_read_value(client, THMC50_REG_REMOTE_TEMP);
|
||||
data->remote_temp_os =
|
||||
thmc50_read_value(client, THMC50_REG_REMOTE_TEMP_OS);
|
||||
data->remote_temp_hyst =
|
||||
thmc50_read_value(client, THMC50_REG_REMOTE_TEMP_HYST);
|
||||
data->inter = thmc50_read_value(client, THMC50_REG_INTER);
|
||||
data->inter_mask =
|
||||
thmc50_read_value(client, THMC50_REG_INTER_MASK);
|
||||
data->die_code =
|
||||
thmc50_read_value(client, THMC50_REG_DIE_CODE);
|
||||
data->analog_out =
|
||||
thmc50_read_value(client, THMC50_REG_ANALOG_OUT);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
up(&data->update_lock);
|
||||
up(&data->update_lock);
|
||||
}
|
||||
|
||||
|
||||
void thmc50_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->temp_os = TEMP_TO_REG(results[0]);
|
||||
thmc50_write_value(client,THMC50_REG_TEMP_OS,data->temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->temp_hyst = TEMP_TO_REG(results[1]);
|
||||
thmc50_write_value(client,THMC50_REG_TEMP_HYST,data->temp_hyst);
|
||||
}
|
||||
}
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->temp_os = TEMP_TO_REG(results[0]);
|
||||
thmc50_write_value(client, THMC50_REG_TEMP_OS,
|
||||
data->temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->temp_hyst = TEMP_TO_REG(results[1]);
|
||||
thmc50_write_value(client, THMC50_REG_TEMP_HYST,
|
||||
data->temp_hyst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thmc50_remote_temp(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void thmc50_remote_temp(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->remote_temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->remote_temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->remote_temp_os = TEMP_TO_REG(results[0]);
|
||||
thmc50_write_value(client,THMC50_REG_REMOTE_TEMP_OS,data->remote_temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->remote_temp_hyst = TEMP_TO_REG(results[1]);
|
||||
thmc50_write_value(client,THMC50_REG_REMOTE_TEMP_HYST,data->remote_temp_hyst);
|
||||
}
|
||||
}
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = TEMP_FROM_REG(data->remote_temp_os);
|
||||
results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
|
||||
results[2] = TEMP_FROM_REG(data->remote_temp);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->remote_temp_os = TEMP_TO_REG(results[0]);
|
||||
thmc50_write_value(client,
|
||||
THMC50_REG_REMOTE_TEMP_OS,
|
||||
data->remote_temp_os);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->remote_temp_hyst = TEMP_TO_REG(results[1]);
|
||||
thmc50_write_value(client,
|
||||
THMC50_REG_REMOTE_TEMP_HYST,
|
||||
data->remote_temp_hyst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thmc50_inter(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
int *nrels_mag, long *results)
|
||||
{
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = data->inter;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
printk("thmc50.o: No writes to Interrupt register!\n");
|
||||
}
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = data->inter;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
printk("thmc50.o: No writes to Interrupt register!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thmc50_inter_mask(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void thmc50_inter_mask(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = data->inter_mask;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->inter_mask = results[0];
|
||||
thmc50_write_value(client,THMC50_REG_INTER_MASK,data->inter_mask);
|
||||
}
|
||||
}
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = data->inter_mask;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->inter_mask = results[0];
|
||||
thmc50_write_value(client, THMC50_REG_INTER_MASK,
|
||||
data->inter_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thmc50_die_code(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void thmc50_die_code(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = data->die_code;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
printk("thmc50.o: No writes to Die-Code register!\n");
|
||||
}
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = data->die_code;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
printk("thmc50.o: No writes to Die-Code register!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thmc50_analog_out(struct i2c_client *client, int operation, int ctl_name,
|
||||
int *nrels_mag, long *results)
|
||||
void thmc50_analog_out(struct i2c_client *client, int operation,
|
||||
int ctl_name, int *nrels_mag, long *results)
|
||||
{
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = data->analog_out;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->analog_out = results[0];
|
||||
thmc50_write_value(client,THMC50_REG_ANALOG_OUT,data->analog_out);
|
||||
}
|
||||
}
|
||||
struct thmc50_data *data = client->data;
|
||||
if (operation == SENSORS_PROC_REAL_INFO)
|
||||
*nrels_mag = 0;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
thmc50_update_client(client);
|
||||
results[0] = data->analog_out;
|
||||
*nrels_mag = 1;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->analog_out = results[0];
|
||||
thmc50_write_value(client, THMC50_REG_ANALOG_OUT,
|
||||
data->analog_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -502,50 +530,52 @@ void thmc50_analog_out(struct i2c_client *client, int operation, int ctl_name,
|
||||
|
||||
int __init sensors_thmc50_init(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
printk("thmc50.o version %s (%s)\n",LM_VERSION,LM_DATE);
|
||||
thmc50_initialized = 0;
|
||||
if ((res = i2c_add_driver(&thmc50_driver))) {
|
||||
printk("thmc50.o: Driver registration failed, module not inserted.\n");
|
||||
thmc50_cleanup();
|
||||
return res;
|
||||
}
|
||||
thmc50_initialized ++;
|
||||
return 0;
|
||||
printk("thmc50.o version %s (%s)\n", LM_VERSION, LM_DATE);
|
||||
thmc50_initialized = 0;
|
||||
if ((res = i2c_add_driver(&thmc50_driver))) {
|
||||
printk
|
||||
("thmc50.o: Driver registration failed, module not inserted.\n");
|
||||
thmc50_cleanup();
|
||||
return res;
|
||||
}
|
||||
thmc50_initialized++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init thmc50_cleanup(void)
|
||||
{
|
||||
int res;
|
||||
int res;
|
||||
|
||||
if (thmc50_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&thmc50_driver))) {
|
||||
printk("thmc50.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
thmc50_initialized --;
|
||||
}
|
||||
if (thmc50_initialized >= 1) {
|
||||
if ((res = i2c_del_driver(&thmc50_driver))) {
|
||||
printk
|
||||
("thmc50.o: Driver deregistration failed, module not removed.\n");
|
||||
return res;
|
||||
}
|
||||
thmc50_initialized--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_NO_SYMBOLS;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_AUTHOR
|
||||
("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
|
||||
MODULE_DESCRIPTION("THMC50 driver");
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return sensors_thmc50_init();
|
||||
return sensors_thmc50_init();
|
||||
}
|
||||
|
||||
int cleanup_module(void)
|
||||
{
|
||||
return thmc50_cleanup();
|
||||
return thmc50_cleanup();
|
||||
}
|
||||
|
||||
#endif /* MODULE */
|
||||
|
||||
#endif /* MODULE */
|
||||
+1314
-1123
File diff suppressed because it is too large.
Load diff
@@ -24,7 +24,7 @@
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
/* Detect whether we are on the isa bus. If this returns true, all i2c
|
||||
access will fail! */
|
||||
@@ -33,6 +33,6 @@
|
||||
#define i2c_is_isa_adapter(adapptr) \
|
||||
((adapptr)->algo->id == I2C_ALGO_ISA)
|
||||
|
||||
#endif /* def __KERNEL__ */
|
||||
#endif /* def __KERNEL__ */
|
||||
|
||||
#endif /* ndef SENSORS_ISA_H */
|
||||
#endif /* ndef SENSORS_ISA_H */
|
||||
+115
-114
@@ -29,9 +29,9 @@
|
||||
#include <linux/sysctl.h>
|
||||
|
||||
/* The type of callback functions used in sensors_{proc,sysctl}_real */
|
||||
typedef void (*sensors_real_callback) (struct i2c_client *client,
|
||||
int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
typedef void (*sensors_real_callback) (struct i2c_client * client,
|
||||
int operation, int ctl_name,
|
||||
int *nrels_mag, long *results);
|
||||
|
||||
/* Values for the operation field in the above function type */
|
||||
#define SENSORS_PROC_REAL_INFO 1
|
||||
@@ -55,11 +55,12 @@ typedef void (*sensors_real_callback) (struct i2c_client *client,
|
||||
found.
|
||||
In all cases, client points to the client we wish to interact with,
|
||||
and ctl_name is the SYSCTL id of the file we are accessing. */
|
||||
extern int sensors_sysctl_real (ctl_table *table, int *name, int nlen,
|
||||
void *oldval, size_t *oldlenp, void *newval,
|
||||
size_t newlen, void **context);
|
||||
extern int sensors_proc_real(ctl_table *ctl, int write, struct file * filp,
|
||||
void *buffer, size_t *lenp);
|
||||
extern int sensors_sysctl_real(ctl_table * table, int *name, int nlen,
|
||||
void *oldval, size_t * oldlenp,
|
||||
void *newval, size_t newlen,
|
||||
void **context);
|
||||
extern int sensors_proc_real(ctl_table * ctl, int write, struct file *filp,
|
||||
void *buffer, size_t * lenp);
|
||||
|
||||
|
||||
|
||||
@@ -70,10 +71,10 @@ extern int sensors_proc_real(ctl_table *ctl, int write, struct file * filp,
|
||||
copied in memory. The extra2 field of each file is set to point to client.
|
||||
If any driver wants subdirectories within the newly created directory,
|
||||
these functions must be updated! */
|
||||
extern int sensors_register_entry(struct i2c_client *client ,
|
||||
const char *prefix,
|
||||
ctl_table *ctl_template,
|
||||
struct module *controlling_mod);
|
||||
extern int sensors_register_entry(struct i2c_client *client,
|
||||
const char *prefix,
|
||||
ctl_table * ctl_template,
|
||||
struct module *controlling_mod);
|
||||
|
||||
extern void sensors_deregister_entry(int id);
|
||||
|
||||
@@ -91,8 +92,8 @@ extern void sensors_deregister_entry(int id);
|
||||
kind: The kind of chip. 0 equals any chip.
|
||||
*/
|
||||
struct sensors_force_data {
|
||||
unsigned short *force;
|
||||
unsigned short kind;
|
||||
unsigned short *force;
|
||||
unsigned short kind;
|
||||
};
|
||||
|
||||
/* A structure containing the detect information.
|
||||
@@ -135,15 +136,15 @@ struct sensors_force_data {
|
||||
the force field is NULL.
|
||||
*/
|
||||
struct sensors_address_data {
|
||||
unsigned short *normal_i2c;
|
||||
unsigned short *normal_i2c_range;
|
||||
unsigned int *normal_isa;
|
||||
unsigned int *normal_isa_range;
|
||||
unsigned short *probe;
|
||||
unsigned short *probe_range;
|
||||
unsigned short *ignore;
|
||||
unsigned short *ignore_range;
|
||||
struct sensors_force_data *forces;
|
||||
unsigned short *normal_i2c;
|
||||
unsigned short *normal_i2c_range;
|
||||
unsigned int *normal_isa;
|
||||
unsigned int *normal_isa_range;
|
||||
unsigned short *probe;
|
||||
unsigned short *probe_range;
|
||||
unsigned short *ignore;
|
||||
unsigned short *ignore_range;
|
||||
struct sensors_force_data *forces;
|
||||
};
|
||||
|
||||
/* Internal numbers to terminate lists */
|
||||
@@ -194,7 +195,7 @@ struct sensors_address_data {
|
||||
SENSORS_MODULE_PARM(force_ ## name, \
|
||||
"List of adapter,address pairs which are unquestionably" \
|
||||
" assumed to contain a `" # name "' chip")
|
||||
|
||||
|
||||
|
||||
/* This defines several insmod variables, and the addr_data structure */
|
||||
#define SENSORS_INSMOD \
|
||||
@@ -323,32 +324,32 @@ struct sensors_address_data {
|
||||
{NULL}}; \
|
||||
SENSORS_INSMOD
|
||||
|
||||
typedef int sensors_found_addr_proc (struct i2c_adapter *adapter,
|
||||
int addr, unsigned short flags,
|
||||
int kind);
|
||||
typedef int sensors_found_addr_proc(struct i2c_adapter *adapter,
|
||||
int addr, unsigned short flags,
|
||||
int kind);
|
||||
|
||||
/* Detect function. It itterates over all possible addresses itself. For
|
||||
SMBus addresses, it will only call found_proc if some client is connected
|
||||
to the SMBus (unless a 'force' matched); for ISA detections, this is not
|
||||
done. */
|
||||
extern int sensors_detect(struct i2c_adapter *adapter,
|
||||
struct sensors_address_data *address_data,
|
||||
sensors_found_addr_proc *found_proc);
|
||||
struct sensors_address_data *address_data,
|
||||
sensors_found_addr_proc * found_proc);
|
||||
|
||||
|
||||
/* This macro is used to scale user-input to sensible values in almost all
|
||||
chip drivers. */
|
||||
extern inline int SENSORS_LIMIT(long value, long low, long high)
|
||||
{
|
||||
if (value < low)
|
||||
return low;
|
||||
else if (value > high)
|
||||
return high;
|
||||
else
|
||||
return value;
|
||||
if (value < low)
|
||||
return low;
|
||||
else if (value > high)
|
||||
return high;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif /* def __KERNEL__ */
|
||||
#endif /* def __KERNEL__ */
|
||||
|
||||
|
||||
/* The maximum length of the prefix */
|
||||
@@ -376,31 +377,31 @@ extern inline int SENSORS_LIMIT(long value, long low, long high)
|
||||
/* Sysctl IDs */
|
||||
#ifdef DEV_HWMON
|
||||
#define DEV_SENSORS DEV_HWMON
|
||||
#else /* ndef DEV_HWMOM */
|
||||
#define DEV_SENSORS 2 /* The id of the lm_sensors directory within the
|
||||
dev table */
|
||||
#endif /* def DEV_HWMON */
|
||||
#else /* ndef DEV_HWMOM */
|
||||
#define DEV_SENSORS 2 /* The id of the lm_sensors directory within the
|
||||
dev table */
|
||||
#endif /* def DEV_HWMON */
|
||||
|
||||
#define SENSORS_CHIPS 1
|
||||
struct sensors_chips_data {
|
||||
int sysctl_id;
|
||||
char name[SENSORS_PREFIX_MAX + 13];
|
||||
int sysctl_id;
|
||||
char name[SENSORS_PREFIX_MAX + 13];
|
||||
};
|
||||
|
||||
#define LM78_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define LM78_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define LM78_SYSCTL_IN1 1001
|
||||
#define LM78_SYSCTL_IN2 1002
|
||||
#define LM78_SYSCTL_IN3 1003
|
||||
#define LM78_SYSCTL_IN4 1004
|
||||
#define LM78_SYSCTL_IN5 1005
|
||||
#define LM78_SYSCTL_IN6 1006
|
||||
#define LM78_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define LM78_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define LM78_SYSCTL_FAN2 1102
|
||||
#define LM78_SYSCTL_FAN3 1103
|
||||
#define LM78_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
|
||||
#define LM78_SYSCTL_VID 1300 /* Volts * 100 */
|
||||
#define LM78_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define LM78_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define LM78_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
|
||||
#define LM78_SYSCTL_VID 1300 /* Volts * 100 */
|
||||
#define LM78_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define LM78_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
|
||||
#define LM78_ALARM_IN0 0x0001
|
||||
#define LM78_ALARM_IN1 0x0002
|
||||
@@ -418,7 +419,7 @@ struct sensors_chips_data {
|
||||
#define LM78_ALARM_FIFO 0x2000
|
||||
#define LM78_ALARM_SMI_IN 0x4000
|
||||
|
||||
#define W83781D_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define W83781D_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define W83781D_SYSCTL_IN1 1001
|
||||
#define W83781D_SYSCTL_IN2 1002
|
||||
#define W83781D_SYSCTL_IN3 1003
|
||||
@@ -427,26 +428,26 @@ struct sensors_chips_data {
|
||||
#define W83781D_SYSCTL_IN6 1006
|
||||
#define W83781D_SYSCTL_IN7 1007
|
||||
#define W83781D_SYSCTL_IN8 1008
|
||||
#define W83781D_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define W83781D_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define W83781D_SYSCTL_FAN2 1102
|
||||
#define W83781D_SYSCTL_FAN3 1103
|
||||
#define W83781D_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */
|
||||
#define W83781D_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */
|
||||
#define W83781D_SYSCTL_TEMP3 1202 /* Degrees Celcius * 10 */
|
||||
#define W83781D_SYSCTL_VID 1300 /* Volts * 100 */
|
||||
#define W83781D_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */
|
||||
#define W83781D_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */
|
||||
#define W83781D_SYSCTL_TEMP3 1202 /* Degrees Celcius * 10 */
|
||||
#define W83781D_SYSCTL_VID 1300 /* Volts * 100 */
|
||||
#define W83781D_SYSCTL_PWM1 1401
|
||||
#define W83781D_SYSCTL_PWM2 1402
|
||||
#define W83781D_SYSCTL_PWM3 1403
|
||||
#define W83781D_SYSCTL_PWM4 1404
|
||||
#define W83781D_SYSCTL_SENS1 1501 /* 1, 2, or Beta (3000-5000) */
|
||||
#define W83781D_SYSCTL_SENS1 1501 /* 1, 2, or Beta (3000-5000) */
|
||||
#define W83781D_SYSCTL_SENS2 1502
|
||||
#define W83781D_SYSCTL_SENS3 1503
|
||||
#define W83781D_SYSCTL_RT1 1601 /* 32-entry table */
|
||||
#define W83781D_SYSCTL_RT2 1602 /* 32-entry table */
|
||||
#define W83781D_SYSCTL_RT3 1603 /* 32-entry table */
|
||||
#define W83781D_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define W83781D_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define W83781D_SYSCTL_BEEP 2002 /* bitvector */
|
||||
#define W83781D_SYSCTL_RT1 1601 /* 32-entry table */
|
||||
#define W83781D_SYSCTL_RT2 1602 /* 32-entry table */
|
||||
#define W83781D_SYSCTL_RT3 1603 /* 32-entry table */
|
||||
#define W83781D_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define W83781D_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define W83781D_SYSCTL_BEEP 2002 /* bitvector */
|
||||
|
||||
#define W83781D_ALARM_IN0 0x0001
|
||||
#define W83781D_ALARM_IN1 0x0002
|
||||
@@ -461,17 +462,17 @@ struct sensors_chips_data {
|
||||
#define W83781D_ALARM_FAN2 0x0080
|
||||
#define W83781D_ALARM_FAN3 0x0800
|
||||
#define W83781D_ALARM_TEMP1 0x0010
|
||||
#define W83781D_ALARM_TEMP23 0x0020 /* 781D only */
|
||||
#define W83781D_ALARM_TEMP2 0x0020 /* 782D/783S */
|
||||
#define W83781D_ALARM_TEMP3 0x2000 /* 782D only */
|
||||
#define W83781D_ALARM_TEMP23 0x0020 /* 781D only */
|
||||
#define W83781D_ALARM_TEMP2 0x0020 /* 782D/783S */
|
||||
#define W83781D_ALARM_TEMP3 0x2000 /* 782D only */
|
||||
#define W83781D_ALARM_CHAS 0x1000
|
||||
|
||||
#define LM75_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
|
||||
#define LM75_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
|
||||
|
||||
#define ADM1021_SYSCTL_TEMP 1200
|
||||
#define ADM1021_SYSCTL_TEMP 1200
|
||||
#define ADM1021_SYSCTL_REMOTE_TEMP 1201
|
||||
#define ADM1021_SYSCTL_DIE_CODE 1202
|
||||
#define ADM1021_SYSCTL_ALARMS 1203
|
||||
#define ADM1021_SYSCTL_DIE_CODE 1202
|
||||
#define ADM1021_SYSCTL_ALARMS 1203
|
||||
|
||||
#define ADM1021_ALARM_TEMP_HIGH 0x40
|
||||
#define ADM1021_ALARM_TEMP_LOW 0x20
|
||||
@@ -479,16 +480,16 @@ struct sensors_chips_data {
|
||||
#define ADM1021_ALARM_RTEMP_LOW 0x08
|
||||
#define ADM1021_ALARM_RTEMP_NA 0x04
|
||||
|
||||
#define GL518_SYSCTL_VDD 1000 /* Volts * 100 */
|
||||
#define GL518_SYSCTL_VDD 1000 /* Volts * 100 */
|
||||
#define GL518_SYSCTL_VIN1 1001
|
||||
#define GL518_SYSCTL_VIN2 1002
|
||||
#define GL518_SYSCTL_VIN3 1003
|
||||
#define GL518_SYSCTL_FAN1 1101 /* RPM */
|
||||
#define GL518_SYSCTL_FAN1 1101 /* RPM */
|
||||
#define GL518_SYSCTL_FAN2 1102
|
||||
#define GL518_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
|
||||
#define GL518_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define GL518_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define GL518_SYSCTL_BEEP 2002 /* bitvector */
|
||||
#define GL518_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
|
||||
#define GL518_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define GL518_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define GL518_SYSCTL_BEEP 2002 /* bitvector */
|
||||
#define GL518_SYSCTL_FAN1OFF 2003
|
||||
#define GL518_SYSCTL_ITERATE 2004
|
||||
|
||||
@@ -500,19 +501,19 @@ struct sensors_chips_data {
|
||||
#define GL518_ALARM_FAN1 0x20
|
||||
#define GL518_ALARM_FAN2 0x40
|
||||
|
||||
#define GL520_SYSCTL_VDD 1000 /* Volts * 100 */
|
||||
#define GL520_SYSCTL_VDD 1000 /* Volts * 100 */
|
||||
#define GL520_SYSCTL_VIN1 1001
|
||||
#define GL520_SYSCTL_VIN2 1002
|
||||
#define GL520_SYSCTL_VIN3 1003
|
||||
#define GL520_SYSCTL_VIN4 1004
|
||||
#define GL520_SYSCTL_FAN1 1101 /* RPM */
|
||||
#define GL520_SYSCTL_FAN1 1101 /* RPM */
|
||||
#define GL520_SYSCTL_FAN2 1102
|
||||
#define GL520_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */
|
||||
#define GL520_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */
|
||||
#define GL520_SYSCTL_VID 1300
|
||||
#define GL520_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define GL520_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define GL520_SYSCTL_BEEP 2002 /* bitvector */
|
||||
#define GL520_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */
|
||||
#define GL520_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */
|
||||
#define GL520_SYSCTL_VID 1300
|
||||
#define GL520_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define GL520_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define GL520_SYSCTL_BEEP 2002 /* bitvector */
|
||||
#define GL520_SYSCTL_FAN1OFF 2003
|
||||
#define GL520_SYSCTL_CONFIG 2004
|
||||
|
||||
@@ -535,30 +536,30 @@ struct sensors_chips_data {
|
||||
#define EEPROM_SYSCTL7 1006
|
||||
#define EEPROM_SYSCTL8 1007
|
||||
|
||||
#define LM80_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define LM80_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define LM80_SYSCTL_IN1 1001
|
||||
#define LM80_SYSCTL_IN2 1002
|
||||
#define LM80_SYSCTL_IN3 1003
|
||||
#define LM80_SYSCTL_IN4 1004
|
||||
#define LM80_SYSCTL_IN5 1005
|
||||
#define LM80_SYSCTL_IN6 1006
|
||||
#define LM80_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define LM80_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define LM80_SYSCTL_FAN2 1102
|
||||
#define LM80_SYSCTL_TEMP 1250 /* Degrees Celcius * 100 */
|
||||
#define LM80_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define LM80_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define LM80_SYSCTL_TEMP 1250 /* Degrees Celcius * 100 */
|
||||
#define LM80_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define LM80_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
|
||||
#define ADM9240_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define ADM9240_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define ADM9240_SYSCTL_IN1 1001
|
||||
#define ADM9240_SYSCTL_IN2 1002
|
||||
#define ADM9240_SYSCTL_IN3 1003
|
||||
#define ADM9240_SYSCTL_IN4 1004
|
||||
#define ADM9240_SYSCTL_IN5 1005
|
||||
#define ADM9240_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define ADM9240_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define ADM9240_SYSCTL_FAN2 1102
|
||||
#define ADM9240_SYSCTL_TEMP 1250 /* Degrees Celcius * 100 */
|
||||
#define ADM9240_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define ADM9240_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define ADM9240_SYSCTL_TEMP 1250 /* Degrees Celcius * 100 */
|
||||
#define ADM9240_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define ADM9240_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define ADM9240_SYSCTL_ANALOG_OUT 2002
|
||||
#define ADM9240_SYSCTL_VID 2003
|
||||
|
||||
@@ -591,20 +592,20 @@ struct sensors_chips_data {
|
||||
#define LM80_ALARM_BTI 0x0200
|
||||
#define LM80_ALARM_INT_IN 0x0080
|
||||
|
||||
#define MAXI_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define MAXI_SYSCTL_FAN2 1102 /* Rotations/min */
|
||||
#define MAXI_SYSCTL_FAN3 1103 /* Rotations/min */
|
||||
#define MAXI_SYSCTL_TEMP1 1201 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_TEMP2 1202 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_TEMP3 1203 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_TEMP4 1204 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_TEMP5 1205 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_PLL 1301 /* MHz */
|
||||
#define MAXI_SYSCTL_VID1 1401 /* Volts / 6.337 */
|
||||
#define MAXI_SYSCTL_VID2 1402 /* Volts */
|
||||
#define MAXI_SYSCTL_VID3 1403 /* Volts */
|
||||
#define MAXI_SYSCTL_VID4 1404 /* Volts */
|
||||
#define MAXI_SYSCTL_ALARMS 2001 /* Bitvector (see below) */
|
||||
#define MAXI_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define MAXI_SYSCTL_FAN2 1102 /* Rotations/min */
|
||||
#define MAXI_SYSCTL_FAN3 1103 /* Rotations/min */
|
||||
#define MAXI_SYSCTL_TEMP1 1201 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_TEMP2 1202 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_TEMP3 1203 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_TEMP4 1204 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_TEMP5 1205 /* Degrees Celcius */
|
||||
#define MAXI_SYSCTL_PLL 1301 /* MHz */
|
||||
#define MAXI_SYSCTL_VID1 1401 /* Volts / 6.337 */
|
||||
#define MAXI_SYSCTL_VID2 1402 /* Volts */
|
||||
#define MAXI_SYSCTL_VID3 1403 /* Volts */
|
||||
#define MAXI_SYSCTL_VID4 1404 /* Volts */
|
||||
#define MAXI_SYSCTL_ALARMS 2001 /* Bitvector (see below) */
|
||||
|
||||
#define MAXI_ALARM_VID4 0x0001
|
||||
#define MAXI_ALARM_TEMP2 0x0002
|
||||
@@ -618,15 +619,15 @@ struct sensors_chips_data {
|
||||
#define MAXI_ALARM_FAN2 0x2000
|
||||
#define MAXI_ALARM_FAN3 0x4000
|
||||
|
||||
#define SIS5595_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define SIS5595_SYSCTL_IN0 1000 /* Volts * 100 */
|
||||
#define SIS5595_SYSCTL_IN1 1001
|
||||
#define SIS5595_SYSCTL_IN2 1002
|
||||
#define SIS5595_SYSCTL_IN3 1003
|
||||
#define SIS5595_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define SIS5595_SYSCTL_FAN1 1101 /* Rotations/min */
|
||||
#define SIS5595_SYSCTL_FAN2 1102
|
||||
#define SIS5595_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
|
||||
#define SIS5595_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define SIS5595_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
#define SIS5595_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
|
||||
#define SIS5595_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
|
||||
#define SIS5595_SYSCTL_ALARMS 2001 /* bitvector */
|
||||
|
||||
#define SIS5595_ALARM_IN0 0x01
|
||||
#define SIS5595_ALARM_IN1 0x02
|
||||
@@ -648,12 +649,12 @@ struct sensors_chips_data {
|
||||
|
||||
#define MATORB_SYSCTL_DISP 1000
|
||||
|
||||
#define THMC50_SYSCTL_TEMP 1200 /* Degrees Celcius */
|
||||
#define THMC50_SYSCTL_REMOTE_TEMP 1201 /* Degrees Celcius */
|
||||
#define THMC50_SYSCTL_TEMP 1200 /* Degrees Celcius */
|
||||
#define THMC50_SYSCTL_REMOTE_TEMP 1201 /* Degrees Celcius */
|
||||
#define THMC50_SYSCTL_INTER 1202
|
||||
#define THMC50_SYSCTL_INTER_MASK 1203
|
||||
#define THMC50_SYSCTL_DIE_CODE 1204
|
||||
#define THMC50_SYSCTL_ANALOG_OUT 1205
|
||||
|
||||
|
||||
#endif /* def SENSORS_SENSORS_H */
|
||||
#endif /* def SENSORS_SENSORS_H */
|
||||
+630
-551
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user