xref: /rk3399_rockchip-uboot/drivers/clk/at91/pmc.c (revision 6cadaa046b196bebebd7acb13edd840bcfef98e2)
19e5935c0SWenyou Yang /*
29e5935c0SWenyou Yang  * Copyright (C) 2016 Atmel Corporation
39e5935c0SWenyou Yang  *               Wenyou.Yang <wenyou.yang@atmel.com>
49e5935c0SWenyou Yang  *
59e5935c0SWenyou Yang  * SPDX-License-Identifier:	GPL-2.0+
69e5935c0SWenyou Yang  */
79e5935c0SWenyou Yang 
89e5935c0SWenyou Yang #include <common.h>
99e5935c0SWenyou Yang #include <clk-uclass.h>
109e5935c0SWenyou Yang #include <dm/device.h>
119e5935c0SWenyou Yang #include <dm/lists.h>
129e5935c0SWenyou Yang #include <dm/root.h>
139e5935c0SWenyou Yang #include "pmc.h"
149e5935c0SWenyou Yang 
159e5935c0SWenyou Yang DECLARE_GLOBAL_DATA_PTR;
169e5935c0SWenyou Yang 
179e5935c0SWenyou Yang static const struct udevice_id at91_pmc_match[] = {
189e5935c0SWenyou Yang 	{ .compatible = "atmel,sama5d2-pmc" },
199e5935c0SWenyou Yang 	{}
209e5935c0SWenyou Yang };
219e5935c0SWenyou Yang 
229e5935c0SWenyou Yang U_BOOT_DRIVER(at91_pmc) = {
23b892b054SWenyou Yang 	.name = "at91-pmc",
24b892b054SWenyou Yang 	.id = UCLASS_SIMPLE_BUS,
259e5935c0SWenyou Yang 	.of_match = at91_pmc_match,
269e5935c0SWenyou Yang };
279e5935c0SWenyou Yang 
28*6cadaa04SWenyou Yang /*---------------------------------------------------------*/
29*6cadaa04SWenyou Yang 
309e5935c0SWenyou Yang int at91_pmc_core_probe(struct udevice *dev)
319e5935c0SWenyou Yang {
329e5935c0SWenyou Yang 	struct pmc_platdata *plat = dev_get_platdata(dev);
339e5935c0SWenyou Yang 
349e5935c0SWenyou Yang 	dev = dev_get_parent(dev);
359e5935c0SWenyou Yang 
369e5935c0SWenyou Yang 	plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev);
379e5935c0SWenyou Yang 
389e5935c0SWenyou Yang 	return 0;
399e5935c0SWenyou Yang }
409e5935c0SWenyou Yang 
41*6cadaa04SWenyou Yang /**
42*6cadaa04SWenyou Yang  * at91_clk_sub_device_bind() - for the at91 clock driver
43*6cadaa04SWenyou Yang  * Recursively bind its children as clk devices.
44*6cadaa04SWenyou Yang  *
45*6cadaa04SWenyou Yang  * @return: 0 on success, or negative error code on failure
46*6cadaa04SWenyou Yang  */
47*6cadaa04SWenyou Yang int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name)
489e5935c0SWenyou Yang {
499e5935c0SWenyou Yang 	const void *fdt = gd->fdt_blob;
509e5935c0SWenyou Yang 	int offset = dev->of_offset;
51*6cadaa04SWenyou Yang 	bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
529e5935c0SWenyou Yang 	const char *name;
539e5935c0SWenyou Yang 	int ret;
549e5935c0SWenyou Yang 
559e5935c0SWenyou Yang 	for (offset = fdt_first_subnode(fdt, offset);
569e5935c0SWenyou Yang 	     offset > 0;
579e5935c0SWenyou Yang 	     offset = fdt_next_subnode(fdt, offset)) {
58*6cadaa04SWenyou Yang 		if (pre_reloc_only &&
59*6cadaa04SWenyou Yang 		    !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL))
60*6cadaa04SWenyou Yang 			continue;
61*6cadaa04SWenyou Yang 		/*
62*6cadaa04SWenyou Yang 		 * If this node has "compatible" property, this is not
63*6cadaa04SWenyou Yang 		 * a clock sub-node, but a normal device. skip.
64*6cadaa04SWenyou Yang 		 */
65*6cadaa04SWenyou Yang 		fdt_get_property(fdt, offset, "compatible", &ret);
66*6cadaa04SWenyou Yang 		if (ret >= 0)
67*6cadaa04SWenyou Yang 			continue;
68*6cadaa04SWenyou Yang 
69*6cadaa04SWenyou Yang 		if (ret != -FDT_ERR_NOTFOUND)
70*6cadaa04SWenyou Yang 			return ret;
71*6cadaa04SWenyou Yang 
729e5935c0SWenyou Yang 		name = fdt_get_name(fdt, offset, NULL);
739e5935c0SWenyou Yang 		if (!name)
749e5935c0SWenyou Yang 			return -EINVAL;
75*6cadaa04SWenyou Yang 		ret = device_bind_driver_to_node(dev, drv_name, name,
769e5935c0SWenyou Yang 						 offset, NULL);
779e5935c0SWenyou Yang 		if (ret)
789e5935c0SWenyou Yang 			return ret;
799e5935c0SWenyou Yang 	}
809e5935c0SWenyou Yang 
819e5935c0SWenyou Yang 	return 0;
829e5935c0SWenyou Yang }
839e5935c0SWenyou Yang 
84*6cadaa04SWenyou Yang int at91_clk_of_xlate(struct clk *clk, struct fdtdec_phandle_args *args)
85*6cadaa04SWenyou Yang {
86*6cadaa04SWenyou Yang 	int periph;
87*6cadaa04SWenyou Yang 
88*6cadaa04SWenyou Yang 	if (args->args_count) {
89*6cadaa04SWenyou Yang 		debug("Invalid args_count: %d\n", args->args_count);
90*6cadaa04SWenyou Yang 		return -EINVAL;
91*6cadaa04SWenyou Yang 	}
92*6cadaa04SWenyou Yang 
93*6cadaa04SWenyou Yang 	periph = fdtdec_get_uint(gd->fdt_blob, clk->dev->of_offset, "reg", -1);
94*6cadaa04SWenyou Yang 	if (periph < 0)
95*6cadaa04SWenyou Yang 		return -EINVAL;
96*6cadaa04SWenyou Yang 
97*6cadaa04SWenyou Yang 	clk->id = periph;
98*6cadaa04SWenyou Yang 
99*6cadaa04SWenyou Yang 	return 0;
100*6cadaa04SWenyou Yang }
101*6cadaa04SWenyou Yang 
102*6cadaa04SWenyou Yang int at91_clk_probe(struct udevice *dev)
103*6cadaa04SWenyou Yang {
104*6cadaa04SWenyou Yang 	struct udevice *dev_periph_container, *dev_pmc;
105*6cadaa04SWenyou Yang 	struct pmc_platdata *plat = dev_get_platdata(dev);
106*6cadaa04SWenyou Yang 
107*6cadaa04SWenyou Yang 	dev_periph_container = dev_get_parent(dev);
108*6cadaa04SWenyou Yang 	dev_pmc = dev_get_parent(dev_periph_container);
109*6cadaa04SWenyou Yang 
110*6cadaa04SWenyou Yang 	plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev_pmc);
111*6cadaa04SWenyou Yang 
112*6cadaa04SWenyou Yang 	return 0;
113*6cadaa04SWenyou Yang }
114