diff options
-rw-r--r-- | drivers/i2c/i2c-core.c | 162 | ||||
-rw-r--r-- | include/linux/i2c.h | 2 |
2 files changed, 49 insertions, 115 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0040981b6698..02e335a04f09 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -19,7 +19,8 @@ | |||
19 | 19 | ||
20 | /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. | 20 | /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. |
21 | All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> | 21 | All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> |
22 | SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */ | 22 | SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and |
23 | Jean Delvare <khali@linux-fr.org> */ | ||
23 | 24 | ||
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
@@ -830,101 +831,44 @@ crc8(u16 data) | |||
830 | return (u8)(data >> 8); | 831 | return (u8)(data >> 8); |
831 | } | 832 | } |
832 | 833 | ||
833 | /* CRC over count bytes in the first array plus the bytes in the rest | 834 | /* Incremental CRC8 over count bytes in the array pointed to by p */ |
834 | array if it is non-null. rest[0] is the (length of rest) - 1 | 835 | static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) |
835 | and is included. */ | ||
836 | static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest) | ||
837 | { | 836 | { |
838 | int i; | 837 | int i; |
839 | 838 | ||
840 | for(i = 0; i < count; i++) | 839 | for(i = 0; i < count; i++) |
841 | crc = crc8((crc ^ first[i]) << 8); | 840 | crc = crc8((crc ^ p[i]) << 8); |
842 | if(rest != NULL) | ||
843 | for(i = 0; i <= rest[0]; i++) | ||
844 | crc = crc8((crc ^ rest[i]) << 8); | ||
845 | return crc; | 841 | return crc; |
846 | } | 842 | } |
847 | 843 | ||
848 | static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest) | 844 | /* Assume a 7-bit address, which is reasonable for SMBus */ |
845 | static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg) | ||
849 | { | 846 | { |
850 | return i2c_smbus_partial_pec(0, count, first, rest); | 847 | /* The address will be sent first */ |
848 | u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD); | ||
849 | pec = i2c_smbus_pec(pec, &addr, 1); | ||
850 | |||
851 | /* The data buffer follows */ | ||
852 | return i2c_smbus_pec(pec, msg->buf, msg->len); | ||
851 | } | 853 | } |
852 | 854 | ||
853 | /* Returns new "size" (transaction type) | 855 | /* Used for write only transactions */ |
854 | Note that we convert byte to byte_data and byte_data to word_data | 856 | static inline void i2c_smbus_add_pec(struct i2c_msg *msg) |
855 | rather than invent new xxx_PEC transactions. */ | ||
856 | static int i2c_smbus_add_pec(u16 addr, u8 command, int size, | ||
857 | union i2c_smbus_data *data) | ||
858 | { | 857 | { |
859 | u8 buf[3]; | 858 | msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg); |
860 | 859 | msg->len++; | |
861 | buf[0] = addr << 1; | ||
862 | buf[1] = command; | ||
863 | switch(size) { | ||
864 | case I2C_SMBUS_BYTE: | ||
865 | data->byte = i2c_smbus_pec(2, buf, NULL); | ||
866 | size = I2C_SMBUS_BYTE_DATA; | ||
867 | break; | ||
868 | case I2C_SMBUS_BYTE_DATA: | ||
869 | buf[2] = data->byte; | ||
870 | data->word = buf[2] | | ||
871 | (i2c_smbus_pec(3, buf, NULL) << 8); | ||
872 | size = I2C_SMBUS_WORD_DATA; | ||
873 | break; | ||
874 | case I2C_SMBUS_WORD_DATA: | ||
875 | /* unsupported */ | ||
876 | break; | ||
877 | case I2C_SMBUS_BLOCK_DATA: | ||
878 | data->block[data->block[0] + 1] = | ||
879 | i2c_smbus_pec(2, buf, data->block); | ||
880 | size = I2C_SMBUS_BLOCK_DATA_PEC; | ||
881 | break; | ||
882 | } | ||
883 | return size; | ||
884 | } | 860 | } |
885 | 861 | ||
886 | static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial, | 862 | /* Return <0 on CRC error |
887 | union i2c_smbus_data *data) | 863 | If there was a write before this read (most cases) we need to take the |
864 | partial CRC from the write part into account. | ||
865 | Note that this function does modify the message (we need to decrease the | ||
866 | message length to hide the CRC byte from the caller). */ | ||
867 | static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) | ||
888 | { | 868 | { |
889 | u8 buf[3], rpec, cpec; | 869 | u8 rpec = msg->buf[--msg->len]; |
870 | cpec = i2c_smbus_msg_pec(cpec, msg); | ||
890 | 871 | ||
891 | buf[1] = command; | ||
892 | switch(size) { | ||
893 | case I2C_SMBUS_BYTE_DATA: | ||
894 | buf[0] = (addr << 1) | 1; | ||
895 | cpec = i2c_smbus_pec(2, buf, NULL); | ||
896 | rpec = data->byte; | ||
897 | break; | ||
898 | case I2C_SMBUS_WORD_DATA: | ||
899 | buf[0] = (addr << 1) | 1; | ||
900 | buf[2] = data->word & 0xff; | ||
901 | cpec = i2c_smbus_pec(3, buf, NULL); | ||
902 | rpec = data->word >> 8; | ||
903 | break; | ||
904 | case I2C_SMBUS_WORD_DATA_PEC: | ||
905 | /* unsupported */ | ||
906 | cpec = rpec = 0; | ||
907 | break; | ||
908 | case I2C_SMBUS_PROC_CALL_PEC: | ||
909 | /* unsupported */ | ||
910 | cpec = rpec = 0; | ||
911 | break; | ||
912 | case I2C_SMBUS_BLOCK_DATA_PEC: | ||
913 | buf[0] = (addr << 1); | ||
914 | buf[2] = (addr << 1) | 1; | ||
915 | cpec = i2c_smbus_pec(3, buf, data->block); | ||
916 | rpec = data->block[data->block[0] + 1]; | ||
917 | break; | ||
918 | case I2C_SMBUS_BLOCK_PROC_CALL_PEC: | ||
919 | buf[0] = (addr << 1) | 1; | ||
920 | rpec = i2c_smbus_partial_pec(partial, 1, | ||
921 | buf, data->block); | ||
922 | cpec = data->block[data->block[0] + 1]; | ||
923 | break; | ||
924 | default: | ||
925 | cpec = rpec = 0; | ||
926 | break; | ||
927 | } | ||
928 | if (rpec != cpec) { | 872 | if (rpec != cpec) { |
929 | pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n", | 873 | pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n", |
930 | rpec, cpec); | 874 | rpec, cpec); |
@@ -951,9 +895,8 @@ s32 i2c_smbus_read_byte(struct i2c_client *client) | |||
951 | 895 | ||
952 | s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value) | 896 | s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value) |
953 | { | 897 | { |
954 | union i2c_smbus_data data; /* only for PEC */ | ||
955 | return i2c_smbus_xfer(client->adapter,client->addr,client->flags, | 898 | return i2c_smbus_xfer(client->adapter,client->addr,client->flags, |
956 | I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data); | 899 | I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); |
957 | } | 900 | } |
958 | 901 | ||
959 | s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) | 902 | s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) |
@@ -1043,6 +986,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, | |||
1043 | { addr, flags | I2C_M_RD, 0, msgbuf1 } | 986 | { addr, flags | I2C_M_RD, 0, msgbuf1 } |
1044 | }; | 987 | }; |
1045 | int i; | 988 | int i; |
989 | u8 partial_pec = 0; | ||
1046 | 990 | ||
1047 | msgbuf0[0] = command; | 991 | msgbuf0[0] = command; |
1048 | switch(size) { | 992 | switch(size) { |
@@ -1085,7 +1029,6 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, | |||
1085 | msgbuf0[2] = (data->word >> 8) & 0xff; | 1029 | msgbuf0[2] = (data->word >> 8) & 0xff; |
1086 | break; | 1030 | break; |
1087 | case I2C_SMBUS_BLOCK_DATA: | 1031 | case I2C_SMBUS_BLOCK_DATA: |
1088 | case I2C_SMBUS_BLOCK_DATA_PEC: | ||
1089 | if (read_write == I2C_SMBUS_READ) { | 1032 | if (read_write == I2C_SMBUS_READ) { |
1090 | dev_err(&adapter->dev, "Block read not supported " | 1033 | dev_err(&adapter->dev, "Block read not supported " |
1091 | "under I2C emulation!\n"); | 1034 | "under I2C emulation!\n"); |
@@ -1098,14 +1041,11 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, | |||
1098 | data->block[0]); | 1041 | data->block[0]); |
1099 | return -1; | 1042 | return -1; |
1100 | } | 1043 | } |
1101 | if(size == I2C_SMBUS_BLOCK_DATA_PEC) | ||
1102 | (msg[0].len)++; | ||
1103 | for (i = 1; i < msg[0].len; i++) | 1044 | for (i = 1; i < msg[0].len; i++) |
1104 | msgbuf0[i] = data->block[i-1]; | 1045 | msgbuf0[i] = data->block[i-1]; |
1105 | } | 1046 | } |
1106 | break; | 1047 | break; |
1107 | case I2C_SMBUS_BLOCK_PROC_CALL: | 1048 | case I2C_SMBUS_BLOCK_PROC_CALL: |
1108 | case I2C_SMBUS_BLOCK_PROC_CALL_PEC: | ||
1109 | dev_dbg(&adapter->dev, "Block process call not supported " | 1049 | dev_dbg(&adapter->dev, "Block process call not supported " |
1110 | "under I2C emulation!\n"); | 1050 | "under I2C emulation!\n"); |
1111 | return -1; | 1051 | return -1; |
@@ -1130,9 +1070,30 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, | |||
1130 | return -1; | 1070 | return -1; |
1131 | } | 1071 | } |
1132 | 1072 | ||
1073 | i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK | ||
1074 | && size != I2C_SMBUS_I2C_BLOCK_DATA); | ||
1075 | if (i) { | ||
1076 | /* Compute PEC if first message is a write */ | ||
1077 | if (!(msg[0].flags & I2C_M_RD)) { | ||
1078 | if (num == 1) /* Write only */ | ||
1079 | i2c_smbus_add_pec(&msg[0]); | ||
1080 | else /* Write followed by read */ | ||
1081 | partial_pec = i2c_smbus_msg_pec(0, &msg[0]); | ||
1082 | } | ||
1083 | /* Ask for PEC if last message is a read */ | ||
1084 | if (msg[num-1].flags & I2C_M_RD) | ||
1085 | msg[num-1].len++; | ||
1086 | } | ||
1087 | |||
1133 | if (i2c_transfer(adapter, msg, num) < 0) | 1088 | if (i2c_transfer(adapter, msg, num) < 0) |
1134 | return -1; | 1089 | return -1; |
1135 | 1090 | ||
1091 | /* Check PEC if last message is a read */ | ||
1092 | if (i && (msg[num-1].flags & I2C_M_RD)) { | ||
1093 | if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0) | ||
1094 | return -1; | ||
1095 | } | ||
1096 | |||
1136 | if (read_write == I2C_SMBUS_READ) | 1097 | if (read_write == I2C_SMBUS_READ) |
1137 | switch(size) { | 1098 | switch(size) { |
1138 | case I2C_SMBUS_BYTE: | 1099 | case I2C_SMBUS_BYTE: |
@@ -1161,28 +1122,8 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, | |||
1161 | union i2c_smbus_data * data) | 1122 | union i2c_smbus_data * data) |
1162 | { | 1123 | { |
1163 | s32 res; | 1124 | s32 res; |
1164 | int swpec = 0; | ||
1165 | u8 partial = 0; | ||
1166 | 1125 | ||
1167 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; | 1126 | flags &= I2C_M_TEN | I2C_CLIENT_PEC; |
1168 | if((flags & I2C_CLIENT_PEC) && | ||
1169 | !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) { | ||
1170 | swpec = 1; | ||
1171 | if(read_write == I2C_SMBUS_READ && | ||
1172 | size == I2C_SMBUS_BLOCK_DATA) | ||
1173 | size = I2C_SMBUS_BLOCK_DATA_PEC; | ||
1174 | else if(size == I2C_SMBUS_PROC_CALL) | ||
1175 | size = I2C_SMBUS_PROC_CALL_PEC; | ||
1176 | else if(size == I2C_SMBUS_BLOCK_PROC_CALL) { | ||
1177 | i2c_smbus_add_pec(addr, command, | ||
1178 | I2C_SMBUS_BLOCK_DATA, data); | ||
1179 | partial = data->block[data->block[0] + 1]; | ||
1180 | size = I2C_SMBUS_BLOCK_PROC_CALL_PEC; | ||
1181 | } else if(read_write == I2C_SMBUS_WRITE && | ||
1182 | size != I2C_SMBUS_QUICK && | ||
1183 | size != I2C_SMBUS_I2C_BLOCK_DATA) | ||
1184 | size = i2c_smbus_add_pec(addr, command, size, data); | ||
1185 | } | ||
1186 | 1127 | ||
1187 | if (adapter->algo->smbus_xfer) { | 1128 | if (adapter->algo->smbus_xfer) { |
1188 | down(&adapter->bus_lock); | 1129 | down(&adapter->bus_lock); |
@@ -1193,13 +1134,6 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, | |||
1193 | res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, | 1134 | res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, |
1194 | command,size,data); | 1135 | command,size,data); |
1195 | 1136 | ||
1196 | if(res >= 0 && swpec && | ||
1197 | size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA && | ||
1198 | (read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC || | ||
1199 | size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) { | ||
1200 | if(i2c_smbus_check_pec(addr, command, size, partial, data)) | ||
1201 | return -1; | ||
1202 | } | ||
1203 | return res; | 1137 | return res; |
1204 | } | 1138 | } |
1205 | 1139 | ||
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index bcd4bb1b450c..78c64f7b3105 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
@@ -434,7 +434,7 @@ union i2c_smbus_data { | |||
434 | __u8 byte; | 434 | __u8 byte; |
435 | __u16 word; | 435 | __u16 word; |
436 | __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ | 436 | __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ |
437 | /* and one more for PEC */ | 437 | /* and one more for user-space compatibility */ |
438 | }; | 438 | }; |
439 | 439 | ||
440 | /* smbus_access read or write markers */ | 440 | /* smbus_access read or write markers */ |