]>
Commit | Line | Data |
---|---|---|
9e5935c0 WY |
1 | /* |
2 | * Copyright (C) 2016 Atmel Corporation | |
3 | * Wenyou.Yang <wenyou.yang@atmel.com> | |
4 | * | |
5 | * SPDX-License-Identifier: GPL-2.0+ | |
6 | */ | |
7 | ||
8 | #include <common.h> | |
9 | #include <clk-uclass.h> | |
10 | #include <dm/device.h> | |
11 | #include <dm/lists.h> | |
12 | #include <dm/root.h> | |
13 | #include "pmc.h" | |
14 | ||
15 | DECLARE_GLOBAL_DATA_PTR; | |
16 | ||
9e5935c0 WY |
17 | static const struct udevice_id at91_pmc_match[] = { |
18 | { .compatible = "atmel,sama5d2-pmc" }, | |
19 | {} | |
20 | }; | |
21 | ||
22 | U_BOOT_DRIVER(at91_pmc) = { | |
b892b054 WY |
23 | .name = "at91-pmc", |
24 | .id = UCLASS_SIMPLE_BUS, | |
9e5935c0 | 25 | .of_match = at91_pmc_match, |
9e5935c0 WY |
26 | }; |
27 | ||
6cadaa04 WY |
28 | /*---------------------------------------------------------*/ |
29 | ||
9e5935c0 WY |
30 | int at91_pmc_core_probe(struct udevice *dev) |
31 | { | |
32 | struct pmc_platdata *plat = dev_get_platdata(dev); | |
33 | ||
34 | dev = dev_get_parent(dev); | |
35 | ||
36 | plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev); | |
37 | ||
38 | return 0; | |
39 | } | |
40 | ||
6cadaa04 WY |
41 | /** |
42 | * at91_clk_sub_device_bind() - for the at91 clock driver | |
43 | * Recursively bind its children as clk devices. | |
44 | * | |
45 | * @return: 0 on success, or negative error code on failure | |
46 | */ | |
47 | int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name) | |
9e5935c0 WY |
48 | { |
49 | const void *fdt = gd->fdt_blob; | |
e160f7d4 | 50 | int offset = dev_of_offset(dev); |
6cadaa04 | 51 | bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC); |
9e5935c0 WY |
52 | const char *name; |
53 | int ret; | |
54 | ||
55 | for (offset = fdt_first_subnode(fdt, offset); | |
56 | offset > 0; | |
57 | offset = fdt_next_subnode(fdt, offset)) { | |
6cadaa04 WY |
58 | if (pre_reloc_only && |
59 | !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL)) | |
60 | continue; | |
61 | /* | |
62 | * If this node has "compatible" property, this is not | |
63 | * a clock sub-node, but a normal device. skip. | |
64 | */ | |
65 | fdt_get_property(fdt, offset, "compatible", &ret); | |
66 | if (ret >= 0) | |
67 | continue; | |
68 | ||
69 | if (ret != -FDT_ERR_NOTFOUND) | |
70 | return ret; | |
71 | ||
9e5935c0 WY |
72 | name = fdt_get_name(fdt, offset, NULL); |
73 | if (!name) | |
74 | return -EINVAL; | |
6cadaa04 | 75 | ret = device_bind_driver_to_node(dev, drv_name, name, |
9e5935c0 WY |
76 | offset, NULL); |
77 | if (ret) | |
78 | return ret; | |
79 | } | |
80 | ||
81 | return 0; | |
82 | } | |
83 | ||
6cadaa04 WY |
84 | int at91_clk_of_xlate(struct clk *clk, struct fdtdec_phandle_args *args) |
85 | { | |
86 | int periph; | |
87 | ||
88 | if (args->args_count) { | |
89 | debug("Invalid args_count: %d\n", args->args_count); | |
90 | return -EINVAL; | |
91 | } | |
92 | ||
e160f7d4 SG |
93 | periph = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(clk->dev), "reg", |
94 | -1); | |
6cadaa04 WY |
95 | if (periph < 0) |
96 | return -EINVAL; | |
97 | ||
98 | clk->id = periph; | |
99 | ||
100 | return 0; | |
101 | } | |
102 | ||
103 | int at91_clk_probe(struct udevice *dev) | |
104 | { | |
105 | struct udevice *dev_periph_container, *dev_pmc; | |
106 | struct pmc_platdata *plat = dev_get_platdata(dev); | |
107 | ||
108 | dev_periph_container = dev_get_parent(dev); | |
109 | dev_pmc = dev_get_parent(dev_periph_container); | |
110 | ||
111 | plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev_pmc); | |
112 | ||
113 | return 0; | |
114 | } |