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 |