aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFaiz Abbas <faiz_abbas@ti.com>2018-01-16 06:37:13 -0500
committerMarc Kleine-Budde <mkl@pengutronix.de>2018-01-16 09:11:34 -0500
commitcdf8259d65739a04871513d4d17bb342ba1d4a46 (patch)
treea875f7ef76231766a17ead391c11c858a02397cf
parent63dffc1c699d2b808e7d192ffd67d443be136a56 (diff)
can: m_can: Add PM Support
Add support for CONFIG_PM which is the new way to handle managing clocks. Move the clock management to pm_runtime_resume() and pm_runtime_suspend() callbacks for the driver. CONFIG_PM is required by OMAP based devices to handle clock management. Therefore, this allows future Texas Instruments SoCs that have the MCAN IP to work with this driver. Signed-off-by: Faiz Abbas <faiz_abbas@ti.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/net/can/m_can/m_can.c100
1 files changed, 62 insertions, 38 deletions
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index f882cd5df4fa..2f0e56d4c332 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -23,6 +23,7 @@
23#include <linux/of.h> 23#include <linux/of.h>
24#include <linux/of_device.h> 24#include <linux/of_device.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/pm_runtime.h>
26#include <linux/iopoll.h> 27#include <linux/iopoll.h>
27#include <linux/can/dev.h> 28#include <linux/can/dev.h>
28 29
@@ -631,21 +632,16 @@ static int m_can_clk_start(struct m_can_priv *priv)
631{ 632{
632 int err; 633 int err;
633 634
634 err = clk_prepare_enable(priv->hclk); 635 err = pm_runtime_get_sync(priv->device);
635 if (err) 636 if (err)
636 return err; 637 pm_runtime_put_noidle(priv->device);
637
638 err = clk_prepare_enable(priv->cclk);
639 if (err)
640 clk_disable_unprepare(priv->hclk);
641 638
642 return err; 639 return err;
643} 640}
644 641
645static void m_can_clk_stop(struct m_can_priv *priv) 642static void m_can_clk_stop(struct m_can_priv *priv)
646{ 643{
647 clk_disable_unprepare(priv->cclk); 644 pm_runtime_put_sync(priv->device);
648 clk_disable_unprepare(priv->hclk);
649} 645}
650 646
651static int m_can_get_berr_counter(const struct net_device *dev, 647static int m_can_get_berr_counter(const struct net_device *dev,
@@ -1594,37 +1590,26 @@ static int m_can_plat_probe(struct platform_device *pdev)
1594 goto failed_ret; 1590 goto failed_ret;
1595 } 1591 }
1596 1592
1597 /* Enable clocks. Necessary to read Core Release in order to determine
1598 * M_CAN version
1599 */
1600 ret = clk_prepare_enable(hclk);
1601 if (ret)
1602 goto disable_hclk_ret;
1603
1604 ret = clk_prepare_enable(cclk);
1605 if (ret)
1606 goto disable_cclk_ret;
1607
1608 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can"); 1593 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can");
1609 addr = devm_ioremap_resource(&pdev->dev, res); 1594 addr = devm_ioremap_resource(&pdev->dev, res);
1610 irq = platform_get_irq_byname(pdev, "int0"); 1595 irq = platform_get_irq_byname(pdev, "int0");
1611 1596
1612 if (IS_ERR(addr) || irq < 0) { 1597 if (IS_ERR(addr) || irq < 0) {
1613 ret = -EINVAL; 1598 ret = -EINVAL;
1614 goto disable_cclk_ret; 1599 goto failed_ret;
1615 } 1600 }
1616 1601
1617 /* message ram could be shared */ 1602 /* message ram could be shared */
1618 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); 1603 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram");
1619 if (!res) { 1604 if (!res) {
1620 ret = -ENODEV; 1605 ret = -ENODEV;
1621 goto disable_cclk_ret; 1606 goto failed_ret;
1622 } 1607 }
1623 1608
1624 mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 1609 mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
1625 if (!mram_addr) { 1610 if (!mram_addr) {
1626 ret = -ENOMEM; 1611 ret = -ENOMEM;
1627 goto disable_cclk_ret; 1612 goto failed_ret;
1628 } 1613 }
1629 1614
1630 /* get message ram configuration */ 1615 /* get message ram configuration */
@@ -1633,7 +1618,7 @@ static int m_can_plat_probe(struct platform_device *pdev)
1633 sizeof(mram_config_vals) / 4); 1618 sizeof(mram_config_vals) / 4);
1634 if (ret) { 1619 if (ret) {
1635 dev_err(&pdev->dev, "Could not get Message RAM configuration."); 1620 dev_err(&pdev->dev, "Could not get Message RAM configuration.");
1636 goto disable_cclk_ret; 1621 goto failed_ret;
1637 } 1622 }
1638 1623
1639 /* Get TX FIFO size 1624 /* Get TX FIFO size
@@ -1645,13 +1630,9 @@ static int m_can_plat_probe(struct platform_device *pdev)
1645 dev = alloc_candev(sizeof(*priv), tx_fifo_size); 1630 dev = alloc_candev(sizeof(*priv), tx_fifo_size);
1646 if (!dev) { 1631 if (!dev) {
1647 ret = -ENOMEM; 1632 ret = -ENOMEM;
1648 goto disable_cclk_ret; 1633 goto failed_ret;
1649 } 1634 }
1650 1635
1651 ret = m_can_dev_setup(pdev, dev, addr);
1652 if (ret)
1653 goto failed_free_dev;
1654
1655 priv = netdev_priv(dev); 1636 priv = netdev_priv(dev);
1656 dev->irq = irq; 1637 dev->irq = irq;
1657 priv->device = &pdev->dev; 1638 priv->device = &pdev->dev;
@@ -1665,11 +1646,23 @@ static int m_can_plat_probe(struct platform_device *pdev)
1665 platform_set_drvdata(pdev, dev); 1646 platform_set_drvdata(pdev, dev);
1666 SET_NETDEV_DEV(dev, &pdev->dev); 1647 SET_NETDEV_DEV(dev, &pdev->dev);
1667 1648
1649 /* Enable clocks. Necessary to read Core Release in order to determine
1650 * M_CAN version
1651 */
1652 pm_runtime_enable(&pdev->dev);
1653 ret = m_can_clk_start(priv);
1654 if (ret)
1655 goto pm_runtime_fail;
1656
1657 ret = m_can_dev_setup(pdev, dev, addr);
1658 if (ret)
1659 goto clk_disable;
1660
1668 ret = register_m_can_dev(dev); 1661 ret = register_m_can_dev(dev);
1669 if (ret) { 1662 if (ret) {
1670 dev_err(&pdev->dev, "registering %s failed (err=%d)\n", 1663 dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
1671 KBUILD_MODNAME, ret); 1664 KBUILD_MODNAME, ret);
1672 goto failed_free_dev; 1665 goto clk_disable;
1673 } 1666 }
1674 1667
1675 devm_can_led_init(dev); 1668 devm_can_led_init(dev);
@@ -1680,15 +1673,13 @@ static int m_can_plat_probe(struct platform_device *pdev)
1680 /* Probe finished 1673 /* Probe finished
1681 * Stop clocks. They will be reactivated once the M_CAN device is opened 1674 * Stop clocks. They will be reactivated once the M_CAN device is opened
1682 */ 1675 */
1683 1676clk_disable:
1684 goto disable_cclk_ret; 1677 m_can_clk_stop(priv);
1685 1678pm_runtime_fail:
1686failed_free_dev: 1679 if (ret) {
1687 free_candev(dev); 1680 pm_runtime_disable(&pdev->dev);
1688disable_cclk_ret: 1681 free_candev(dev);
1689 clk_disable_unprepare(cclk); 1682 }
1690disable_hclk_ret:
1691 clk_disable_unprepare(hclk);
1692failed_ret: 1683failed_ret:
1693 return ret; 1684 return ret;
1694} 1685}
@@ -1746,6 +1737,9 @@ static int m_can_plat_remove(struct platform_device *pdev)
1746 struct net_device *dev = platform_get_drvdata(pdev); 1737 struct net_device *dev = platform_get_drvdata(pdev);
1747 1738
1748 unregister_m_can_dev(dev); 1739 unregister_m_can_dev(dev);
1740
1741 pm_runtime_disable(&pdev->dev);
1742
1749 platform_set_drvdata(pdev, NULL); 1743 platform_set_drvdata(pdev, NULL);
1750 1744
1751 free_candev(dev); 1745 free_candev(dev);
@@ -1753,7 +1747,37 @@ static int m_can_plat_remove(struct platform_device *pdev)
1753 return 0; 1747 return 0;
1754} 1748}
1755 1749
1750static int m_can_runtime_suspend(struct device *dev)
1751{
1752 struct net_device *ndev = dev_get_drvdata(dev);
1753 struct m_can_priv *priv = netdev_priv(ndev);
1754
1755 clk_disable_unprepare(priv->cclk);
1756 clk_disable_unprepare(priv->hclk);
1757
1758 return 0;
1759}
1760
1761static int m_can_runtime_resume(struct device *dev)
1762{
1763 struct net_device *ndev = dev_get_drvdata(dev);
1764 struct m_can_priv *priv = netdev_priv(ndev);
1765 int err;
1766
1767 err = clk_prepare_enable(priv->hclk);
1768 if (err)
1769 return err;
1770
1771 err = clk_prepare_enable(priv->cclk);
1772 if (err)
1773 clk_disable_unprepare(priv->hclk);
1774
1775 return err;
1776}
1777
1756static const struct dev_pm_ops m_can_pmops = { 1778static const struct dev_pm_ops m_can_pmops = {
1779 SET_RUNTIME_PM_OPS(m_can_runtime_suspend,
1780 m_can_runtime_resume, NULL)
1757 SET_SYSTEM_SLEEP_PM_OPS(m_can_suspend, m_can_resume) 1781 SET_SYSTEM_SLEEP_PM_OPS(m_can_suspend, m_can_resume)
1758}; 1782};
1759 1783