Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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;
}