diff options
author | holt@sgi.com <holt@sgi.com> | 2011-08-16 13:32:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-08-17 23:36:38 -0400 |
commit | 97efe9aef1ae8922666d32f28d712745a86859e9 (patch) | |
tree | c02a00d17b63b8454dd69d874bc207fccb8d0aa7 /drivers/net/can/flexcan.c | |
parent | c8aef4cb788b760331e6df06a5d93389824882b4 (diff) |
flexcan: Prefer device tree clock frequency if available.
If our CAN device's device tree node has a clock-frequency property,
then use that value for the can devices clock frequency. If not, fall
back to asking the platform/mach code for the clock frequency associated
with the flexcan device.
Signed-off-by: Robin Holt <holt@sgi.com>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>,
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>,
Cc: U Bhaskar-B22300 <B22300@freescale.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: socketcan-core@lists.berlios.de,
Cc: netdev@vger.kernel.org,
Cc: PPC list <linuxppc-dev@lists.ozlabs.org>
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can/flexcan.c')
-rw-r--r-- | drivers/net/can/flexcan.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index cc1e0a7b554f..e02337953f41 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/list.h> | 34 | #include <linux/list.h> |
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/of.h> | ||
36 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
37 | 38 | ||
38 | #define DRV_NAME "flexcan" | 39 | #define DRV_NAME "flexcan" |
@@ -925,16 +926,29 @@ static int __devinit flexcan_probe(struct platform_device *pdev) | |||
925 | struct net_device *dev; | 926 | struct net_device *dev; |
926 | struct flexcan_priv *priv; | 927 | struct flexcan_priv *priv; |
927 | struct resource *mem; | 928 | struct resource *mem; |
928 | struct clk *clk; | 929 | struct clk *clk = NULL; |
929 | void __iomem *base; | 930 | void __iomem *base; |
930 | resource_size_t mem_size; | 931 | resource_size_t mem_size; |
931 | int err, irq; | 932 | int err, irq; |
933 | u32 clock_freq = 0; | ||
934 | |||
935 | if (pdev->dev.of_node) { | ||
936 | const u32 *clock_freq_p; | ||
932 | 937 | ||
933 | clk = clk_get(&pdev->dev, NULL); | 938 | clock_freq_p = of_get_property(pdev->dev.of_node, |
934 | if (IS_ERR(clk)) { | 939 | "clock-frequency", NULL); |
935 | dev_err(&pdev->dev, "no clock defined\n"); | 940 | if (clock_freq_p) |
936 | err = PTR_ERR(clk); | 941 | clock_freq = *clock_freq_p; |
937 | goto failed_clock; | 942 | } |
943 | |||
944 | if (!clock_freq) { | ||
945 | clk = clk_get(&pdev->dev, NULL); | ||
946 | if (IS_ERR(clk)) { | ||
947 | dev_err(&pdev->dev, "no clock defined\n"); | ||
948 | err = PTR_ERR(clk); | ||
949 | goto failed_clock; | ||
950 | } | ||
951 | clock_freq = clk_get_rate(clk); | ||
938 | } | 952 | } |
939 | 953 | ||
940 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 954 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -967,7 +981,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev) | |||
967 | dev->flags |= IFF_ECHO; /* we support local echo in hardware */ | 981 | dev->flags |= IFF_ECHO; /* we support local echo in hardware */ |
968 | 982 | ||
969 | priv = netdev_priv(dev); | 983 | priv = netdev_priv(dev); |
970 | priv->can.clock.freq = clk_get_rate(clk); | 984 | priv->can.clock.freq = clock_freq; |
971 | priv->can.bittiming_const = &flexcan_bittiming_const; | 985 | priv->can.bittiming_const = &flexcan_bittiming_const; |
972 | priv->can.do_set_mode = flexcan_set_mode; | 986 | priv->can.do_set_mode = flexcan_set_mode; |
973 | priv->can.do_get_berr_counter = flexcan_get_berr_counter; | 987 | priv->can.do_get_berr_counter = flexcan_get_berr_counter; |
@@ -1002,7 +1016,8 @@ static int __devinit flexcan_probe(struct platform_device *pdev) | |||
1002 | failed_map: | 1016 | failed_map: |
1003 | release_mem_region(mem->start, mem_size); | 1017 | release_mem_region(mem->start, mem_size); |
1004 | failed_get: | 1018 | failed_get: |
1005 | clk_put(clk); | 1019 | if (clk) |
1020 | clk_put(clk); | ||
1006 | failed_clock: | 1021 | failed_clock: |
1007 | return err; | 1022 | return err; |
1008 | } | 1023 | } |
@@ -1020,7 +1035,8 @@ static int __devexit flexcan_remove(struct platform_device *pdev) | |||
1020 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1035 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1021 | release_mem_region(mem->start, resource_size(mem)); | 1036 | release_mem_region(mem->start, resource_size(mem)); |
1022 | 1037 | ||
1023 | clk_put(priv->clk); | 1038 | if (priv->clk) |
1039 | clk_put(priv->clk); | ||
1024 | 1040 | ||
1025 | free_candev(dev); | 1041 | free_candev(dev); |
1026 | 1042 | ||