diff options
author | Kedareswara rao Appana <appana.durga.rao@xilinx.com> | 2015-10-26 02:11:54 -0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2015-11-23 03:51:34 -0500 |
commit | 4716620d1b6291ce45522d1346c086f76b995d1c (patch) | |
tree | 8946259f6b06769d0f1987ab91c92cd16f74dc3e /drivers/net/can | |
parent | 3f8c0f7efb4fcac11f31afa97584d06118c614bb (diff) |
can: xilinx: Convert to runtime_pm
Instead of enabling/disabling clocks at several locations in the driver,
Use the runtime_pm framework. This consolidates the actions for runtime PM
In the appropriate callbacks and makes the driver more readable and mantainable.
Signed-off-by: Kedareswara rao Appana <appanad@xilinx.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/xilinx_can.c | 176 |
1 files changed, 101 insertions, 75 deletions
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index fc55e8e0351d..ad3806542d33 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/can/dev.h> | 32 | #include <linux/can/dev.h> |
33 | #include <linux/can/error.h> | 33 | #include <linux/can/error.h> |
34 | #include <linux/can/led.h> | 34 | #include <linux/can/led.h> |
35 | #include <linux/pm_runtime.h> | ||
35 | 36 | ||
36 | #define DRIVER_NAME "xilinx_can" | 37 | #define DRIVER_NAME "xilinx_can" |
37 | 38 | ||
@@ -138,7 +139,7 @@ struct xcan_priv { | |||
138 | u32 (*read_reg)(const struct xcan_priv *priv, enum xcan_reg reg); | 139 | u32 (*read_reg)(const struct xcan_priv *priv, enum xcan_reg reg); |
139 | void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, | 140 | void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, |
140 | u32 val); | 141 | u32 val); |
141 | struct net_device *dev; | 142 | struct device *dev; |
142 | void __iomem *reg_base; | 143 | void __iomem *reg_base; |
143 | unsigned long irq_flags; | 144 | unsigned long irq_flags; |
144 | struct clk *bus_clk; | 145 | struct clk *bus_clk; |
@@ -843,6 +844,13 @@ static int xcan_open(struct net_device *ndev) | |||
843 | struct xcan_priv *priv = netdev_priv(ndev); | 844 | struct xcan_priv *priv = netdev_priv(ndev); |
844 | int ret; | 845 | int ret; |
845 | 846 | ||
847 | ret = pm_runtime_get_sync(priv->dev); | ||
848 | if (ret < 0) { | ||
849 | netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", | ||
850 | __func__, ret); | ||
851 | return ret; | ||
852 | } | ||
853 | |||
846 | ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, | 854 | ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, |
847 | ndev->name, ndev); | 855 | ndev->name, ndev); |
848 | if (ret < 0) { | 856 | if (ret < 0) { |
@@ -850,29 +858,17 @@ static int xcan_open(struct net_device *ndev) | |||
850 | goto err; | 858 | goto err; |
851 | } | 859 | } |
852 | 860 | ||
853 | ret = clk_prepare_enable(priv->can_clk); | ||
854 | if (ret) { | ||
855 | netdev_err(ndev, "unable to enable device clock\n"); | ||
856 | goto err_irq; | ||
857 | } | ||
858 | |||
859 | ret = clk_prepare_enable(priv->bus_clk); | ||
860 | if (ret) { | ||
861 | netdev_err(ndev, "unable to enable bus clock\n"); | ||
862 | goto err_can_clk; | ||
863 | } | ||
864 | |||
865 | /* Set chip into reset mode */ | 861 | /* Set chip into reset mode */ |
866 | ret = set_reset_mode(ndev); | 862 | ret = set_reset_mode(ndev); |
867 | if (ret < 0) { | 863 | if (ret < 0) { |
868 | netdev_err(ndev, "mode resetting failed!\n"); | 864 | netdev_err(ndev, "mode resetting failed!\n"); |
869 | goto err_bus_clk; | 865 | goto err_irq; |
870 | } | 866 | } |
871 | 867 | ||
872 | /* Common open */ | 868 | /* Common open */ |
873 | ret = open_candev(ndev); | 869 | ret = open_candev(ndev); |
874 | if (ret) | 870 | if (ret) |
875 | goto err_bus_clk; | 871 | goto err_irq; |
876 | 872 | ||
877 | ret = xcan_chip_start(ndev); | 873 | ret = xcan_chip_start(ndev); |
878 | if (ret < 0) { | 874 | if (ret < 0) { |
@@ -888,13 +884,11 @@ static int xcan_open(struct net_device *ndev) | |||
888 | 884 | ||
889 | err_candev: | 885 | err_candev: |
890 | close_candev(ndev); | 886 | close_candev(ndev); |
891 | err_bus_clk: | ||
892 | clk_disable_unprepare(priv->bus_clk); | ||
893 | err_can_clk: | ||
894 | clk_disable_unprepare(priv->can_clk); | ||
895 | err_irq: | 887 | err_irq: |
896 | free_irq(ndev->irq, ndev); | 888 | free_irq(ndev->irq, ndev); |
897 | err: | 889 | err: |
890 | pm_runtime_put(priv->dev); | ||
891 | |||
898 | return ret; | 892 | return ret; |
899 | } | 893 | } |
900 | 894 | ||
@@ -911,12 +905,11 @@ static int xcan_close(struct net_device *ndev) | |||
911 | netif_stop_queue(ndev); | 905 | netif_stop_queue(ndev); |
912 | napi_disable(&priv->napi); | 906 | napi_disable(&priv->napi); |
913 | xcan_chip_stop(ndev); | 907 | xcan_chip_stop(ndev); |
914 | clk_disable_unprepare(priv->bus_clk); | ||
915 | clk_disable_unprepare(priv->can_clk); | ||
916 | free_irq(ndev->irq, ndev); | 908 | free_irq(ndev->irq, ndev); |
917 | close_candev(ndev); | 909 | close_candev(ndev); |
918 | 910 | ||
919 | can_led_event(ndev, CAN_LED_EVENT_STOP); | 911 | can_led_event(ndev, CAN_LED_EVENT_STOP); |
912 | pm_runtime_put(priv->dev); | ||
920 | 913 | ||
921 | return 0; | 914 | return 0; |
922 | } | 915 | } |
@@ -935,27 +928,20 @@ static int xcan_get_berr_counter(const struct net_device *ndev, | |||
935 | struct xcan_priv *priv = netdev_priv(ndev); | 928 | struct xcan_priv *priv = netdev_priv(ndev); |
936 | int ret; | 929 | int ret; |
937 | 930 | ||
938 | ret = clk_prepare_enable(priv->can_clk); | 931 | ret = pm_runtime_get_sync(priv->dev); |
939 | if (ret) | 932 | if (ret < 0) { |
940 | goto err; | 933 | netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", |
941 | 934 | __func__, ret); | |
942 | ret = clk_prepare_enable(priv->bus_clk); | 935 | return ret; |
943 | if (ret) | 936 | } |
944 | goto err_clk; | ||
945 | 937 | ||
946 | bec->txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK; | 938 | bec->txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK; |
947 | bec->rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) & | 939 | bec->rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) & |
948 | XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT); | 940 | XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT); |
949 | 941 | ||
950 | clk_disable_unprepare(priv->bus_clk); | 942 | pm_runtime_put(priv->dev); |
951 | clk_disable_unprepare(priv->can_clk); | ||
952 | 943 | ||
953 | return 0; | 944 | return 0; |
954 | |||
955 | err_clk: | ||
956 | clk_disable_unprepare(priv->can_clk); | ||
957 | err: | ||
958 | return ret; | ||
959 | } | 945 | } |
960 | 946 | ||
961 | 947 | ||
@@ -968,15 +954,45 @@ static const struct net_device_ops xcan_netdev_ops = { | |||
968 | 954 | ||
969 | /** | 955 | /** |
970 | * xcan_suspend - Suspend method for the driver | 956 | * xcan_suspend - Suspend method for the driver |
971 | * @dev: Address of the platform_device structure | 957 | * @dev: Address of the device structure |
972 | * | 958 | * |
973 | * Put the driver into low power mode. | 959 | * Put the driver into low power mode. |
974 | * Return: 0 always | 960 | * Return: 0 on success and failure value on error |
975 | */ | 961 | */ |
976 | static int __maybe_unused xcan_suspend(struct device *dev) | 962 | static int __maybe_unused xcan_suspend(struct device *dev) |
977 | { | 963 | { |
978 | struct platform_device *pdev = dev_get_drvdata(dev); | 964 | if (!device_may_wakeup(dev)) |
979 | struct net_device *ndev = platform_get_drvdata(pdev); | 965 | return pm_runtime_force_suspend(dev); |
966 | |||
967 | return 0; | ||
968 | } | ||
969 | |||
970 | /** | ||
971 | * xcan_resume - Resume from suspend | ||
972 | * @dev: Address of the device structure | ||
973 | * | ||
974 | * Resume operation after suspend. | ||
975 | * Return: 0 on success and failure value on error | ||
976 | */ | ||
977 | static int __maybe_unused xcan_resume(struct device *dev) | ||
978 | { | ||
979 | if (!device_may_wakeup(dev)) | ||
980 | return pm_runtime_force_resume(dev); | ||
981 | |||
982 | return 0; | ||
983 | |||
984 | } | ||
985 | |||
986 | /** | ||
987 | * xcan_runtime_suspend - Runtime suspend method for the driver | ||
988 | * @dev: Address of the device structure | ||
989 | * | ||
990 | * Put the driver into low power mode. | ||
991 | * Return: 0 always | ||
992 | */ | ||
993 | static int __maybe_unused xcan_runtime_suspend(struct device *dev) | ||
994 | { | ||
995 | struct net_device *ndev = dev_get_drvdata(dev); | ||
980 | struct xcan_priv *priv = netdev_priv(ndev); | 996 | struct xcan_priv *priv = netdev_priv(ndev); |
981 | 997 | ||
982 | if (netif_running(ndev)) { | 998 | if (netif_running(ndev)) { |
@@ -987,43 +1003,55 @@ static int __maybe_unused xcan_suspend(struct device *dev) | |||
987 | priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK); | 1003 | priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK); |
988 | priv->can.state = CAN_STATE_SLEEPING; | 1004 | priv->can.state = CAN_STATE_SLEEPING; |
989 | 1005 | ||
990 | clk_disable(priv->bus_clk); | 1006 | clk_disable_unprepare(priv->bus_clk); |
991 | clk_disable(priv->can_clk); | 1007 | clk_disable_unprepare(priv->can_clk); |
992 | 1008 | ||
993 | return 0; | 1009 | return 0; |
994 | } | 1010 | } |
995 | 1011 | ||
996 | /** | 1012 | /** |
997 | * xcan_resume - Resume from suspend | 1013 | * xcan_runtime_resume - Runtime resume from suspend |
998 | * @dev: Address of the platformdevice structure | 1014 | * @dev: Address of the device structure |
999 | * | 1015 | * |
1000 | * Resume operation after suspend. | 1016 | * Resume operation after suspend. |
1001 | * Return: 0 on success and failure value on error | 1017 | * Return: 0 on success and failure value on error |
1002 | */ | 1018 | */ |
1003 | static int __maybe_unused xcan_resume(struct device *dev) | 1019 | static int __maybe_unused xcan_runtime_resume(struct device *dev) |
1004 | { | 1020 | { |
1005 | struct platform_device *pdev = dev_get_drvdata(dev); | 1021 | struct net_device *ndev = dev_get_drvdata(dev); |
1006 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
1007 | struct xcan_priv *priv = netdev_priv(ndev); | 1022 | struct xcan_priv *priv = netdev_priv(ndev); |
1008 | int ret; | 1023 | int ret; |
1024 | u32 isr, status; | ||
1009 | 1025 | ||
1010 | ret = clk_enable(priv->bus_clk); | 1026 | ret = clk_prepare_enable(priv->bus_clk); |
1011 | if (ret) { | 1027 | if (ret) { |
1012 | dev_err(dev, "Cannot enable clock.\n"); | 1028 | dev_err(dev, "Cannot enable clock.\n"); |
1013 | return ret; | 1029 | return ret; |
1014 | } | 1030 | } |
1015 | ret = clk_enable(priv->can_clk); | 1031 | ret = clk_prepare_enable(priv->can_clk); |
1016 | if (ret) { | 1032 | if (ret) { |
1017 | dev_err(dev, "Cannot enable clock.\n"); | 1033 | dev_err(dev, "Cannot enable clock.\n"); |
1018 | clk_disable_unprepare(priv->bus_clk); | 1034 | clk_disable_unprepare(priv->bus_clk); |
1019 | return ret; | 1035 | return ret; |
1020 | } | 1036 | } |
1021 | 1037 | ||
1022 | priv->write_reg(priv, XCAN_MSR_OFFSET, 0); | 1038 | priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); |
1023 | priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK); | 1039 | isr = priv->read_reg(priv, XCAN_ISR_OFFSET); |
1024 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | 1040 | status = priv->read_reg(priv, XCAN_SR_OFFSET); |
1025 | 1041 | ||
1026 | if (netif_running(ndev)) { | 1042 | if (netif_running(ndev)) { |
1043 | if (isr & XCAN_IXR_BSOFF_MASK) { | ||
1044 | priv->can.state = CAN_STATE_BUS_OFF; | ||
1045 | priv->write_reg(priv, XCAN_SRR_OFFSET, | ||
1046 | XCAN_SRR_RESET_MASK); | ||
1047 | } else if ((status & XCAN_SR_ESTAT_MASK) == | ||
1048 | XCAN_SR_ESTAT_MASK) { | ||
1049 | priv->can.state = CAN_STATE_ERROR_PASSIVE; | ||
1050 | } else if (status & XCAN_SR_ERRWRN_MASK) { | ||
1051 | priv->can.state = CAN_STATE_ERROR_WARNING; | ||
1052 | } else { | ||
1053 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
1054 | } | ||
1027 | netif_device_attach(ndev); | 1055 | netif_device_attach(ndev); |
1028 | netif_start_queue(ndev); | 1056 | netif_start_queue(ndev); |
1029 | } | 1057 | } |
@@ -1031,7 +1059,10 @@ static int __maybe_unused xcan_resume(struct device *dev) | |||
1031 | return 0; | 1059 | return 0; |
1032 | } | 1060 | } |
1033 | 1061 | ||
1034 | static SIMPLE_DEV_PM_OPS(xcan_dev_pm_ops, xcan_suspend, xcan_resume); | 1062 | static const struct dev_pm_ops xcan_dev_pm_ops = { |
1063 | SET_SYSTEM_SLEEP_PM_OPS(xcan_suspend, xcan_resume) | ||
1064 | SET_RUNTIME_PM_OPS(xcan_runtime_suspend, xcan_runtime_resume, NULL) | ||
1065 | }; | ||
1035 | 1066 | ||
1036 | /** | 1067 | /** |
1037 | * xcan_probe - Platform registration call | 1068 | * xcan_probe - Platform registration call |
@@ -1072,7 +1103,7 @@ static int xcan_probe(struct platform_device *pdev) | |||
1072 | return -ENOMEM; | 1103 | return -ENOMEM; |
1073 | 1104 | ||
1074 | priv = netdev_priv(ndev); | 1105 | priv = netdev_priv(ndev); |
1075 | priv->dev = ndev; | 1106 | priv->dev = &pdev->dev; |
1076 | priv->can.bittiming_const = &xcan_bittiming_const; | 1107 | priv->can.bittiming_const = &xcan_bittiming_const; |
1077 | priv->can.do_set_mode = xcan_do_set_mode; | 1108 | priv->can.do_set_mode = xcan_do_set_mode; |
1078 | priv->can.do_get_berr_counter = xcan_get_berr_counter; | 1109 | priv->can.do_get_berr_counter = xcan_get_berr_counter; |
@@ -1114,21 +1145,17 @@ static int xcan_probe(struct platform_device *pdev) | |||
1114 | } | 1145 | } |
1115 | } | 1146 | } |
1116 | 1147 | ||
1117 | ret = clk_prepare_enable(priv->can_clk); | ||
1118 | if (ret) { | ||
1119 | dev_err(&pdev->dev, "unable to enable device clock\n"); | ||
1120 | goto err_free; | ||
1121 | } | ||
1122 | |||
1123 | ret = clk_prepare_enable(priv->bus_clk); | ||
1124 | if (ret) { | ||
1125 | dev_err(&pdev->dev, "unable to enable bus clock\n"); | ||
1126 | goto err_unprepare_disable_dev; | ||
1127 | } | ||
1128 | |||
1129 | priv->write_reg = xcan_write_reg_le; | 1148 | priv->write_reg = xcan_write_reg_le; |
1130 | priv->read_reg = xcan_read_reg_le; | 1149 | priv->read_reg = xcan_read_reg_le; |
1131 | 1150 | ||
1151 | pm_runtime_enable(&pdev->dev); | ||
1152 | ret = pm_runtime_get_sync(&pdev->dev); | ||
1153 | if (ret < 0) { | ||
1154 | netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", | ||
1155 | __func__, ret); | ||
1156 | goto err_pmdisable; | ||
1157 | } | ||
1158 | |||
1132 | if (priv->read_reg(priv, XCAN_SR_OFFSET) != XCAN_SR_CONFIG_MASK) { | 1159 | if (priv->read_reg(priv, XCAN_SR_OFFSET) != XCAN_SR_CONFIG_MASK) { |
1133 | priv->write_reg = xcan_write_reg_be; | 1160 | priv->write_reg = xcan_write_reg_be; |
1134 | priv->read_reg = xcan_read_reg_be; | 1161 | priv->read_reg = xcan_read_reg_be; |
@@ -1141,22 +1168,23 @@ static int xcan_probe(struct platform_device *pdev) | |||
1141 | ret = register_candev(ndev); | 1168 | ret = register_candev(ndev); |
1142 | if (ret) { | 1169 | if (ret) { |
1143 | dev_err(&pdev->dev, "fail to register failed (err=%d)\n", ret); | 1170 | dev_err(&pdev->dev, "fail to register failed (err=%d)\n", ret); |
1144 | goto err_unprepare_disable_busclk; | 1171 | goto err_disableclks; |
1145 | } | 1172 | } |
1146 | 1173 | ||
1147 | devm_can_led_init(ndev); | 1174 | devm_can_led_init(ndev); |
1148 | clk_disable_unprepare(priv->bus_clk); | 1175 | |
1149 | clk_disable_unprepare(priv->can_clk); | 1176 | pm_runtime_put(&pdev->dev); |
1177 | |||
1150 | netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n", | 1178 | netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n", |
1151 | priv->reg_base, ndev->irq, priv->can.clock.freq, | 1179 | priv->reg_base, ndev->irq, priv->can.clock.freq, |
1152 | priv->tx_max); | 1180 | priv->tx_max); |
1153 | 1181 | ||
1154 | return 0; | 1182 | return 0; |
1155 | 1183 | ||
1156 | err_unprepare_disable_busclk: | 1184 | err_disableclks: |
1157 | clk_disable_unprepare(priv->bus_clk); | 1185 | pm_runtime_put(priv->dev); |
1158 | err_unprepare_disable_dev: | 1186 | err_pmdisable: |
1159 | clk_disable_unprepare(priv->can_clk); | 1187 | pm_runtime_disable(&pdev->dev); |
1160 | err_free: | 1188 | err_free: |
1161 | free_candev(ndev); | 1189 | free_candev(ndev); |
1162 | err: | 1190 | err: |
@@ -1175,10 +1203,8 @@ static int xcan_remove(struct platform_device *pdev) | |||
1175 | struct net_device *ndev = platform_get_drvdata(pdev); | 1203 | struct net_device *ndev = platform_get_drvdata(pdev); |
1176 | struct xcan_priv *priv = netdev_priv(ndev); | 1204 | struct xcan_priv *priv = netdev_priv(ndev); |
1177 | 1205 | ||
1178 | if (set_reset_mode(ndev) < 0) | ||
1179 | netdev_err(ndev, "mode resetting failed!\n"); | ||
1180 | |||
1181 | unregister_candev(ndev); | 1206 | unregister_candev(ndev); |
1207 | pm_runtime_disable(&pdev->dev); | ||
1182 | netif_napi_del(&priv->napi); | 1208 | netif_napi_del(&priv->napi); |
1183 | free_candev(ndev); | 1209 | free_candev(ndev); |
1184 | 1210 | ||