blob: 06c417b10431e3415ba7072a79c413387446e903 [file] [log] [blame]
Yann Gautier9aea69e2018-07-24 17:13:36 +02001/*
Yann Gautier1a3fc9f2019-01-17 14:35:22 +01002 * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
Yann Gautier9aea69e2018-07-24 17:13:36 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Yann Gautier9aea69e2018-07-24 17:13:36 +02007#include <errno.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
Yann Gautier9aea69e2018-07-24 17:13:36 +02009#include <libfdt.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010
Yann Gautier57e282b2019-01-07 11:17:24 +010011#include <platform_def.h>
12
Yann Gautier4d429472019-02-14 11:15:20 +010013#include <drivers/st/stm32_gpio.h>
14#include <drivers/st/stm32mp_clkfunc.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000015#include <drivers/st/stm32mp1_clk.h>
16#include <drivers/st/stm32mp1_clkfunc.h>
17#include <dt-bindings/clock/stm32mp1-clksrc.h>
18
Yann Gautier9aea69e2018-07-24 17:13:36 +020019const char *stm32mp_osc_node_label[NB_OSC] = {
20 [_LSI] = "clk-lsi",
21 [_LSE] = "clk-lse",
22 [_HSI] = "clk-hsi",
23 [_HSE] = "clk-hse",
24 [_CSI] = "clk-csi",
25 [_I2S_CKIN] = "i2s_ckin",
26 [_USB_PHY_48] = "ck_usbo_48m"
27};
28
Yann Gautier4d429472019-02-14 11:15:20 +010029/*
30 * Get the frequency of an oscillator from its name in device tree.
31 * @param name: oscillator name
32 * @param freq: stores the frequency of the oscillator
33 * @return: 0 on success, and a negative FDT/ERRNO error code on failure.
34 */
Yann Gautier9aea69e2018-07-24 17:13:36 +020035int fdt_osc_read_freq(const char *name, uint32_t *freq)
36{
37 int node, subnode;
38 void *fdt;
39
40 if (fdt_get_address(&fdt) == 0) {
41 return -ENOENT;
42 }
43
44 node = fdt_path_offset(fdt, "/clocks");
45 if (node < 0) {
46 return -FDT_ERR_NOTFOUND;
47 }
48
49 fdt_for_each_subnode(subnode, fdt, node) {
50 const char *cchar;
51 int ret;
52
53 cchar = fdt_get_name(fdt, subnode, &ret);
54 if (cchar == NULL) {
55 return ret;
56 }
57
58 if (strncmp(cchar, name, (size_t)ret) == 0) {
59 const fdt32_t *cuint;
60
61 cuint = fdt_getprop(fdt, subnode, "clock-frequency",
62 &ret);
63 if (cuint == NULL) {
64 return ret;
65 }
66
67 *freq = fdt32_to_cpu(*cuint);
68
69 return 0;
70 }
71 }
72
73 /* Oscillator not found, freq=0 */
74 *freq = 0;
75 return 0;
76}
77
Yann Gautier4d429472019-02-14 11:15:20 +010078/*
79 * Check the presence of an oscillator property from its id.
80 * @param osc_id: oscillator ID
81 * @param prop_name: property name
82 * @return: true/false regarding search result.
83 */
Yann Gautier9aea69e2018-07-24 17:13:36 +020084bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name)
85{
86 int node, subnode;
87 void *fdt;
88
89 if (fdt_get_address(&fdt) == 0) {
90 return false;
91 }
92
93 if (osc_id >= NB_OSC) {
94 return false;
95 }
96
97 node = fdt_path_offset(fdt, "/clocks");
98 if (node < 0) {
99 return false;
100 }
101
102 fdt_for_each_subnode(subnode, fdt, node) {
103 const char *cchar;
104 int ret;
105
106 cchar = fdt_get_name(fdt, subnode, &ret);
107 if (cchar == NULL) {
108 return false;
109 }
110
111 if (strncmp(cchar, stm32mp_osc_node_label[osc_id],
112 (size_t)ret) != 0) {
113 continue;
114 }
115
116 if (fdt_getprop(fdt, subnode, prop_name, NULL) != NULL) {
117 return true;
118 }
119 }
120
121 return false;
122}
123
Yann Gautier4d429472019-02-14 11:15:20 +0100124/*
125 * Get the value of a oscillator property from its ID.
126 * @param osc_id: oscillator ID
127 * @param prop_name: property name
128 * @param dflt_value: default value
129 * @return oscillator value on success, default value if property not found.
130 */
Yann Gautier9aea69e2018-07-24 17:13:36 +0200131uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id,
132 const char *prop_name, uint32_t dflt_value)
133{
134 int node, subnode;
135 void *fdt;
136
137 if (fdt_get_address(&fdt) == 0) {
138 return dflt_value;
139 }
140
141 if (osc_id >= NB_OSC) {
142 return dflt_value;
143 }
144
145 node = fdt_path_offset(fdt, "/clocks");
146 if (node < 0) {
147 return dflt_value;
148 }
149
150 fdt_for_each_subnode(subnode, fdt, node) {
151 const char *cchar;
152 int ret;
153
154 cchar = fdt_get_name(fdt, subnode, &ret);
155 if (cchar == NULL) {
156 return dflt_value;
157 }
158
159 if (strncmp(cchar, stm32mp_osc_node_label[osc_id],
160 (size_t)ret) != 0) {
161 continue;
162 }
163
164 return fdt_read_uint32_default(subnode, prop_name, dflt_value);
165 }
166
167 return dflt_value;
168}