+#define rmwl(addr, mask, val) \
+ writel(((readl(addr) & ~(mask)) | ((val) & (mask))), addr)
+
+static int cmn_init(struct platform_device *pdev)
+{
+ struct resource *res;
+ void __iomem *cmn_base;
+ void __iomem *tcsr_base;
+ u32 val;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cmn");
+ if (!res)
+ return 0;
+
+ cmn_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR_OR_NULL(cmn_base))
+ return PTR_ERR(cmn_base);
+
+ /* For IPQ50xx, tcsr is necessary to enable cmn block */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tcsr");
+ if (res) {
+ tcsr_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR_OR_NULL(tcsr_base))
+ return PTR_ERR(tcsr_base);
+
+ rmwl((tcsr_base + TCSR_ETH_CMN), TCSR_ETH_CMN_ENABLE,
+ TCSR_ETH_CMN_ENABLE);
+ }
+
+ rmwl((cmn_base + CMN_PLL_REFCLK_SRC),
+ CMN_PLL_REFCLK_SRC_FROM_MASK,
+ CMN_PLL_REFCLK_SRC_FROM_REG);
+ rmwl((cmn_base + CMN_PLL_REFCLK),
+ (CMN_PLL_REFCLK_EXTERNAL | CMN_PLL_REFCLK_FREQ_MASK
+ | CMN_PLL_REFCLK_DIV_MASK),
+ (CMN_PLL_REFCLK_FREQ_48M | CMN_PLL_REFCLK_DIV(2)));
+
+ rmwl((cmn_base + CMN_PLL_CTRL), CMN_PLL_CTRL_RST_N, 0);
+ msleep(1);
+ rmwl((cmn_base + CMN_PLL_CTRL), CMN_PLL_CTRL_RST_N,
+ CMN_PLL_CTRL_RST_N);
+ msleep(1);
+
+ return read_poll_timeout(readl, val,
+ (val & CMN_PLL_STATUS_LOCKED),
+ 100, 200000, false,
+ (cmn_base + CMN_PLL_STATUS));
+}
+