flexcan: Prefer device tree clock frequency if available.
authorholt@sgi.com <holt@sgi.com>
Tue, 16 Aug 2011 17:32:23 +0000 (17:32 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Aug 2011 03:36:38 +0000 (20:36 -0700)
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>
Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
drivers/net/can/flexcan.c

index 8dfb98b..1ad80d5 100644 (file)
@@ -11,6 +11,7 @@ Required properties:
 
 - reg : Offset and length of the register set for this device
 - interrupts : Interrupt tuple for this device
+- clock-frequency : The oscillator frequency driving the flexcan device
 
 Example:
 
@@ -19,4 +20,5 @@ Example:
                reg = <0x1c000 0x1000>;
                interrupts = <48 0x2>;
                interrupt-parent = <&mpic>;
+               clock-frequency = <200000000>; // filled in by bootloader
        };
index cc1e0a7..e023379 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 
 #define DRV_NAME                       "flexcan"
@@ -925,16 +926,29 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
        struct net_device *dev;
        struct flexcan_priv *priv;
        struct resource *mem;
-       struct clk *clk;
+       struct clk *clk = NULL;
        void __iomem *base;
        resource_size_t mem_size;
        int err, irq;
+       u32 clock_freq = 0;
+
+       if (pdev->dev.of_node) {
+               const u32 *clock_freq_p;
 
-       clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(clk)) {
-               dev_err(&pdev->dev, "no clock defined\n");
-               err = PTR_ERR(clk);
-               goto failed_clock;
+               clock_freq_p = of_get_property(pdev->dev.of_node,
+                                               "clock-frequency", NULL);
+               if (clock_freq_p)
+                       clock_freq = *clock_freq_p;
+       }
+
+       if (!clock_freq) {
+               clk = clk_get(&pdev->dev, NULL);
+               if (IS_ERR(clk)) {
+                       dev_err(&pdev->dev, "no clock defined\n");
+                       err = PTR_ERR(clk);
+                       goto failed_clock;
+               }
+               clock_freq = clk_get_rate(clk);
        }
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -967,7 +981,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
        dev->flags |= IFF_ECHO; /* we support local echo in hardware */
 
        priv = netdev_priv(dev);
-       priv->can.clock.freq = clk_get_rate(clk);
+       priv->can.clock.freq = clock_freq;
        priv->can.bittiming_const = &flexcan_bittiming_const;
        priv->can.do_set_mode = flexcan_set_mode;
        priv->can.do_get_berr_counter = flexcan_get_berr_counter;
@@ -1002,7 +1016,8 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
  failed_map:
        release_mem_region(mem->start, mem_size);
  failed_get:
-       clk_put(clk);
+       if (clk)
+               clk_put(clk);
  failed_clock:
        return err;
 }
@@ -1020,7 +1035,8 @@ static int __devexit flexcan_remove(struct platform_device *pdev)
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem->start, resource_size(mem));
 
-       clk_put(priv->clk);
+       if (priv->clk)
+               clk_put(priv->clk);
 
        free_candev(dev);