diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2016-08-18 18:30:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-19 20:15:36 -0400 |
commit | d9338023fb8e60aa09014034a993f8ddc86c65fa (patch) | |
tree | 0ddb59520c731a0940d9de4a92cffc90b2296d38 /drivers/net/dsa | |
parent | a85fad1436b0fd0fe9d7f1d23387e83e7cd21c0a (diff) |
net: dsa: bcm_sf2: Make it a real platform device driver
The Broadcom Starfighter 2 switch driver should be a proper platform
driver, now that the DSA code has been updated to allow that, register a
switch device, feed it with the proper configuration data coming from
Device Tree and register our switch device with DSA.
The bulk of the changes consist in moving what bcm_sf2_sw_setup() did
into the platform driver probe function.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 178 |
1 files changed, 118 insertions, 60 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index b2b838724a9b..fe1cc92f72a8 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c | |||
@@ -1571,23 +1571,84 @@ static int bcm_sf2_sw_vlan_dump(struct dsa_switch *ds, int port, | |||
1571 | 1571 | ||
1572 | static int bcm_sf2_sw_setup(struct dsa_switch *ds) | 1572 | static int bcm_sf2_sw_setup(struct dsa_switch *ds) |
1573 | { | 1573 | { |
1574 | const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME; | ||
1575 | struct bcm_sf2_priv *priv = ds_to_priv(ds); | 1574 | struct bcm_sf2_priv *priv = ds_to_priv(ds); |
1576 | struct device_node *dn; | ||
1577 | void __iomem **base; | ||
1578 | unsigned int port; | 1575 | unsigned int port; |
1576 | |||
1577 | /* Enable all valid ports and disable those unused */ | ||
1578 | for (port = 0; port < priv->hw_params.num_ports; port++) { | ||
1579 | /* IMP port receives special treatment */ | ||
1580 | if ((1 << port) & ds->enabled_port_mask) | ||
1581 | bcm_sf2_port_setup(ds, port, NULL); | ||
1582 | else if (dsa_is_cpu_port(ds, port)) | ||
1583 | bcm_sf2_imp_setup(ds, port); | ||
1584 | else | ||
1585 | bcm_sf2_port_disable(ds, port, NULL); | ||
1586 | } | ||
1587 | |||
1588 | bcm_sf2_sw_configure_vlan(ds); | ||
1589 | |||
1590 | return 0; | ||
1591 | } | ||
1592 | |||
1593 | static struct dsa_switch_driver bcm_sf2_switch_driver = { | ||
1594 | .tag_protocol = DSA_TAG_PROTO_BRCM, | ||
1595 | .probe = bcm_sf2_sw_drv_probe, | ||
1596 | .setup = bcm_sf2_sw_setup, | ||
1597 | .set_addr = bcm_sf2_sw_set_addr, | ||
1598 | .get_phy_flags = bcm_sf2_sw_get_phy_flags, | ||
1599 | .get_strings = bcm_sf2_sw_get_strings, | ||
1600 | .get_ethtool_stats = bcm_sf2_sw_get_ethtool_stats, | ||
1601 | .get_sset_count = bcm_sf2_sw_get_sset_count, | ||
1602 | .adjust_link = bcm_sf2_sw_adjust_link, | ||
1603 | .fixed_link_update = bcm_sf2_sw_fixed_link_update, | ||
1604 | .suspend = bcm_sf2_sw_suspend, | ||
1605 | .resume = bcm_sf2_sw_resume, | ||
1606 | .get_wol = bcm_sf2_sw_get_wol, | ||
1607 | .set_wol = bcm_sf2_sw_set_wol, | ||
1608 | .port_enable = bcm_sf2_port_setup, | ||
1609 | .port_disable = bcm_sf2_port_disable, | ||
1610 | .get_eee = bcm_sf2_sw_get_eee, | ||
1611 | .set_eee = bcm_sf2_sw_set_eee, | ||
1612 | .port_bridge_join = bcm_sf2_sw_br_join, | ||
1613 | .port_bridge_leave = bcm_sf2_sw_br_leave, | ||
1614 | .port_stp_state_set = bcm_sf2_sw_br_set_stp_state, | ||
1615 | .port_fdb_prepare = bcm_sf2_sw_fdb_prepare, | ||
1616 | .port_fdb_add = bcm_sf2_sw_fdb_add, | ||
1617 | .port_fdb_del = bcm_sf2_sw_fdb_del, | ||
1618 | .port_fdb_dump = bcm_sf2_sw_fdb_dump, | ||
1619 | .port_vlan_filtering = bcm_sf2_sw_vlan_filtering, | ||
1620 | .port_vlan_prepare = bcm_sf2_sw_vlan_prepare, | ||
1621 | .port_vlan_add = bcm_sf2_sw_vlan_add, | ||
1622 | .port_vlan_del = bcm_sf2_sw_vlan_del, | ||
1623 | .port_vlan_dump = bcm_sf2_sw_vlan_dump, | ||
1624 | }; | ||
1625 | |||
1626 | static int bcm_sf2_sw_probe(struct platform_device *pdev) | ||
1627 | { | ||
1628 | const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME; | ||
1629 | struct device_node *dn = pdev->dev.of_node; | ||
1630 | struct bcm_sf2_priv *priv; | ||
1631 | struct dsa_switch *ds; | ||
1632 | void __iomem **base; | ||
1579 | unsigned int i; | 1633 | unsigned int i; |
1580 | u32 reg, rev; | 1634 | u32 reg, rev; |
1581 | int ret; | 1635 | int ret; |
1582 | 1636 | ||
1637 | ds = devm_kzalloc(&pdev->dev, sizeof(*ds) + sizeof(*priv), GFP_KERNEL); | ||
1638 | if (!ds) | ||
1639 | return -ENOMEM; | ||
1640 | |||
1641 | priv = (struct bcm_sf2_priv *)(ds + 1); | ||
1642 | ds->priv = priv; | ||
1643 | ds->dev = &pdev->dev; | ||
1644 | ds->drv = &bcm_sf2_switch_driver; | ||
1645 | |||
1646 | dev_set_drvdata(&pdev->dev, ds); | ||
1647 | |||
1583 | spin_lock_init(&priv->indir_lock); | 1648 | spin_lock_init(&priv->indir_lock); |
1584 | mutex_init(&priv->stats_mutex); | 1649 | mutex_init(&priv->stats_mutex); |
1585 | 1650 | ||
1586 | /* All the interesting properties are at the parent device_node | 1651 | bcm_sf2_identify_ports(priv, dn->child); |
1587 | * level | ||
1588 | */ | ||
1589 | dn = ds->cd->of_node->parent; | ||
1590 | bcm_sf2_identify_ports(priv, ds->cd->of_node); | ||
1591 | 1652 | ||
1592 | priv->irq0 = irq_of_parse_and_map(dn, 0); | 1653 | priv->irq0 = irq_of_parse_and_map(dn, 0); |
1593 | priv->irq1 = irq_of_parse_and_map(dn, 1); | 1654 | priv->irq1 = irq_of_parse_and_map(dn, 1); |
@@ -1649,19 +1710,6 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) | |||
1649 | &priv->hw_params.num_gphy)) | 1710 | &priv->hw_params.num_gphy)) |
1650 | priv->hw_params.num_gphy = 1; | 1711 | priv->hw_params.num_gphy = 1; |
1651 | 1712 | ||
1652 | /* Enable all valid ports and disable those unused */ | ||
1653 | for (port = 0; port < priv->hw_params.num_ports; port++) { | ||
1654 | /* IMP port receives special treatment */ | ||
1655 | if ((1 << port) & ds->enabled_port_mask) | ||
1656 | bcm_sf2_port_setup(ds, port, NULL); | ||
1657 | else if (dsa_is_cpu_port(ds, port)) | ||
1658 | bcm_sf2_imp_setup(ds, port); | ||
1659 | else | ||
1660 | bcm_sf2_port_disable(ds, port, NULL); | ||
1661 | } | ||
1662 | |||
1663 | bcm_sf2_sw_configure_vlan(ds); | ||
1664 | |||
1665 | rev = reg_readl(priv, REG_SWITCH_REVISION); | 1713 | rev = reg_readl(priv, REG_SWITCH_REVISION); |
1666 | priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) & | 1714 | priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) & |
1667 | SWITCH_TOP_REV_MASK; | 1715 | SWITCH_TOP_REV_MASK; |
@@ -1670,6 +1718,10 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) | |||
1670 | rev = reg_readl(priv, REG_PHY_REVISION); | 1718 | rev = reg_readl(priv, REG_PHY_REVISION); |
1671 | priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK; | 1719 | priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK; |
1672 | 1720 | ||
1721 | ret = dsa_register_switch(ds, dn); | ||
1722 | if (ret) | ||
1723 | goto out_free_irq1; | ||
1724 | |||
1673 | pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: %d, %d\n", | 1725 | pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: %d, %d\n", |
1674 | priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff, | 1726 | priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff, |
1675 | priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff, | 1727 | priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff, |
@@ -1677,6 +1729,8 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) | |||
1677 | 1729 | ||
1678 | return 0; | 1730 | return 0; |
1679 | 1731 | ||
1732 | out_free_irq1: | ||
1733 | free_irq(priv->irq1, priv); | ||
1680 | out_free_irq0: | 1734 | out_free_irq0: |
1681 | free_irq(priv->irq0, priv); | 1735 | free_irq(priv->irq0, priv); |
1682 | out_mdio: | 1736 | out_mdio: |
@@ -1691,52 +1745,56 @@ out_unmap: | |||
1691 | return ret; | 1745 | return ret; |
1692 | } | 1746 | } |
1693 | 1747 | ||
1694 | static struct dsa_switch_driver bcm_sf2_switch_driver = { | 1748 | static int bcm_sf2_sw_remove(struct platform_device *pdev) |
1695 | .tag_protocol = DSA_TAG_PROTO_BRCM, | ||
1696 | .probe = bcm_sf2_sw_drv_probe, | ||
1697 | .setup = bcm_sf2_sw_setup, | ||
1698 | .set_addr = bcm_sf2_sw_set_addr, | ||
1699 | .get_phy_flags = bcm_sf2_sw_get_phy_flags, | ||
1700 | .get_strings = bcm_sf2_sw_get_strings, | ||
1701 | .get_ethtool_stats = bcm_sf2_sw_get_ethtool_stats, | ||
1702 | .get_sset_count = bcm_sf2_sw_get_sset_count, | ||
1703 | .adjust_link = bcm_sf2_sw_adjust_link, | ||
1704 | .fixed_link_update = bcm_sf2_sw_fixed_link_update, | ||
1705 | .suspend = bcm_sf2_sw_suspend, | ||
1706 | .resume = bcm_sf2_sw_resume, | ||
1707 | .get_wol = bcm_sf2_sw_get_wol, | ||
1708 | .set_wol = bcm_sf2_sw_set_wol, | ||
1709 | .port_enable = bcm_sf2_port_setup, | ||
1710 | .port_disable = bcm_sf2_port_disable, | ||
1711 | .get_eee = bcm_sf2_sw_get_eee, | ||
1712 | .set_eee = bcm_sf2_sw_set_eee, | ||
1713 | .port_bridge_join = bcm_sf2_sw_br_join, | ||
1714 | .port_bridge_leave = bcm_sf2_sw_br_leave, | ||
1715 | .port_stp_state_set = bcm_sf2_sw_br_set_stp_state, | ||
1716 | .port_fdb_prepare = bcm_sf2_sw_fdb_prepare, | ||
1717 | .port_fdb_add = bcm_sf2_sw_fdb_add, | ||
1718 | .port_fdb_del = bcm_sf2_sw_fdb_del, | ||
1719 | .port_fdb_dump = bcm_sf2_sw_fdb_dump, | ||
1720 | .port_vlan_filtering = bcm_sf2_sw_vlan_filtering, | ||
1721 | .port_vlan_prepare = bcm_sf2_sw_vlan_prepare, | ||
1722 | .port_vlan_add = bcm_sf2_sw_vlan_add, | ||
1723 | .port_vlan_del = bcm_sf2_sw_vlan_del, | ||
1724 | .port_vlan_dump = bcm_sf2_sw_vlan_dump, | ||
1725 | }; | ||
1726 | |||
1727 | static int __init bcm_sf2_init(void) | ||
1728 | { | 1749 | { |
1729 | register_switch_driver(&bcm_sf2_switch_driver); | 1750 | struct dsa_switch *ds = platform_get_drvdata(pdev); |
1751 | struct bcm_sf2_priv *priv = ds_to_priv(ds); | ||
1752 | |||
1753 | /* Disable all ports and interrupts */ | ||
1754 | priv->wol_ports_mask = 0; | ||
1755 | bcm_sf2_sw_suspend(ds); | ||
1756 | dsa_unregister_switch(ds); | ||
1757 | bcm_sf2_mdio_unregister(priv); | ||
1730 | 1758 | ||
1731 | return 0; | 1759 | return 0; |
1732 | } | 1760 | } |
1733 | module_init(bcm_sf2_init); | ||
1734 | 1761 | ||
1735 | static void __exit bcm_sf2_exit(void) | 1762 | #ifdef CONFIG_PM_SLEEP |
1763 | static int bcm_sf2_suspend(struct device *dev) | ||
1736 | { | 1764 | { |
1737 | unregister_switch_driver(&bcm_sf2_switch_driver); | 1765 | struct platform_device *pdev = to_platform_device(dev); |
1766 | struct dsa_switch *ds = platform_get_drvdata(pdev); | ||
1767 | |||
1768 | return dsa_switch_suspend(ds); | ||
1738 | } | 1769 | } |
1739 | module_exit(bcm_sf2_exit); | 1770 | |
1771 | static int bcm_sf2_resume(struct device *dev) | ||
1772 | { | ||
1773 | struct platform_device *pdev = to_platform_device(dev); | ||
1774 | struct dsa_switch *ds = platform_get_drvdata(pdev); | ||
1775 | |||
1776 | return dsa_switch_resume(ds); | ||
1777 | } | ||
1778 | #endif /* CONFIG_PM_SLEEP */ | ||
1779 | |||
1780 | static SIMPLE_DEV_PM_OPS(bcm_sf2_pm_ops, | ||
1781 | bcm_sf2_suspend, bcm_sf2_resume); | ||
1782 | |||
1783 | static const struct of_device_id bcm_sf2_of_match[] = { | ||
1784 | { .compatible = "brcm,bcm7445-switch-v4.0" }, | ||
1785 | { /* sentinel */ }, | ||
1786 | }; | ||
1787 | |||
1788 | static struct platform_driver bcm_sf2_driver = { | ||
1789 | .probe = bcm_sf2_sw_probe, | ||
1790 | .remove = bcm_sf2_sw_remove, | ||
1791 | .driver = { | ||
1792 | .name = "brcm-sf2", | ||
1793 | .of_match_table = bcm_sf2_of_match, | ||
1794 | .pm = &bcm_sf2_pm_ops, | ||
1795 | }, | ||
1796 | }; | ||
1797 | module_platform_driver(bcm_sf2_driver); | ||
1740 | 1798 | ||
1741 | MODULE_AUTHOR("Broadcom Corporation"); | 1799 | MODULE_AUTHOR("Broadcom Corporation"); |
1742 | MODULE_DESCRIPTION("Driver for Broadcom Starfighter 2 ethernet switch chip"); | 1800 | MODULE_DESCRIPTION("Driver for Broadcom Starfighter 2 ethernet switch chip"); |