diff options
Diffstat (limited to 'drivers/i2c')
| -rw-r--r-- | drivers/i2c/i2c-core.c | 162 |
1 files changed, 48 insertions, 114 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 | ||
