Changeset 4014
- Timestamp:
- 11/05/05 18:06:20 (8 years ago)
- Files:
-
- 1 modified
-
i2c/trunk/kernel/i2c-core.c (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
i2c/trunk/kernel/i2c-core.c
r4004 r4014 20 20 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. 21 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 25 /* i2c-core.c,v 1.91.2.2 2003/01/21 10:00:19 kmalkki Exp */ … … 943 944 } 944 945 945 /* CRC over count bytes in the first array plus the bytes in the rest 946 array if it is non-null. rest[0] is the (length of rest) - 1 947 and is included. */ 948 u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest) 946 /* Incremental CRC8 over count bytes in the array pointed to by p */ 947 static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) 949 948 { 950 949 int i; 951 950 952 951 for(i = 0; i < count; i++) 953 crc = crc8((crc ^ first[i]) << 8); 954 if(rest != NULL) 955 for(i = 0; i <= rest[0]; i++) 956 crc = crc8((crc ^ rest[i]) << 8); 952 crc = crc8((crc ^ p[i]) << 8); 957 953 return crc; 958 954 } 959 955 960 u8 i2c_smbus_pec(int count, u8 *first, u8 *rest) 961 { 962 return i2c_smbus_partial_pec(0, count, first, rest); 963 } 964 965 /* Returns new "size" (transaction type) 966 Note that we convert byte to byte_data and byte_data to word_data 967 rather than invent new xxx_PEC transactions. */ 968 int i2c_smbus_add_pec(u16 addr, u8 command, int size, 969 union i2c_smbus_data *data) 970 { 971 u8 buf[3]; 972 973 buf[0] = addr << 1; 974 buf[1] = command; 975 switch(size) { 976 case I2C_SMBUS_BYTE: 977 data->byte = i2c_smbus_pec(2, buf, NULL); 978 size = I2C_SMBUS_BYTE_DATA; 979 break; 980 case I2C_SMBUS_BYTE_DATA: 981 buf[2] = data->byte; 982 data->word = buf[2] | 983 (i2c_smbus_pec(3, buf, NULL) << 8); 984 size = I2C_SMBUS_WORD_DATA; 985 break; 986 case I2C_SMBUS_WORD_DATA: 987 /* unsupported */ 988 break; 989 case I2C_SMBUS_BLOCK_DATA: 990 data->block[data->block[0] + 1] = 991 i2c_smbus_pec(2, buf, data->block); 992 size = I2C_SMBUS_BLOCK_DATA_PEC; 993 break; 994 } 995 return size; 996 } 997 998 int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial, 999 union i2c_smbus_data *data) 1000 { 1001 u8 buf[3], rpec, cpec; 1002 1003 buf[1] = command; 1004 switch(size) { 1005 case I2C_SMBUS_BYTE_DATA: 1006 buf[0] = (addr << 1) | 1; 1007 cpec = i2c_smbus_pec(2, buf, NULL); 1008 rpec = data->byte; 1009 break; 1010 case I2C_SMBUS_WORD_DATA: 1011 buf[0] = (addr << 1) | 1; 1012 buf[2] = data->word & 0xff; 1013 cpec = i2c_smbus_pec(3, buf, NULL); 1014 rpec = data->word >> 8; 1015 break; 1016 case I2C_SMBUS_WORD_DATA_PEC: 1017 /* unsupported */ 1018 cpec = rpec = 0; 1019 break; 1020 case I2C_SMBUS_PROC_CALL_PEC: 1021 /* unsupported */ 1022 cpec = rpec = 0; 1023 break; 1024 case I2C_SMBUS_BLOCK_DATA_PEC: 1025 buf[0] = (addr << 1); 1026 buf[2] = (addr << 1) | 1; 1027 cpec = i2c_smbus_pec(3, buf, data->block); 1028 rpec = data->block[data->block[0] + 1]; 1029 break; 1030 case I2C_SMBUS_BLOCK_PROC_CALL_PEC: 1031 buf[0] = (addr << 1) | 1; 1032 rpec = i2c_smbus_partial_pec(partial, 1, 1033 buf, data->block); 1034 cpec = data->block[data->block[0] + 1]; 1035 break; 1036 default: 1037 cpec = rpec = 0; 1038 break; 1039 } 956 /* Assume a 7-bit address, which is reasonable for SMBus */ 957 static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg) 958 { 959 /* The address will be sent first */ 960 u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD); 961 pec = i2c_smbus_pec(pec, &addr, 1); 962 963 /* The data buffer follows */ 964 return i2c_smbus_pec(pec, msg->buf, msg->len); 965 } 966 967 /* Used for write only transactions */ 968 static inline void i2c_smbus_add_pec(struct i2c_msg *msg) 969 { 970 msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg); 971 msg->len++; 972 } 973 974 /* Return <0 on CRC error 975 If there was a write before this read (most cases) we need to take the 976 partial CRC from the write part into account. 977 Note that this function does modify the message (we need to decrease the 978 message length to hide the CRC byte from the caller). */ 979 int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) 980 { 981 u8 rpec = msg->buf[--msg->len]; 982 cpec = i2c_smbus_msg_pec(cpec, msg); 983 1040 984 if(rpec != cpec) { 1041 985 DEB(printk(KERN_DEBUG "i2c-core.o: Bad PEC 0x%02x vs. 0x%02x\n", … … 1064 1008 extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value) 1065 1009 { 1066 union i2c_smbus_data data; /* only for PEC */1067 1010 return i2c_smbus_xfer(client->adapter,client->addr,client->flags, 1068 I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE,&data);1011 I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); 1069 1012 } 1070 1013 … … 1224 1167 }; 1225 1168 int i, len; 1169 u8 partial_pec = 0; 1226 1170 1227 1171 msgbuf0[0] = command; … … 1266 1210 break; 1267 1211 case I2C_SMBUS_BLOCK_DATA: 1268 case I2C_SMBUS_BLOCK_DATA_PEC:1269 1212 if (read_write == I2C_SMBUS_READ) { 1270 1213 /* I2C_FUNC_SMBUS_EMUL doesn't include I2C_FUNC_SMBUS_READ_BLOCK_DATA */ … … 1279 1222 msg[1].flags |= I2C_M_RECV_LEN; 1280 1223 msg[1].len = I2C_SMBUS_BLOCK_MAX + 1; 1281 if (size == I2C_SMBUS_BLOCK_DATA_PEC) { 1282 msg[1].len++; 1224 if (flags & I2C_CLIENT_PEC) 1283 1225 msg[1].flags |= I2C_M_RECV_PEC; 1284 }1285 1226 } else { 1286 1227 msg[0].len = data->block[0] + 2; … … 1291 1232 return -1; 1292 1233 } 1293 if(size == I2C_SMBUS_BLOCK_DATA_PEC)1294 (msg[0].len)++;1295 1234 for (i = 1; i < msg[0].len; i++) 1296 1235 msgbuf0[i] = data->block[i-1]; … … 1298 1237 break; 1299 1238 case I2C_SMBUS_BLOCK_PROC_CALL: 1300 case I2C_SMBUS_BLOCK_PROC_CALL_PEC:1301 1239 /* I2C_FUNC_SMBUS_EMUL doesn't include I2C_FUNC_SMBUS_BLOCK_PROC_CALL */ 1302 1240 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_PROC_CALL)) { … … 1322 1260 msg[1].flags |= I2C_M_RECV_LEN; 1323 1261 msg[1].len = I2C_SMBUS_BLOCK_MAX + 1; 1324 if (size == I2C_SMBUS_BLOCK_PROC_CALL_PEC) { 1325 msg[1].len++; 1262 if (flags & I2C_CLIENT_PEC) 1326 1263 msg[1].flags |= I2C_M_RECV_PEC; 1327 }1328 1264 break; 1329 1265 case I2C_SMBUS_I2C_BLOCK_DATA: … … 1348 1284 } 1349 1285 1286 i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK 1287 && size != I2C_SMBUS_I2C_BLOCK_DATA); 1288 if (i) { 1289 /* Compute PEC if first message is a write */ 1290 if (!(msg[0].flags & I2C_M_RD)) { 1291 if (num == 1) /* Write only */ 1292 i2c_smbus_add_pec(&msg[0]); 1293 else /* Write followed by read */ 1294 partial_pec = i2c_smbus_msg_pec(0, &msg[0]); 1295 } 1296 /* Ask for PEC if last message is a read */ 1297 if (msg[num-1].flags & I2C_M_RD) 1298 msg[num-1].len++; 1299 } 1300 1350 1301 if (i2c_transfer(adapter, msg, num) < 0) 1351 1302 return -1; 1303 1304 /* Check PEC if last message is a read */ 1305 if (i && (msg[num-1].flags & I2C_M_RD)) { 1306 if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0) 1307 return -1; 1308 } 1352 1309 1353 1310 if (read_write == I2C_SMBUS_READ) … … 1371 1328 case I2C_SMBUS_BLOCK_DATA: 1372 1329 case I2C_SMBUS_BLOCK_PROC_CALL: 1373 case I2C_SMBUS_BLOCK_DATA_PEC:1374 case I2C_SMBUS_BLOCK_PROC_CALL_PEC:1375 1330 len = msgbuf1[0] + 1; 1376 if(size == I2C_SMBUS_BLOCK_DATA_PEC ||1377 size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)1378 len++;1379 1331 for (i = 0; i < len; i++) 1380 1332 data->block[i] = msgbuf1[i]; … … 1390 1342 { 1391 1343 s32 res; 1392 int swpec = 0;1393 u8 partial = 0;1394 1344 1395 1345 flags &= I2C_M_TEN | I2C_CLIENT_PEC; 1396 if((flags & I2C_CLIENT_PEC) &&1397 !(i2c_check_functionality(adap, I2C_FUNC_SMBUS_HWPEC_CALC))) {1398 swpec = 1;1399 if(read_write == I2C_SMBUS_READ &&1400 size == I2C_SMBUS_BLOCK_DATA)1401 size = I2C_SMBUS_BLOCK_DATA_PEC;1402 else if(size == I2C_SMBUS_PROC_CALL)1403 size = I2C_SMBUS_PROC_CALL_PEC;1404 else if(size == I2C_SMBUS_BLOCK_PROC_CALL) {1405 i2c_smbus_add_pec(addr, command,1406 I2C_SMBUS_BLOCK_DATA, data);1407 partial = data->block[data->block[0] + 1];1408 size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;1409 } else if(read_write == I2C_SMBUS_WRITE &&1410 size != I2C_SMBUS_QUICK &&1411 size != I2C_SMBUS_I2C_BLOCK_DATA)1412 size = i2c_smbus_add_pec(addr, command, size, data);1413 }1414 1346 1415 1347 if (adap->algo->smbus_xfer) { … … 1422 1354 command,size,data); 1423 1355 1424 if(res >= 0 && swpec &&1425 size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA &&1426 (read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC ||1427 size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {1428 if(i2c_smbus_check_pec(addr, command, size, partial, data))1429 return -1;1430 }1431 1356 return res; 1432 1357 }
