From 89e21832615eb389ad4819bd201879187886973f Mon Sep 17 00:00:00 2001 From: Frodo Looijaard Date: Thu, 10 Dec 1998 16:20:03 +0000 Subject: [PATCH] Fixed a byte swapping bug in both the LM75 and the GL518SM drivers. Strangly enough, both these devices use a high byte, low byte order for word-sized reads and writes. The SMBus documentation specifies the reverse (low, high) order, though. If all devices use the high,low order, we should change this in smbus.c. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@64 7894878c-1315-0410-8ee3-d5d059ff63e0 --- TODO | 2 +- kernel/chips/gl518sm.c | 18 +++++++++++++++--- kernel/chips/lm75.c | 11 +++++++---- src/gl518sm.c | 18 +++++++++++++++--- src/lm75.c | 11 +++++++---- 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/TODO b/TODO index faae3892..eafa5a3a 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,7 @@ Many, many things. Most notably: * Check whether the FAN count divisors in the lm78 module are correct - (probably not!) + (probably not!); correct gl518sm changed-fan_div_but_did_not_update_fans * Wouldn't it be better to display all natural voltages for the LM78 chip, and do *all* conversions through a user program? * kmalloc with GFP_KERNEL can cause a context switch! Check whether this is diff --git a/kernel/chips/gl518sm.c b/kernel/chips/gl518sm.c index 36080aec..34fbc42e 100644 --- a/kernel/chips/gl518sm.c +++ b/kernel/chips/gl518sm.c @@ -132,6 +132,7 @@ static int gl518_command(struct i2c_client *client, unsigned int cmd, void *arg); static void gl518_inc_use (struct i2c_client *client); static void gl518_dec_use (struct i2c_client *client); +static u16 swap_bytes(u16 val); static int gl518_read_value(struct i2c_client *client, u8 reg); static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value); static void gl518_update_client(struct i2c_client *client); @@ -362,19 +363,30 @@ void gl518_dec_use (struct i2c_client *client) #endif } -/* Registers 0x07 to 0x0c are word-sized, others are byte-sized */ +u16 swap_bytes(u16 val) +{ + return (val >> 8) | (val << 8); +} + +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized + GL518 uses a high-byte first convention, which is exactly opposite to + the usual practice. */ int gl518_read_value(struct i2c_client *client, u8 reg) { if ((reg >= 0x07) && (reg <= 0x0c)) - return smbus_read_word_data(client->adapter,client->addr,reg); + return swap_bytes(smbus_read_word_data(client->adapter,client->addr,reg)); else return smbus_read_byte_data(client->adapter,client->addr,reg); } +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized + GL518 uses a high-byte first convention, which is exactly opposite to + the usual practice. */ int gl518_write_value(struct i2c_client *client, u8 reg, u16 value) { if ((reg >= 0x07) && (reg <= 0x0c)) - return smbus_write_word_data(client->adapter,client->addr,reg,value); + return smbus_write_word_data(client->adapter,client->addr,reg, + swap_bytes(value)); else return smbus_write_byte_data(client->adapter,client->addr,reg,value); } diff --git a/kernel/chips/lm75.c b/kernel/chips/lm75.c index 71d68495..6e7f6adf 100644 --- a/kernel/chips/lm75.c +++ b/kernel/chips/lm75.c @@ -242,8 +242,8 @@ u16 swap_bytes(u16 val) } /* 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?!? */ + LM75 uses a high-byte first convention, which is exactly opposite to + the usual practice. */ int lm75_read_value(struct i2c_client *client, u8 reg) { if (reg == LM75_REG_CONF) @@ -252,13 +252,16 @@ int lm75_read_value(struct i2c_client *client, u8 reg) return swap_bytes(smbus_read_word_data(client->adapter,client->addr,reg)); } -/* No swapping needed here! */ +/* All registers are word-sized, except for the configuration register. + LM75 uses a high-byte first convention, which is exactly opposite to + the usual practice. */ int lm75_write_value(struct i2c_client *client, u8 reg, u16 value) { if (reg == LM75_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, + swap_bytes(value)); } void lm75_update_client(struct i2c_client *client) diff --git a/src/gl518sm.c b/src/gl518sm.c index 36080aec..34fbc42e 100644 --- a/src/gl518sm.c +++ b/src/gl518sm.c @@ -132,6 +132,7 @@ static int gl518_command(struct i2c_client *client, unsigned int cmd, void *arg); static void gl518_inc_use (struct i2c_client *client); static void gl518_dec_use (struct i2c_client *client); +static u16 swap_bytes(u16 val); static int gl518_read_value(struct i2c_client *client, u8 reg); static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value); static void gl518_update_client(struct i2c_client *client); @@ -362,19 +363,30 @@ void gl518_dec_use (struct i2c_client *client) #endif } -/* Registers 0x07 to 0x0c are word-sized, others are byte-sized */ +u16 swap_bytes(u16 val) +{ + return (val >> 8) | (val << 8); +} + +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized + GL518 uses a high-byte first convention, which is exactly opposite to + the usual practice. */ int gl518_read_value(struct i2c_client *client, u8 reg) { if ((reg >= 0x07) && (reg <= 0x0c)) - return smbus_read_word_data(client->adapter,client->addr,reg); + return swap_bytes(smbus_read_word_data(client->adapter,client->addr,reg)); else return smbus_read_byte_data(client->adapter,client->addr,reg); } +/* Registers 0x07 to 0x0c are word-sized, others are byte-sized + GL518 uses a high-byte first convention, which is exactly opposite to + the usual practice. */ int gl518_write_value(struct i2c_client *client, u8 reg, u16 value) { if ((reg >= 0x07) && (reg <= 0x0c)) - return smbus_write_word_data(client->adapter,client->addr,reg,value); + return smbus_write_word_data(client->adapter,client->addr,reg, + swap_bytes(value)); else return smbus_write_byte_data(client->adapter,client->addr,reg,value); } diff --git a/src/lm75.c b/src/lm75.c index 71d68495..6e7f6adf 100644 --- a/src/lm75.c +++ b/src/lm75.c @@ -242,8 +242,8 @@ u16 swap_bytes(u16 val) } /* 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?!? */ + LM75 uses a high-byte first convention, which is exactly opposite to + the usual practice. */ int lm75_read_value(struct i2c_client *client, u8 reg) { if (reg == LM75_REG_CONF) @@ -252,13 +252,16 @@ int lm75_read_value(struct i2c_client *client, u8 reg) return swap_bytes(smbus_read_word_data(client->adapter,client->addr,reg)); } -/* No swapping needed here! */ +/* All registers are word-sized, except for the configuration register. + LM75 uses a high-byte first convention, which is exactly opposite to + the usual practice. */ int lm75_write_value(struct i2c_client *client, u8 reg, u16 value) { if (reg == LM75_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, + swap_bytes(value)); } void lm75_update_client(struct i2c_client *client)