drivers/clk/imx/clk-imx6q.c

Source file repositories/reference/linux-study-clean/drivers/clk/imx/clk-imx6q.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/imx/clk-imx6q.c
Extension
.c
Size
59937 bytes
Lines
1002
Domain
Driver Families
Bucket
drivers/clk
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (rc < 0) {
			/* skip empty (null) phandles */
			if (rc == -ENOENT)
				continue;
			else
				return;
		}
		if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
			pr_err("ccm: parent clock %d not in ccm\n", index);
			of_node_put(clkspec.np);
			return;
		}
		parent = clkspec.args[0];
		of_node_put(clkspec.np);

		rc = of_parse_phandle_with_args(node, "assigned-clocks",
				"#clock-cells", index, &clkspec);
		if (rc < 0)
			return;
		if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
			pr_err("ccm: child clock %d not in ccm\n", index);
			of_node_put(clkspec.np);
			return;
		}
		child = clkspec.args[0];
		of_node_put(clkspec.np);

		if (child != IMX6QDL_CLK_LDB_DI0_SEL &&
		    child != IMX6QDL_CLK_LDB_DI1_SEL)
			continue;

		sel = ldb_di_sel_by_clock_id(parent);
		if (sel < 0) {
			pr_err("ccm: invalid ldb_di%d parent clock: %d\n",
			       child == IMX6QDL_CLK_LDB_DI1_SEL, parent);
			continue;
		}

		if (child == IMX6QDL_CLK_LDB_DI0_SEL)
			*ldb_di0_sel = sel;
		if (child == IMX6QDL_CLK_LDB_DI1_SEL)
			*ldb_di1_sel = sel;
	}
}

static bool pll6_bypassed(struct device_node *node)
{
	int index, ret, num_clocks;
	struct of_phandle_args clkspec;

	num_clocks = of_count_phandle_with_args(node, "assigned-clocks",
						"#clock-cells");
	if (num_clocks < 0)
		return false;

	for (index = 0; index < num_clocks; index++) {
		ret = of_parse_phandle_with_args(node, "assigned-clocks",
						 "#clock-cells", index,
						 &clkspec);
		if (ret < 0)
			return false;

		if (clkspec.np == node &&
		    clkspec.args[0] == IMX6QDL_PLL6_BYPASS) {
			of_node_put(clkspec.np);
			break;
		}
		of_node_put(clkspec.np);
	}

	/* PLL6 bypass is not part of the assigned clock list */
	if (index == num_clocks)
		return false;

	ret = of_parse_phandle_with_args(node, "assigned-clock-parents",
					 "#clock-cells", index, &clkspec);

	if (!ret)
		of_node_put(clkspec.np);

	if (clkspec.args[0] != IMX6QDL_CLK_PLL6)
		return true;

	return false;
}

#define CCM_CCSR		0x0c
#define CCM_CS2CDR		0x2c

#define CCSR_PLL3_SW_CLK_SEL		BIT(0)

Annotation

Implementation Notes