diff options
-rw-r--r-- | drivers/net/can/flexcan.c | 81 |
1 files changed, 32 insertions, 49 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 7b0be0910f4b..c48174ed49cc 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c | |||
@@ -850,12 +850,17 @@ static int flexcan_open(struct net_device *dev) | |||
850 | struct flexcan_priv *priv = netdev_priv(dev); | 850 | struct flexcan_priv *priv = netdev_priv(dev); |
851 | int err; | 851 | int err; |
852 | 852 | ||
853 | clk_prepare_enable(priv->clk_ipg); | 853 | err = clk_prepare_enable(priv->clk_ipg); |
854 | clk_prepare_enable(priv->clk_per); | 854 | if (err) |
855 | return err; | ||
856 | |||
857 | err = clk_prepare_enable(priv->clk_per); | ||
858 | if (err) | ||
859 | goto out_disable_ipg; | ||
855 | 860 | ||
856 | err = open_candev(dev); | 861 | err = open_candev(dev); |
857 | if (err) | 862 | if (err) |
858 | goto out; | 863 | goto out_disable_per; |
859 | 864 | ||
860 | err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev); | 865 | err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev); |
861 | if (err) | 866 | if (err) |
@@ -875,8 +880,9 @@ static int flexcan_open(struct net_device *dev) | |||
875 | 880 | ||
876 | out_close: | 881 | out_close: |
877 | close_candev(dev); | 882 | close_candev(dev); |
878 | out: | 883 | out_disable_per: |
879 | clk_disable_unprepare(priv->clk_per); | 884 | clk_disable_unprepare(priv->clk_per); |
885 | out_disable_ipg: | ||
880 | clk_disable_unprepare(priv->clk_ipg); | 886 | clk_disable_unprepare(priv->clk_ipg); |
881 | 887 | ||
882 | return err; | 888 | return err; |
@@ -933,8 +939,13 @@ static int register_flexcandev(struct net_device *dev) | |||
933 | struct flexcan_regs __iomem *regs = priv->base; | 939 | struct flexcan_regs __iomem *regs = priv->base; |
934 | u32 reg, err; | 940 | u32 reg, err; |
935 | 941 | ||
936 | clk_prepare_enable(priv->clk_ipg); | 942 | err = clk_prepare_enable(priv->clk_ipg); |
937 | clk_prepare_enable(priv->clk_per); | 943 | if (err) |
944 | return err; | ||
945 | |||
946 | err = clk_prepare_enable(priv->clk_per); | ||
947 | if (err) | ||
948 | goto out_disable_ipg; | ||
938 | 949 | ||
939 | /* select "bus clock", chip must be disabled */ | 950 | /* select "bus clock", chip must be disabled */ |
940 | flexcan_chip_disable(priv); | 951 | flexcan_chip_disable(priv); |
@@ -959,15 +970,16 @@ static int register_flexcandev(struct net_device *dev) | |||
959 | if (!(reg & FLEXCAN_MCR_FEN)) { | 970 | if (!(reg & FLEXCAN_MCR_FEN)) { |
960 | netdev_err(dev, "Could not enable RX FIFO, unsupported core\n"); | 971 | netdev_err(dev, "Could not enable RX FIFO, unsupported core\n"); |
961 | err = -ENODEV; | 972 | err = -ENODEV; |
962 | goto out; | 973 | goto out_disable_per; |
963 | } | 974 | } |
964 | 975 | ||
965 | err = register_candev(dev); | 976 | err = register_candev(dev); |
966 | 977 | ||
967 | out: | 978 | out_disable_per: |
968 | /* disable core and turn off clocks */ | 979 | /* disable core and turn off clocks */ |
969 | flexcan_chip_disable(priv); | 980 | flexcan_chip_disable(priv); |
970 | clk_disable_unprepare(priv->clk_per); | 981 | clk_disable_unprepare(priv->clk_per); |
982 | out_disable_ipg: | ||
971 | clk_disable_unprepare(priv->clk_ipg); | 983 | clk_disable_unprepare(priv->clk_ipg); |
972 | 984 | ||
973 | return err; | 985 | return err; |
@@ -1001,7 +1013,6 @@ static int flexcan_probe(struct platform_device *pdev) | |||
1001 | struct resource *mem; | 1013 | struct resource *mem; |
1002 | struct clk *clk_ipg = NULL, *clk_per = NULL; | 1014 | struct clk *clk_ipg = NULL, *clk_per = NULL; |
1003 | void __iomem *base; | 1015 | void __iomem *base; |
1004 | resource_size_t mem_size; | ||
1005 | int err, irq; | 1016 | int err, irq; |
1006 | u32 clock_freq = 0; | 1017 | u32 clock_freq = 0; |
1007 | 1018 | ||
@@ -1013,43 +1024,25 @@ static int flexcan_probe(struct platform_device *pdev) | |||
1013 | clk_ipg = devm_clk_get(&pdev->dev, "ipg"); | 1024 | clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
1014 | if (IS_ERR(clk_ipg)) { | 1025 | if (IS_ERR(clk_ipg)) { |
1015 | dev_err(&pdev->dev, "no ipg clock defined\n"); | 1026 | dev_err(&pdev->dev, "no ipg clock defined\n"); |
1016 | err = PTR_ERR(clk_ipg); | 1027 | return PTR_ERR(clk_ipg); |
1017 | goto failed_clock; | ||
1018 | } | 1028 | } |
1019 | clock_freq = clk_get_rate(clk_ipg); | 1029 | clock_freq = clk_get_rate(clk_ipg); |
1020 | 1030 | ||
1021 | clk_per = devm_clk_get(&pdev->dev, "per"); | 1031 | clk_per = devm_clk_get(&pdev->dev, "per"); |
1022 | if (IS_ERR(clk_per)) { | 1032 | if (IS_ERR(clk_per)) { |
1023 | dev_err(&pdev->dev, "no per clock defined\n"); | 1033 | dev_err(&pdev->dev, "no per clock defined\n"); |
1024 | err = PTR_ERR(clk_per); | 1034 | return PTR_ERR(clk_per); |
1025 | goto failed_clock; | ||
1026 | } | 1035 | } |
1027 | } | 1036 | } |
1028 | 1037 | ||
1029 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1038 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1030 | irq = platform_get_irq(pdev, 0); | 1039 | irq = platform_get_irq(pdev, 0); |
1031 | if (!mem || irq <= 0) { | 1040 | if (irq <= 0) |
1032 | err = -ENODEV; | 1041 | return -ENODEV; |
1033 | goto failed_get; | ||
1034 | } | ||
1035 | 1042 | ||
1036 | mem_size = resource_size(mem); | 1043 | base = devm_ioremap_resource(&pdev->dev, mem); |
1037 | if (!request_mem_region(mem->start, mem_size, pdev->name)) { | 1044 | if (IS_ERR(base)) |
1038 | err = -EBUSY; | 1045 | return PTR_ERR(base); |
1039 | goto failed_get; | ||
1040 | } | ||
1041 | |||
1042 | base = ioremap(mem->start, mem_size); | ||
1043 | if (!base) { | ||
1044 | err = -ENOMEM; | ||
1045 | goto failed_map; | ||
1046 | } | ||
1047 | |||
1048 | dev = alloc_candev(sizeof(struct flexcan_priv), 1); | ||
1049 | if (!dev) { | ||
1050 | err = -ENOMEM; | ||
1051 | goto failed_alloc; | ||
1052 | } | ||
1053 | 1046 | ||
1054 | of_id = of_match_device(flexcan_of_match, &pdev->dev); | 1047 | of_id = of_match_device(flexcan_of_match, &pdev->dev); |
1055 | if (of_id) { | 1048 | if (of_id) { |
@@ -1058,10 +1051,13 @@ static int flexcan_probe(struct platform_device *pdev) | |||
1058 | devtype_data = (struct flexcan_devtype_data *) | 1051 | devtype_data = (struct flexcan_devtype_data *) |
1059 | pdev->id_entry->driver_data; | 1052 | pdev->id_entry->driver_data; |
1060 | } else { | 1053 | } else { |
1061 | err = -ENODEV; | 1054 | return -ENODEV; |
1062 | goto failed_devtype; | ||
1063 | } | 1055 | } |
1064 | 1056 | ||
1057 | dev = alloc_candev(sizeof(struct flexcan_priv), 1); | ||
1058 | if (!dev) | ||
1059 | return -ENOMEM; | ||
1060 | |||
1065 | dev->netdev_ops = &flexcan_netdev_ops; | 1061 | dev->netdev_ops = &flexcan_netdev_ops; |
1066 | dev->irq = irq; | 1062 | dev->irq = irq; |
1067 | dev->flags |= IFF_ECHO; | 1063 | dev->flags |= IFF_ECHO; |
@@ -1104,28 +1100,15 @@ static int flexcan_probe(struct platform_device *pdev) | |||
1104 | return 0; | 1100 | return 0; |
1105 | 1101 | ||
1106 | failed_register: | 1102 | failed_register: |
1107 | failed_devtype: | ||
1108 | free_candev(dev); | 1103 | free_candev(dev); |
1109 | failed_alloc: | ||
1110 | iounmap(base); | ||
1111 | failed_map: | ||
1112 | release_mem_region(mem->start, mem_size); | ||
1113 | failed_get: | ||
1114 | failed_clock: | ||
1115 | return err; | 1104 | return err; |
1116 | } | 1105 | } |
1117 | 1106 | ||
1118 | static int flexcan_remove(struct platform_device *pdev) | 1107 | static int flexcan_remove(struct platform_device *pdev) |
1119 | { | 1108 | { |
1120 | struct net_device *dev = platform_get_drvdata(pdev); | 1109 | struct net_device *dev = platform_get_drvdata(pdev); |
1121 | struct flexcan_priv *priv = netdev_priv(dev); | ||
1122 | struct resource *mem; | ||
1123 | 1110 | ||
1124 | unregister_flexcandev(dev); | 1111 | unregister_flexcandev(dev); |
1125 | iounmap(priv->base); | ||
1126 | |||
1127 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1128 | release_mem_region(mem->start, resource_size(mem)); | ||
1129 | 1112 | ||
1130 | free_candev(dev); | 1113 | free_candev(dev); |
1131 | 1114 | ||