static void __init sun8i_r40_ccu_setup(struct device_node *node) { void __iomem *reg; u32 val; reg = of_io_request_and_map(node, 0, of_node_full_name(node)); if (IS_ERR(reg)) { pr_err("%s: Could not map the clock registers\n", of_node_full_name(node)); return; } /* Force the PLL-Audio-1x divider to 4 */ val = readl(reg + SUN8I_R40_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); writel(val | (3 << 16), reg + SUN8I_R40_PLL_AUDIO_REG); /* Force PLL-MIPI to MIPI mode */ val = readl(reg + SUN8I_R40_PLL_MIPI_REG); val &= ~BIT(16); writel(val, reg + SUN8I_R40_PLL_MIPI_REG); /* Force OHCI 12M parent to 12M divided from 48M */ val = readl(reg + SUN8I_R40_USB_CLK_REG); val &= ~GENMASK(25, 20); writel(val, reg + SUN8I_R40_USB_CLK_REG); sunxi_ccu_probe(node, reg, &sun8i_r40_ccu_desc); /* Gate then ungate PLL CPU after any rate changes */ ccu_pll_notifier_register(&sun8i_r40_pll_cpu_nb); /* Reparent CPU during PLL CPU rate changes */ ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, &sun8i_r40_cpu_nb); }
static void __init sun8i_a33_ccu_setup(struct device_node *node) { void __iomem *reg; u32 val; reg = of_io_request_and_map(node, 0, of_node_full_name(node)); if (IS_ERR(reg)) { pr_err("%s: Could not map the clock registers\n", of_node_full_name(node)); return; } /* Force the PLL-Audio-1x divider to 4 */ val = readl(reg + SUN8I_A33_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); writel(val | (3 << 16), reg + SUN8I_A33_PLL_AUDIO_REG); /* Force PLL-MIPI to MIPI mode */ val = readl(reg + SUN8I_A33_PLL_MIPI_REG); val &= ~BIT(16); writel(val, reg + SUN8I_A33_PLL_MIPI_REG); sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc); }
static int sun50i_h6_ccu_probe(struct platform_device *pdev) { struct resource *res; void __iomem *reg; u32 val; int i; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(reg)) return PTR_ERR(reg); /* Enable the lock bits on all PLLs */ for (i = 0; i < ARRAY_SIZE(pll_regs); i++) { val = readl(reg + pll_regs[i]); val |= BIT(29); writel(val, reg + pll_regs[i]); } /* * Force the output divider of video PLLs to 0. * * See the comment before pll-video0 definition for the reason. */ for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) { val = readl(reg + pll_video_regs[i]); val &= ~BIT(0); writel(val, reg + pll_video_regs[i]); } /* * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz) * * This clock mux is still mysterious, and the code just enforces * it to have a valid clock parent. */ for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) { val = readl(reg + usb2_clk_regs[i]); val &= ~GENMASK(25, 24); writel (val, reg + usb2_clk_regs[i]); } /* * Force the post-divider of pll-audio to 8 and the output divider * of it to 1, to make the clock name represents the real frequency. */ val = readl(reg + SUN50I_H6_PLL_AUDIO_REG); val &= ~(GENMASK(21, 16) | BIT(0)); writel(val | (7 << 16), reg + SUN50I_H6_PLL_AUDIO_REG); /* * First clock parent (osc32K) is unusable for CEC. But since there * is no good way to force parent switch (both run with same frequency), * just set second clock parent here. */ val = readl(reg + SUN50I_H6_HDMI_CEC_CLK_REG); val |= BIT(24); writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG); return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc); }
static int sunxi_de2_clk_probe(struct platform_device *pdev) { struct resource *res; struct clk *bus_clk, *mod_clk; struct reset_control *rstc; void __iomem *reg; const struct sunxi_ccu_desc *ccu_desc; int ret; ccu_desc = of_device_get_match_data(&pdev->dev); if (!ccu_desc) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(reg)) return PTR_ERR(reg); bus_clk = devm_clk_get(&pdev->dev, "bus"); if (IS_ERR(bus_clk)) { ret = PTR_ERR(bus_clk); if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret); return ret; } mod_clk = devm_clk_get(&pdev->dev, "mod"); if (IS_ERR(mod_clk)) { ret = PTR_ERR(mod_clk); if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "Couldn't get mod clk: %d\n", ret); return ret; } rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(rstc)) { ret = PTR_ERR(rstc); if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "Couldn't get reset control: %d\n", ret); return ret; } /* The clocks need to be enabled for us to access the registers */ ret = clk_prepare_enable(bus_clk); if (ret) { dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret); return ret; } ret = clk_prepare_enable(mod_clk); if (ret) { dev_err(&pdev->dev, "Couldn't enable mod clk: %d\n", ret); goto err_disable_bus_clk; } /* The reset control needs to be asserted for the controls to work */ ret = reset_control_deassert(rstc); if (ret) { dev_err(&pdev->dev, "Couldn't deassert reset control: %d\n", ret); goto err_disable_mod_clk; } ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc); if (ret) goto err_assert_reset; return 0; err_assert_reset: reset_control_assert(rstc); err_disable_mod_clk: clk_disable_unprepare(mod_clk); err_disable_bus_clk: clk_disable_unprepare(bus_clk); return ret; }