diff options
| -rw-r--r-- | drivers/net/ucc_geth.c | 300 |
1 files changed, 149 insertions, 151 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 3b647d07e410..a39368a46352 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
| @@ -1412,6 +1412,155 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) | |||
| 1412 | return 0; | 1412 | return 0; |
| 1413 | } | 1413 | } |
| 1414 | 1414 | ||
| 1415 | static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) | ||
| 1416 | { | ||
| 1417 | struct ucc_fast_private *uccf; | ||
| 1418 | u32 cecr_subblock; | ||
| 1419 | u32 temp; | ||
| 1420 | int i = 10; | ||
| 1421 | |||
| 1422 | uccf = ugeth->uccf; | ||
| 1423 | |||
| 1424 | /* Mask GRACEFUL STOP TX interrupt bit and clear it */ | ||
| 1425 | clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA); | ||
| 1426 | out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA); /* clear by writing 1 */ | ||
| 1427 | |||
| 1428 | /* Issue host command */ | ||
| 1429 | cecr_subblock = | ||
| 1430 | ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); | ||
| 1431 | qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock, | ||
| 1432 | QE_CR_PROTOCOL_ETHERNET, 0); | ||
| 1433 | |||
| 1434 | /* Wait for command to complete */ | ||
| 1435 | do { | ||
| 1436 | msleep(10); | ||
| 1437 | temp = in_be32(uccf->p_ucce); | ||
| 1438 | } while (!(temp & UCC_GETH_UCCE_GRA) && --i); | ||
| 1439 | |||
| 1440 | uccf->stopped_tx = 1; | ||
| 1441 | |||
| 1442 | return 0; | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | static int ugeth_graceful_stop_rx(struct ucc_geth_private *ugeth) | ||
| 1446 | { | ||
| 1447 | struct ucc_fast_private *uccf; | ||
| 1448 | u32 cecr_subblock; | ||
| 1449 | u8 temp; | ||
| 1450 | int i = 10; | ||
| 1451 | |||
| 1452 | uccf = ugeth->uccf; | ||
| 1453 | |||
| 1454 | /* Clear acknowledge bit */ | ||
| 1455 | temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); | ||
| 1456 | temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX; | ||
| 1457 | out_8(&ugeth->p_rx_glbl_pram->rxgstpack, temp); | ||
| 1458 | |||
| 1459 | /* Keep issuing command and checking acknowledge bit until | ||
| 1460 | it is asserted, according to spec */ | ||
| 1461 | do { | ||
| 1462 | /* Issue host command */ | ||
| 1463 | cecr_subblock = | ||
| 1464 | ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info. | ||
| 1465 | ucc_num); | ||
| 1466 | qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, | ||
| 1467 | QE_CR_PROTOCOL_ETHERNET, 0); | ||
| 1468 | msleep(10); | ||
| 1469 | temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); | ||
| 1470 | } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i); | ||
| 1471 | |||
| 1472 | uccf->stopped_rx = 1; | ||
| 1473 | |||
| 1474 | return 0; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | static int ugeth_restart_tx(struct ucc_geth_private *ugeth) | ||
| 1478 | { | ||
| 1479 | struct ucc_fast_private *uccf; | ||
| 1480 | u32 cecr_subblock; | ||
| 1481 | |||
| 1482 | uccf = ugeth->uccf; | ||
| 1483 | |||
| 1484 | cecr_subblock = | ||
| 1485 | ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); | ||
| 1486 | qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0); | ||
| 1487 | uccf->stopped_tx = 0; | ||
| 1488 | |||
| 1489 | return 0; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | static int ugeth_restart_rx(struct ucc_geth_private *ugeth) | ||
| 1493 | { | ||
| 1494 | struct ucc_fast_private *uccf; | ||
| 1495 | u32 cecr_subblock; | ||
| 1496 | |||
| 1497 | uccf = ugeth->uccf; | ||
| 1498 | |||
| 1499 | cecr_subblock = | ||
| 1500 | ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); | ||
| 1501 | qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, | ||
| 1502 | 0); | ||
| 1503 | uccf->stopped_rx = 0; | ||
| 1504 | |||
| 1505 | return 0; | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode) | ||
| 1509 | { | ||
| 1510 | struct ucc_fast_private *uccf; | ||
| 1511 | int enabled_tx, enabled_rx; | ||
| 1512 | |||
| 1513 | uccf = ugeth->uccf; | ||
| 1514 | |||
| 1515 | /* check if the UCC number is in range. */ | ||
| 1516 | if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { | ||
| 1517 | if (netif_msg_probe(ugeth)) | ||
| 1518 | ugeth_err("%s: ucc_num out of range.", __func__); | ||
| 1519 | return -EINVAL; | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | enabled_tx = uccf->enabled_tx; | ||
| 1523 | enabled_rx = uccf->enabled_rx; | ||
| 1524 | |||
| 1525 | /* Get Tx and Rx going again, in case this channel was actively | ||
| 1526 | disabled. */ | ||
| 1527 | if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx) | ||
| 1528 | ugeth_restart_tx(ugeth); | ||
| 1529 | if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx) | ||
| 1530 | ugeth_restart_rx(ugeth); | ||
| 1531 | |||
| 1532 | ucc_fast_enable(uccf, mode); /* OK to do even if not disabled */ | ||
| 1533 | |||
| 1534 | return 0; | ||
| 1535 | |||
| 1536 | } | ||
| 1537 | |||
| 1538 | static int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode) | ||
| 1539 | { | ||
| 1540 | struct ucc_fast_private *uccf; | ||
| 1541 | |||
| 1542 | uccf = ugeth->uccf; | ||
| 1543 | |||
| 1544 | /* check if the UCC number is in range. */ | ||
| 1545 | if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { | ||
| 1546 | if (netif_msg_probe(ugeth)) | ||
| 1547 | ugeth_err("%s: ucc_num out of range.", __func__); | ||
| 1548 | return -EINVAL; | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | /* Stop any transmissions */ | ||
| 1552 | if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx) | ||
| 1553 | ugeth_graceful_stop_tx(ugeth); | ||
| 1554 | |||
| 1555 | /* Stop any receptions */ | ||
| 1556 | if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx) | ||
| 1557 | ugeth_graceful_stop_rx(ugeth); | ||
| 1558 | |||
| 1559 | ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */ | ||
| 1560 | |||
| 1561 | return 0; | ||
| 1562 | } | ||
| 1563 | |||
| 1415 | /* Called every time the controller might need to be made | 1564 | /* Called every time the controller might need to be made |
| 1416 | * aware of new link state. The PHY code conveys this | 1565 | * aware of new link state. The PHY code conveys this |
| 1417 | * information through variables in the ugeth structure, and this | 1566 | * information through variables in the ugeth structure, and this |
| @@ -1587,157 +1736,6 @@ static int init_phy(struct net_device *dev) | |||
| 1587 | return 0; | 1736 | return 0; |
| 1588 | } | 1737 | } |
| 1589 | 1738 | ||
| 1590 | |||
| 1591 | |||
| 1592 | static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) | ||
| 1593 | { | ||
| 1594 | struct ucc_fast_private *uccf; | ||
| 1595 | u32 cecr_subblock; | ||
| 1596 | u32 temp; | ||
| 1597 | int i = 10; | ||
| 1598 | |||
| 1599 | uccf = ugeth->uccf; | ||
| 1600 | |||
| 1601 | /* Mask GRACEFUL STOP TX interrupt bit and clear it */ | ||
| 1602 | clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA); | ||
| 1603 | out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA); /* clear by writing 1 */ | ||
| 1604 | |||
| 1605 | /* Issue host command */ | ||
| 1606 | cecr_subblock = | ||
| 1607 | ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); | ||
| 1608 | qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock, | ||
| 1609 | QE_CR_PROTOCOL_ETHERNET, 0); | ||
| 1610 | |||
| 1611 | /* Wait for command to complete */ | ||
| 1612 | do { | ||
| 1613 | msleep(10); | ||
| 1614 | temp = in_be32(uccf->p_ucce); | ||
| 1615 | } while (!(temp & UCC_GETH_UCCE_GRA) && --i); | ||
| 1616 | |||
| 1617 | uccf->stopped_tx = 1; | ||
| 1618 | |||
| 1619 | return 0; | ||
| 1620 | } | ||
| 1621 | |||
| 1622 | static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth) | ||
| 1623 | { | ||
| 1624 | struct ucc_fast_private *uccf; | ||
| 1625 | u32 cecr_subblock; | ||
| 1626 | u8 temp; | ||
| 1627 | int i = 10; | ||
| 1628 | |||
| 1629 | uccf = ugeth->uccf; | ||
| 1630 | |||
| 1631 | /* Clear acknowledge bit */ | ||
| 1632 | temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); | ||
| 1633 | temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX; | ||
| 1634 | out_8(&ugeth->p_rx_glbl_pram->rxgstpack, temp); | ||
| 1635 | |||
| 1636 | /* Keep issuing command and checking acknowledge bit until | ||
| 1637 | it is asserted, according to spec */ | ||
| 1638 | do { | ||
| 1639 | /* Issue host command */ | ||
| 1640 | cecr_subblock = | ||
| 1641 | ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info. | ||
| 1642 | ucc_num); | ||
| 1643 | qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, | ||
| 1644 | QE_CR_PROTOCOL_ETHERNET, 0); | ||
| 1645 | msleep(10); | ||
| 1646 | temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); | ||
| 1647 | } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i); | ||
| 1648 | |||
| 1649 | uccf->stopped_rx = 1; | ||
| 1650 | |||
| 1651 | return 0; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | static int ugeth_restart_tx(struct ucc_geth_private *ugeth) | ||
| 1655 | { | ||
| 1656 | struct ucc_fast_private *uccf; | ||
| 1657 | u32 cecr_subblock; | ||
| 1658 | |||
| 1659 | uccf = ugeth->uccf; | ||
| 1660 | |||
| 1661 | cecr_subblock = | ||
| 1662 | ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); | ||
| 1663 | qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0); | ||
| 1664 | uccf->stopped_tx = 0; | ||
| 1665 | |||
| 1666 | return 0; | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | static int ugeth_restart_rx(struct ucc_geth_private *ugeth) | ||
| 1670 | { | ||
| 1671 | struct ucc_fast_private *uccf; | ||
| 1672 | u32 cecr_subblock; | ||
| 1673 | |||
| 1674 | uccf = ugeth->uccf; | ||
| 1675 | |||
| 1676 | cecr_subblock = | ||
| 1677 | ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); | ||
| 1678 | qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, | ||
| 1679 | 0); | ||
| 1680 | uccf->stopped_rx = 0; | ||
| 1681 | |||
| 1682 | return 0; | ||
| 1683 | } | ||
| 1684 | |||
| 1685 | static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode) | ||
| 1686 | { | ||
| 1687 | struct ucc_fast_private *uccf; | ||
| 1688 | int enabled_tx, enabled_rx; | ||
| 1689 | |||
| 1690 | uccf = ugeth->uccf; | ||
| 1691 | |||
| 1692 | /* check if the UCC number is in range. */ | ||
| 1693 | if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { | ||
| 1694 | if (netif_msg_probe(ugeth)) | ||
| 1695 | ugeth_err("%s: ucc_num out of range.", __func__); | ||
| 1696 | return -EINVAL; | ||
| 1697 | } | ||
| 1698 | |||
| 1699 | enabled_tx = uccf->enabled_tx; | ||
| 1700 | enabled_rx = uccf->enabled_rx; | ||
| 1701 | |||
| 1702 | /* Get Tx and Rx going again, in case this channel was actively | ||
| 1703 | disabled. */ | ||
| 1704 | if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx) | ||
| 1705 | ugeth_restart_tx(ugeth); | ||
| 1706 | if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx) | ||
| 1707 | ugeth_restart_rx(ugeth); | ||
| 1708 | |||
| 1709 | ucc_fast_enable(uccf, mode); /* OK to do even if not disabled */ | ||
| 1710 | |||
| 1711 | return 0; | ||
| 1712 | |||
| 1713 | } | ||
| 1714 | |||
| 1715 | static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode) | ||
| 1716 | { | ||
| 1717 | struct ucc_fast_private *uccf; | ||
| 1718 | |||
| 1719 | uccf = ugeth->uccf; | ||
| 1720 | |||
| 1721 | /* check if the UCC number is in range. */ | ||
| 1722 | if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { | ||
| 1723 | if (netif_msg_probe(ugeth)) | ||
| 1724 | ugeth_err("%s: ucc_num out of range.", __func__); | ||
| 1725 | return -EINVAL; | ||
| 1726 | } | ||
| 1727 | |||
| 1728 | /* Stop any transmissions */ | ||
| 1729 | if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx) | ||
| 1730 | ugeth_graceful_stop_tx(ugeth); | ||
| 1731 | |||
| 1732 | /* Stop any receptions */ | ||
| 1733 | if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx) | ||
| 1734 | ugeth_graceful_stop_rx(ugeth); | ||
| 1735 | |||
| 1736 | ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */ | ||
| 1737 | |||
| 1738 | return 0; | ||
| 1739 | } | ||
| 1740 | |||
| 1741 | static void ugeth_dump_regs(struct ucc_geth_private *ugeth) | 1739 | static void ugeth_dump_regs(struct ucc_geth_private *ugeth) |
| 1742 | { | 1740 | { |
| 1743 | #ifdef DEBUG | 1741 | #ifdef DEBUG |
