2
0
mirror of https://github.com/lm-sensors/lm-sensors synced 2025-08-30 22:05:11 +00:00

(Phil) Now functional serial eeprom interface! A couple limitations:

* Only first 64 bytes are read (enough for SDRAM EEPROM data) in 16 byte
blocks (separate proc files).

* No writing to EEPROMs.  It's actually quite easy to add support for
writing, but I was being very paranoid about killing my DIMMs.  I may add
write support, but make it only available when a #define is specified.

Now for a user app to decode the values...


git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@71 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
Philip Edelbrock
1998-12-13 08:43:14 +00:00
parent 812f463a20
commit d1786aa42b
2 changed files with 138 additions and 72 deletions

View File

@@ -27,10 +27,16 @@
/* Many constants specified below */
/* EEPROM memory types: */
#define ONE_K 1
#define TWO_K 2
#define FOUR_K 3
#define EIGHT_K 4
#define SIXTEEN_K 5
/* Conversions */
/* Initial values */
/* Size of EEPROM in bytes */
#define EEPROM_SIZE 16
/* Each client has this additional data */
struct eeprom_data {
@@ -40,8 +46,8 @@ struct eeprom_data {
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
/* These need to change. (PAE) */
u16 temp,temp_os,temp_hyst; /* Register values */
u8 data[EEPROM_SIZE]; /* Register values */
int memtype;
};
#ifdef MODULE
@@ -65,7 +71,7 @@ static u16 swap_bytes(u16 val);
static int eeprom_read_value(struct i2c_client *client, u8 reg);
static int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value);
static void eeprom_data(struct i2c_client *client, int operation, int ctl_name,
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);
@@ -88,8 +94,14 @@ 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_SYSCTL, "EEPROM", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_data },
{ EEPROM_SYSCTL1, "data0-15", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_contents },
{ EEPROM_SYSCTL2, "data16-31", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_contents },
{ EEPROM_SYSCTL3, "data32-47", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_contents },
{ EEPROM_SYSCTL4, "data48-63", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_contents },
{ 0 }
};
@@ -116,20 +128,24 @@ int eeprom_attach_adapter(struct i2c_adapter *adapter)
/* Set err only if a global error would make registering other clients
impossible too (like out-of-memory). */
/* Serial EEPROMs for SMBus use addresses from 0x28 to 0x2f */
for (address = 0x28; (! err) && (address <= 0x2f); address ++) {
/* Serial EEPROMs for SMBus use addresses from 0x50 to 0x57 */
for (address = 0x50; (! err) && (address <= 0x57); address ++) {
/* Later on, we will keep a list of registered addresses for each
adapter, and check whether they are used here */
if (smbus_read_byte_data(adapter,address,0) < 0)
if (smbus_read_byte(adapter,address) < 0) {
#ifdef DEBUG
printk("eeprom.o: No eeprom found at: 0x%X\n",address);
#endif
continue;
}
/* Real detection code goes here */
/* Allocate space for a new client structure */
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
sizeof(struct eeprom5_data),
sizeof(struct eeprom_data),
GFP_KERNEL))) {
err = -ENOMEM;
continue;
@@ -169,8 +185,6 @@ int eeprom_attach_adapter(struct i2c_adapter *adapter)
data->sysctl_id = err;
err = 0;
/* Initialize the chip -- No init needed for EEPROMs*/
continue;
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
@@ -215,14 +229,18 @@ int eeprom_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
/* Nothing here yet */
void eeprom_inc_use (struct i2c_client *client)
{
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
}
/* Nothing here yet */
void eeprom_dec_use (struct i2c_client *client)
{
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
}
u16 swap_bytes(u16 val)
@@ -230,29 +248,22 @@ u16 swap_bytes(u16 val)
return (val >> 8) | (val << 8);
}
/* All registers are word-sized, except for the configuration register.
For some reason, we must swap the low and high byte, but only on
reading words?!? */
int eeprom_read_value(struct i2c_client *client, u8 reg)
{
if (reg == EEPROM_REG_CONF)
return smbus_read_byte_data(client->adapter,client->addr,reg);
else
return swap_bytes(smbus_read_word_data(client->adapter,client->addr,reg));
}
/* No swapping needed here! */
int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value)
{
{/*
if (reg == EEPROM_REG_CONF)
return smbus_write_byte_data(client->adapter,client->addr,reg,value);
else
return smbus_write_word_data(client->adapter,client->addr,reg,value);
return smbus_write_word_data(client->adapter,client->addr,reg,value); */
/* No writes yet (PAE) */
return 0;
}
void eeprom_update_client(struct i2c_client *client)
{
struct eeprom_data *data = client->data;
int i;
down(&data->update_lock);
@@ -263,8 +274,14 @@ void eeprom_update_client(struct i2c_client *client)
printk("Starting eeprom update\n");
#endif
/* Need to read the data here (PAE) */
data->eeprom = eeprom_read_value(client,EEPROM_REG_TEMP);
if (smbus_write_byte(client->adapter,client->addr,0)) {
#ifdef DEBUG
printk("eeprom read start has failed!\n");
#endif
}
for (i=0;i<EEPROM_SIZE;i++) {
data->data[i] = smbus_read_byte(client->adapter,client->addr);
}
data->last_updated = jiffies;
data->valid = 1;
@@ -273,18 +290,34 @@ void eeprom_update_client(struct i2c_client *client)
up(&data->update_lock);
}
/* ? (PAE) */
void eeprom_data(struct i2c_client *client, int operation, int ctl_name,
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 (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 1;
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
eeprom_update_client(client);
results[0] = DATA_FROM_REG(data->temp_os);
/* ... More needs to go here (PAE) */
*nrels_mag = 3;
/* just for testing, we won't do the whole thing */
for (i=0; i<EEPROM_SIZE; 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<EEPROM_SIZE; i++) {
printk(" 0x%X",data->data[i + base]);
}
printk(" .\n");
#endif
*nrels_mag = EEPROM_SIZE;
} else if (operation == SENSORS_PROC_REAL_WRITE) {
/* No writes to the EEPROM (yet, anyway) (PAE) */

View File

@@ -27,10 +27,16 @@
/* Many constants specified below */
/* EEPROM memory types: */
#define ONE_K 1
#define TWO_K 2
#define FOUR_K 3
#define EIGHT_K 4
#define SIXTEEN_K 5
/* Conversions */
/* Initial values */
/* Size of EEPROM in bytes */
#define EEPROM_SIZE 16
/* Each client has this additional data */
struct eeprom_data {
@@ -40,8 +46,8 @@ struct eeprom_data {
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
/* These need to change. (PAE) */
u16 temp,temp_os,temp_hyst; /* Register values */
u8 data[EEPROM_SIZE]; /* Register values */
int memtype;
};
#ifdef MODULE
@@ -65,7 +71,7 @@ static u16 swap_bytes(u16 val);
static int eeprom_read_value(struct i2c_client *client, u8 reg);
static int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value);
static void eeprom_data(struct i2c_client *client, int operation, int ctl_name,
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);
@@ -88,8 +94,14 @@ 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_SYSCTL, "EEPROM", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_data },
{ EEPROM_SYSCTL1, "data0-15", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_contents },
{ EEPROM_SYSCTL2, "data16-31", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_contents },
{ EEPROM_SYSCTL3, "data32-47", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_contents },
{ EEPROM_SYSCTL4, "data48-63", NULL, 0, 0644, NULL, &sensors_proc_real,
&sensors_sysctl_real, NULL, &eeprom_contents },
{ 0 }
};
@@ -116,20 +128,24 @@ int eeprom_attach_adapter(struct i2c_adapter *adapter)
/* Set err only if a global error would make registering other clients
impossible too (like out-of-memory). */
/* Serial EEPROMs for SMBus use addresses from 0x28 to 0x2f */
for (address = 0x28; (! err) && (address <= 0x2f); address ++) {
/* Serial EEPROMs for SMBus use addresses from 0x50 to 0x57 */
for (address = 0x50; (! err) && (address <= 0x57); address ++) {
/* Later on, we will keep a list of registered addresses for each
adapter, and check whether they are used here */
if (smbus_read_byte_data(adapter,address,0) < 0)
if (smbus_read_byte(adapter,address) < 0) {
#ifdef DEBUG
printk("eeprom.o: No eeprom found at: 0x%X\n",address);
#endif
continue;
}
/* Real detection code goes here */
/* Allocate space for a new client structure */
if (! (new_client = kmalloc(sizeof(struct i2c_client) +
sizeof(struct eeprom5_data),
sizeof(struct eeprom_data),
GFP_KERNEL))) {
err = -ENOMEM;
continue;
@@ -169,8 +185,6 @@ int eeprom_attach_adapter(struct i2c_adapter *adapter)
data->sysctl_id = err;
err = 0;
/* Initialize the chip -- No init needed for EEPROMs*/
continue;
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
@@ -215,14 +229,18 @@ int eeprom_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
/* Nothing here yet */
void eeprom_inc_use (struct i2c_client *client)
{
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
}
/* Nothing here yet */
void eeprom_dec_use (struct i2c_client *client)
{
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
}
u16 swap_bytes(u16 val)
@@ -230,29 +248,22 @@ u16 swap_bytes(u16 val)
return (val >> 8) | (val << 8);
}
/* All registers are word-sized, except for the configuration register.
For some reason, we must swap the low and high byte, but only on
reading words?!? */
int eeprom_read_value(struct i2c_client *client, u8 reg)
{
if (reg == EEPROM_REG_CONF)
return smbus_read_byte_data(client->adapter,client->addr,reg);
else
return swap_bytes(smbus_read_word_data(client->adapter,client->addr,reg));
}
/* No swapping needed here! */
int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value)
{
{/*
if (reg == EEPROM_REG_CONF)
return smbus_write_byte_data(client->adapter,client->addr,reg,value);
else
return smbus_write_word_data(client->adapter,client->addr,reg,value);
return smbus_write_word_data(client->adapter,client->addr,reg,value); */
/* No writes yet (PAE) */
return 0;
}
void eeprom_update_client(struct i2c_client *client)
{
struct eeprom_data *data = client->data;
int i;
down(&data->update_lock);
@@ -263,8 +274,14 @@ void eeprom_update_client(struct i2c_client *client)
printk("Starting eeprom update\n");
#endif
/* Need to read the data here (PAE) */
data->eeprom = eeprom_read_value(client,EEPROM_REG_TEMP);
if (smbus_write_byte(client->adapter,client->addr,0)) {
#ifdef DEBUG
printk("eeprom read start has failed!\n");
#endif
}
for (i=0;i<EEPROM_SIZE;i++) {
data->data[i] = smbus_read_byte(client->adapter,client->addr);
}
data->last_updated = jiffies;
data->valid = 1;
@@ -273,18 +290,34 @@ void eeprom_update_client(struct i2c_client *client)
up(&data->update_lock);
}
/* ? (PAE) */
void eeprom_data(struct i2c_client *client, int operation, int ctl_name,
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 (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 1;
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
eeprom_update_client(client);
results[0] = DATA_FROM_REG(data->temp_os);
/* ... More needs to go here (PAE) */
*nrels_mag = 3;
/* just for testing, we won't do the whole thing */
for (i=0; i<EEPROM_SIZE; 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<EEPROM_SIZE; i++) {
printk(" 0x%X",data->data[i + base]);
}
printk(" .\n");
#endif
*nrels_mag = EEPROM_SIZE;
} else if (operation == SENSORS_PROC_REAL_WRITE) {
/* No writes to the EEPROM (yet, anyway) (PAE) */