`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:
Frodo Looijaard committed 2000-01-24 20:37:01 +00:00
1 parent 83d5845df5
commit 6a2c82b491
29 files changed
+10217 -9155

No files matched your search

+332 -301
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
File diff suppressed because it is too large. Load diff
+322 -292
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+341 -325
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+579 -522
View File
File diff suppressed because it is too large. Load diff
+177 -165
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+433 -383
View File
File diff suppressed because it is too large. Load diff
+186 -179
View File
@@ -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 */ &ltc1710_attach_adapter,
/* detach_client */ &ltc1710_detach_client,
/* command */ &ltc1710_command,
/* inc_use */ &ltc1710_inc_use,
/* dec_use */ &ltc1710_dec_use
/* name */ "LTC1710 sensor chip driver",
/* id */ I2C_DRIVERID_LTC1710,
/* flags */ I2C_DF_NOTIFY,
/* attach_adapter */ &ltc1710_attach_adapter,
/* detach_client */ &ltc1710_detach_client,
/* command */ &ltc1710_command,
/* inc_use */ &ltc1710_inc_use,
/* dec_use */ &ltc1710_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, &ltc1710_switch1 },
{ LTC1710_SYSCTL_SWITCH_2, "switch2", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &ltc1710_switch2 },
{ 0 }
{LTC1710_SYSCTL_SWITCH_1, "switch1", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &ltc1710_switch1},
{LTC1710_SYSCTL_SWITCH_2, "switch2", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &ltc1710_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 = &ltc1710_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 = &ltc1710_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(&ltc1710_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(&ltc1710_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(&ltc1710_driver))) {
printk("ltc1710.o: Driver deregistration failed, module not removed.\n");
return res;
}
ltc1710_initialized --;
}
if (ltc1710_initialized >= 1) {
if ((res = i2c_del_driver(&ltc1710_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
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+430 -386
View File
File diff suppressed because it is too large. Load diff
+315 -285
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+3 -3
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff