Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

holt@sgi.com and committed by
David S. Miller
97efe9ae c8aef4cb

+27 -9
+2
Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
··· 11 11 12 12 - reg : Offset and length of the register set for this device 13 13 - interrupts : Interrupt tuple for this device 14 + - clock-frequency : The oscillator frequency driving the flexcan device 14 15 15 16 Example: 16 17 ··· 20 19 reg = <0x1c000 0x1000>; 21 20 interrupts = <48 0x2>; 22 21 interrupt-parent = <&mpic>; 22 + clock-frequency = <200000000>; // filled in by bootloader 23 23 };
+25 -9
drivers/net/can/flexcan.c
··· 33 33 #include <linux/kernel.h> 34 34 #include <linux/list.h> 35 35 #include <linux/module.h> 36 + #include <linux/of.h> 36 37 #include <linux/platform_device.h> 37 38 38 39 #define DRV_NAME "flexcan" ··· 926 925 struct net_device *dev; 927 926 struct flexcan_priv *priv; 928 927 struct resource *mem; 929 - struct clk *clk; 928 + struct clk *clk = NULL; 930 929 void __iomem *base; 931 930 resource_size_t mem_size; 932 931 int err, irq; 932 + u32 clock_freq = 0; 933 933 934 - clk = clk_get(&pdev->dev, NULL); 935 - if (IS_ERR(clk)) { 936 - dev_err(&pdev->dev, "no clock defined\n"); 937 - err = PTR_ERR(clk); 938 - goto failed_clock; 934 + if (pdev->dev.of_node) { 935 + const u32 *clock_freq_p; 936 + 937 + clock_freq_p = of_get_property(pdev->dev.of_node, 938 + "clock-frequency", NULL); 939 + if (clock_freq_p) 940 + clock_freq = *clock_freq_p; 941 + } 942 + 943 + if (!clock_freq) { 944 + clk = clk_get(&pdev->dev, NULL); 945 + if (IS_ERR(clk)) { 946 + dev_err(&pdev->dev, "no clock defined\n"); 947 + err = PTR_ERR(clk); 948 + goto failed_clock; 949 + } 950 + clock_freq = clk_get_rate(clk); 939 951 } 940 952 941 953 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ··· 981 967 dev->flags |= IFF_ECHO; /* we support local echo in hardware */ 982 968 983 969 priv = netdev_priv(dev); 984 - priv->can.clock.freq = clk_get_rate(clk); 970 + priv->can.clock.freq = clock_freq; 985 971 priv->can.bittiming_const = &flexcan_bittiming_const; 986 972 priv->can.do_set_mode = flexcan_set_mode; 987 973 priv->can.do_get_berr_counter = flexcan_get_berr_counter; ··· 1016 1002 failed_map: 1017 1003 release_mem_region(mem->start, mem_size); 1018 1004 failed_get: 1019 - clk_put(clk); 1005 + if (clk) 1006 + clk_put(clk); 1020 1007 failed_clock: 1021 1008 return err; 1022 1009 } ··· 1035 1020 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1036 1021 release_mem_region(mem->start, resource_size(mem)); 1037 1022 1038 - clk_put(priv->clk); 1023 + if (priv->clk) 1024 + clk_put(priv->clk); 1039 1025 1040 1026 free_candev(dev); 1041 1027