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