drm/radeon: Add probing of clocks from device-tree
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 9 Aug 2010 06:16:36 +0000 (16:16 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 11 Aug 2010 23:41:20 +0000 (09:41 +1000)
When we find no ROM we understand and a device-tree is present, see
if we can retreive clock info from there.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/radeon_clocks.c

index f64936cc4dd9dfaffeee50d02ea529544b338abc..14448a740ba632cf5f2fcbaf2d2d5804f3446b93 100644 (file)
@@ -91,6 +91,85 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
        return mclk;
 }
 
+#ifdef CONFIG_OF
+/*
+ * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device
+ * tree. Hopefully, ATI OF driver is kind enough to fill these
+ */
+static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+{
+       struct radeon_device *rdev = dev->dev_private;
+       struct device_node *dp = rdev->pdev->dev.of_node;
+       const u32 *val;
+       struct radeon_pll *p1pll = &rdev->clock.p1pll;
+       struct radeon_pll *p2pll = &rdev->clock.p2pll;
+       struct radeon_pll *spll = &rdev->clock.spll;
+       struct radeon_pll *mpll = &rdev->clock.mpll;
+
+       if (dp == NULL)
+               return false;
+       val = of_get_property(dp, "ATY,RefCLK", NULL);
+       if (!val || !*val) {
+               printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
+               return false;
+       }
+       p1pll->reference_freq = p2pll->reference_freq = (*val) / 10;
+       p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
+       if (p1pll->reference_div < 2)
+               p1pll->reference_div = 12;
+       p2pll->reference_div = p1pll->reference_div;    
+
+       /* These aren't in the device-tree */
+       if (rdev->family >= CHIP_R420) {
+               p1pll->pll_in_min = 100;
+               p1pll->pll_in_max = 1350;
+               p1pll->pll_out_min = 20000;
+               p1pll->pll_out_max = 50000;
+               p2pll->pll_in_min = 100;
+               p2pll->pll_in_max = 1350;
+               p2pll->pll_out_min = 20000;
+               p2pll->pll_out_max = 50000;
+       } else {
+               p1pll->pll_in_min = 40;
+               p1pll->pll_in_max = 500;
+               p1pll->pll_out_min = 12500;
+               p1pll->pll_out_max = 35000;
+               p2pll->pll_in_min = 40;
+               p2pll->pll_in_max = 500;
+               p2pll->pll_out_min = 12500;
+               p2pll->pll_out_max = 35000;
+       }
+
+       spll->reference_freq = mpll->reference_freq = p1pll->reference_freq;
+       spll->reference_div = mpll->reference_div =
+               RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
+                           RADEON_M_SPLL_REF_DIV_MASK;
+
+       val = of_get_property(dp, "ATY,SCLK", NULL);
+       if (val && *val)
+               rdev->clock.default_sclk = (*val) / 10;
+       else
+               rdev->clock.default_sclk =
+                       radeon_legacy_get_engine_clock(rdev);
+                       
+       val = of_get_property(dp, "ATY,MCLK", NULL);
+       if (val && *val)
+               rdev->clock.default_mclk = (*val) / 10;
+       else
+               rdev->clock.default_mclk =
+                       radeon_legacy_get_memory_clock(rdev);
+
+       DRM_INFO("Using device-tree clock info\n");
+       
+       return true;
+}
+#else
+static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
+{
+       return false;
+}
+#endif /* CONFIG_OF */
+
 void radeon_get_clock_info(struct drm_device *dev)
 {
        struct radeon_device *rdev = dev->dev_private;
@@ -105,6 +184,8 @@ void radeon_get_clock_info(struct drm_device *dev)
                ret = radeon_atom_get_clock_info(dev);
        else
                ret = radeon_combios_get_clock_info(dev);
+       if (!ret)
+               ret = radeon_read_clocks_OF(dev);
 
        if (ret) {
                if (p1pll->reference_div < 2) {