56 void ec_fsm_master_validate_vendor(ec_fsm_t *); |
56 void ec_fsm_master_validate_vendor(ec_fsm_t *); |
57 void ec_fsm_master_validate_product(ec_fsm_t *); |
57 void ec_fsm_master_validate_product(ec_fsm_t *); |
58 void ec_fsm_master_reconfigure(ec_fsm_t *); |
58 void ec_fsm_master_reconfigure(ec_fsm_t *); |
59 void ec_fsm_master_address(ec_fsm_t *); |
59 void ec_fsm_master_address(ec_fsm_t *); |
60 void ec_fsm_master_conf(ec_fsm_t *); |
60 void ec_fsm_master_conf(ec_fsm_t *); |
|
61 void ec_fsm_master_eeprom(ec_fsm_t *); |
61 |
62 |
62 void ec_fsm_slave_start_reading(ec_fsm_t *); |
63 void ec_fsm_slave_start_reading(ec_fsm_t *); |
63 void ec_fsm_slave_read_status(ec_fsm_t *); |
64 void ec_fsm_slave_read_status(ec_fsm_t *); |
64 void ec_fsm_slave_read_base(ec_fsm_t *); |
65 void ec_fsm_slave_read_base(ec_fsm_t *); |
65 void ec_fsm_slave_read_dl(ec_fsm_t *); |
66 void ec_fsm_slave_read_dl(ec_fsm_t *); |
75 void ec_fsm_slave_saveop(ec_fsm_t *); |
76 void ec_fsm_slave_saveop(ec_fsm_t *); |
76 void ec_fsm_slave_op(ec_fsm_t *); |
77 void ec_fsm_slave_op(ec_fsm_t *); |
77 void ec_fsm_slave_op2(ec_fsm_t *); |
78 void ec_fsm_slave_op2(ec_fsm_t *); |
78 |
79 |
79 void ec_fsm_sii_start_reading(ec_fsm_t *); |
80 void ec_fsm_sii_start_reading(ec_fsm_t *); |
80 void ec_fsm_sii_check(ec_fsm_t *); |
81 void ec_fsm_sii_read_check(ec_fsm_t *); |
81 void ec_fsm_sii_fetch(ec_fsm_t *); |
82 void ec_fsm_sii_read_fetch(ec_fsm_t *); |
|
83 void ec_fsm_sii_start_writing(ec_fsm_t *); |
|
84 void ec_fsm_sii_write_check(ec_fsm_t *); |
|
85 void ec_fsm_sii_write_check2(ec_fsm_t *); |
82 void ec_fsm_sii_end(ec_fsm_t *); |
86 void ec_fsm_sii_end(ec_fsm_t *); |
83 void ec_fsm_sii_error(ec_fsm_t *); |
87 void ec_fsm_sii_error(ec_fsm_t *); |
84 |
88 |
85 void ec_fsm_change_start(ec_fsm_t *); |
89 void ec_fsm_change_start(ec_fsm_t *); |
86 void ec_fsm_change_check(ec_fsm_t *); |
90 void ec_fsm_change_check(ec_fsm_t *); |
404 fsm->master_state = ec_fsm_master_conf; |
408 fsm->master_state = ec_fsm_master_conf; |
405 fsm->master_state(fsm); // execute immediately |
409 fsm->master_state(fsm); // execute immediately |
406 return; |
410 return; |
407 } |
411 } |
408 |
412 |
409 // nothing to configure. restart master state machine. |
413 if (master->mode == EC_MASTER_MODE_FREERUN) { |
|
414 // nothing to configure. check for pending EEPROM write operations. |
|
415 list_for_each_entry(slave, &master->slaves, list) { |
|
416 if (!slave->new_eeprom_data) continue; |
|
417 |
|
418 // found pending EEPROM write operation. execute it! |
|
419 EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position); |
|
420 fsm->sii_offset = 0x0000; |
|
421 memcpy(fsm->sii_value, slave->new_eeprom_data, 2); |
|
422 fsm->sii_mode = 1; |
|
423 fsm->sii_state = ec_fsm_sii_start_writing; |
|
424 fsm->slave = slave; |
|
425 fsm->master_state = ec_fsm_master_eeprom; |
|
426 fsm->master_state(fsm); // execute immediately |
|
427 return; |
|
428 } |
|
429 } |
|
430 |
|
431 // nothing to do. restart master state machine. |
410 fsm->master_state = ec_fsm_master_start; |
432 fsm->master_state = ec_fsm_master_start; |
411 fsm->master_state(fsm); // execute immediately |
433 fsm->master_state(fsm); // execute immediately |
412 } |
434 } |
413 |
435 |
414 /*****************************************************************************/ |
436 /*****************************************************************************/ |
470 return; |
492 return; |
471 } |
493 } |
472 |
494 |
473 if (fsm->sii_state != ec_fsm_sii_end) return; |
495 if (fsm->sii_state != ec_fsm_sii_end) return; |
474 |
496 |
475 if (EC_READ_U32(fsm->sii_result) != slave->sii_product_code) { |
497 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) { |
476 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
498 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
477 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
499 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
478 EC_READ_U32(fsm->sii_result)); |
500 EC_READ_U32(fsm->sii_value)); |
479 fsm->master_state = ec_fsm_master_start; |
501 fsm->master_state = ec_fsm_master_start; |
480 fsm->master_state(fsm); // execute immediately |
502 fsm->master_state(fsm); // execute immediately |
481 return; |
503 return; |
482 } |
504 } |
483 |
505 |
664 if (fsm->slave_state != ec_fsm_slave_end) return; |
686 if (fsm->slave_state != ec_fsm_slave_end) return; |
665 fsm->master_state = ec_fsm_master_proc_states; |
687 fsm->master_state = ec_fsm_master_proc_states; |
666 fsm->master_state(fsm); // execute immediately |
688 fsm->master_state(fsm); // execute immediately |
667 } |
689 } |
668 |
690 |
|
691 /*****************************************************************************/ |
|
692 |
|
693 /** |
|
694 Master state: EEPROM. |
|
695 */ |
|
696 |
|
697 void ec_fsm_master_eeprom(ec_fsm_t *fsm /**< finite state machine */) |
|
698 { |
|
699 ec_slave_t *slave = fsm->slave; |
|
700 |
|
701 fsm->sii_state(fsm); // execute SII state machine |
|
702 |
|
703 if (fsm->sii_state == ec_fsm_sii_error) { |
|
704 EC_ERR("Failed to write EEPROM contents to slave %i.\n", |
|
705 slave->ring_position); |
|
706 kfree(slave->new_eeprom_data); |
|
707 slave->new_eeprom_data = NULL; |
|
708 fsm->master_state = ec_fsm_master_start; |
|
709 fsm->master_state(fsm); // execute immediately |
|
710 return; |
|
711 } |
|
712 |
|
713 if (fsm->sii_state != ec_fsm_sii_end) return; |
|
714 |
|
715 fsm->sii_offset++; |
|
716 if (fsm->sii_offset < slave->new_eeprom_size) { |
|
717 memcpy(fsm->sii_value, slave->new_eeprom_data + fsm->sii_offset, 2); |
|
718 fsm->sii_state = ec_fsm_sii_start_writing; |
|
719 fsm->sii_state(fsm); // execute immediately |
|
720 return; |
|
721 } |
|
722 |
|
723 // finished writing EEPROM |
|
724 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position); |
|
725 kfree(slave->new_eeprom_data); |
|
726 slave->new_eeprom_data = NULL; |
|
727 |
|
728 // restart master state machine. |
|
729 fsm->master_state = ec_fsm_master_start; |
|
730 fsm->master_state(fsm); // execute immediately |
|
731 return; |
|
732 } |
|
733 |
669 /****************************************************************************** |
734 /****************************************************************************** |
670 * slave state machine |
735 * slave state machine |
671 *****************************************************************************/ |
736 *****************************************************************************/ |
672 |
737 |
673 /** |
738 /** |
832 return; |
897 return; |
833 } |
898 } |
834 |
899 |
835 if (fsm->sii_state != ec_fsm_sii_end) return; |
900 if (fsm->sii_state != ec_fsm_sii_end) return; |
836 |
901 |
837 cat_type = EC_READ_U16(fsm->sii_result); |
902 cat_type = EC_READ_U16(fsm->sii_value); |
838 cat_size = EC_READ_U16(fsm->sii_result + 2); |
903 cat_size = EC_READ_U16(fsm->sii_value + 2); |
839 |
904 |
840 if (cat_type != 0xFFFF) { // not the last category |
905 if (cat_type != 0xFFFF) { // not the last category |
841 fsm->sii_offset += cat_size + 2; |
906 fsm->sii_offset += cat_size + 2; |
842 fsm->sii_state = ec_fsm_sii_start_reading; |
907 fsm->sii_state = ec_fsm_sii_start_reading; |
843 fsm->sii_state(fsm); // execute state immediately |
908 fsm->sii_state(fsm); // execute state immediately |
893 if (fsm->sii_state != ec_fsm_sii_end) return; |
958 if (fsm->sii_state != ec_fsm_sii_end) return; |
894 |
959 |
895 // 2 words fetched |
960 // 2 words fetched |
896 |
961 |
897 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit |
962 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) { // 2 words fit |
898 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_result, 4); |
963 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 4); |
899 } |
964 } |
900 else { // copy the last word |
965 else { // copy the last word |
901 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_result, 2); |
966 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 2); |
902 } |
967 } |
903 |
968 |
904 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) { |
969 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) { |
905 // fetch the next 2 words |
970 // fetch the next 2 words |
906 fsm->sii_offset += 2; |
971 fsm->sii_offset += 2; |
1303 |
1368 |
1304 EC_WRITE_U8 (command->data, 0x00); // read-only access |
1369 EC_WRITE_U8 (command->data, 0x00); // read-only access |
1305 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
1370 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
1306 EC_WRITE_U16(command->data + 2, fsm->sii_offset); |
1371 EC_WRITE_U16(command->data + 2, fsm->sii_offset); |
1307 ec_master_queue_command(fsm->master, command); |
1372 ec_master_queue_command(fsm->master, command); |
1308 fsm->sii_state = ec_fsm_sii_check; |
1373 fsm->sii_state = ec_fsm_sii_read_check; |
1309 } |
1374 } |
1310 |
1375 |
1311 /*****************************************************************************/ |
1376 /*****************************************************************************/ |
1312 |
1377 |
1313 /** |
1378 /** |
1314 SII state: CHECK. |
1379 SII state: READ_CHECK. |
1315 Checks, if the SII-read-command has been sent and issues a fetch command. |
1380 Checks, if the SII-read-command has been sent and issues a fetch command. |
1316 */ |
1381 */ |
1317 |
1382 |
1318 void ec_fsm_sii_check(ec_fsm_t *fsm /**< finite state machine */) |
1383 void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */) |
1319 { |
1384 { |
1320 ec_command_t *command = &fsm->command; |
1385 ec_command_t *command = &fsm->command; |
1321 |
1386 |
1322 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1387 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1323 EC_ERR("SII: Reception of read command failed.\n"); |
1388 EC_ERR("SII: Reception of read command failed.\n"); |
1334 else { |
1399 else { |
1335 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
1400 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
1336 } |
1401 } |
1337 |
1402 |
1338 ec_master_queue_command(fsm->master, command); |
1403 ec_master_queue_command(fsm->master, command); |
1339 fsm->sii_state = ec_fsm_sii_fetch; |
1404 fsm->sii_state = ec_fsm_sii_read_fetch; |
1340 } |
1405 } |
1341 |
1406 |
1342 /*****************************************************************************/ |
1407 /*****************************************************************************/ |
1343 |
1408 |
1344 /** |
1409 /** |
1345 SII state: FETCH. |
1410 SII state: READ_FETCH. |
1346 Fetches the result of an SII-read command. |
1411 Fetches the result of an SII-read command. |
1347 */ |
1412 */ |
1348 |
1413 |
1349 void ec_fsm_sii_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1414 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1350 { |
1415 { |
1351 ec_command_t *command = &fsm->command; |
1416 ec_command_t *command = &fsm->command; |
1352 |
1417 |
1353 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1418 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1354 EC_ERR("SII: Reception of check/fetch command failed.\n"); |
1419 EC_ERR("SII: Reception of check/fetch command failed.\n"); |
1389 EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7), |
1454 EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7), |
1390 EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9)); |
1455 EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9)); |
1391 #endif |
1456 #endif |
1392 |
1457 |
1393 // SII value received. |
1458 // SII value received. |
1394 memcpy(fsm->sii_result, command->data + 6, 4); |
1459 memcpy(fsm->sii_value, command->data + 6, 4); |
1395 fsm->sii_state = ec_fsm_sii_end; |
1460 fsm->sii_state = ec_fsm_sii_end; |
|
1461 } |
|
1462 |
|
1463 /*****************************************************************************/ |
|
1464 |
|
1465 /** |
|
1466 SII state: START_WRITING. |
|
1467 Starts reading the slave information interface. |
|
1468 */ |
|
1469 |
|
1470 void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */) |
|
1471 { |
|
1472 ec_command_t *command = &fsm->command; |
|
1473 |
|
1474 // initiate write operation |
|
1475 ec_command_npwr(command, fsm->slave->station_address, 0x502, 8); |
|
1476 EC_WRITE_U8 (command->data, 0x01); // enable write access |
|
1477 EC_WRITE_U8 (command->data + 1, 0x02); // request write operation |
|
1478 EC_WRITE_U32(command->data + 2, fsm->sii_offset); |
|
1479 memcpy(command->data + 6, fsm->sii_value, 2); |
|
1480 ec_master_queue_command(fsm->master, command); |
|
1481 fsm->sii_state = ec_fsm_sii_write_check; |
|
1482 } |
|
1483 |
|
1484 /*****************************************************************************/ |
|
1485 |
|
1486 /** |
|
1487 SII state: WRITE_CHECK. |
|
1488 */ |
|
1489 |
|
1490 void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */) |
|
1491 { |
|
1492 ec_command_t *command = &fsm->command; |
|
1493 |
|
1494 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
|
1495 EC_ERR("SII: Reception of write command failed.\n"); |
|
1496 fsm->sii_state = ec_fsm_sii_error; |
|
1497 return; |
|
1498 } |
|
1499 |
|
1500 fsm->sii_start = get_cycles(); |
|
1501 |
|
1502 // issue check/fetch command |
|
1503 ec_command_nprd(command, fsm->slave->station_address, 0x502, 2); |
|
1504 ec_master_queue_command(fsm->master, command); |
|
1505 fsm->sii_state = ec_fsm_sii_write_check2; |
|
1506 } |
|
1507 |
|
1508 /*****************************************************************************/ |
|
1509 |
|
1510 /** |
|
1511 SII state: WRITE_CHECK2. |
|
1512 */ |
|
1513 |
|
1514 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */) |
|
1515 { |
|
1516 ec_command_t *command = &fsm->command; |
|
1517 |
|
1518 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
|
1519 EC_ERR("SII: Reception of write check command failed.\n"); |
|
1520 fsm->sii_state = ec_fsm_sii_error; |
|
1521 return; |
|
1522 } |
|
1523 |
|
1524 if (EC_READ_U8(command->data + 1) & 0x82) { |
|
1525 // still busy... timeout? |
|
1526 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
|
1527 EC_ERR("SII: Write timeout.\n"); |
|
1528 fsm->sii_state = ec_fsm_sii_error; |
|
1529 } |
|
1530 |
|
1531 // issue check/fetch command again |
|
1532 ec_master_queue_command(fsm->master, command); |
|
1533 } |
|
1534 else if (EC_READ_U8(command->data + 1) & 0x40) { |
|
1535 EC_ERR("SII: Write operation failed!\n"); |
|
1536 fsm->sii_state = ec_fsm_sii_error; |
|
1537 } |
|
1538 else { // success |
|
1539 fsm->sii_state = ec_fsm_sii_end; |
|
1540 } |
1396 } |
1541 } |
1397 |
1542 |
1398 /*****************************************************************************/ |
1543 /*****************************************************************************/ |
1399 |
1544 |
1400 /** |
1545 /** |